diff --git a/.github/workflows/runtimes-matrix.json b/.github/workflows/runtimes-matrix.json
index 104e73521331e95f4cc3c9c0b6734fcc28199a5f..ff16b7397247fdfaab8d6e95d9ab96da4a6c2fbe 100644
--- a/.github/workflows/runtimes-matrix.json
+++ b/.github/workflows/runtimes-matrix.json
@@ -145,7 +145,7 @@
   {
     "name": "glutton-westend",
     "package": "glutton-westend-runtime",
-    "path": "cumulus/parachains/runtimes/gluttons/glutton-westend",
+    "path": "cumulus/parachains/runtimes/glutton/glutton-westend",
     "header": "cumulus/file_header.txt",
     "template": "cumulus/templates/xcm-bench-template.hbs",
     "bench_features": "runtime-benchmarks",
diff --git a/Cargo.lock b/Cargo.lock
index 3c55a14256c51cfeb45bc1796afb0ead16a55cfc..b0fb0586be3873672536625fc8e31e2348afef40 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -959,11 +959,11 @@ dependencies = [
  "cumulus-pallet-aura-ext 0.7.0",
  "cumulus-pallet-parachain-system 0.7.0",
  "cumulus-pallet-session-benchmarking 9.0.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-pallet-xcm 0.7.0",
  "cumulus-pallet-xcmp-queue 0.7.0",
  "cumulus-primitives-aura 0.7.0",
  "cumulus-primitives-core 0.7.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "cumulus-primitives-utility 0.7.0",
  "frame-benchmarking 28.0.0",
  "frame-executive 28.0.0",
@@ -1095,11 +1095,11 @@ dependencies = [
  "cumulus-pallet-aura-ext 0.7.0",
  "cumulus-pallet-parachain-system 0.7.0",
  "cumulus-pallet-session-benchmarking 9.0.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-pallet-xcm 0.7.0",
  "cumulus-pallet-xcmp-queue 0.7.0",
  "cumulus-primitives-aura 0.7.0",
  "cumulus-primitives-core 0.7.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "cumulus-primitives-utility 0.7.0",
  "frame-benchmarking 28.0.0",
  "frame-executive 28.0.0",
@@ -2666,11 +2666,11 @@ dependencies = [
  "cumulus-pallet-aura-ext 0.7.0",
  "cumulus-pallet-parachain-system 0.7.0",
  "cumulus-pallet-session-benchmarking 9.0.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-pallet-xcm 0.7.0",
  "cumulus-pallet-xcmp-queue 0.7.0",
  "cumulus-primitives-aura 0.7.0",
  "cumulus-primitives-core 0.7.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "cumulus-primitives-utility 0.7.0",
  "frame-benchmarking 28.0.0",
  "frame-executive 28.0.0",
@@ -2905,11 +2905,11 @@ dependencies = [
  "cumulus-pallet-aura-ext 0.7.0",
  "cumulus-pallet-parachain-system 0.7.0",
  "cumulus-pallet-session-benchmarking 9.0.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-pallet-xcm 0.7.0",
  "cumulus-pallet-xcmp-queue 0.7.0",
  "cumulus-primitives-aura 0.7.0",
  "cumulus-primitives-core 0.7.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "cumulus-primitives-utility 0.7.0",
  "frame-benchmarking 28.0.0",
  "frame-executive 28.0.0",
@@ -3645,11 +3645,11 @@ dependencies = [
  "cumulus-pallet-aura-ext 0.7.0",
  "cumulus-pallet-parachain-system 0.7.0",
  "cumulus-pallet-session-benchmarking 9.0.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-pallet-xcm 0.7.0",
  "cumulus-pallet-xcmp-queue 0.7.0",
  "cumulus-primitives-aura 0.7.0",
  "cumulus-primitives-core 0.7.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "cumulus-primitives-utility 0.7.0",
  "frame-benchmarking 28.0.0",
  "frame-executive 28.0.0",
@@ -3952,11 +3952,11 @@ dependencies = [
  "cumulus-pallet-aura-ext 0.7.0",
  "cumulus-pallet-parachain-system 0.7.0",
  "cumulus-pallet-session-benchmarking 9.0.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-pallet-xcm 0.7.0",
  "cumulus-pallet-xcmp-queue 0.7.0",
  "cumulus-primitives-aura 0.7.0",
  "cumulus-primitives-core 0.7.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "cumulus-primitives-utility 0.7.0",
  "frame-benchmarking 28.0.0",
  "frame-executive 28.0.0",
@@ -4095,11 +4095,11 @@ dependencies = [
  "cumulus-pallet-aura-ext 0.7.0",
  "cumulus-pallet-parachain-system 0.7.0",
  "cumulus-pallet-session-benchmarking 9.0.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-pallet-xcm 0.7.0",
  "cumulus-pallet-xcmp-queue 0.7.0",
  "cumulus-primitives-aura 0.7.0",
  "cumulus-primitives-core 0.7.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "cumulus-primitives-utility 0.7.0",
  "frame-benchmarking 28.0.0",
  "frame-executive 28.0.0",
@@ -4196,11 +4196,11 @@ dependencies = [
  "cumulus-pallet-aura-ext 0.7.0",
  "cumulus-pallet-parachain-system 0.7.0",
  "cumulus-pallet-session-benchmarking 9.0.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-pallet-xcm 0.7.0",
  "cumulus-pallet-xcmp-queue 0.7.0",
  "cumulus-primitives-aura 0.7.0",
  "cumulus-primitives-core 0.7.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "cumulus-primitives-utility 0.7.0",
  "frame-benchmarking 28.0.0",
  "frame-executive 28.0.0",
@@ -5074,6 +5074,25 @@ dependencies = [
  "sp-runtime 39.0.2",
 ]
 
+[[package]]
+name = "cumulus-pallet-weight-reclaim"
+version = "1.0.0"
+dependencies = [
+ "cumulus-primitives-proof-size-hostfunction 0.2.0",
+ "cumulus-primitives-storage-weight-reclaim 1.0.0",
+ "derivative",
+ "docify",
+ "frame-benchmarking 28.0.0",
+ "frame-support 28.0.0",
+ "frame-system 28.0.0",
+ "log",
+ "parity-scale-codec",
+ "scale-info",
+ "sp-io 30.0.0",
+ "sp-runtime 31.0.1",
+ "sp-trie 29.0.0",
+]
+
 [[package]]
 name = "cumulus-pallet-xcm"
 version = "0.7.0"
@@ -5524,10 +5543,10 @@ dependencies = [
 name = "cumulus-test-client"
 version = "0.1.0"
 dependencies = [
+ "cumulus-pallet-weight-reclaim",
  "cumulus-primitives-core 0.7.0",
  "cumulus-primitives-parachain-inherent 0.7.0",
  "cumulus-primitives-proof-size-hostfunction 0.2.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "cumulus-test-relay-sproof-builder 0.7.0",
  "cumulus-test-runtime",
  "cumulus-test-service",
@@ -5589,9 +5608,9 @@ version = "0.1.0"
 dependencies = [
  "cumulus-pallet-aura-ext 0.7.0",
  "cumulus-pallet-parachain-system 0.7.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-primitives-aura 0.7.0",
  "cumulus-primitives-core 0.7.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "frame-executive 28.0.0",
  "frame-support 28.0.0",
  "frame-system 28.0.0",
@@ -5643,8 +5662,8 @@ dependencies = [
  "cumulus-client-pov-recovery",
  "cumulus-client-service",
  "cumulus-pallet-parachain-system 0.7.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-primitives-core 0.7.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "cumulus-relay-chain-inprocess-interface",
  "cumulus-relay-chain-interface",
  "cumulus-relay-chain-minimal-node",
@@ -16742,11 +16761,11 @@ dependencies = [
  "cumulus-pallet-aura-ext 0.7.0",
  "cumulus-pallet-parachain-system 0.7.0",
  "cumulus-pallet-session-benchmarking 9.0.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-pallet-xcm 0.7.0",
  "cumulus-pallet-xcmp-queue 0.7.0",
  "cumulus-primitives-aura 0.7.0",
  "cumulus-primitives-core 0.7.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "cumulus-primitives-utility 0.7.0",
  "enumflags2",
  "frame-benchmarking 28.0.0",
@@ -16845,11 +16864,11 @@ dependencies = [
  "cumulus-pallet-aura-ext 0.7.0",
  "cumulus-pallet-parachain-system 0.7.0",
  "cumulus-pallet-session-benchmarking 9.0.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-pallet-xcm 0.7.0",
  "cumulus-pallet-xcmp-queue 0.7.0",
  "cumulus-primitives-aura 0.7.0",
  "cumulus-primitives-core 0.7.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "cumulus-primitives-utility 0.7.0",
  "enumflags2",
  "frame-benchmarking 28.0.0",
@@ -18645,6 +18664,7 @@ dependencies = [
  "cumulus-pallet-parachain-system-proc-macro 0.6.0",
  "cumulus-pallet-session-benchmarking 9.0.0",
  "cumulus-pallet-solo-to-para 0.7.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-pallet-xcm 0.7.0",
  "cumulus-pallet-xcmp-queue 0.7.0",
  "cumulus-ping 0.7.0",
@@ -19233,8 +19253,8 @@ dependencies = [
  "cumulus-client-service",
  "cumulus-pallet-aura-ext 0.7.0",
  "cumulus-pallet-parachain-system 0.7.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-primitives-proof-size-hostfunction 0.2.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "docify",
  "frame-benchmarking 28.0.0",
  "frame-executive 28.0.0",
@@ -21447,12 +21467,12 @@ version = "0.6.0"
 dependencies = [
  "cumulus-pallet-aura-ext 0.7.0",
  "cumulus-pallet-parachain-system 0.7.0",
+ "cumulus-pallet-weight-reclaim",
  "cumulus-pallet-xcm 0.7.0",
  "cumulus-pallet-xcmp-queue 0.7.0",
  "cumulus-ping 0.7.0",
  "cumulus-primitives-aura 0.7.0",
  "cumulus-primitives-core 0.7.0",
- "cumulus-primitives-storage-weight-reclaim 1.0.0",
  "cumulus-primitives-utility 0.7.0",
  "frame-benchmarking 28.0.0",
  "frame-executive 28.0.0",
diff --git a/Cargo.toml b/Cargo.toml
index 64a11a340d10d31d68129b0684007dc1954e6d05..c917a8a8fead4960cd60d1a86e802673afd74f0d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -83,6 +83,7 @@ members = [
 	"cumulus/pallets/parachain-system/proc-macro",
 	"cumulus/pallets/session-benchmarking",
 	"cumulus/pallets/solo-to-para",
+	"cumulus/pallets/weight-reclaim",
 	"cumulus/pallets/xcm",
 	"cumulus/pallets/xcmp-queue",
 	"cumulus/parachains/common",
@@ -717,6 +718,7 @@ cumulus-pallet-parachain-system = { path = "cumulus/pallets/parachain-system", d
 cumulus-pallet-parachain-system-proc-macro = { path = "cumulus/pallets/parachain-system/proc-macro", default-features = false }
 cumulus-pallet-session-benchmarking = { path = "cumulus/pallets/session-benchmarking", default-features = false }
 cumulus-pallet-solo-to-para = { path = "cumulus/pallets/solo-to-para", default-features = false }
+cumulus-pallet-weight-reclaim = { path = "cumulus/pallets/weight-reclaim", default-features = false }
 cumulus-pallet-xcm = { path = "cumulus/pallets/xcm", default-features = false }
 cumulus-pallet-xcmp-queue = { path = "cumulus/pallets/xcmp-queue", default-features = false }
 cumulus-ping = { path = "cumulus/parachains/pallets/ping", default-features = false }
diff --git a/cumulus/pallets/weight-reclaim/Cargo.toml b/cumulus/pallets/weight-reclaim/Cargo.toml
new file mode 100644
index 0000000000000000000000000000000000000000..8bde6abaff6a1a9e53f0e7048d94b18cc43c5325
--- /dev/null
+++ b/cumulus/pallets/weight-reclaim/Cargo.toml
@@ -0,0 +1,63 @@
+[package]
+name = "cumulus-pallet-weight-reclaim"
+version = "1.0.0"
+authors.workspace = true
+edition.workspace = true
+license = "Apache-2.0"
+homepage.workspace = true
+repository.workspace = true
+description = "pallet and transaction extensions for accurate proof size reclaim"
+
+[lints]
+workspace = true
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[dependencies]
+# Substrate dependencies
+sp-io = { workspace = true }
+sp-runtime = { workspace = true }
+sp-trie = { workspace = true }
+
+cumulus-primitives-storage-weight-reclaim = { workspace = true }
+frame-benchmarking = { optional = true, workspace = true }
+frame-support = { workspace = true }
+frame-system = { workspace = true }
+
+# Other dependencies
+codec = { features = ["derive"], workspace = true }
+derivative = { features = ["use_core"], workspace = true }
+docify = { workspace = true }
+log = { workspace = true, default-features = true }
+scale-info = { features = ["derive"], workspace = true }
+
+[dev-dependencies]
+cumulus-primitives-proof-size-hostfunction = { workspace = true }
+
+[features]
+default = ["std"]
+std = [
+	"codec/std",
+	"cumulus-primitives-proof-size-hostfunction/std",
+	"cumulus-primitives-storage-weight-reclaim/std",
+	"frame-benchmarking?/std",
+	"frame-support/std",
+	"frame-system/std",
+	"log/std",
+	"scale-info/std",
+	"sp-io/std",
+	"sp-runtime/std",
+	"sp-trie/std",
+]
+runtime-benchmarks = [
+	"frame-benchmarking/runtime-benchmarks",
+	"frame-support/runtime-benchmarks",
+	"frame-system/runtime-benchmarks",
+	"sp-runtime/runtime-benchmarks",
+]
+try-runtime = [
+	"frame-support/try-runtime",
+	"frame-system/try-runtime",
+	"sp-runtime/try-runtime",
+]
diff --git a/cumulus/pallets/weight-reclaim/src/benchmarks.rs b/cumulus/pallets/weight-reclaim/src/benchmarks.rs
new file mode 100644
index 0000000000000000000000000000000000000000..78bebc967d96bd91ec3f9edd878caf7314523861
--- /dev/null
+++ b/cumulus/pallets/weight-reclaim/src/benchmarks.rs
@@ -0,0 +1,71 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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.
+
+// Cumulus 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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+#![cfg(feature = "runtime-benchmarks")]
+
+use super::*;
+use frame_support::pallet_prelude::{DispatchClass, Pays};
+use frame_system::RawOrigin;
+use sp_runtime::traits::{AsTransactionAuthorizedOrigin, DispatchTransaction};
+
+#[frame_benchmarking::v2::benchmarks(
+	where T: Send + Sync,
+		<T as frame_system::Config>::RuntimeCall:
+			Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
+		<T as frame_system::Config>::RuntimeOrigin: AsTransactionAuthorizedOrigin,
+)]
+mod bench {
+	use super::*;
+	use frame_benchmarking::impl_test_function;
+
+	#[benchmark]
+	fn storage_weight_reclaim() {
+		let ext = StorageWeightReclaim::<T, ()>::new(());
+
+		let origin = RawOrigin::Root.into();
+		let call = T::RuntimeCall::from(frame_system::Call::remark { remark: alloc::vec![] });
+
+		let overestimate = 10_000;
+		let info = DispatchInfo {
+			call_weight: Weight::zero().add_proof_size(overestimate),
+			extension_weight: Weight::zero(),
+			class: DispatchClass::Normal,
+			pays_fee: Pays::No,
+		};
+
+		let post_info = PostDispatchInfo { actual_weight: None, pays_fee: Pays::No };
+
+		let mut block_weight = frame_system::ConsumedWeight::default();
+		block_weight.accrue(Weight::from_parts(0, overestimate), info.class);
+
+		frame_system::BlockWeight::<T>::put(block_weight);
+
+		#[block]
+		{
+			assert!(ext.test_run(origin, &call, &info, 0, 0, |_| Ok(post_info)).unwrap().is_ok());
+		}
+
+		let final_block_proof_size =
+			frame_system::BlockWeight::<T>::get().get(info.class).proof_size();
+
+		assert!(
+			final_block_proof_size < overestimate,
+			"The proof size measured should be less than {overestimate}"
+		);
+	}
+
+	impl_benchmark_test_suite!(Pallet, crate::tests::setup_test_ext_default(), crate::tests::Test);
+}
diff --git a/cumulus/pallets/weight-reclaim/src/lib.rs b/cumulus/pallets/weight-reclaim/src/lib.rs
new file mode 100644
index 0000000000000000000000000000000000000000..bd9929033af14e43614ea1cd70bdd1b3232a6cfe
--- /dev/null
+++ b/cumulus/pallets/weight-reclaim/src/lib.rs
@@ -0,0 +1,311 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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.
+
+// Cumulus 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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Pallet and transaction extensions to reclaim PoV proof size weight after an extrinsic has been
+//! applied.
+//!
+//! This crate provides:
+//! * [`StorageWeightReclaim`] transaction extension: it must wrap the whole transaction extension
+//!   pipeline.
+//! * The pallet required for the transaction extensions weight information and benchmarks.
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+extern crate alloc;
+#[cfg(not(feature = "std"))]
+use alloc::vec::Vec;
+use codec::{Decode, Encode};
+use cumulus_primitives_storage_weight_reclaim::get_proof_size;
+use derivative::Derivative;
+use frame_support::{
+	dispatch::{DispatchInfo, PostDispatchInfo},
+	pallet_prelude::Weight,
+	traits::Defensive,
+};
+use scale_info::TypeInfo;
+use sp_runtime::{
+	traits::{DispatchInfoOf, Dispatchable, Implication, PostDispatchInfoOf, TransactionExtension},
+	transaction_validity::{TransactionSource, TransactionValidityError, ValidTransaction},
+	DispatchResult,
+};
+
+#[cfg(feature = "runtime-benchmarks")]
+pub mod benchmarks;
+#[cfg(test)]
+mod tests;
+mod weights;
+
+pub use pallet::*;
+pub use weights::WeightInfo;
+
+const LOG_TARGET: &'static str = "runtime::storage_reclaim_pallet";
+
+/// Pallet to use alongside the transaction extension [`StorageWeightReclaim`], the pallet provides
+/// weight information and benchmarks.
+#[frame_support::pallet]
+pub mod pallet {
+	use super::*;
+
+	#[pallet::pallet]
+	pub struct Pallet<T>(_);
+
+	#[pallet::config]
+	pub trait Config: frame_system::Config {
+		type WeightInfo: WeightInfo;
+	}
+}
+
+/// Storage weight reclaim mechanism.
+///
+/// This extension must wrap all the transaction extensions:
+#[doc = docify::embed!("./src/tests.rs", Tx)]
+///
+/// This extension checks the size of the node-side storage proof before and after executing a given
+/// extrinsic using the proof size host function. The difference between benchmarked and used weight
+/// is reclaimed.
+///
+/// If the benchmark was underestimating the proof size, then it is added to the block weight.
+///
+/// For the time part of the weight, it does same as system `WeightReclaim` extension, it
+/// calculates the unused weight using the post information and reclaim the unused weight.
+/// So this extension can be used as a drop-in replacement for `WeightReclaim` extension for
+/// parachains.
+#[derive(Encode, Decode, TypeInfo, Derivative)]
+#[derivative(
+	Clone(bound = "S: Clone"),
+	Eq(bound = "S: Eq"),
+	PartialEq(bound = "S: PartialEq"),
+	Default(bound = "S: Default")
+)]
+#[scale_info(skip_type_params(T))]
+pub struct StorageWeightReclaim<T, S>(pub S, core::marker::PhantomData<T>);
+
+impl<T, S> StorageWeightReclaim<T, S> {
+	/// Create a new `StorageWeightReclaim` instance.
+	pub fn new(s: S) -> Self {
+		Self(s, Default::default())
+	}
+}
+
+impl<T, S> From<S> for StorageWeightReclaim<T, S> {
+	fn from(s: S) -> Self {
+		Self::new(s)
+	}
+}
+
+impl<T, S: core::fmt::Debug> core::fmt::Debug for StorageWeightReclaim<T, S> {
+	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
+		#[cfg(feature = "std")]
+		let _ = write!(f, "StorageWeightReclaim<{:?}>", self.0);
+
+		#[cfg(not(feature = "std"))]
+		let _ = write!(f, "StorageWeightReclaim<wasm-stripped>");
+
+		Ok(())
+	}
+}
+
+impl<T: Config + Send + Sync, S: TransactionExtension<T::RuntimeCall>>
+	TransactionExtension<T::RuntimeCall> for StorageWeightReclaim<T, S>
+where
+	T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
+{
+	const IDENTIFIER: &'static str = "StorageWeightReclaim<Use `metadata()`!>";
+
+	type Implicit = S::Implicit;
+
+	// Initial proof size and inner extension value.
+	type Val = (Option<u64>, S::Val);
+
+	// Initial proof size and inner extension pre.
+	type Pre = (Option<u64>, S::Pre);
+
+	fn implicit(&self) -> Result<Self::Implicit, TransactionValidityError> {
+		self.0.implicit()
+	}
+
+	fn metadata() -> Vec<sp_runtime::traits::TransactionExtensionMetadata> {
+		let mut inner = S::metadata();
+		inner.push(sp_runtime::traits::TransactionExtensionMetadata {
+			identifier: "StorageWeightReclaim",
+			ty: scale_info::meta_type::<()>(),
+			implicit: scale_info::meta_type::<()>(),
+		});
+		inner
+	}
+
+	fn weight(&self, call: &T::RuntimeCall) -> Weight {
+		T::WeightInfo::storage_weight_reclaim().saturating_add(self.0.weight(call))
+	}
+
+	fn validate(
+		&self,
+		origin: T::RuntimeOrigin,
+		call: &T::RuntimeCall,
+		info: &DispatchInfoOf<T::RuntimeCall>,
+		len: usize,
+		self_implicit: Self::Implicit,
+		inherited_implication: &impl Implication,
+		source: TransactionSource,
+	) -> Result<(ValidTransaction, Self::Val, T::RuntimeOrigin), TransactionValidityError> {
+		let proof_size = get_proof_size();
+
+		self.0
+			.validate(origin, call, info, len, self_implicit, inherited_implication, source)
+			.map(|(validity, val, origin)| (validity, (proof_size, val), origin))
+	}
+
+	fn prepare(
+		self,
+		val: Self::Val,
+		origin: &T::RuntimeOrigin,
+		call: &T::RuntimeCall,
+		info: &DispatchInfoOf<T::RuntimeCall>,
+		len: usize,
+	) -> Result<Self::Pre, TransactionValidityError> {
+		let (proof_size, inner_val) = val;
+		self.0.prepare(inner_val, origin, call, info, len).map(|pre| (proof_size, pre))
+	}
+
+	fn post_dispatch_details(
+		pre: Self::Pre,
+		info: &DispatchInfoOf<T::RuntimeCall>,
+		post_info: &PostDispatchInfoOf<T::RuntimeCall>,
+		len: usize,
+		result: &DispatchResult,
+	) -> Result<Weight, TransactionValidityError> {
+		let (proof_size_before_dispatch, inner_pre) = pre;
+
+		let mut post_info_with_inner = *post_info;
+		S::post_dispatch(inner_pre, info, &mut post_info_with_inner, len, result)?;
+
+		let inner_refund = if let (Some(before_weight), Some(after_weight)) =
+			(post_info.actual_weight, post_info_with_inner.actual_weight)
+		{
+			before_weight.saturating_sub(after_weight)
+		} else {
+			Weight::zero()
+		};
+
+		let Some(proof_size_before_dispatch) = proof_size_before_dispatch else {
+			// We have no proof size information, there is nothing we can do.
+			return Ok(inner_refund);
+		};
+
+		let Some(proof_size_after_dispatch) = get_proof_size().defensive_proof(
+			"Proof recording enabled during prepare, now disabled. This should not happen.",
+		) else {
+			return Ok(inner_refund)
+		};
+
+		// The consumed proof size as measured by the host.
+		let measured_proof_size =
+			proof_size_after_dispatch.saturating_sub(proof_size_before_dispatch);
+
+		// The consumed weight as benchmarked. Calculated from post info and info.
+		// NOTE: `calc_actual_weight` will take the minimum of `post_info` and `info` weights.
+		// This means any underestimation of compute time in the pre dispatch info will not be
+		// taken into account.
+		let benchmarked_actual_weight = post_info_with_inner.calc_actual_weight(info);
+
+		let benchmarked_actual_proof_size = benchmarked_actual_weight.proof_size();
+		if benchmarked_actual_proof_size < measured_proof_size {
+			log::error!(
+				target: LOG_TARGET,
+				"Benchmarked storage weight smaller than consumed storage weight. \
+				benchmarked: {benchmarked_actual_proof_size} consumed: {measured_proof_size}"
+			);
+		} else {
+			log::trace!(
+				target: LOG_TARGET,
+				"Reclaiming storage weight. benchmarked: {benchmarked_actual_proof_size},
+				consumed: {measured_proof_size}"
+			);
+		}
+
+		let accurate_weight = benchmarked_actual_weight.set_proof_size(measured_proof_size);
+
+		let pov_size_missing_from_node = frame_system::BlockWeight::<T>::mutate(|current_weight| {
+			let already_reclaimed = frame_system::ExtrinsicWeightReclaimed::<T>::get();
+			current_weight.accrue(already_reclaimed, info.class);
+			current_weight.reduce(info.total_weight(), info.class);
+			current_weight.accrue(accurate_weight, info.class);
+
+			// If we encounter a situation where the node-side proof size is already higher than
+			// what we have in the runtime bookkeeping, we add the difference to the `BlockWeight`.
+			// This prevents that the proof size grows faster than the runtime proof size.
+			let extrinsic_len = frame_system::AllExtrinsicsLen::<T>::get().unwrap_or(0);
+			let node_side_pov_size = proof_size_after_dispatch.saturating_add(extrinsic_len.into());
+			let block_weight_proof_size = current_weight.total().proof_size();
+			let pov_size_missing_from_node =
+				node_side_pov_size.saturating_sub(block_weight_proof_size);
+			if pov_size_missing_from_node > 0 {
+				log::warn!(
+					target: LOG_TARGET,
+					"Node-side PoV size higher than runtime proof size weight. node-side: \
+					{node_side_pov_size} extrinsic_len: {extrinsic_len} runtime: \
+					{block_weight_proof_size}, missing: {pov_size_missing_from_node}. Setting to \
+					node-side proof size."
+				);
+				current_weight
+					.accrue(Weight::from_parts(0, pov_size_missing_from_node), info.class);
+			}
+
+			pov_size_missing_from_node
+		});
+
+		// The saturation will happen if the pre-dispatch weight is underestimating the proof
+		// size or if the node-side proof size is higher than expected.
+		// In this case the extrinsic proof size weight reclaimed is 0 and not a negative reclaim.
+		let accurate_unspent = info
+			.total_weight()
+			.saturating_sub(accurate_weight)
+			.saturating_sub(Weight::from_parts(0, pov_size_missing_from_node));
+		frame_system::ExtrinsicWeightReclaimed::<T>::put(accurate_unspent);
+
+		// Call have already returned their unspent amount.
+		// (also transaction extension prior in the pipeline, but there shouldn't be any.)
+		let already_unspent_in_tx_ext_pipeline = post_info.calc_unspent(info);
+		Ok(accurate_unspent.saturating_sub(already_unspent_in_tx_ext_pipeline))
+	}
+
+	fn bare_validate(
+		call: &T::RuntimeCall,
+		info: &DispatchInfoOf<T::RuntimeCall>,
+		len: usize,
+	) -> frame_support::pallet_prelude::TransactionValidity {
+		S::bare_validate(call, info, len)
+	}
+
+	fn bare_validate_and_prepare(
+		call: &T::RuntimeCall,
+		info: &DispatchInfoOf<T::RuntimeCall>,
+		len: usize,
+	) -> Result<(), TransactionValidityError> {
+		S::bare_validate_and_prepare(call, info, len)
+	}
+
+	fn bare_post_dispatch(
+		info: &DispatchInfoOf<T::RuntimeCall>,
+		post_info: &mut PostDispatchInfoOf<T::RuntimeCall>,
+		len: usize,
+		result: &DispatchResult,
+	) -> Result<(), TransactionValidityError> {
+		S::bare_post_dispatch(info, post_info, len, result)?;
+
+		frame_system::Pallet::<T>::reclaim_weight(info, post_info)
+	}
+}
diff --git a/cumulus/pallets/weight-reclaim/src/tests.rs b/cumulus/pallets/weight-reclaim/src/tests.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b87c107c7ec71ce8dea8b04b702f673373dfd16f
--- /dev/null
+++ b/cumulus/pallets/weight-reclaim/src/tests.rs
@@ -0,0 +1,1050 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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.
+
+// Cumulus 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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+#![cfg(test)]
+
+use super::*;
+use cumulus_primitives_proof_size_hostfunction::PROOF_RECORDING_DISABLED;
+use frame_support::{
+	assert_ok, derive_impl, dispatch::GetDispatchInfo, pallet_prelude::DispatchClass,
+};
+use sp_runtime::{
+	generic,
+	traits::{Applyable, BlakeTwo256, DispatchTransaction, Get},
+	BuildStorage,
+};
+use sp_trie::proof_size_extension::ProofSizeExt;
+
+thread_local! {
+	static CHECK_WEIGHT_WEIGHT: core::cell::RefCell<Weight> = Default::default();
+	static STORAGE_WEIGHT_RECLAIM_WEIGHT: core::cell::RefCell<Weight> = Default::default();
+	static MOCK_EXT_WEIGHT: core::cell::RefCell<Weight> = Default::default();
+	static MOCK_EXT_REFUND: core::cell::RefCell<Weight> = Default::default();
+}
+
+/// An extension which has some proof_size weight and some proof_size refund.
+#[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, scale_info::TypeInfo)]
+pub struct MockExtensionWithRefund;
+
+impl TransactionExtension<RuntimeCall> for MockExtensionWithRefund {
+	const IDENTIFIER: &'static str = "mock_extension_with_refund";
+	type Implicit = ();
+	type Val = ();
+	type Pre = ();
+	fn weight(&self, _: &RuntimeCall) -> Weight {
+		MOCK_EXT_WEIGHT.with_borrow(|v| *v)
+	}
+	fn post_dispatch_details(
+		_pre: Self::Pre,
+		_info: &DispatchInfoOf<RuntimeCall>,
+		_post_info: &PostDispatchInfoOf<RuntimeCall>,
+		_len: usize,
+		_result: &DispatchResult,
+	) -> Result<Weight, TransactionValidityError> {
+		Ok(MOCK_EXT_REFUND.with_borrow(|v| *v))
+	}
+	fn bare_post_dispatch(
+		_info: &DispatchInfoOf<RuntimeCall>,
+		post_info: &mut PostDispatchInfoOf<RuntimeCall>,
+		_len: usize,
+		_result: &DispatchResult,
+	) -> Result<(), TransactionValidityError> {
+		if let Some(ref mut w) = post_info.actual_weight {
+			*w -= MOCK_EXT_REFUND.with_borrow(|v| *v);
+		}
+		Ok(())
+	}
+
+	sp_runtime::impl_tx_ext_default!(RuntimeCall; validate prepare);
+}
+
+pub type Tx =
+	crate::StorageWeightReclaim<Test, (frame_system::CheckWeight<Test>, MockExtensionWithRefund)>;
+type AccountId = u64;
+type Extrinsic = generic::UncheckedExtrinsic<AccountId, RuntimeCall, (), Tx>;
+type Block = generic::Block<generic::Header<AccountId, BlakeTwo256>, Extrinsic>;
+
+#[frame_support::runtime]
+mod runtime {
+	#[runtime::runtime]
+	#[runtime::derive(
+		RuntimeCall,
+		RuntimeEvent,
+		RuntimeError,
+		RuntimeOrigin,
+		RuntimeFreezeReason,
+		RuntimeHoldReason,
+		RuntimeSlashReason,
+		RuntimeLockId,
+		RuntimeTask
+	)]
+	pub struct Test;
+
+	#[runtime::pallet_index(0)]
+	pub type System = frame_system::Pallet<Test>;
+
+	#[runtime::pallet_index(1)]
+	pub type WeightReclaim = crate::Pallet<Test>;
+}
+
+pub struct MockWeightInfo;
+
+impl frame_system::ExtensionsWeightInfo for MockWeightInfo {
+	fn check_genesis() -> Weight {
+		Default::default()
+	}
+	fn check_mortality_mortal_transaction() -> Weight {
+		Default::default()
+	}
+	fn check_mortality_immortal_transaction() -> Weight {
+		Default::default()
+	}
+	fn check_non_zero_sender() -> Weight {
+		Default::default()
+	}
+	fn check_nonce() -> Weight {
+		Default::default()
+	}
+	fn check_spec_version() -> Weight {
+		Default::default()
+	}
+	fn check_tx_version() -> Weight {
+		Default::default()
+	}
+	fn check_weight() -> Weight {
+		CHECK_WEIGHT_WEIGHT.with_borrow(|v| *v)
+	}
+	fn weight_reclaim() -> Weight {
+		Default::default()
+	}
+}
+
+impl frame_system::WeightInfo for MockWeightInfo {
+	fn remark(_b: u32) -> Weight {
+		Weight::from_parts(400, 0)
+	}
+	fn set_code() -> Weight {
+		Weight::zero()
+	}
+	fn set_storage(_i: u32) -> Weight {
+		Weight::zero()
+	}
+	fn kill_prefix(_p: u32) -> Weight {
+		Weight::zero()
+	}
+	fn kill_storage(_i: u32) -> Weight {
+		Weight::zero()
+	}
+	fn set_heap_pages() -> Weight {
+		Weight::zero()
+	}
+	fn remark_with_event(_b: u32) -> Weight {
+		Weight::zero()
+	}
+	fn authorize_upgrade() -> Weight {
+		Weight::zero()
+	}
+	fn apply_authorized_upgrade() -> Weight {
+		Weight::zero()
+	}
+}
+
+impl crate::WeightInfo for MockWeightInfo {
+	fn storage_weight_reclaim() -> Weight {
+		STORAGE_WEIGHT_RECLAIM_WEIGHT.with_borrow(|v| *v)
+	}
+}
+
+#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
+impl frame_system::Config for Test {
+	type Block = Block;
+	type AccountData = ();
+	type MaxConsumers = frame_support::traits::ConstU32<3>;
+	type ExtensionsWeightInfo = MockWeightInfo;
+}
+
+impl crate::Config for Test {
+	type WeightInfo = MockWeightInfo;
+}
+
+fn new_test_ext() -> sp_io::TestExternalities {
+	RuntimeGenesisConfig::default().build_storage().unwrap().into()
+}
+
+struct TestRecorder {
+	return_values: Box<[usize]>,
+	counter: core::sync::atomic::AtomicUsize,
+}
+
+impl TestRecorder {
+	fn new(values: &[usize]) -> Self {
+		TestRecorder { return_values: values.into(), counter: Default::default() }
+	}
+}
+
+impl sp_trie::ProofSizeProvider for TestRecorder {
+	fn estimate_encoded_size(&self) -> usize {
+		let counter = self.counter.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
+		self.return_values[counter]
+	}
+}
+
+fn setup_test_externalities(proof_values: &[usize]) -> sp_io::TestExternalities {
+	let mut test_ext = new_test_ext();
+	let test_recorder = TestRecorder::new(proof_values);
+	test_ext.register_extension(ProofSizeExt::new(test_recorder));
+	test_ext
+}
+
+#[cfg(feature = "runtime-benchmarks")]
+pub fn setup_test_ext_default() -> sp_io::TestExternalities {
+	setup_test_externalities(&[0; 32])
+}
+
+fn set_current_storage_weight(new_weight: u64) {
+	frame_system::BlockWeight::<Test>::mutate(|current_weight| {
+		current_weight.set(Weight::from_parts(0, new_weight), DispatchClass::Normal);
+	});
+}
+
+fn get_storage_weight() -> Weight {
+	*frame_system::BlockWeight::<Test>::get().get(DispatchClass::Normal)
+}
+
+const CALL: &<Test as frame_system::Config>::RuntimeCall =
+	&RuntimeCall::System(frame_system::Call::set_heap_pages { pages: 0u64 });
+const ALICE_ORIGIN: frame_system::Origin<Test> = frame_system::Origin::<Test>::Signed(99);
+const LEN: usize = 150;
+
+fn new_tx_ext() -> Tx {
+	Tx::new((frame_system::CheckWeight::new(), MockExtensionWithRefund))
+}
+
+fn new_extrinsic() -> generic::CheckedExtrinsic<AccountId, RuntimeCall, Tx> {
+	generic::CheckedExtrinsic {
+		format: generic::ExtrinsicFormat::Signed(99, new_tx_ext()),
+		function: RuntimeCall::System(frame_system::Call::remark { remark: vec![] }),
+	}
+}
+
+#[allow(unused)]
+mod doc {
+	type Runtime = super::Test;
+	use crate::StorageWeightReclaim;
+
+	#[docify::export(Tx)]
+	type Tx = StorageWeightReclaim<
+		Runtime,
+		(
+			frame_system::CheckNonce<Runtime>,
+			frame_system::CheckWeight<Runtime>,
+			// ... all other extensions
+			// No need for `frame_system::WeightReclaim` as the reclaim.
+		),
+	>;
+}
+
+#[test]
+fn basic_refund_no_post_info() {
+	// The real cost will be 100 bytes of storage size
+	let mut test_ext = setup_test_externalities(&[0, 100]);
+
+	test_ext.execute_with(|| {
+		set_current_storage_weight(1000);
+
+		// Benchmarked storage weight: 500
+		let info = DispatchInfo { call_weight: Weight::from_parts(0, 500), ..Default::default() };
+		let mut post_info = PostDispatchInfo::default();
+
+		let tx_ext = new_tx_ext();
+
+		// Check weight should add 500 + 150 (len) to weight.
+		let (pre, _) = tx_ext
+			.validate_and_prepare(ALICE_ORIGIN.clone().into(), CALL, &info, LEN, 0)
+			.unwrap();
+
+		assert_eq!(pre.0, Some(0));
+
+		assert_ok!(Tx::post_dispatch(pre, &info, &mut post_info, LEN, &Ok(())));
+
+		assert_eq!(post_info.actual_weight, None);
+		assert_eq!(get_storage_weight().proof_size(), 1250);
+	});
+}
+
+#[test]
+fn basic_refund_some_post_info() {
+	// The real cost will be 100 bytes of storage size
+	let mut test_ext = setup_test_externalities(&[0, 100]);
+
+	test_ext.execute_with(|| {
+		set_current_storage_weight(1000);
+
+		// Benchmarked storage weight: 500
+		let info = DispatchInfo { call_weight: Weight::from_parts(0, 500), ..Default::default() };
+		let mut post_info = PostDispatchInfo::default();
+		post_info.actual_weight = Some(info.total_weight());
+
+		let tx_ext = new_tx_ext();
+
+		// Check weight should add 500 + 150 (len) to weight.
+		let (pre, _) = tx_ext
+			.validate_and_prepare(ALICE_ORIGIN.clone().into(), CALL, &info, LEN, 0)
+			.unwrap();
+
+		assert_eq!(pre.0, Some(0));
+
+		assert_ok!(Tx::post_dispatch(pre, &info, &mut post_info, LEN, &Ok(())));
+
+		assert_eq!(post_info.actual_weight.unwrap(), Weight::from_parts(0, 100));
+		assert_eq!(get_storage_weight().proof_size(), 1250);
+	});
+}
+
+#[test]
+fn does_nothing_without_extension() {
+	// Proof size extension not registered
+	let mut test_ext = new_test_ext();
+
+	test_ext.execute_with(|| {
+		set_current_storage_weight(1000);
+
+		// Benchmarked storage weight: 500
+		let info = DispatchInfo { call_weight: Weight::from_parts(0, 500), ..Default::default() };
+		let mut post_info = PostDispatchInfo::default();
+		post_info.actual_weight = Some(info.total_weight());
+
+		let tx_ext = new_tx_ext();
+
+		// Check weight should add 500 + 150 (len) to weight.
+		let (pre, _) = tx_ext
+			.validate_and_prepare(ALICE_ORIGIN.clone().into(), CALL, &info, LEN, 0)
+			.unwrap();
+
+		assert_eq!(pre.0, None);
+
+		assert_ok!(Tx::post_dispatch(pre, &info, &mut post_info, LEN, &Ok(())));
+
+		assert_eq!(post_info.actual_weight.unwrap(), info.total_weight());
+		assert_eq!(get_storage_weight().proof_size(), 1650);
+	})
+}
+
+#[test]
+fn negative_refund_is_added_to_weight() {
+	let mut test_ext = setup_test_externalities(&[100, 300]);
+
+	test_ext.execute_with(|| {
+		set_current_storage_weight(1000);
+		// Benchmarked storage weight: 100
+		let info = DispatchInfo { call_weight: Weight::from_parts(0, 100), ..Default::default() };
+		let mut post_info = PostDispatchInfo::default();
+		post_info.actual_weight = Some(info.total_weight());
+
+		let tx_ext = new_tx_ext();
+
+		// Weight added should be 100 + 150 (len)
+		let (pre, _) = tx_ext
+			.validate_and_prepare(ALICE_ORIGIN.clone().into(), CALL, &info, LEN, 0)
+			.unwrap();
+
+		assert_eq!(pre.0, Some(100));
+
+		// We expect no refund
+		assert_ok!(Tx::post_dispatch(pre, &info, &mut post_info, LEN, &Ok(())));
+
+		assert_eq!(post_info.actual_weight.unwrap(), info.total_weight());
+		assert_eq!(
+			get_storage_weight().proof_size(),
+			1100 + LEN as u64 + info.total_weight().proof_size()
+		);
+	})
+}
+
+#[test]
+fn test_zero_proof_size() {
+	let mut test_ext = setup_test_externalities(&[0, 0]);
+
+	test_ext.execute_with(|| {
+		let info = DispatchInfo { call_weight: Weight::from_parts(0, 500), ..Default::default() };
+		let mut post_info = PostDispatchInfo::default();
+		post_info.actual_weight = Some(info.total_weight());
+
+		let tx_ext = new_tx_ext();
+
+		let (pre, _) = tx_ext
+			.validate_and_prepare(ALICE_ORIGIN.clone().into(), CALL, &info, LEN, 0)
+			.unwrap();
+
+		assert_eq!(pre.0, Some(0));
+
+		assert_ok!(Tx::post_dispatch(pre, &info, &mut post_info, LEN, &Ok(())));
+
+		assert_eq!(post_info.actual_weight.unwrap(), Weight::from_parts(0, 0));
+		// Proof size should be exactly equal to extrinsic length
+		assert_eq!(get_storage_weight().proof_size(), LEN as u64);
+	});
+}
+
+#[test]
+fn test_larger_pre_dispatch_proof_size() {
+	let mut test_ext = setup_test_externalities(&[300, 100]);
+
+	test_ext.execute_with(|| {
+		set_current_storage_weight(1300);
+
+		let info = DispatchInfo { call_weight: Weight::from_parts(0, 500), ..Default::default() };
+		let mut post_info = PostDispatchInfo::default();
+		post_info.actual_weight = Some(info.total_weight());
+
+		let tx_ext = new_tx_ext();
+
+		// Adds 500 + 150 (len) weight, total weight is 1950
+		let (pre, _) = tx_ext
+			.validate_and_prepare(ALICE_ORIGIN.clone().into(), CALL, &info, LEN, 0)
+			.unwrap();
+
+		assert_eq!(pre.0, Some(300));
+
+		// check weight:
+		// Refund 500 unspent weight according to `post_info`, total weight is now 1650
+		//
+		// storage reclaim:
+		// Recorded proof size is negative -200, total weight is now 1450
+		assert_ok!(Tx::post_dispatch(pre, &info, &mut post_info, LEN, &Ok(())));
+
+		assert_eq!(post_info.actual_weight.unwrap(), Weight::from_parts(0, 0));
+		assert_eq!(get_storage_weight().proof_size(), 1450);
+	});
+}
+
+#[test]
+fn test_incorporates_check_weight_unspent_weight() {
+	let mut test_ext = setup_test_externalities(&[100, 300]);
+
+	test_ext.execute_with(|| {
+		set_current_storage_weight(1000);
+
+		// Benchmarked storage weight: 300
+		let info = DispatchInfo { call_weight: Weight::from_parts(100, 300), ..Default::default() };
+
+		// Actual weight is 50
+		let mut post_info = PostDispatchInfo {
+			actual_weight: Some(Weight::from_parts(50, 250)),
+			pays_fee: Default::default(),
+		};
+
+		let tx_ext = new_tx_ext();
+
+		// Check weight should add 300 + 150 (len) of weight
+		let (pre, _) = tx_ext
+			.validate_and_prepare(ALICE_ORIGIN.clone().into(), CALL, &info, LEN, 0)
+			.unwrap();
+
+		assert_eq!(pre.0, Some(100));
+
+		// The `CheckWeight` extension will refund `actual_weight` from `PostDispatchInfo`
+		// we always need to call `post_dispatch` to verify that they interoperate correctly.
+		assert_ok!(Tx::post_dispatch(pre, &info, &mut post_info, LEN, &Ok(())));
+
+		assert_eq!(post_info.actual_weight.unwrap(), Weight::from_parts(50, 350 - LEN as u64));
+		// Reclaimed 100
+		assert_eq!(get_storage_weight().proof_size(), 1350);
+	})
+}
+
+#[test]
+fn test_incorporates_check_weight_unspent_weight_on_negative() {
+	let mut test_ext = setup_test_externalities(&[100, 300]);
+
+	test_ext.execute_with(|| {
+		set_current_storage_weight(1000);
+		// Benchmarked storage weight: 50
+		let info = DispatchInfo { call_weight: Weight::from_parts(100, 50), ..Default::default() };
+
+		// Actual weight is 25
+		let mut post_info = PostDispatchInfo {
+			actual_weight: Some(Weight::from_parts(50, 25)),
+			pays_fee: Default::default(),
+		};
+
+		let tx_ext = new_tx_ext();
+
+		// Adds 50 + 150 (len) weight, total weight 1200
+		let (pre, _) = tx_ext
+			.validate_and_prepare(ALICE_ORIGIN.clone().into(), CALL, &info, LEN, 0)
+			.unwrap();
+		assert_eq!(pre.0, Some(100));
+
+		// The `CheckWeight` extension will refund `actual_weight` from `PostDispatchInfo`
+		// CheckWeight: refunds unspent 25 weight according to `post_info`, 1175
+		//
+		// storage reclaim:
+		// Adds 200 - 25 (unspent) == 175 weight, total weight 1350
+		assert_ok!(Tx::post_dispatch(pre, &info, &mut post_info, LEN, &Ok(())));
+
+		assert_eq!(post_info.actual_weight.unwrap(), Weight::from_parts(50, 25));
+		assert_eq!(get_storage_weight().proof_size(), 1350);
+	})
+}
+
+#[test]
+fn test_nothing_reclaimed() {
+	let mut test_ext = setup_test_externalities(&[0, 100]);
+
+	test_ext.execute_with(|| {
+		set_current_storage_weight(0);
+		// Benchmarked storage weight: 100
+		let info = DispatchInfo { call_weight: Weight::from_parts(100, 100), ..Default::default() };
+
+		// Actual proof size is 100
+		let mut post_info = PostDispatchInfo {
+			actual_weight: Some(Weight::from_parts(50, 100)),
+			pays_fee: Default::default(),
+		};
+
+		let tx_ext = new_tx_ext();
+
+		// Adds benchmarked weight 100 + 150 (len), total weight is now 250
+		let (pre, _) = tx_ext
+			.validate_and_prepare(ALICE_ORIGIN.clone().into(), CALL, &info, LEN, 0)
+			.unwrap();
+
+		// Weight should go up by 150 len + 100 proof size weight, total weight 250
+		assert_eq!(get_storage_weight().proof_size(), 250);
+
+		// Should return `setup_test_externalities` proof recorder value: 100.
+		assert_eq!(pre.0, Some(0));
+
+		// The `CheckWeight` extension will refund `actual_weight` from `PostDispatchInfo`
+		// we always need to call `post_dispatch` to verify that they interoperate correctly.
+		// Nothing to refund, unspent is 0, total weight 250
+		//
+		// weight reclaim:
+		// `setup_test_externalities` proof recorder value: 200, so this means the extrinsic
+		// actually used 100 proof size.
+		// Nothing to refund or add, weight matches proof recorder
+		assert_ok!(Tx::post_dispatch(pre, &info, &mut post_info, LEN, &Ok(())));
+
+		assert_eq!(post_info.actual_weight.unwrap(), Weight::from_parts(50, 100));
+		// Check block len weight was not reclaimed:
+		// 100 weight + 150 extrinsic len == 250 proof size
+		assert_eq!(get_storage_weight().proof_size(), 250);
+	})
+}
+
+// Test for refund of calls and related proof size
+#[test]
+fn test_series() {
+	struct TestCfg {
+		measured_proof_size_pre_dispatch: u64,
+		measured_proof_size_post_dispatch: u64,
+		info_call_weight: Weight,
+		info_extension_weight: Weight,
+		post_info_actual_weight: Option<Weight>,
+		block_weight_pre_dispatch: Weight,
+		mock_ext_refund: Weight,
+		assert_post_info_weight: Option<Weight>,
+		assert_block_weight_post_dispatch: Weight,
+	}
+
+	let base_extrinsic = <<Test as frame_system::Config>::BlockWeights as Get<
+		frame_system::limits::BlockWeights,
+	>>::get()
+	.per_class
+	.get(DispatchClass::Normal)
+	.base_extrinsic;
+
+	let tests = vec![
+		// Info is exact, no post info, no refund.
+		TestCfg {
+			measured_proof_size_pre_dispatch: 100,
+			measured_proof_size_post_dispatch: 400,
+			info_call_weight: Weight::from_parts(40, 100),
+			info_extension_weight: Weight::from_parts(60, 200),
+			post_info_actual_weight: None,
+			block_weight_pre_dispatch: Weight::from_parts(1000, 1000),
+			mock_ext_refund: Weight::from_parts(0, 0),
+			assert_post_info_weight: None,
+			assert_block_weight_post_dispatch: base_extrinsic +
+				Weight::from_parts(1100, 1300 + LEN as u64),
+		},
+		// some tx ext refund is ignored, because post info is None.
+		TestCfg {
+			measured_proof_size_pre_dispatch: 100,
+			measured_proof_size_post_dispatch: 400,
+			info_call_weight: Weight::from_parts(40, 100),
+			info_extension_weight: Weight::from_parts(60, 200),
+			post_info_actual_weight: None,
+			block_weight_pre_dispatch: Weight::from_parts(1000, 1000),
+			mock_ext_refund: Weight::from_parts(20, 20),
+			assert_post_info_weight: None,
+			assert_block_weight_post_dispatch: base_extrinsic +
+				Weight::from_parts(1100, 1300 + LEN as u64),
+		},
+		// some tx ext refund is ignored on proof size because lower than actual measure.
+		TestCfg {
+			measured_proof_size_pre_dispatch: 100,
+			measured_proof_size_post_dispatch: 400,
+			info_call_weight: Weight::from_parts(40, 100),
+			info_extension_weight: Weight::from_parts(60, 200),
+			post_info_actual_weight: Some(Weight::from_parts(100, 300)),
+			block_weight_pre_dispatch: Weight::from_parts(1000, 1000),
+			mock_ext_refund: Weight::from_parts(20, 20),
+			assert_post_info_weight: Some(Weight::from_parts(80, 300)),
+			assert_block_weight_post_dispatch: base_extrinsic +
+				Weight::from_parts(1080, 1300 + LEN as u64),
+		},
+		// post info doesn't double refund the call and is missing some.
+		TestCfg {
+			measured_proof_size_pre_dispatch: 100,
+			measured_proof_size_post_dispatch: 350,
+			info_call_weight: Weight::from_parts(40, 100),
+			info_extension_weight: Weight::from_parts(60, 200),
+			post_info_actual_weight: Some(Weight::from_parts(60, 200)),
+			block_weight_pre_dispatch: Weight::from_parts(1000, 1000),
+			mock_ext_refund: Weight::from_parts(20, 20),
+			// 50 are missed in pov because 100 is unspent in post info but it should be only 50.
+			assert_post_info_weight: Some(Weight::from_parts(40, 200)),
+			assert_block_weight_post_dispatch: base_extrinsic +
+				Weight::from_parts(1040, 1250 + LEN as u64),
+		},
+		// post info doesn't double refund the call and is accurate.
+		TestCfg {
+			measured_proof_size_pre_dispatch: 100,
+			measured_proof_size_post_dispatch: 250,
+			info_call_weight: Weight::from_parts(40, 100),
+			info_extension_weight: Weight::from_parts(60, 200),
+			post_info_actual_weight: Some(Weight::from_parts(60, 200)),
+			block_weight_pre_dispatch: Weight::from_parts(1000, 1000),
+			mock_ext_refund: Weight::from_parts(20, 20),
+			assert_post_info_weight: Some(Weight::from_parts(40, 150)),
+			assert_block_weight_post_dispatch: base_extrinsic +
+				Weight::from_parts(1040, 1150 + LEN as u64),
+		},
+		// post info doesn't double refund the call and is accurate. Even if mock ext is refunding
+		// too much.
+		TestCfg {
+			measured_proof_size_pre_dispatch: 100,
+			measured_proof_size_post_dispatch: 250,
+			info_call_weight: Weight::from_parts(40, 100),
+			info_extension_weight: Weight::from_parts(60, 200),
+			post_info_actual_weight: Some(Weight::from_parts(60, 200)),
+			block_weight_pre_dispatch: Weight::from_parts(1000, 1000),
+			mock_ext_refund: Weight::from_parts(20, 300),
+			assert_post_info_weight: Some(Weight::from_parts(40, 150)),
+			assert_block_weight_post_dispatch: base_extrinsic +
+				Weight::from_parts(1040, 1150 + LEN as u64),
+		},
+	];
+
+	for (i, test) in tests.into_iter().enumerate() {
+		dbg!("test number: ", i);
+		MOCK_EXT_REFUND.with_borrow_mut(|v| *v = test.mock_ext_refund);
+		let mut test_ext = setup_test_externalities(&[
+			test.measured_proof_size_pre_dispatch as usize,
+			test.measured_proof_size_post_dispatch as usize,
+		]);
+
+		test_ext.execute_with(|| {
+			frame_system::BlockWeight::<Test>::mutate(|current_weight| {
+				current_weight.set(test.block_weight_pre_dispatch, DispatchClass::Normal);
+			});
+			// Benchmarked storage weight: 50
+			let info = DispatchInfo {
+				call_weight: test.info_call_weight,
+				extension_weight: test.info_extension_weight,
+				..Default::default()
+			};
+			let mut post_info = PostDispatchInfo {
+				actual_weight: test.post_info_actual_weight,
+				pays_fee: Default::default(),
+			};
+			let tx_ext = new_tx_ext();
+			let (pre, _) = tx_ext
+				.validate_and_prepare(ALICE_ORIGIN.clone().into(), CALL, &info, LEN, 0)
+				.unwrap();
+			assert_ok!(Tx::post_dispatch(pre, &info, &mut post_info, LEN, &Ok(())));
+
+			assert_eq!(post_info.actual_weight, test.assert_post_info_weight);
+			assert_eq!(
+				*frame_system::BlockWeight::<Test>::get().get(DispatchClass::Normal),
+				test.assert_block_weight_post_dispatch,
+			);
+		})
+	}
+}
+
+#[test]
+fn storage_size_reported_correctly() {
+	let mut test_ext = setup_test_externalities(&[1000]);
+	test_ext.execute_with(|| {
+		assert_eq!(get_proof_size(), Some(1000));
+	});
+
+	let mut test_ext = new_test_ext();
+
+	let test_recorder = TestRecorder::new(&[0]);
+
+	test_ext.register_extension(ProofSizeExt::new(test_recorder));
+
+	test_ext.execute_with(|| {
+		assert_eq!(get_proof_size(), Some(0));
+	});
+}
+
+#[test]
+fn storage_size_disabled_reported_correctly() {
+	let mut test_ext = setup_test_externalities(&[PROOF_RECORDING_DISABLED as usize]);
+
+	test_ext.execute_with(|| {
+		assert_eq!(get_proof_size(), None);
+	});
+}
+
+#[test]
+fn full_basic_refund() {
+	// Settings for the test:
+	let actual_used_proof_size = 200;
+	let check_weight = 100;
+	let storage_weight_reclaim = 100;
+	let mock_ext = 142;
+	let mock_ext_refund = 100;
+
+	// Test execution:
+	CHECK_WEIGHT_WEIGHT.with_borrow_mut(|v| *v = Weight::from_parts(1, check_weight));
+	STORAGE_WEIGHT_RECLAIM_WEIGHT
+		.with_borrow_mut(|v| *v = Weight::from_parts(1, storage_weight_reclaim));
+	MOCK_EXT_WEIGHT.with_borrow_mut(|v| *v = Weight::from_parts(36, mock_ext));
+	MOCK_EXT_REFUND.with_borrow_mut(|v| *v = Weight::from_parts(35, mock_ext_refund));
+
+	let initial_storage_weight = 1212u64;
+
+	let mut test_ext = setup_test_externalities(&[
+		initial_storage_weight as usize,
+		initial_storage_weight as usize + actual_used_proof_size,
+	]);
+
+	test_ext.execute_with(|| {
+		set_current_storage_weight(initial_storage_weight);
+
+		let extrinsic = new_extrinsic();
+		let call_info = extrinsic.function.get_dispatch_info();
+
+		let info = extrinsic.get_dispatch_info();
+		let post_info = extrinsic.apply::<Test>(&info, LEN).unwrap().unwrap();
+
+		// Assertions:
+		assert_eq!(
+			post_info.actual_weight.unwrap().ref_time(),
+			call_info.call_weight.ref_time() + 3,
+		);
+		assert_eq!(
+			post_info.actual_weight.unwrap().proof_size(),
+			// LEN is part of the base extrinsic, not the post info weight actual weight.
+			actual_used_proof_size as u64,
+		);
+		assert_eq!(
+			get_storage_weight().proof_size(),
+			initial_storage_weight + actual_used_proof_size as u64 + LEN as u64
+		);
+	});
+}
+
+#[test]
+fn full_accrue() {
+	// Settings for the test:
+	let actual_used_proof_size = 400;
+	let check_weight = 100;
+	let storage_weight_reclaim = 100;
+	let mock_ext = 142;
+	let mock_ext_refund = 100;
+
+	// Test execution:
+	CHECK_WEIGHT_WEIGHT.with_borrow_mut(|v| *v = Weight::from_parts(1, check_weight));
+	STORAGE_WEIGHT_RECLAIM_WEIGHT
+		.with_borrow_mut(|v| *v = Weight::from_parts(1, storage_weight_reclaim));
+	MOCK_EXT_WEIGHT.with_borrow_mut(|v| *v = Weight::from_parts(36, mock_ext));
+	MOCK_EXT_REFUND.with_borrow_mut(|v| *v = Weight::from_parts(35, mock_ext_refund));
+
+	let initial_storage_weight = 1212u64;
+
+	let mut test_ext = setup_test_externalities(&[
+		initial_storage_weight as usize,
+		initial_storage_weight as usize + actual_used_proof_size,
+	]);
+
+	test_ext.execute_with(|| {
+		set_current_storage_weight(initial_storage_weight);
+
+		let extrinsic = new_extrinsic();
+		let call_info = extrinsic.function.get_dispatch_info();
+
+		let info = extrinsic.get_dispatch_info();
+		let post_info = extrinsic.apply::<Test>(&info, LEN).unwrap().unwrap();
+
+		// Assertions:
+		assert_eq!(
+			post_info.actual_weight.unwrap().ref_time(),
+			call_info.call_weight.ref_time() + 3,
+		);
+		assert_eq!(
+			post_info.actual_weight.unwrap().proof_size(),
+			info.total_weight().proof_size(), // The post info doesn't get the accrue.
+		);
+		assert_eq!(
+			get_storage_weight().proof_size(),
+			initial_storage_weight + actual_used_proof_size as u64 + LEN as u64
+		);
+	});
+}
+
+#[test]
+fn bare_is_reclaimed() {
+	let mut test_ext = setup_test_externalities(&[]);
+	test_ext.execute_with(|| {
+		let info = DispatchInfo {
+			call_weight: Weight::from_parts(100, 100),
+			extension_weight: Weight::from_parts(100, 100),
+			class: DispatchClass::Normal,
+			pays_fee: Default::default(),
+		};
+		let mut post_info = PostDispatchInfo {
+			actual_weight: Some(Weight::from_parts(100, 100)),
+			pays_fee: Default::default(),
+		};
+		MOCK_EXT_REFUND.with_borrow_mut(|v| *v = Weight::from_parts(10, 10));
+
+		frame_system::BlockWeight::<Test>::mutate(|current_weight| {
+			current_weight
+				.set(Weight::from_parts(45, 45) + info.total_weight(), DispatchClass::Normal);
+		});
+
+		StorageWeightReclaim::<Test, MockExtensionWithRefund>::bare_post_dispatch(
+			&info,
+			&mut post_info,
+			0,
+			&Ok(()),
+		)
+		.expect("tx is valid");
+
+		assert_eq!(
+			*frame_system::BlockWeight::<Test>::get().get(DispatchClass::Normal),
+			Weight::from_parts(45 + 90, 45 + 90),
+		);
+	});
+}
+
+#[test]
+fn sets_to_node_storage_proof_if_higher() {
+	struct TestCfg {
+		initial_proof_size: u64,
+		post_dispatch_proof_size: u64,
+		mock_ext_proof_size: u64,
+		pre_dispatch_block_proof_size: u64,
+		assert_final_block_proof_size: u64,
+	}
+
+	let tests = vec![
+		// The storage proof reported by the proof recorder is higher than what is stored on
+		// the runtime side.
+		TestCfg {
+			initial_proof_size: 1000,
+			post_dispatch_proof_size: 1005,
+			mock_ext_proof_size: 0,
+			pre_dispatch_block_proof_size: 5,
+			// We expect that the storage weight was set to the node-side proof size (1005) +
+			// extrinsics length (150)
+			assert_final_block_proof_size: 1155,
+		},
+		// In this second scenario the proof size on the node side is only lower
+		// after reclaim happened.
+		TestCfg {
+			initial_proof_size: 175,
+			post_dispatch_proof_size: 180,
+			mock_ext_proof_size: 100,
+			pre_dispatch_block_proof_size: 85,
+			// After the pre_dispatch, the BlockWeight proof size will be
+			// 85 (initial) + 100 (benched) + 150 (tx length) = 335
+			//
+			// We expect that the storage weight was set to the node-side proof weight
+			// First we will reclaim 95, which leaves us with 240 BlockWeight.
+			// This is lower than 180 (proof size hf) + 150 (length).
+			// So we expect it to be set to 330.
+			assert_final_block_proof_size: 330,
+		},
+	];
+
+	for test in tests {
+		let mut test_ext = setup_test_externalities(&[
+			test.initial_proof_size as usize,
+			test.post_dispatch_proof_size as usize,
+		]);
+
+		CHECK_WEIGHT_WEIGHT.with_borrow_mut(|v| *v = Weight::from_parts(0, 0));
+		STORAGE_WEIGHT_RECLAIM_WEIGHT.with_borrow_mut(|v| *v = Weight::from_parts(0, 0));
+		MOCK_EXT_WEIGHT.with_borrow_mut(|v| *v = Weight::from_parts(0, test.mock_ext_proof_size));
+
+		test_ext.execute_with(|| {
+			set_current_storage_weight(test.pre_dispatch_block_proof_size);
+
+			let extrinsic = new_extrinsic();
+			let call_info = extrinsic.function.get_dispatch_info();
+			assert_eq!(call_info.call_weight.proof_size(), 0);
+
+			let info = extrinsic.get_dispatch_info();
+			let _post_info = extrinsic.apply::<Test>(&info, LEN).unwrap().unwrap();
+
+			assert_eq!(get_storage_weight().proof_size(), test.assert_final_block_proof_size);
+		})
+	}
+}
+
+#[test]
+fn test_pov_missing_from_node_reclaim() {
+	// Test scenario: after dispatch the pov size from node side is less than block weight.
+	// Ensure `pov_size_missing_from_node` is calculated correctly, and `ExtrinsicWeightReclaimed`
+	// is updated correctly.
+
+	// Proof size:
+	let bench_pre_dispatch_call = 220;
+	let bench_post_dispatch_actual = 90;
+	let len = 20; // Only one extrinsic in the scenario. So all extrinsics length.
+	let block_pre_dispatch = 100;
+	let missing_from_node = 50;
+	let node_diff = 70;
+
+	let node_pre_dispatch = block_pre_dispatch + missing_from_node;
+	let node_post_dispatch = node_pre_dispatch + node_diff;
+
+	// Initialize the test.
+	let mut test_ext =
+		setup_test_externalities(&[node_pre_dispatch as usize, node_post_dispatch as usize]);
+
+	test_ext.execute_with(|| {
+		set_current_storage_weight(block_pre_dispatch);
+		let info = DispatchInfo {
+			call_weight: Weight::from_parts(0, bench_pre_dispatch_call),
+			extension_weight: Weight::from_parts(0, 0),
+			..Default::default()
+		};
+		let post_info = PostDispatchInfo {
+			actual_weight: Some(Weight::from_parts(0, bench_post_dispatch_actual)),
+			..Default::default()
+		};
+
+		// Execute the transaction.
+		let tx_ext = StorageWeightReclaim::<Test, frame_system::CheckWeight<Test>>::new(
+			frame_system::CheckWeight::new(),
+		);
+		tx_ext
+			.test_run(ALICE_ORIGIN.clone().into(), CALL, &info, len as usize, 0, |_| Ok(post_info))
+			.expect("valid")
+			.expect("success");
+
+		// Assert the results.
+		assert_eq!(
+			frame_system::BlockWeight::<Test>::get().get(DispatchClass::Normal).proof_size(),
+			node_post_dispatch + len,
+		);
+		assert_eq!(
+			frame_system::ExtrinsicWeightReclaimed::<Test>::get().proof_size(),
+			bench_pre_dispatch_call - node_diff - missing_from_node,
+		);
+	});
+}
+
+#[test]
+fn test_ref_time_weight_reclaim() {
+	// Test scenario: after dispatch the time weight is refunded correctly.
+
+	// Time weight:
+	let bench_pre_dispatch_call = 145;
+	let bench_post_dispatch_actual = 104;
+	let bench_mock_ext_weight = 63;
+	let bench_mock_ext_refund = 22;
+	let len = 20; // Only one extrinsic in the scenario. So all extrinsics length.
+	let block_pre_dispatch = 121;
+	let node_pre_dispatch = 0;
+	let node_post_dispatch = 0;
+
+	// Initialize the test.
+	CHECK_WEIGHT_WEIGHT.with_borrow_mut(|v| *v = Weight::from_parts(0, 0));
+	STORAGE_WEIGHT_RECLAIM_WEIGHT.with_borrow_mut(|v| *v = Weight::from_parts(0, 0));
+	MOCK_EXT_WEIGHT.with_borrow_mut(|v| *v = Weight::from_parts(bench_mock_ext_weight, 0));
+	MOCK_EXT_REFUND.with_borrow_mut(|v| *v = Weight::from_parts(bench_mock_ext_refund, 0));
+
+	let base_extrinsic = <<Test as frame_system::Config>::BlockWeights as Get<
+		frame_system::limits::BlockWeights,
+	>>::get()
+	.per_class
+	.get(DispatchClass::Normal)
+	.base_extrinsic;
+
+	let mut test_ext =
+		setup_test_externalities(&[node_pre_dispatch as usize, node_post_dispatch as usize]);
+
+	test_ext.execute_with(|| {
+		frame_system::BlockWeight::<Test>::mutate(|current_weight| {
+			current_weight.set(Weight::from_parts(block_pre_dispatch, 0), DispatchClass::Normal);
+		});
+		let info = DispatchInfo {
+			call_weight: Weight::from_parts(bench_pre_dispatch_call, 0),
+			extension_weight: Weight::from_parts(bench_mock_ext_weight, 0),
+			..Default::default()
+		};
+		let post_info = PostDispatchInfo {
+			actual_weight: Some(Weight::from_parts(bench_post_dispatch_actual, 0)),
+			..Default::default()
+		};
+
+		type InnerTxExt = (frame_system::CheckWeight<Test>, MockExtensionWithRefund);
+		// Execute the transaction.
+		let tx_ext = StorageWeightReclaim::<Test, InnerTxExt>::new((
+			frame_system::CheckWeight::new(),
+			MockExtensionWithRefund,
+		));
+		tx_ext
+			.test_run(ALICE_ORIGIN.clone().into(), CALL, &info, len as usize, 0, |_| Ok(post_info))
+			.expect("valid transaction extension pipeline")
+			.expect("success");
+
+		// Assert the results.
+		assert_eq!(
+			frame_system::BlockWeight::<Test>::get().get(DispatchClass::Normal).ref_time(),
+			block_pre_dispatch +
+				base_extrinsic.ref_time() +
+				bench_post_dispatch_actual +
+				bench_mock_ext_weight -
+				bench_mock_ext_refund,
+		);
+		assert_eq!(
+			frame_system::ExtrinsicWeightReclaimed::<Test>::get().ref_time(),
+			bench_pre_dispatch_call - bench_post_dispatch_actual + bench_mock_ext_refund,
+		);
+	});
+}
+
+#[test]
+fn test_metadata() {
+	assert_eq!(
+		StorageWeightReclaim::<Test, frame_system::CheckWeight<Test>>::metadata()
+			.iter()
+			.map(|m| m.identifier)
+			.collect::<Vec<_>>(),
+		vec!["CheckWeight", "StorageWeightReclaim"]
+	);
+}
diff --git a/cumulus/pallets/weight-reclaim/src/weights.rs b/cumulus/pallets/weight-reclaim/src/weights.rs
new file mode 100644
index 0000000000000000000000000000000000000000..e651c8a783185b048f59e284ef957539a0221d2f
--- /dev/null
+++ b/cumulus/pallets/weight-reclaim/src/weights.rs
@@ -0,0 +1,74 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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.
+
+// Cumulus 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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Autogenerated weights for `cumulus_pallet_weight_reclaim`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-08-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! HOSTNAME: `fedora`, CPU: `13th Gen Intel(R) Core(TM) i7-1360P`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024`
+
+// Executed Command:
+// ./target/release/parachain-template-node
+// benchmark
+// pallet
+// --pallet
+// cumulus-pallet-weight-reclaim
+// --chain
+// dev
+// --output
+// cumulus/pallets/weight-reclaim/src/weights.rs
+// --template
+// substrate/.maintain/frame-weight-template.hbs
+// --extrinsic
+// *
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use core::marker::PhantomData;
+
+/// Weight functions needed for `cumulus_pallet_weight_reclaim`.
+pub trait WeightInfo {
+	fn storage_weight_reclaim() -> Weight;
+}
+
+/// Weights for `cumulus_pallet_weight_reclaim` using the Substrate node and recommended hardware.
+pub struct SubstrateWeight<T>(PhantomData<T>);
+impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
+	fn storage_weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 2_247_000 picoseconds.
+		Weight::from_parts(2_466_000, 0)
+	}
+}
+
+// For backwards compatibility and tests.
+impl WeightInfo for () {
+	fn storage_weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 2_247_000 picoseconds.
+		Weight::from_parts(2_466_000, 0)
+	}
+}
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml
index c954ddb7b8c7a9ad523ec5700f7b6d36f7d261b7..abe59a8439a8af9f064dd179f07e629a9e7a5038 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml
@@ -80,11 +80,11 @@ assets-common = { workspace = true }
 cumulus-pallet-aura-ext = { workspace = true }
 cumulus-pallet-parachain-system = { workspace = true }
 cumulus-pallet-session-benchmarking = { workspace = true }
+cumulus-pallet-weight-reclaim = { workspace = true }
 cumulus-pallet-xcm = { workspace = true }
 cumulus-pallet-xcmp-queue = { features = ["bridging"], workspace = true }
 cumulus-primitives-aura = { workspace = true }
 cumulus-primitives-core = { workspace = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true }
 cumulus-primitives-utility = { workspace = true }
 pallet-collator-selection = { workspace = true }
 parachain-info = { workspace = true }
@@ -112,6 +112,7 @@ runtime-benchmarks = [
 	"assets-common/runtime-benchmarks",
 	"cumulus-pallet-parachain-system/runtime-benchmarks",
 	"cumulus-pallet-session-benchmarking/runtime-benchmarks",
+	"cumulus-pallet-weight-reclaim/runtime-benchmarks",
 	"cumulus-pallet-xcmp-queue/runtime-benchmarks",
 	"cumulus-primitives-core/runtime-benchmarks",
 	"cumulus-primitives-utility/runtime-benchmarks",
@@ -151,6 +152,7 @@ runtime-benchmarks = [
 try-runtime = [
 	"cumulus-pallet-aura-ext/try-runtime",
 	"cumulus-pallet-parachain-system/try-runtime",
+	"cumulus-pallet-weight-reclaim/try-runtime",
 	"cumulus-pallet-xcm/try-runtime",
 	"cumulus-pallet-xcmp-queue/try-runtime",
 	"frame-executive/try-runtime",
@@ -192,11 +194,11 @@ std = [
 	"cumulus-pallet-aura-ext/std",
 	"cumulus-pallet-parachain-system/std",
 	"cumulus-pallet-session-benchmarking/std",
+	"cumulus-pallet-weight-reclaim/std",
 	"cumulus-pallet-xcm/std",
 	"cumulus-pallet-xcmp-queue/std",
 	"cumulus-primitives-aura/std",
 	"cumulus-primitives-core/std",
-	"cumulus-primitives-storage-weight-reclaim/std",
 	"cumulus-primitives-utility/std",
 	"frame-benchmarking?/std",
 	"frame-executive/std",
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs
index 8f4ae4670acda3950251ddda7abee932df48de4c..1db152e39fd9818b60e0b19ee27b7646bae1d791 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs
@@ -182,6 +182,10 @@ impl frame_system::Config for Runtime {
 	type MaxConsumers = frame_support::traits::ConstU32<16>;
 }
 
+impl cumulus_pallet_weight_reclaim::Config for Runtime {
+	type WeightInfo = weights::cumulus_pallet_weight_reclaim::WeightInfo<Runtime>;
+}
+
 impl pallet_timestamp::Config for Runtime {
 	/// A timestamp: milliseconds since the unix epoch.
 	type Moment = u64;
@@ -958,6 +962,7 @@ construct_runtime!(
 		ParachainSystem: cumulus_pallet_parachain_system = 1,
 		Timestamp: pallet_timestamp = 3,
 		ParachainInfo: parachain_info = 4,
+		WeightReclaim: cumulus_pallet_weight_reclaim = 5,
 
 		// Monetary stuff.
 		Balances: pallet_balances = 10,
@@ -1012,18 +1017,20 @@ pub type SignedBlock = generic::SignedBlock<Block>;
 /// BlockId type as expected by this runtime.
 pub type BlockId = generic::BlockId<Block>;
 /// The extension to the basic transaction logic.
-pub type TxExtension = (
-	frame_system::CheckNonZeroSender<Runtime>,
-	frame_system::CheckSpecVersion<Runtime>,
-	frame_system::CheckTxVersion<Runtime>,
-	frame_system::CheckGenesis<Runtime>,
-	frame_system::CheckEra<Runtime>,
-	frame_system::CheckNonce<Runtime>,
-	frame_system::CheckWeight<Runtime>,
-	pallet_asset_conversion_tx_payment::ChargeAssetTxPayment<Runtime>,
-	cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim<Runtime>,
-	frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
-);
+pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+	Runtime,
+	(
+		frame_system::CheckNonZeroSender<Runtime>,
+		frame_system::CheckSpecVersion<Runtime>,
+		frame_system::CheckTxVersion<Runtime>,
+		frame_system::CheckGenesis<Runtime>,
+		frame_system::CheckEra<Runtime>,
+		frame_system::CheckNonce<Runtime>,
+		frame_system::CheckWeight<Runtime>,
+		pallet_asset_conversion_tx_payment::ChargeAssetTxPayment<Runtime>,
+		frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+	),
+>;
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
 	generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
@@ -1207,6 +1214,7 @@ mod benches {
 		// NOTE: Make sure you point to the individual modules below.
 		[pallet_xcm_benchmarks::fungible, XcmBalances]
 		[pallet_xcm_benchmarks::generic, XcmGeneric]
+		[cumulus_pallet_weight_reclaim, WeightReclaim]
 	);
 }
 
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/cumulus_pallet_weight_reclaim.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/cumulus_pallet_weight_reclaim.rs
new file mode 100644
index 0000000000000000000000000000000000000000..c8f9bb7cd56c3c2d56224aa8043e3817901c18c4
--- /dev/null
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/cumulus_pallet_weight_reclaim.rs
@@ -0,0 +1,67 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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.
+
+// Cumulus 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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Autogenerated weights for `cumulus_pallet_weight_reclaim`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024
+
+// Executed Command:
+// target/production/polkadot-parachain
+// benchmark
+// pallet
+// --steps=50
+// --repeat=20
+// --extrinsic=*
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
+// --pallet=cumulus_pallet_weight_reclaim
+// --chain=asset-hub-rococo-dev
+// --header=./cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::Weight};
+use core::marker::PhantomData;
+
+/// Weight functions for `cumulus_pallet_weight_reclaim`.
+pub struct WeightInfo<T>(PhantomData<T>);
+impl<T: frame_system::Config> cumulus_pallet_weight_reclaim::WeightInfo for WeightInfo<T> {
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:0)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	fn storage_weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1533`
+		// Minimum execution time: 7_301_000 picoseconds.
+		Weight::from_parts(7_536_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
+}
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/frame_system_extensions.rs
index 182410f20fffe19f74f887fa7858c7072d855172..a5c9fea3cdf53f3daacd3fb1a223056729d01fcf 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/frame_system_extensions.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/frame_system_extensions.rs
@@ -16,28 +16,29 @@
 
 //! Autogenerated weights for `frame_system_extensions`
 //!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-10-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor`
-//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024
+//! HOSTNAME: `697235d969a1`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024
 
 // Executed Command:
-// ./target/release/polkadot-parachain
+// frame-omni-bencher
+// v1
 // benchmark
 // pallet
-// --wasm-execution=compiled
+// --extrinsic=*
+// --runtime=target/release/wbuild/asset-hub-rococo-runtime/asset_hub_rococo_runtime.wasm
 // --pallet=frame_system_extensions
+// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights
+// --wasm-execution=compiled
+// --steps=50
+// --repeat=20
+// --heap-pages=4096
 // --no-storage-info
-// --no-median-slopes
 // --no-min-squares
-// --extrinsic=*
-// --steps=2
-// --repeat=2
-// --json
-// --header=./cumulus/file_header.txt
-// --output=./cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/
-// --chain=asset-hub-rococo-dev
+// --no-median-slopes
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
@@ -56,8 +57,8 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `54`
 		//  Estimated: `3509`
-		// Minimum execution time: 3_637_000 picoseconds.
-		Weight::from_parts(6_382_000, 0)
+		// Minimum execution time: 8_313_000 picoseconds.
+		Weight::from_parts(8_528_000, 0)
 			.saturating_add(Weight::from_parts(0, 3509))
 			.saturating_add(T::DbWeight::get().reads(1))
 	}
@@ -67,8 +68,8 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `92`
 		//  Estimated: `3509`
-		// Minimum execution time: 5_841_000 picoseconds.
-		Weight::from_parts(8_776_000, 0)
+		// Minimum execution time: 12_527_000 picoseconds.
+		Weight::from_parts(13_006_000, 0)
 			.saturating_add(Weight::from_parts(0, 3509))
 			.saturating_add(T::DbWeight::get().reads(1))
 	}
@@ -78,8 +79,8 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `92`
 		//  Estimated: `3509`
-		// Minimum execution time: 5_841_000 picoseconds.
-		Weight::from_parts(8_776_000, 0)
+		// Minimum execution time: 12_380_000 picoseconds.
+		Weight::from_parts(12_922_000, 0)
 			.saturating_add(Weight::from_parts(0, 3509))
 			.saturating_add(T::DbWeight::get().reads(1))
 	}
@@ -87,44 +88,64 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 561_000 picoseconds.
-		Weight::from_parts(2_705_000, 0)
+		// Minimum execution time: 782_000 picoseconds.
+		Weight::from_parts(855_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
+	/// Storage: `System::Account` (r:1 w:1)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn check_nonce() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `0`
-		//  Estimated: `0`
-		// Minimum execution time: 3_316_000 picoseconds.
-		Weight::from_parts(5_771_000, 0)
-			.saturating_add(Weight::from_parts(0, 0))
+		//  Measured:  `101`
+		//  Estimated: `3593`
+		// Minimum execution time: 11_743_000 picoseconds.
+		Weight::from_parts(12_067_000, 0)
+			.saturating_add(Weight::from_parts(0, 3593))
+			.saturating_add(T::DbWeight::get().reads(1))
+			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	fn check_spec_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 511_000 picoseconds.
-		Weight::from_parts(2_575_000, 0)
+		// Minimum execution time: 644_000 picoseconds.
+		Weight::from_parts(697_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	fn check_tx_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 501_000 picoseconds.
-		Weight::from_parts(2_595_000, 0)
+		// Minimum execution time: 605_000 picoseconds.
+		Weight::from_parts(700_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
 	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
 	/// Storage: `System::BlockWeight` (r:1 w:1)
 	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
 	fn check_weight() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `24`
 		//  Estimated: `1533`
-		// Minimum execution time: 3_687_000 picoseconds.
-		Weight::from_parts(6_192_000, 0)
+		// Minimum execution time: 9_796_000 picoseconds.
+		Weight::from_parts(10_365_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(3))
+	}
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `1533`
+		// Minimum execution time: 4_855_000 picoseconds.
+		Weight::from_parts(5_050_000, 0)
 			.saturating_add(Weight::from_parts(0, 1533))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs
index 33f111009ed0fb3e4be1e5277ed3d3e960a0dd09..ae78a56d8b3c1fef27e54e37b940098396426883 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs
@@ -16,6 +16,7 @@
 
 pub mod block_weights;
 pub mod cumulus_pallet_parachain_system;
+pub mod cumulus_pallet_weight_reclaim;
 pub mod cumulus_pallet_xcmp_queue;
 pub mod extrinsic_weights;
 pub mod frame_system;
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml
index 7c31745d8f6e1c10c7d9a0ad3c3be022ed4884db..cb10ae9a480034b3067e436a4760692357789645 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml
@@ -81,11 +81,11 @@ assets-common = { workspace = true }
 cumulus-pallet-aura-ext = { workspace = true }
 cumulus-pallet-parachain-system = { workspace = true }
 cumulus-pallet-session-benchmarking = { workspace = true }
+cumulus-pallet-weight-reclaim = { workspace = true }
 cumulus-pallet-xcm = { workspace = true }
 cumulus-pallet-xcmp-queue = { features = ["bridging"], workspace = true }
 cumulus-primitives-aura = { workspace = true }
 cumulus-primitives-core = { workspace = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true }
 cumulus-primitives-utility = { workspace = true }
 pallet-collator-selection = { workspace = true }
 pallet-message-queue = { workspace = true }
@@ -114,6 +114,7 @@ runtime-benchmarks = [
 	"assets-common/runtime-benchmarks",
 	"cumulus-pallet-parachain-system/runtime-benchmarks",
 	"cumulus-pallet-session-benchmarking/runtime-benchmarks",
+	"cumulus-pallet-weight-reclaim/runtime-benchmarks",
 	"cumulus-pallet-xcmp-queue/runtime-benchmarks",
 	"cumulus-primitives-core/runtime-benchmarks",
 	"cumulus-primitives-utility/runtime-benchmarks",
@@ -155,6 +156,7 @@ runtime-benchmarks = [
 try-runtime = [
 	"cumulus-pallet-aura-ext/try-runtime",
 	"cumulus-pallet-parachain-system/try-runtime",
+	"cumulus-pallet-weight-reclaim/try-runtime",
 	"cumulus-pallet-xcm/try-runtime",
 	"cumulus-pallet-xcmp-queue/try-runtime",
 	"frame-executive/try-runtime",
@@ -198,11 +200,11 @@ std = [
 	"cumulus-pallet-aura-ext/std",
 	"cumulus-pallet-parachain-system/std",
 	"cumulus-pallet-session-benchmarking/std",
+	"cumulus-pallet-weight-reclaim/std",
 	"cumulus-pallet-xcm/std",
 	"cumulus-pallet-xcmp-queue/std",
 	"cumulus-primitives-aura/std",
 	"cumulus-primitives-core/std",
-	"cumulus-primitives-storage-weight-reclaim/std",
 	"cumulus-primitives-utility/std",
 	"frame-benchmarking?/std",
 	"frame-executive/std",
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
index 26ef3219a1e968812b60b2511af181e255f1c3f0..5fb495e4e8cf7d928ef6b8a8cc1537b88508fc2e 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
@@ -183,6 +183,10 @@ impl frame_system::Config for Runtime {
 	type MaxConsumers = frame_support::traits::ConstU32<16>;
 }
 
+impl cumulus_pallet_weight_reclaim::Config for Runtime {
+	type WeightInfo = weights::cumulus_pallet_weight_reclaim::WeightInfo<Runtime>;
+}
+
 impl pallet_timestamp::Config for Runtime {
 	/// A timestamp: milliseconds since the unix epoch.
 	type Moment = u64;
@@ -1000,6 +1004,7 @@ construct_runtime!(
 		// RandomnessCollectiveFlip = 2 removed
 		Timestamp: pallet_timestamp = 3,
 		ParachainInfo: parachain_info = 4,
+		WeightReclaim: cumulus_pallet_weight_reclaim = 5,
 
 		// Monetary stuff.
 		Balances: pallet_balances = 10,
@@ -1057,18 +1062,20 @@ pub type SignedBlock = generic::SignedBlock<Block>;
 /// BlockId type as expected by this runtime.
 pub type BlockId = generic::BlockId<Block>;
 /// The extension to the basic transaction logic.
-pub type TxExtension = (
-	frame_system::CheckNonZeroSender<Runtime>,
-	frame_system::CheckSpecVersion<Runtime>,
-	frame_system::CheckTxVersion<Runtime>,
-	frame_system::CheckGenesis<Runtime>,
-	frame_system::CheckEra<Runtime>,
-	frame_system::CheckNonce<Runtime>,
-	frame_system::CheckWeight<Runtime>,
-	pallet_asset_conversion_tx_payment::ChargeAssetTxPayment<Runtime>,
-	cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim<Runtime>,
-	frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
-);
+pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+	Runtime,
+	(
+		frame_system::CheckNonZeroSender<Runtime>,
+		frame_system::CheckSpecVersion<Runtime>,
+		frame_system::CheckTxVersion<Runtime>,
+		frame_system::CheckGenesis<Runtime>,
+		frame_system::CheckEra<Runtime>,
+		frame_system::CheckNonce<Runtime>,
+		frame_system::CheckWeight<Runtime>,
+		pallet_asset_conversion_tx_payment::ChargeAssetTxPayment<Runtime>,
+		frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+	),
+>;
 
 /// Default extensions applied to Ethereum transactions.
 #[derive(Clone, PartialEq, Eq, Debug)]
@@ -1088,9 +1095,9 @@ impl EthExtra for EthExtraImpl {
 			frame_system::CheckNonce::<Runtime>::from(nonce),
 			frame_system::CheckWeight::<Runtime>::new(),
 			pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::<Runtime>::from(tip, None),
-			cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::<Runtime>::new(),
 			frame_metadata_hash_extension::CheckMetadataHash::<Runtime>::new(false),
 		)
+			.into()
 	}
 }
 
@@ -1337,6 +1344,7 @@ mod benches {
 		// NOTE: Make sure you point to the individual modules below.
 		[pallet_xcm_benchmarks::fungible, XcmBalances]
 		[pallet_xcm_benchmarks::generic, XcmGeneric]
+		[cumulus_pallet_weight_reclaim, WeightReclaim]
 	);
 }
 
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/cumulus_pallet_weight_reclaim.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/cumulus_pallet_weight_reclaim.rs
new file mode 100644
index 0000000000000000000000000000000000000000..1573a278e24674344714b1d466e47e723fbaca7b
--- /dev/null
+++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/cumulus_pallet_weight_reclaim.rs
@@ -0,0 +1,67 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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.
+
+// Cumulus 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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Autogenerated weights for `cumulus_pallet_weight_reclaim`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024
+
+// Executed Command:
+// target/production/polkadot-parachain
+// benchmark
+// pallet
+// --steps=50
+// --repeat=20
+// --extrinsic=*
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
+// --pallet=cumulus_pallet_weight_reclaim
+// --chain=asset-hub-westend-dev
+// --header=./cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::Weight};
+use core::marker::PhantomData;
+
+/// Weight functions for `cumulus_pallet_weight_reclaim`.
+pub struct WeightInfo<T>(PhantomData<T>);
+impl<T: frame_system::Config> cumulus_pallet_weight_reclaim::WeightInfo for WeightInfo<T> {
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:0)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	fn storage_weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1533`
+		// Minimum execution time: 7_470_000 picoseconds.
+		Weight::from_parts(7_695_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
+}
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/frame_system_extensions.rs
index e8dd9763c28261c19928d05719ccd3a4f5492416..a1bb92cf7008b99030421ca5fc81e1c5fda6faa8 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/frame_system_extensions.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/frame_system_extensions.rs
@@ -16,28 +16,29 @@
 
 //! Autogenerated weights for `frame_system_extensions`
 //!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-10-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor`
-//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024
+//! HOSTNAME: `697235d969a1`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024
 
 // Executed Command:
-// ./target/release/polkadot-parachain
+// frame-omni-bencher
+// v1
 // benchmark
 // pallet
-// --wasm-execution=compiled
+// --extrinsic=*
+// --runtime=target/release/wbuild/asset-hub-westend-runtime/asset_hub_westend_runtime.wasm
 // --pallet=frame_system_extensions
+// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights
+// --wasm-execution=compiled
+// --steps=50
+// --repeat=20
+// --heap-pages=4096
 // --no-storage-info
-// --no-median-slopes
 // --no-min-squares
-// --extrinsic=*
-// --steps=2
-// --repeat=2
-// --json
-// --header=./cumulus/file_header.txt
-// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/
-// --chain=asset-hub-westend-dev
+// --no-median-slopes
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
@@ -56,8 +57,8 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `54`
 		//  Estimated: `3509`
-		// Minimum execution time: 3_206_000 picoseconds.
-		Weight::from_parts(6_212_000, 0)
+		// Minimum execution time: 6_329_000 picoseconds.
+		Weight::from_parts(6_665_000, 0)
 			.saturating_add(Weight::from_parts(0, 3509))
 			.saturating_add(T::DbWeight::get().reads(1))
 	}
@@ -67,8 +68,8 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `92`
 		//  Estimated: `3509`
-		// Minimum execution time: 5_851_000 picoseconds.
-		Weight::from_parts(8_847_000, 0)
+		// Minimum execution time: 12_110_000 picoseconds.
+		Weight::from_parts(12_883_000, 0)
 			.saturating_add(Weight::from_parts(0, 3509))
 			.saturating_add(T::DbWeight::get().reads(1))
 	}
@@ -78,8 +79,8 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `92`
 		//  Estimated: `3509`
-		// Minimum execution time: 5_851_000 picoseconds.
-		Weight::from_parts(8_847_000, 0)
+		// Minimum execution time: 12_241_000 picoseconds.
+		Weight::from_parts(12_780_000, 0)
 			.saturating_add(Weight::from_parts(0, 3509))
 			.saturating_add(T::DbWeight::get().reads(1))
 	}
@@ -87,44 +88,64 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 631_000 picoseconds.
-		Weight::from_parts(3_086_000, 0)
+		// Minimum execution time: 825_000 picoseconds.
+		Weight::from_parts(890_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
+	/// Storage: `System::Account` (r:1 w:1)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn check_nonce() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `0`
-		//  Estimated: `0`
-		// Minimum execution time: 3_446_000 picoseconds.
-		Weight::from_parts(5_911_000, 0)
-			.saturating_add(Weight::from_parts(0, 0))
+		//  Measured:  `101`
+		//  Estimated: `3593`
+		// Minimum execution time: 10_159_000 picoseconds.
+		Weight::from_parts(10_461_000, 0)
+			.saturating_add(Weight::from_parts(0, 3593))
+			.saturating_add(T::DbWeight::get().reads(1))
+			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	fn check_spec_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 481_000 picoseconds.
-		Weight::from_parts(2_916_000, 0)
+		// Minimum execution time: 578_000 picoseconds.
+		Weight::from_parts(660_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	fn check_tx_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 501_000 picoseconds.
-		Weight::from_parts(2_595_000, 0)
+		// Minimum execution time: 618_000 picoseconds.
+		Weight::from_parts(682_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
 	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
 	/// Storage: `System::BlockWeight` (r:1 w:1)
 	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
 	fn check_weight() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `24`
 		//  Estimated: `1533`
-		// Minimum execution time: 3_927_000 picoseconds.
-		Weight::from_parts(6_613_000, 0)
+		// Minimum execution time: 9_964_000 picoseconds.
+		Weight::from_parts(10_419_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(3))
+	}
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `1533`
+		// Minimum execution time: 4_890_000 picoseconds.
+		Weight::from_parts(5_163_000, 0)
 			.saturating_add(Weight::from_parts(0, 1533))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs
index b0f986768f408fac1a31877f9f86839d4fffb921..442b58635f48ad5ae910cc3612d45cab512e4a51 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs
@@ -15,6 +15,7 @@
 
 pub mod block_weights;
 pub mod cumulus_pallet_parachain_system;
+pub mod cumulus_pallet_weight_reclaim;
 pub mod cumulus_pallet_xcmp_queue;
 pub mod extrinsic_weights;
 pub mod frame_system;
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 3fabea3b02f4f6f7904192055a82202b0416bc84..3dba65ae99f183581710736581d45017b4a79c59 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml
@@ -72,11 +72,11 @@ xcm-runtime-apis = { workspace = true }
 cumulus-pallet-aura-ext = { workspace = true }
 cumulus-pallet-parachain-system = { workspace = true }
 cumulus-pallet-session-benchmarking = { workspace = true }
+cumulus-pallet-weight-reclaim = { workspace = true }
 cumulus-pallet-xcm = { workspace = true }
 cumulus-pallet-xcmp-queue = { features = ["bridging"], workspace = true }
 cumulus-primitives-aura = { workspace = true }
 cumulus-primitives-core = { workspace = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true }
 cumulus-primitives-utility = { workspace = true }
 pallet-collator-selection = { workspace = true }
 parachain-info = { workspace = true }
@@ -151,11 +151,11 @@ std = [
 	"cumulus-pallet-aura-ext/std",
 	"cumulus-pallet-parachain-system/std",
 	"cumulus-pallet-session-benchmarking/std",
+	"cumulus-pallet-weight-reclaim/std",
 	"cumulus-pallet-xcm/std",
 	"cumulus-pallet-xcmp-queue/std",
 	"cumulus-primitives-aura/std",
 	"cumulus-primitives-core/std",
-	"cumulus-primitives-storage-weight-reclaim/std",
 	"cumulus-primitives-utility/std",
 	"frame-benchmarking/std",
 	"frame-executive/std",
@@ -230,6 +230,7 @@ runtime-benchmarks = [
 	"bridge-runtime-common/runtime-benchmarks",
 	"cumulus-pallet-parachain-system/runtime-benchmarks",
 	"cumulus-pallet-session-benchmarking/runtime-benchmarks",
+	"cumulus-pallet-weight-reclaim/runtime-benchmarks",
 	"cumulus-pallet-xcmp-queue/runtime-benchmarks",
 	"cumulus-primitives-core/runtime-benchmarks",
 	"cumulus-primitives-utility/runtime-benchmarks",
@@ -272,6 +273,7 @@ runtime-benchmarks = [
 try-runtime = [
 	"cumulus-pallet-aura-ext/try-runtime",
 	"cumulus-pallet-parachain-system/try-runtime",
+	"cumulus-pallet-weight-reclaim/try-runtime",
 	"cumulus-pallet-xcm/try-runtime",
 	"cumulus-pallet-xcmp-queue/try-runtime",
 	"frame-executive/try-runtime",
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs
index 88146cecb9ef263384956d6a9a618c7e6cd21db8..35af034310d9202337f38984e8c92c8480bf8a9a 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs
@@ -124,20 +124,22 @@ pub type SignedBlock = generic::SignedBlock<Block>;
 pub type BlockId = generic::BlockId<Block>;
 
 /// The TransactionExtension to the basic transaction logic.
-pub type TxExtension = (
-	frame_system::CheckNonZeroSender<Runtime>,
-	frame_system::CheckSpecVersion<Runtime>,
-	frame_system::CheckTxVersion<Runtime>,
-	frame_system::CheckGenesis<Runtime>,
-	frame_system::CheckEra<Runtime>,
-	frame_system::CheckNonce<Runtime>,
-	frame_system::CheckWeight<Runtime>,
-	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
-	BridgeRejectObsoleteHeadersAndMessages,
-	(bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages,),
-	frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
-	cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim<Runtime>,
-);
+pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+	Runtime,
+	(
+		frame_system::CheckNonZeroSender<Runtime>,
+		frame_system::CheckSpecVersion<Runtime>,
+		frame_system::CheckTxVersion<Runtime>,
+		frame_system::CheckGenesis<Runtime>,
+		frame_system::CheckEra<Runtime>,
+		frame_system::CheckNonce<Runtime>,
+		frame_system::CheckWeight<Runtime>,
+		pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+		BridgeRejectObsoleteHeadersAndMessages,
+		(bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages,),
+		frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+	),
+>;
 
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
@@ -313,6 +315,10 @@ impl frame_system::Config for Runtime {
 	type MaxConsumers = frame_support::traits::ConstU32<16>;
 }
 
+impl cumulus_pallet_weight_reclaim::Config for Runtime {
+	type WeightInfo = weights::cumulus_pallet_weight_reclaim::WeightInfo<Runtime>;
+}
+
 impl pallet_timestamp::Config for Runtime {
 	/// A timestamp: milliseconds since the unix epoch.
 	type Moment = u64;
@@ -555,6 +561,7 @@ construct_runtime!(
 		ParachainSystem: cumulus_pallet_parachain_system = 1,
 		Timestamp: pallet_timestamp = 2,
 		ParachainInfo: parachain_info = 3,
+		WeightReclaim: cumulus_pallet_weight_reclaim = 4,
 
 		// Monetary stuff.
 		Balances: pallet_balances = 10,
@@ -667,6 +674,7 @@ mod benches {
 		[pallet_collator_selection, CollatorSelection]
 		[cumulus_pallet_parachain_system, ParachainSystem]
 		[cumulus_pallet_xcmp_queue, XcmpQueue]
+		[cumulus_pallet_weight_reclaim, WeightReclaim]
 		// XCM
 		[pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>]
 		// NOTE: Make sure you point to the individual modules below.
@@ -1547,41 +1555,44 @@ mod tests {
 		use bp_polkadot_core::SuffixedCommonTransactionExtensionExt;
 
 		sp_io::TestExternalities::default().execute_with(|| {
-            frame_system::BlockHash::<Runtime>::insert(BlockNumber::zero(), Hash::default());
-            let payload: TxExtension = (
-                frame_system::CheckNonZeroSender::new(),
-                frame_system::CheckSpecVersion::new(),
-                frame_system::CheckTxVersion::new(),
-                frame_system::CheckGenesis::new(),
-                frame_system::CheckEra::from(Era::Immortal),
-                frame_system::CheckNonce::from(10),
-                frame_system::CheckWeight::new(),
-                pallet_transaction_payment::ChargeTransactionPayment::from(10),
-                BridgeRejectObsoleteHeadersAndMessages,
-                (
-                    bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages::default(),
-                ),
-                frame_metadata_hash_extension::CheckMetadataHash::new(false),
-				cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::new(),
-            );
-
-            // for BridgeHubRococo
-            {
-                let bhr_indirect_payload = bp_bridge_hub_rococo::TransactionExtension::from_params(
-                    VERSION.spec_version,
-                    VERSION.transaction_version,
-                    bp_runtime::TransactionEra::Immortal,
-                    System::block_hash(BlockNumber::zero()),
-                    10,
-                    10,
-                    (((), ()), ((), ())),
-                );
-                assert_eq!(payload.encode().split_last().unwrap().1, bhr_indirect_payload.encode());
-                assert_eq!(
-                    TxExtension::implicit(&payload).unwrap().encode().split_last().unwrap().1,
-                    sp_runtime::traits::TransactionExtension::<RuntimeCall>::implicit(&bhr_indirect_payload).unwrap().encode()
-                )
-            }
-        });
+			frame_system::BlockHash::<Runtime>::insert(BlockNumber::zero(), Hash::default());
+			let payload: TxExtension = (
+				frame_system::CheckNonZeroSender::new(),
+				frame_system::CheckSpecVersion::new(),
+				frame_system::CheckTxVersion::new(),
+				frame_system::CheckGenesis::new(),
+				frame_system::CheckEra::from(Era::Immortal),
+				frame_system::CheckNonce::from(10),
+				frame_system::CheckWeight::new(),
+				pallet_transaction_payment::ChargeTransactionPayment::from(10),
+				BridgeRejectObsoleteHeadersAndMessages,
+				(
+					bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages::default(),
+				),
+				frame_metadata_hash_extension::CheckMetadataHash::new(false),
+			).into();
+
+			// for BridgeHubRococo
+			{
+				let bhr_indirect_payload = bp_bridge_hub_rococo::TransactionExtension::from_params(
+					VERSION.spec_version,
+					VERSION.transaction_version,
+					bp_runtime::TransactionEra::Immortal,
+					System::block_hash(BlockNumber::zero()),
+					10,
+					10,
+					(((), ()), ((), ())),
+				);
+				assert_eq!(payload.encode().split_last().unwrap().1, bhr_indirect_payload.encode());
+				assert_eq!(
+					TxExtension::implicit(&payload).unwrap().encode().split_last().unwrap().1,
+					sp_runtime::traits::TransactionExtension::<RuntimeCall>::implicit(
+						&bhr_indirect_payload
+					)
+					.unwrap()
+					.encode()
+				)
+			}
+		});
 	}
 }
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/cumulus_pallet_weight_reclaim.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/cumulus_pallet_weight_reclaim.rs
new file mode 100644
index 0000000000000000000000000000000000000000..ca1d8dcbe56782dba07ea4a2bae3a4978394a1f5
--- /dev/null
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/cumulus_pallet_weight_reclaim.rs
@@ -0,0 +1,67 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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.
+
+// Cumulus 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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Autogenerated weights for `cumulus_pallet_weight_reclaim`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024
+
+// Executed Command:
+// target/production/polkadot-parachain
+// benchmark
+// pallet
+// --steps=50
+// --repeat=20
+// --extrinsic=*
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
+// --pallet=cumulus_pallet_weight_reclaim
+// --chain=bridge-hub-rococo-dev
+// --header=./cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::Weight};
+use core::marker::PhantomData;
+
+/// Weight functions for `cumulus_pallet_weight_reclaim`.
+pub struct WeightInfo<T>(PhantomData<T>);
+impl<T: frame_system::Config> cumulus_pallet_weight_reclaim::WeightInfo for WeightInfo<T> {
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:0)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	fn storage_weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1533`
+		// Minimum execution time: 6_988_000 picoseconds.
+		Weight::from_parts(7_361_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
+}
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/frame_system_extensions.rs
index 64eef1b4f7405abe40327241fe538ed1373edeab..93fb6f3bbbe30706eb278000a66c7e48568cf9e5 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/frame_system_extensions.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/frame_system_extensions.rs
@@ -16,28 +16,26 @@
 
 //! Autogenerated weights for `frame_system_extensions`
 //!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024
 
 // Executed Command:
-// ./target/release/polkadot-parachain
+// target/production/polkadot-parachain
 // benchmark
 // pallet
+// --steps=50
+// --repeat=20
+// --extrinsic=*
 // --wasm-execution=compiled
+// --heap-pages=4096
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
 // --pallet=frame_system_extensions
-// --no-storage-info
-// --no-median-slopes
-// --no-min-squares
-// --extrinsic=*
-// --steps=2
-// --repeat=2
-// --json
+// --chain=bridge-hub-rococo-dev
 // --header=./cumulus/file_header.txt
 // --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/
-// --chain=bridge-hub-rococo-dev
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
@@ -50,81 +48,92 @@ use core::marker::PhantomData;
 /// Weight functions for `frame_system_extensions`.
 pub struct WeightInfo<T>(PhantomData<T>);
 impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<T> {
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_genesis() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `54`
-		//  Estimated: `3509`
-		// Minimum execution time: 3_136_000 picoseconds.
-		Weight::from_parts(5_842_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Estimated: `0`
+		// Minimum execution time: 4_211_000 picoseconds.
+		Weight::from_parts(4_470_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_mortality_mortal_transaction() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `92`
-		//  Estimated: `3509`
-		// Minimum execution time: 5_771_000 picoseconds.
-		Weight::from_parts(8_857_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Estimated: `0`
+		// Minimum execution time: 8_792_000 picoseconds.
+		Weight::from_parts(9_026_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_mortality_immortal_transaction() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `92`
-		//  Estimated: `3509`
-		// Minimum execution time: 5_771_000 picoseconds.
-		Weight::from_parts(8_857_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Estimated: `0`
+		// Minimum execution time: 8_700_000 picoseconds.
+		Weight::from_parts(9_142_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
 	fn check_non_zero_sender() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 732_000 picoseconds.
-		Weight::from_parts(2_875_000, 0)
+		// Minimum execution time: 487_000 picoseconds.
+		Weight::from_parts(534_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
+	/// Storage: `System::Account` (r:1 w:1)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn check_nonce() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `0`
-		//  Estimated: `0`
-		// Minimum execution time: 3_627_000 picoseconds.
-		Weight::from_parts(6_322_000, 0)
-			.saturating_add(Weight::from_parts(0, 0))
+		//  Measured:  `101`
+		//  Estimated: `3593`
+		// Minimum execution time: 6_719_000 picoseconds.
+		Weight::from_parts(6_846_000, 0)
+			.saturating_add(Weight::from_parts(0, 3593))
+			.saturating_add(T::DbWeight::get().reads(1))
+			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	fn check_spec_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 471_000 picoseconds.
-		Weight::from_parts(2_455_000, 0)
+		// Minimum execution time: 410_000 picoseconds.
+		Weight::from_parts(442_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	fn check_tx_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 491_000 picoseconds.
-		Weight::from_parts(2_916_000, 0)
+		// Minimum execution time: 390_000 picoseconds.
+		Weight::from_parts(425_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
 	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
 	/// Storage: `System::BlockWeight` (r:1 w:1)
 	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
 	fn check_weight() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `24`
 		//  Estimated: `1533`
-		// Minimum execution time: 3_798_000 picoseconds.
-		Weight::from_parts(6_272_000, 0)
+		// Minimum execution time: 5_965_000 picoseconds.
+		Weight::from_parts(6_291_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(3))
+	}
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `1533`
+		// Minimum execution time: 2_738_000 picoseconds.
+		Weight::from_parts(2_915_000, 0)
 			.saturating_add(Weight::from_parts(0, 1533))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs
index 74796e626a2ec24b9eec32e5a336819fdb6bc507..7a0accf2e7a4530c291e02fcdb742e834bd2e7c9 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs
@@ -24,6 +24,7 @@ use ::pallet_bridge_relayers::WeightInfo as _;
 
 pub mod block_weights;
 pub mod cumulus_pallet_parachain_system;
+pub mod cumulus_pallet_weight_reclaim;
 pub mod cumulus_pallet_xcmp_queue;
 pub mod extrinsic_weights;
 pub mod frame_system;
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs
index d5baa1c71dfdc7d687dbbaa573be2b05a0c59e9e..c40aae5a82a9035c787f391ebc712d356e56afb5 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs
@@ -184,8 +184,8 @@ fn construct_extrinsic(
 		BridgeRejectObsoleteHeadersAndMessages::default(),
 		(OnBridgeHubRococoRefundBridgeHubWestendMessages::default(),),
 		frame_metadata_hash_extension::CheckMetadataHash::<Runtime>::new(false),
-		cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::new(),
-	);
+	)
+		.into();
 	let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap();
 	let signature = payload.using_encoded(|e| sender.sign(e));
 	UncheckedExtrinsic::new_signed(call, account_id.into(), Signature::Sr25519(signature), tx_ext)
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs
index 8d74b221a609f21f879faf2b6f6577ac22ae9b9f..b0f4366e29cf057b7ed6bc6b4c8a97fc46249456 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs
@@ -63,7 +63,6 @@ fn construct_extrinsic(
 		BridgeRejectObsoleteHeadersAndMessages::default(),
 		(bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages::default(),),
 		frame_metadata_hash_extension::CheckMetadataHash::new(false),
-		cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::new(),
 	)
 		.into();
 	let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap();
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 644aa72d131162510a2fb34d4ad1ed195eafef5e..444023eac722e1b7087a789ec68856f0c9cd812c 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml
@@ -72,11 +72,11 @@ xcm-runtime-apis = { workspace = true }
 cumulus-pallet-aura-ext = { workspace = true }
 cumulus-pallet-parachain-system = { workspace = true }
 cumulus-pallet-session-benchmarking = { workspace = true }
+cumulus-pallet-weight-reclaim = { workspace = true }
 cumulus-pallet-xcm = { workspace = true }
 cumulus-pallet-xcmp-queue = { features = ["bridging"], workspace = true }
 cumulus-primitives-aura = { workspace = true }
 cumulus-primitives-core = { workspace = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true }
 cumulus-primitives-utility = { workspace = true }
 
 pallet-collator-selection = { workspace = true }
@@ -148,11 +148,11 @@ std = [
 	"cumulus-pallet-aura-ext/std",
 	"cumulus-pallet-parachain-system/std",
 	"cumulus-pallet-session-benchmarking/std",
+	"cumulus-pallet-weight-reclaim/std",
 	"cumulus-pallet-xcm/std",
 	"cumulus-pallet-xcmp-queue/std",
 	"cumulus-primitives-aura/std",
 	"cumulus-primitives-core/std",
-	"cumulus-primitives-storage-weight-reclaim/std",
 	"cumulus-primitives-utility/std",
 	"frame-benchmarking/std",
 	"frame-executive/std",
@@ -227,6 +227,7 @@ runtime-benchmarks = [
 	"bridge-runtime-common/runtime-benchmarks",
 	"cumulus-pallet-parachain-system/runtime-benchmarks",
 	"cumulus-pallet-session-benchmarking/runtime-benchmarks",
+	"cumulus-pallet-weight-reclaim/runtime-benchmarks",
 	"cumulus-pallet-xcmp-queue/runtime-benchmarks",
 	"cumulus-primitives-core/runtime-benchmarks",
 	"cumulus-primitives-utility/runtime-benchmarks",
@@ -269,6 +270,7 @@ runtime-benchmarks = [
 try-runtime = [
 	"cumulus-pallet-aura-ext/try-runtime",
 	"cumulus-pallet-parachain-system/try-runtime",
+	"cumulus-pallet-weight-reclaim/try-runtime",
 	"cumulus-pallet-xcm/try-runtime",
 	"cumulus-pallet-xcmp-queue/try-runtime",
 	"frame-executive/try-runtime",
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs
index 1ca709f0d8cb7451ce0d940346210a2b64169aec..2c2e01b4d21dc7160e73b09d3612da05a594af87 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs
@@ -120,20 +120,22 @@ pub type SignedBlock = generic::SignedBlock<Block>;
 pub type BlockId = generic::BlockId<Block>;
 
 /// The TransactionExtension to the basic transaction logic.
-pub type TxExtension = (
-	frame_system::CheckNonZeroSender<Runtime>,
-	frame_system::CheckSpecVersion<Runtime>,
-	frame_system::CheckTxVersion<Runtime>,
-	frame_system::CheckGenesis<Runtime>,
-	frame_system::CheckEra<Runtime>,
-	frame_system::CheckNonce<Runtime>,
-	frame_system::CheckWeight<Runtime>,
-	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
-	BridgeRejectObsoleteHeadersAndMessages,
-	(bridge_to_rococo_config::OnBridgeHubWestendRefundBridgeHubRococoMessages,),
-	frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
-	cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim<Runtime>,
-);
+pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+	Runtime,
+	(
+		frame_system::CheckNonZeroSender<Runtime>,
+		frame_system::CheckSpecVersion<Runtime>,
+		frame_system::CheckTxVersion<Runtime>,
+		frame_system::CheckGenesis<Runtime>,
+		frame_system::CheckEra<Runtime>,
+		frame_system::CheckNonce<Runtime>,
+		frame_system::CheckWeight<Runtime>,
+		pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+		BridgeRejectObsoleteHeadersAndMessages,
+		(bridge_to_rococo_config::OnBridgeHubWestendRefundBridgeHubRococoMessages,),
+		frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+	),
+>;
 
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
@@ -299,6 +301,10 @@ impl frame_system::Config for Runtime {
 	type MaxConsumers = frame_support::traits::ConstU32<16>;
 }
 
+impl cumulus_pallet_weight_reclaim::Config for Runtime {
+	type WeightInfo = weights::cumulus_pallet_weight_reclaim::WeightInfo<Runtime>;
+}
+
 impl pallet_timestamp::Config for Runtime {
 	/// A timestamp: milliseconds since the unix epoch.
 	type Moment = u64;
@@ -532,6 +538,7 @@ construct_runtime!(
 		ParachainSystem: cumulus_pallet_parachain_system = 1,
 		Timestamp: pallet_timestamp = 2,
 		ParachainInfo: parachain_info = 3,
+		WeightReclaim: cumulus_pallet_weight_reclaim = 4,
 
 		// Monetary stuff.
 		Balances: pallet_balances = 10,
@@ -622,6 +629,7 @@ mod benches {
 		[snowbridge_pallet_outbound_queue, EthereumOutboundQueue]
 		[snowbridge_pallet_system, EthereumSystem]
 		[snowbridge_pallet_ethereum_client, EthereumBeaconClient]
+		[cumulus_pallet_weight_reclaim, WeightReclaim]
 	);
 }
 
@@ -1369,40 +1377,43 @@ mod tests {
 		use bp_polkadot_core::SuffixedCommonTransactionExtensionExt;
 
 		sp_io::TestExternalities::default().execute_with(|| {
-            frame_system::BlockHash::<Runtime>::insert(BlockNumber::zero(), Hash::default());
-            let payload: TxExtension = (
-                frame_system::CheckNonZeroSender::new(),
-                frame_system::CheckSpecVersion::new(),
-                frame_system::CheckTxVersion::new(),
-                frame_system::CheckGenesis::new(),
-                frame_system::CheckEra::from(Era::Immortal),
-                frame_system::CheckNonce::from(10),
-                frame_system::CheckWeight::new(),
-                pallet_transaction_payment::ChargeTransactionPayment::from(10),
-                BridgeRejectObsoleteHeadersAndMessages,
-                (
-                    bridge_to_rococo_config::OnBridgeHubWestendRefundBridgeHubRococoMessages::default(),
-                ),
+			frame_system::BlockHash::<Runtime>::insert(BlockNumber::zero(), Hash::default());
+			let payload: TxExtension = (
+				frame_system::CheckNonZeroSender::new(),
+				frame_system::CheckSpecVersion::new(),
+				frame_system::CheckTxVersion::new(),
+				frame_system::CheckGenesis::new(),
+				frame_system::CheckEra::from(Era::Immortal),
+				frame_system::CheckNonce::from(10),
+				frame_system::CheckWeight::new(),
+				pallet_transaction_payment::ChargeTransactionPayment::from(10),
+				BridgeRejectObsoleteHeadersAndMessages,
+				(
+					bridge_to_rococo_config::OnBridgeHubWestendRefundBridgeHubRococoMessages::default(),
+				),
 				frame_metadata_hash_extension::CheckMetadataHash::new(false),
-                cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::new(),
-            );
-
-            {
-                let bh_indirect_payload = bp_bridge_hub_westend::TransactionExtension::from_params(
-                    VERSION.spec_version,
-                    VERSION.transaction_version,
-                    bp_runtime::TransactionEra::Immortal,
-                    System::block_hash(BlockNumber::zero()),
-                    10,
-                    10,
-                    (((), ()), ((), ())),
-                );
-                assert_eq!(payload.encode().split_last().unwrap().1, bh_indirect_payload.encode());
-                assert_eq!(
-                    TxExtension::implicit(&payload).unwrap().encode().split_last().unwrap().1,
-                    sp_runtime::traits::TransactionExtension::<RuntimeCall>::implicit(&bh_indirect_payload).unwrap().encode()
-                )
-            }
-        });
+			).into();
+
+			{
+				let bh_indirect_payload = bp_bridge_hub_westend::TransactionExtension::from_params(
+					VERSION.spec_version,
+					VERSION.transaction_version,
+					bp_runtime::TransactionEra::Immortal,
+					System::block_hash(BlockNumber::zero()),
+					10,
+					10,
+					(((), ()), ((), ())),
+				);
+				assert_eq!(payload.encode().split_last().unwrap().1, bh_indirect_payload.encode());
+				assert_eq!(
+					TxExtension::implicit(&payload).unwrap().encode().split_last().unwrap().1,
+					sp_runtime::traits::TransactionExtension::<RuntimeCall>::implicit(
+						&bh_indirect_payload
+					)
+					.unwrap()
+					.encode()
+				)
+			}
+		});
 	}
 }
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/cumulus_pallet_weight_reclaim.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/cumulus_pallet_weight_reclaim.rs
new file mode 100644
index 0000000000000000000000000000000000000000..955b273254562376b7cdcb0c4175648a4de935f2
--- /dev/null
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/cumulus_pallet_weight_reclaim.rs
@@ -0,0 +1,67 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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.
+
+// Cumulus 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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Autogenerated weights for `cumulus_pallet_weight_reclaim`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-dev")`, DB CACHE: 1024
+
+// Executed Command:
+// target/production/polkadot-parachain
+// benchmark
+// pallet
+// --steps=50
+// --repeat=20
+// --extrinsic=*
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
+// --pallet=cumulus_pallet_weight_reclaim
+// --chain=bridge-hub-westend-dev
+// --header=./cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::Weight};
+use core::marker::PhantomData;
+
+/// Weight functions for `cumulus_pallet_weight_reclaim`.
+pub struct WeightInfo<T>(PhantomData<T>);
+impl<T: frame_system::Config> cumulus_pallet_weight_reclaim::WeightInfo for WeightInfo<T> {
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:0)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	fn storage_weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1533`
+		// Minimum execution time: 6_810_000 picoseconds.
+		Weight::from_parts(7_250_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
+}
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/frame_system_extensions.rs
index 459b137d3b8419765362e4501db525db31135a46..21cadac25e161565c43e03efc9e0684db1c28bc4 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/frame_system_extensions.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/frame_system_extensions.rs
@@ -16,28 +16,26 @@
 
 //! Autogenerated weights for `frame_system_extensions`
 //!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-dev")`, DB CACHE: 1024
 
 // Executed Command:
-// ./target/release/polkadot-parachain
+// target/production/polkadot-parachain
 // benchmark
 // pallet
+// --steps=50
+// --repeat=20
+// --extrinsic=*
 // --wasm-execution=compiled
+// --heap-pages=4096
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
 // --pallet=frame_system_extensions
-// --no-storage-info
-// --no-median-slopes
-// --no-min-squares
-// --extrinsic=*
-// --steps=2
-// --repeat=2
-// --json
+// --chain=bridge-hub-westend-dev
 // --header=./cumulus/file_header.txt
 // --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/
-// --chain=bridge-hub-westend-dev
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
@@ -50,81 +48,92 @@ use core::marker::PhantomData;
 /// Weight functions for `frame_system_extensions`.
 pub struct WeightInfo<T>(PhantomData<T>);
 impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<T> {
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_genesis() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `54`
-		//  Estimated: `3509`
-		// Minimum execution time: 3_166_000 picoseconds.
-		Weight::from_parts(6_021_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Estimated: `0`
+		// Minimum execution time: 4_363_000 picoseconds.
+		Weight::from_parts(4_521_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_mortality_mortal_transaction() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `92`
-		//  Estimated: `3509`
-		// Minimum execution time: 5_651_000 picoseconds.
-		Weight::from_parts(9_177_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Estimated: `0`
+		// Minimum execution time: 8_522_000 picoseconds.
+		Weight::from_parts(8_847_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_mortality_immortal_transaction() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `92`
-		//  Estimated: `3509`
-		// Minimum execution time: 5_651_000 picoseconds.
-		Weight::from_parts(9_177_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Estimated: `0`
+		// Minimum execution time: 8_617_000 picoseconds.
+		Weight::from_parts(8_789_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
 	fn check_non_zero_sender() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 601_000 picoseconds.
-		Weight::from_parts(2_805_000, 0)
+		// Minimum execution time: 485_000 picoseconds.
+		Weight::from_parts(557_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
+	/// Storage: `System::Account` (r:1 w:1)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn check_nonce() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `0`
-		//  Estimated: `0`
-		// Minimum execution time: 3_727_000 picoseconds.
-		Weight::from_parts(6_051_000, 0)
-			.saturating_add(Weight::from_parts(0, 0))
+		//  Measured:  `101`
+		//  Estimated: `3593`
+		// Minimum execution time: 6_682_000 picoseconds.
+		Weight::from_parts(6_821_000, 0)
+			.saturating_add(Weight::from_parts(0, 3593))
+			.saturating_add(T::DbWeight::get().reads(1))
+			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	fn check_spec_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 471_000 picoseconds.
-		Weight::from_parts(2_494_000, 0)
+		// Minimum execution time: 390_000 picoseconds.
+		Weight::from_parts(441_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	fn check_tx_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 521_000 picoseconds.
-		Weight::from_parts(2_655_000, 0)
+		// Minimum execution time: 395_000 picoseconds.
+		Weight::from_parts(455_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
 	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
 	/// Storage: `System::BlockWeight` (r:1 w:1)
 	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
 	fn check_weight() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `24`
 		//  Estimated: `1533`
-		// Minimum execution time: 3_808_000 picoseconds.
-		Weight::from_parts(6_402_000, 0)
+		// Minimum execution time: 6_134_000 picoseconds.
+		Weight::from_parts(6_308_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(3))
+	}
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `1533`
+		// Minimum execution time: 2_764_000 picoseconds.
+		Weight::from_parts(2_893_000, 0)
 			.saturating_add(Weight::from_parts(0, 1533))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/mod.rs
index c1c5c337aca8900e7b6314b0e1aa56ed9a5fdec2..313da55831c8f2446ec570f5c78432ebc1ddca35 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/mod.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/mod.rs
@@ -24,6 +24,7 @@ use ::pallet_bridge_relayers::WeightInfo as _;
 
 pub mod block_weights;
 pub mod cumulus_pallet_parachain_system;
+pub mod cumulus_pallet_weight_reclaim;
 pub mod cumulus_pallet_xcmp_queue;
 pub mod extrinsic_weights;
 pub mod frame_system;
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/snowbridge.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/snowbridge.rs
index d71400fa71b625467144d3f793be1604d95ca146..bc570ef7f74bc58495002cb49507304b928a38d6 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/snowbridge.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/snowbridge.rs
@@ -185,8 +185,8 @@ fn construct_extrinsic(
 		BridgeRejectObsoleteHeadersAndMessages::default(),
 		(bridge_to_rococo_config::OnBridgeHubWestendRefundBridgeHubRococoMessages::default(),),
 		frame_metadata_hash_extension::CheckMetadataHash::<Runtime>::new(false),
-		cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::new(),
-	);
+	)
+		.into();
 	let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap();
 	let signature = payload.using_encoded(|e| sender.sign(e));
 	UncheckedExtrinsic::new_signed(call, account_id.into(), Signature::Sr25519(signature), extra)
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs
index 9d32f28f4fc6c69e96ec37d36c47e7a976be9357..d7e7fbe0c72e56f807c2d488d421519086171a77 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs
@@ -95,7 +95,6 @@ fn construct_extrinsic(
 		BridgeRejectObsoleteHeadersAndMessages::default(),
 		(bridge_to_rococo_config::OnBridgeHubWestendRefundBridgeHubRococoMessages::default(),),
 		frame_metadata_hash_extension::CheckMetadataHash::new(false),
-		cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::new(),
 	)
 		.into();
 	let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap();
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml
index 9c70b65060dd93a2dee8d8f8fa2f849ef1ef330c..2786321e48e2edcc9a975a5ec6f159c0bef41ad5 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml
@@ -77,11 +77,11 @@ xcm-runtime-apis = { workspace = true }
 cumulus-pallet-aura-ext = { workspace = true }
 cumulus-pallet-parachain-system = { workspace = true }
 cumulus-pallet-session-benchmarking = { workspace = true }
+cumulus-pallet-weight-reclaim = { workspace = true }
 cumulus-pallet-xcm = { workspace = true }
 cumulus-pallet-xcmp-queue = { workspace = true }
 cumulus-primitives-aura = { workspace = true }
 cumulus-primitives-core = { workspace = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true }
 cumulus-primitives-utility = { workspace = true }
 pallet-message-queue = { workspace = true }
 
@@ -103,6 +103,7 @@ default = ["std"]
 runtime-benchmarks = [
 	"cumulus-pallet-parachain-system/runtime-benchmarks",
 	"cumulus-pallet-session-benchmarking/runtime-benchmarks",
+	"cumulus-pallet-weight-reclaim/runtime-benchmarks",
 	"cumulus-pallet-xcmp-queue/runtime-benchmarks",
 	"cumulus-primitives-core/runtime-benchmarks",
 	"cumulus-primitives-utility/runtime-benchmarks",
@@ -143,6 +144,7 @@ runtime-benchmarks = [
 try-runtime = [
 	"cumulus-pallet-aura-ext/try-runtime",
 	"cumulus-pallet-parachain-system/try-runtime",
+	"cumulus-pallet-weight-reclaim/try-runtime",
 	"cumulus-pallet-xcm/try-runtime",
 	"cumulus-pallet-xcmp-queue/try-runtime",
 	"frame-executive/try-runtime",
@@ -182,11 +184,11 @@ std = [
 	"cumulus-pallet-aura-ext/std",
 	"cumulus-pallet-parachain-system/std",
 	"cumulus-pallet-session-benchmarking/std",
+	"cumulus-pallet-weight-reclaim/std",
 	"cumulus-pallet-xcm/std",
 	"cumulus-pallet-xcmp-queue/std",
 	"cumulus-primitives-aura/std",
 	"cumulus-primitives-core/std",
-	"cumulus-primitives-storage-weight-reclaim/std",
 	"cumulus-primitives-utility/std",
 	"frame-benchmarking?/std",
 	"frame-executive/std",
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs
index d3cd285ba67ac49d44253f7ea67baf50d1a20cda..e9adc4d1eae74fe0098a5de59889c10b7a101867 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs
@@ -191,6 +191,10 @@ impl frame_system::Config for Runtime {
 	type MaxConsumers = frame_support::traits::ConstU32<16>;
 }
 
+impl cumulus_pallet_weight_reclaim::Config for Runtime {
+	type WeightInfo = weights::cumulus_pallet_weight_reclaim::WeightInfo<Runtime>;
+}
+
 impl pallet_timestamp::Config for Runtime {
 	/// A timestamp: milliseconds since the unix epoch.
 	type Moment = u64;
@@ -669,6 +673,7 @@ construct_runtime!(
 		ParachainSystem: cumulus_pallet_parachain_system = 1,
 		Timestamp: pallet_timestamp = 2,
 		ParachainInfo: parachain_info = 3,
+		WeightReclaim: cumulus_pallet_weight_reclaim = 4,
 
 		// Monetary stuff.
 		Balances: pallet_balances = 10,
@@ -735,16 +740,19 @@ pub type SignedBlock = generic::SignedBlock<Block>;
 /// BlockId type as expected by this runtime.
 pub type BlockId = generic::BlockId<Block>;
 /// The extension to the basic transaction logic.
-pub type TxExtension = (
-	frame_system::CheckNonZeroSender<Runtime>,
-	frame_system::CheckSpecVersion<Runtime>,
-	frame_system::CheckTxVersion<Runtime>,
-	frame_system::CheckGenesis<Runtime>,
-	frame_system::CheckEra<Runtime>,
-	frame_system::CheckNonce<Runtime>,
-	frame_system::CheckWeight<Runtime>,
-	cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim<Runtime>,
-);
+pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+	Runtime,
+	(
+		frame_system::CheckNonZeroSender<Runtime>,
+		frame_system::CheckSpecVersion<Runtime>,
+		frame_system::CheckTxVersion<Runtime>,
+		frame_system::CheckGenesis<Runtime>,
+		frame_system::CheckEra<Runtime>,
+		frame_system::CheckNonce<Runtime>,
+		frame_system::CheckWeight<Runtime>,
+	),
+>;
+
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
 	generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
@@ -806,6 +814,7 @@ mod benches {
 		[pallet_salary, AmbassadorSalary]
 		[pallet_treasury, FellowshipTreasury]
 		[pallet_asset_rate, AssetRate]
+		[cumulus_pallet_weight_reclaim, WeightReclaim]
 	);
 }
 
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/cumulus_pallet_weight_reclaim.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/cumulus_pallet_weight_reclaim.rs
new file mode 100644
index 0000000000000000000000000000000000000000..c286ba132022791157e6bd9861375c62156edf61
--- /dev/null
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/cumulus_pallet_weight_reclaim.rs
@@ -0,0 +1,67 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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.
+
+// Cumulus 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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Autogenerated weights for `cumulus_pallet_weight_reclaim`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-westend-dev")`, DB CACHE: 1024
+
+// Executed Command:
+// target/production/polkadot-parachain
+// benchmark
+// pallet
+// --steps=50
+// --repeat=20
+// --extrinsic=*
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
+// --pallet=cumulus_pallet_weight_reclaim
+// --chain=collectives-westend-dev
+// --header=./cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::Weight};
+use core::marker::PhantomData;
+
+/// Weight functions for `cumulus_pallet_weight_reclaim`.
+pub struct WeightInfo<T>(PhantomData<T>);
+impl<T: frame_system::Config> cumulus_pallet_weight_reclaim::WeightInfo for WeightInfo<T> {
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:0)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	fn storage_weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1533`
+		// Minimum execution time: 6_745_000 picoseconds.
+		Weight::from_parts(6_948_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
+}
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/frame_system_extensions.rs
index f32f2730313570cad4a759e64b2156f30110f60b..8c2abcd4e8c88fa2e888eb3caca38b57f9bac5eb 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/frame_system_extensions.rs
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/frame_system_extensions.rs
@@ -16,28 +16,26 @@
 
 //! Autogenerated weights for `frame_system_extensions`
 //!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-westend-dev")`, DB CACHE: 1024
 
 // Executed Command:
-// ./target/release/polkadot-parachain
+// target/production/polkadot-parachain
 // benchmark
 // pallet
+// --steps=50
+// --repeat=20
+// --extrinsic=*
 // --wasm-execution=compiled
+// --heap-pages=4096
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
 // --pallet=frame_system_extensions
-// --no-storage-info
-// --no-median-slopes
-// --no-min-squares
-// --extrinsic=*
-// --steps=2
-// --repeat=2
-// --json
+// --chain=collectives-westend-dev
 // --header=./cumulus/file_header.txt
 // --output=./cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/
-// --chain=collectives-westend-dev
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
@@ -50,81 +48,92 @@ use core::marker::PhantomData;
 /// Weight functions for `frame_system_extensions`.
 pub struct WeightInfo<T>(PhantomData<T>);
 impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<T> {
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_genesis() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `54`
-		//  Estimated: `3509`
-		// Minimum execution time: 3_497_000 picoseconds.
-		Weight::from_parts(5_961_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Estimated: `0`
+		// Minimum execution time: 4_206_000 picoseconds.
+		Weight::from_parts(4_485_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_mortality_mortal_transaction() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `92`
-		//  Estimated: `3509`
-		// Minimum execution time: 5_240_000 picoseconds.
-		Weight::from_parts(8_175_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Estimated: `0`
+		// Minimum execution time: 7_537_000 picoseconds.
+		Weight::from_parts(7_706_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_mortality_immortal_transaction() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `92`
-		//  Estimated: `3509`
-		// Minimum execution time: 5_240_000 picoseconds.
-		Weight::from_parts(8_175_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Estimated: `0`
+		// Minimum execution time: 7_512_000 picoseconds.
+		Weight::from_parts(7_655_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
 	fn check_non_zero_sender() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 671_000 picoseconds.
-		Weight::from_parts(3_005_000, 0)
+		// Minimum execution time: 447_000 picoseconds.
+		Weight::from_parts(499_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
+	/// Storage: `System::Account` (r:1 w:1)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn check_nonce() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `0`
-		//  Estimated: `0`
-		// Minimum execution time: 3_426_000 picoseconds.
-		Weight::from_parts(6_131_000, 0)
-			.saturating_add(Weight::from_parts(0, 0))
+		//  Measured:  `101`
+		//  Estimated: `3593`
+		// Minimum execution time: 6_667_000 picoseconds.
+		Weight::from_parts(6_868_000, 0)
+			.saturating_add(Weight::from_parts(0, 3593))
+			.saturating_add(T::DbWeight::get().reads(1))
+			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	fn check_spec_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 501_000 picoseconds.
-		Weight::from_parts(2_715_000, 0)
+		// Minimum execution time: 389_000 picoseconds.
+		Weight::from_parts(420_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	fn check_tx_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 491_000 picoseconds.
-		Weight::from_parts(2_635_000, 0)
+		// Minimum execution time: 379_000 picoseconds.
+		Weight::from_parts(420_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
 	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
 	/// Storage: `System::BlockWeight` (r:1 w:1)
 	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
 	fn check_weight() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `24`
 		//  Estimated: `1533`
-		// Minimum execution time: 3_958_000 picoseconds.
-		Weight::from_parts(6_753_000, 0)
+		// Minimum execution time: 6_330_000 picoseconds.
+		Weight::from_parts(6_605_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(3))
+	}
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `1533`
+		// Minimum execution time: 2_784_000 picoseconds.
+		Weight::from_parts(2_960_000, 0)
 			.saturating_add(Weight::from_parts(0, 1533))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/mod.rs
index 00b3bd92d5ef9ce0081ca9e95e43bd35098c6aa0..a1663dc98a347ac584cd60168ffcc54025694733 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/mod.rs
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/mod.rs
@@ -15,6 +15,7 @@
 
 pub mod block_weights;
 pub mod cumulus_pallet_parachain_system;
+pub mod cumulus_pallet_weight_reclaim;
 pub mod cumulus_pallet_xcmp_queue;
 pub mod extrinsic_weights;
 pub mod frame_system;
diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml b/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml
index cb0655d70cf29e4679b5ade41794e0c5089f8568..067c4df3b53654f28fdc40e0ac58a480d7fdfef3 100644
--- a/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml
@@ -70,11 +70,11 @@ xcm-runtime-apis = { workspace = true }
 cumulus-pallet-aura-ext = { workspace = true }
 cumulus-pallet-parachain-system = { workspace = true }
 cumulus-pallet-session-benchmarking = { workspace = true }
+cumulus-pallet-weight-reclaim = { workspace = true }
 cumulus-pallet-xcm = { workspace = true }
 cumulus-pallet-xcmp-queue = { workspace = true }
 cumulus-primitives-aura = { workspace = true }
 cumulus-primitives-core = { workspace = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true }
 cumulus-primitives-utility = { workspace = true }
 pallet-message-queue = { workspace = true }
 
@@ -90,11 +90,11 @@ std = [
 	"cumulus-pallet-aura-ext/std",
 	"cumulus-pallet-parachain-system/std",
 	"cumulus-pallet-session-benchmarking/std",
+	"cumulus-pallet-weight-reclaim/std",
 	"cumulus-pallet-xcm/std",
 	"cumulus-pallet-xcmp-queue/std",
 	"cumulus-primitives-aura/std",
 	"cumulus-primitives-core/std",
-	"cumulus-primitives-storage-weight-reclaim/std",
 	"cumulus-primitives-utility/std",
 	"frame-benchmarking?/std",
 	"frame-executive/std",
@@ -148,6 +148,7 @@ std = [
 runtime-benchmarks = [
 	"cumulus-pallet-parachain-system/runtime-benchmarks",
 	"cumulus-pallet-session-benchmarking/runtime-benchmarks",
+	"cumulus-pallet-weight-reclaim/runtime-benchmarks",
 	"cumulus-pallet-xcmp-queue/runtime-benchmarks",
 	"cumulus-primitives-core/runtime-benchmarks",
 	"cumulus-primitives-utility/runtime-benchmarks",
@@ -179,6 +180,7 @@ runtime-benchmarks = [
 try-runtime = [
 	"cumulus-pallet-aura-ext/try-runtime",
 	"cumulus-pallet-parachain-system/try-runtime",
+	"cumulus-pallet-weight-reclaim/try-runtime",
 	"cumulus-pallet-xcm/try-runtime",
 	"cumulus-pallet-xcmp-queue/try-runtime",
 	"frame-executive/try-runtime",
diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs
index be369565dba9713fff86be19d664b1793c6aa1b9..3348a635df01a63c18369e9258e8f1b3a316bb18 100644
--- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs
@@ -88,17 +88,19 @@ pub type SignedBlock = generic::SignedBlock<Block>;
 /// BlockId type as expected by this runtime.
 pub type BlockId = generic::BlockId<Block>;
 /// The extension to the basic transaction logic.
-pub type TxExtension = (
-	frame_system::CheckNonZeroSender<Runtime>,
-	frame_system::CheckSpecVersion<Runtime>,
-	frame_system::CheckTxVersion<Runtime>,
-	frame_system::CheckGenesis<Runtime>,
-	frame_system::CheckEra<Runtime>,
-	frame_system::CheckNonce<Runtime>,
-	frame_system::CheckWeight<Runtime>,
-	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
-	cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim<Runtime>,
-);
+pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+	Runtime,
+	(
+		frame_system::CheckNonZeroSender<Runtime>,
+		frame_system::CheckSpecVersion<Runtime>,
+		frame_system::CheckTxVersion<Runtime>,
+		frame_system::CheckGenesis<Runtime>,
+		frame_system::CheckEra<Runtime>,
+		frame_system::CheckNonce<Runtime>,
+		frame_system::CheckWeight<Runtime>,
+		pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+	),
+>;
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
 	generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
@@ -201,6 +203,10 @@ impl frame_system::Config for Runtime {
 	type MaxConsumers = ConstU32<16>;
 }
 
+impl cumulus_pallet_weight_reclaim::Config for Runtime {
+	type WeightInfo = ();
+}
+
 impl pallet_timestamp::Config for Runtime {
 	/// A timestamp: milliseconds since the unix epoch.
 	type Moment = u64;
@@ -402,6 +408,7 @@ construct_runtime!(
 		RandomnessCollectiveFlip: pallet_insecure_randomness_collective_flip = 2,
 		Timestamp: pallet_timestamp = 3,
 		ParachainInfo: parachain_info = 4,
+		WeightReclaim: cumulus_pallet_weight_reclaim = 5,
 
 		// Monetary stuff.
 		Balances: pallet_balances = 10,
@@ -448,6 +455,7 @@ mod benches {
 		[cumulus_pallet_parachain_system, ParachainSystem]
 		[pallet_contracts, Contracts]
 		[pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>]
+		[cumulus_pallet_weight_reclaim, WeightReclaim]
 	);
 }
 
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
index 2b5fab329293d58f445ba2e30bbacfa5b8305dff..668b4cc6c7b9bd6a358254f1c86b639dbc487cf5 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
@@ -71,11 +71,11 @@ xcm-runtime-apis = { workspace = true }
 cumulus-pallet-aura-ext = { workspace = true }
 cumulus-pallet-parachain-system = { workspace = true }
 cumulus-pallet-session-benchmarking = { workspace = true }
+cumulus-pallet-weight-reclaim = { workspace = true }
 cumulus-pallet-xcm = { workspace = true }
 cumulus-pallet-xcmp-queue = { workspace = true }
 cumulus-primitives-aura = { workspace = true }
 cumulus-primitives-core = { workspace = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true }
 cumulus-primitives-utility = { workspace = true }
 pallet-collator-selection = { workspace = true }
 parachain-info = { workspace = true }
@@ -92,11 +92,11 @@ std = [
 	"cumulus-pallet-aura-ext/std",
 	"cumulus-pallet-parachain-system/std",
 	"cumulus-pallet-session-benchmarking/std",
+	"cumulus-pallet-weight-reclaim/std",
 	"cumulus-pallet-xcm/std",
 	"cumulus-pallet-xcmp-queue/std",
 	"cumulus-primitives-aura/std",
 	"cumulus-primitives-core/std",
-	"cumulus-primitives-storage-weight-reclaim/std",
 	"cumulus-primitives-utility/std",
 	"frame-benchmarking?/std",
 	"frame-executive/std",
@@ -154,6 +154,7 @@ std = [
 runtime-benchmarks = [
 	"cumulus-pallet-parachain-system/runtime-benchmarks",
 	"cumulus-pallet-session-benchmarking/runtime-benchmarks",
+	"cumulus-pallet-weight-reclaim/runtime-benchmarks",
 	"cumulus-pallet-xcmp-queue/runtime-benchmarks",
 	"cumulus-primitives-core/runtime-benchmarks",
 	"cumulus-primitives-utility/runtime-benchmarks",
@@ -186,6 +187,7 @@ runtime-benchmarks = [
 try-runtime = [
 	"cumulus-pallet-aura-ext/try-runtime",
 	"cumulus-pallet-parachain-system/try-runtime",
+	"cumulus-pallet-weight-reclaim/try-runtime",
 	"cumulus-pallet-xcm/try-runtime",
 	"cumulus-pallet-xcmp-queue/try-runtime",
 	"frame-executive/try-runtime",
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
index c4d43e4361fae91dac774066f28f037825291fec..e9171c79afaec8b871b9e88d52e283d04b1437fb 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
@@ -99,18 +99,20 @@ pub type SignedBlock = generic::SignedBlock<Block>;
 pub type BlockId = generic::BlockId<Block>;
 
 /// The TransactionExtension to the basic transaction logic.
-pub type TxExtension = (
-	frame_system::CheckNonZeroSender<Runtime>,
-	frame_system::CheckSpecVersion<Runtime>,
-	frame_system::CheckTxVersion<Runtime>,
-	frame_system::CheckGenesis<Runtime>,
-	frame_system::CheckEra<Runtime>,
-	frame_system::CheckNonce<Runtime>,
-	frame_system::CheckWeight<Runtime>,
-	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
-	cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim<Runtime>,
-	frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
-);
+pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+	Runtime,
+	(
+		frame_system::CheckNonZeroSender<Runtime>,
+		frame_system::CheckSpecVersion<Runtime>,
+		frame_system::CheckTxVersion<Runtime>,
+		frame_system::CheckGenesis<Runtime>,
+		frame_system::CheckEra<Runtime>,
+		frame_system::CheckNonce<Runtime>,
+		frame_system::CheckWeight<Runtime>,
+		pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+		frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+	),
+>;
 
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
@@ -221,6 +223,10 @@ impl frame_system::Config for Runtime {
 	type MaxConsumers = ConstU32<16>;
 }
 
+impl cumulus_pallet_weight_reclaim::Config for Runtime {
+	type WeightInfo = weights::cumulus_pallet_weight_reclaim::WeightInfo<Runtime>;
+}
+
 impl pallet_timestamp::Config for Runtime {
 	/// A timestamp: milliseconds since the unix epoch.
 	type Moment = u64;
@@ -622,6 +628,7 @@ construct_runtime!(
 		ParachainSystem: cumulus_pallet_parachain_system = 1,
 		Timestamp: pallet_timestamp = 3,
 		ParachainInfo: parachain_info = 4,
+		WeightReclaim: cumulus_pallet_weight_reclaim = 5,
 
 		// Monetary stuff.
 		Balances: pallet_balances = 10,
@@ -672,6 +679,7 @@ mod benches {
 		// NOTE: Make sure you point to the individual modules below.
 		[pallet_xcm_benchmarks::fungible, XcmBalances]
 		[pallet_xcm_benchmarks::generic, XcmGeneric]
+		[cumulus_pallet_weight_reclaim, WeightReclaim]
 	);
 }
 
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/cumulus_pallet_weight_reclaim.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/cumulus_pallet_weight_reclaim.rs
new file mode 100644
index 0000000000000000000000000000000000000000..6298fd6e7f69815e659af5a404b1bc2bf0f41d5b
--- /dev/null
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/cumulus_pallet_weight_reclaim.rs
@@ -0,0 +1,67 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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.
+
+// Cumulus 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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Autogenerated weights for `cumulus_pallet_weight_reclaim`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-rococo-dev")`, DB CACHE: 1024
+
+// Executed Command:
+// target/production/polkadot-parachain
+// benchmark
+// pallet
+// --steps=50
+// --repeat=20
+// --extrinsic=*
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
+// --pallet=cumulus_pallet_weight_reclaim
+// --chain=coretime-rococo-dev
+// --header=./cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::Weight};
+use core::marker::PhantomData;
+
+/// Weight functions for `cumulus_pallet_weight_reclaim`.
+pub struct WeightInfo<T>(PhantomData<T>);
+impl<T: frame_system::Config> cumulus_pallet_weight_reclaim::WeightInfo for WeightInfo<T> {
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:0)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	fn storage_weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1533`
+		// Minimum execution time: 6_638_000 picoseconds.
+		Weight::from_parts(6_806_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
+}
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/frame_system_extensions.rs
index a4d09696a1a116ea5add5d9a1d41b86169bfe272..04b695b5769302f51ce764bfff219900bff107eb 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/frame_system_extensions.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/frame_system_extensions.rs
@@ -129,4 +129,18 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1533`
+		// Minimum execution time: 3_687_000 picoseconds.
+		Weight::from_parts(6_192_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(2))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
 }
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/mod.rs
index 24c4f50e6ab8b8c46ae1bfa177c8afada04a795e..7fee4a728b9ef750224efeac78408ca58827d643 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/mod.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/mod.rs
@@ -19,6 +19,7 @@
 
 pub mod block_weights;
 pub mod cumulus_pallet_parachain_system;
+pub mod cumulus_pallet_weight_reclaim;
 pub mod cumulus_pallet_xcmp_queue;
 pub mod extrinsic_weights;
 pub mod frame_system;
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
index 03df782bc266afe39bcd1a430debb531a5adff3e..915926ff9894ed3164dd37aeee828aa7229bb863 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
@@ -70,11 +70,11 @@ xcm-runtime-apis = { workspace = true }
 cumulus-pallet-aura-ext = { workspace = true }
 cumulus-pallet-parachain-system = { workspace = true }
 cumulus-pallet-session-benchmarking = { workspace = true }
+cumulus-pallet-weight-reclaim = { workspace = true }
 cumulus-pallet-xcm = { workspace = true }
 cumulus-pallet-xcmp-queue = { workspace = true }
 cumulus-primitives-aura = { workspace = true }
 cumulus-primitives-core = { workspace = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true }
 cumulus-primitives-utility = { workspace = true }
 
 pallet-collator-selection = { workspace = true }
@@ -92,11 +92,11 @@ std = [
 	"cumulus-pallet-aura-ext/std",
 	"cumulus-pallet-parachain-system/std",
 	"cumulus-pallet-session-benchmarking/std",
+	"cumulus-pallet-weight-reclaim/std",
 	"cumulus-pallet-xcm/std",
 	"cumulus-pallet-xcmp-queue/std",
 	"cumulus-primitives-aura/std",
 	"cumulus-primitives-core/std",
-	"cumulus-primitives-storage-weight-reclaim/std",
 	"cumulus-primitives-utility/std",
 	"frame-benchmarking?/std",
 	"frame-executive/std",
@@ -152,6 +152,7 @@ std = [
 runtime-benchmarks = [
 	"cumulus-pallet-parachain-system/runtime-benchmarks",
 	"cumulus-pallet-session-benchmarking/runtime-benchmarks",
+	"cumulus-pallet-weight-reclaim/runtime-benchmarks",
 	"cumulus-pallet-xcmp-queue/runtime-benchmarks",
 	"cumulus-primitives-core/runtime-benchmarks",
 	"cumulus-primitives-utility/runtime-benchmarks",
@@ -183,6 +184,7 @@ runtime-benchmarks = [
 try-runtime = [
 	"cumulus-pallet-aura-ext/try-runtime",
 	"cumulus-pallet-parachain-system/try-runtime",
+	"cumulus-pallet-weight-reclaim/try-runtime",
 	"cumulus-pallet-xcm/try-runtime",
 	"cumulus-pallet-xcmp-queue/try-runtime",
 	"frame-executive/try-runtime",
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
index 431bfc8a63ba91fe310484a3f6b5200fcc48f3cc..975856b3b6ff8eeebdc65427d693181eb9919eee 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
@@ -99,18 +99,20 @@ pub type SignedBlock = generic::SignedBlock<Block>;
 pub type BlockId = generic::BlockId<Block>;
 
 /// The TransactionExtension to the basic transaction logic.
-pub type TxExtension = (
-	frame_system::CheckNonZeroSender<Runtime>,
-	frame_system::CheckSpecVersion<Runtime>,
-	frame_system::CheckTxVersion<Runtime>,
-	frame_system::CheckGenesis<Runtime>,
-	frame_system::CheckEra<Runtime>,
-	frame_system::CheckNonce<Runtime>,
-	frame_system::CheckWeight<Runtime>,
-	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
-	cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim<Runtime>,
-	frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
-);
+pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+	Runtime,
+	(
+		frame_system::CheckNonZeroSender<Runtime>,
+		frame_system::CheckSpecVersion<Runtime>,
+		frame_system::CheckTxVersion<Runtime>,
+		frame_system::CheckGenesis<Runtime>,
+		frame_system::CheckEra<Runtime>,
+		frame_system::CheckNonce<Runtime>,
+		frame_system::CheckWeight<Runtime>,
+		pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+		frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+	),
+>;
 
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
@@ -221,6 +223,10 @@ impl frame_system::Config for Runtime {
 	type MaxConsumers = ConstU32<16>;
 }
 
+impl cumulus_pallet_weight_reclaim::Config for Runtime {
+	type WeightInfo = weights::cumulus_pallet_weight_reclaim::WeightInfo<Runtime>;
+}
+
 impl pallet_timestamp::Config for Runtime {
 	/// A timestamp: milliseconds since the unix epoch.
 	type Moment = u64;
@@ -617,6 +623,7 @@ construct_runtime!(
 		ParachainSystem: cumulus_pallet_parachain_system = 1,
 		Timestamp: pallet_timestamp = 3,
 		ParachainInfo: parachain_info = 4,
+		WeightReclaim: cumulus_pallet_weight_reclaim = 5,
 
 		// Monetary stuff.
 		Balances: pallet_balances = 10,
@@ -664,6 +671,7 @@ mod benches {
 		// NOTE: Make sure you point to the individual modules below.
 		[pallet_xcm_benchmarks::fungible, XcmBalances]
 		[pallet_xcm_benchmarks::generic, XcmGeneric]
+		[cumulus_pallet_weight_reclaim, WeightReclaim]
 	);
 }
 
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/cumulus_pallet_weight_reclaim.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/cumulus_pallet_weight_reclaim.rs
new file mode 100644
index 0000000000000000000000000000000000000000..55d52f4b04c8788f1bc05472516e1de4e6d65c92
--- /dev/null
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/cumulus_pallet_weight_reclaim.rs
@@ -0,0 +1,67 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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.
+
+// Cumulus 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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Autogenerated weights for `cumulus_pallet_weight_reclaim`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-westend-dev")`, DB CACHE: 1024
+
+// Executed Command:
+// target/production/polkadot-parachain
+// benchmark
+// pallet
+// --steps=50
+// --repeat=20
+// --extrinsic=*
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
+// --pallet=cumulus_pallet_weight_reclaim
+// --chain=coretime-westend-dev
+// --header=./cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::Weight};
+use core::marker::PhantomData;
+
+/// Weight functions for `cumulus_pallet_weight_reclaim`.
+pub struct WeightInfo<T>(PhantomData<T>);
+impl<T: frame_system::Config> cumulus_pallet_weight_reclaim::WeightInfo for WeightInfo<T> {
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:0)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	fn storage_weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1533`
+		// Minimum execution time: 6_658_000 picoseconds.
+		Weight::from_parts(6_905_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
+}
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/frame_system_extensions.rs
index d928b73613a3f110dc373ea91070377b644c4bbb..9527e0c5549a788b5d5995aa65a0ed30c909f426 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/frame_system_extensions.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/frame_system_extensions.rs
@@ -129,4 +129,18 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1533`
+		// Minimum execution time: 3_687_000 picoseconds.
+		Weight::from_parts(6_192_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(2))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
 }
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/mod.rs
index 24c4f50e6ab8b8c46ae1bfa177c8afada04a795e..7fee4a728b9ef750224efeac78408ca58827d643 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/mod.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/mod.rs
@@ -19,6 +19,7 @@
 
 pub mod block_weights;
 pub mod cumulus_pallet_parachain_system;
+pub mod cumulus_pallet_weight_reclaim;
 pub mod cumulus_pallet_xcmp_queue;
 pub mod extrinsic_weights;
 pub mod frame_system;
diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs
index 763f8abea34a7ae965af26189248bdac04de7d7f..75f45297fe2cdade064fe3478ff1979aecb11ee2 100644
--- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs
@@ -300,6 +300,7 @@ pub type TxExtension = (
 	frame_system::CheckEra<Runtime>,
 	frame_system::CheckNonce<Runtime>,
 	frame_system::CheckWeight<Runtime>,
+	frame_system::WeightReclaim<Runtime>,
 );
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/frame_system_extensions.rs
index 4fbbb8d6f781d97aeedfa7d84779190464ff70a2..db9a14e2cf242ab40c4fb68aaa1a90fbe4605501 100644
--- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/frame_system_extensions.rs
+++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/frame_system_extensions.rs
@@ -16,28 +16,30 @@
 
 //! Autogenerated weights for `frame_system_extensions`
 //!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-10-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor`
-//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("glutton-westend-dev-1300")`, DB CACHE: 1024
+//! HOSTNAME: `697235d969a1`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024
 
 // Executed Command:
-// ./target/release/polkadot-parachain
+// frame-omni-bencher
+// v1
 // benchmark
 // pallet
-// --wasm-execution=compiled
+// --extrinsic=*
+// --runtime=target/release/wbuild/glutton-westend-runtime/glutton_westend_runtime.wasm
 // --pallet=frame_system_extensions
+// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/glutton/glutton-westend/src/weights
+// --wasm-execution=compiled
+// --steps=50
+// --repeat=20
+// --heap-pages=4096
 // --no-storage-info
-// --no-median-slopes
 // --no-min-squares
-// --extrinsic=*
-// --steps=2
-// --repeat=2
-// --json
-// --header=./cumulus/file_header.txt
-// --output=./cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/
-// --chain=glutton-westend-dev-1300
+// --no-median-slopes
+// --genesis-builder-policy=none
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
@@ -54,10 +56,10 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_genesis() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `54`
+		//  Measured:  `0`
 		//  Estimated: `3509`
-		// Minimum execution time: 3_908_000 picoseconds.
-		Weight::from_parts(4_007_000, 0)
+		// Minimum execution time: 2_572_000 picoseconds.
+		Weight::from_parts(2_680_000, 0)
 			.saturating_add(Weight::from_parts(0, 3509))
 			.saturating_add(T::DbWeight::get().reads(1))
 	}
@@ -65,10 +67,10 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_mortality_mortal_transaction() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `92`
+		//  Measured:  `0`
 		//  Estimated: `3509`
-		// Minimum execution time: 5_510_000 picoseconds.
-		Weight::from_parts(6_332_000, 0)
+		// Minimum execution time: 5_818_000 picoseconds.
+		Weight::from_parts(6_024_000, 0)
 			.saturating_add(Weight::from_parts(0, 3509))
 			.saturating_add(T::DbWeight::get().reads(1))
 	}
@@ -76,10 +78,10 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_mortality_immortal_transaction() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `92`
+		//  Measured:  `14`
 		//  Estimated: `3509`
-		// Minimum execution time: 5_510_000 picoseconds.
-		Weight::from_parts(6_332_000, 0)
+		// Minimum execution time: 7_364_000 picoseconds.
+		Weight::from_parts(7_676_000, 0)
 			.saturating_add(Weight::from_parts(0, 3509))
 			.saturating_add(T::DbWeight::get().reads(1))
 	}
@@ -87,44 +89,52 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 651_000 picoseconds.
-		Weight::from_parts(851_000, 0)
+		// Minimum execution time: 657_000 picoseconds.
+		Weight::from_parts(686_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
+	/// Storage: `System::Account` (r:1 w:1)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`)
 	fn check_nonce() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
-		//  Estimated: `0`
-		// Minimum execution time: 3_387_000 picoseconds.
-		Weight::from_parts(3_646_000, 0)
-			.saturating_add(Weight::from_parts(0, 0))
+		//  Estimated: `3529`
+		// Minimum execution time: 6_931_000 picoseconds.
+		Weight::from_parts(7_096_000, 0)
+			.saturating_add(Weight::from_parts(0, 3529))
+			.saturating_add(T::DbWeight::get().reads(1))
+			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	fn check_spec_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 491_000 picoseconds.
-		Weight::from_parts(651_000, 0)
+		// Minimum execution time: 518_000 picoseconds.
+		Weight::from_parts(539_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	fn check_tx_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 451_000 picoseconds.
-		Weight::from_parts(662_000, 0)
+		// Minimum execution time: 530_000 picoseconds.
+		Weight::from_parts(550_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
-	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
-	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
 	fn check_weight() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `24`
-		//  Estimated: `1489`
-		// Minimum execution time: 3_537_000 picoseconds.
-		Weight::from_parts(4_208_000, 0)
-			.saturating_add(Weight::from_parts(0, 1489))
-			.saturating_add(T::DbWeight::get().reads(1))
-			.saturating_add(T::DbWeight::get().writes(1))
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 5_691_000 picoseconds.
+		Weight::from_parts(5_955_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
+	}
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 3_249_000 picoseconds.
+		Weight::from_parts(3_372_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
 }
diff --git a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml
index de2898046c0d75b4ce0613c58e675747795c2302..6391f8c3eeb904586c9a0bc8449eb546218846da 100644
--- a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml
@@ -68,11 +68,11 @@ xcm-runtime-apis = { workspace = true }
 cumulus-pallet-aura-ext = { workspace = true }
 cumulus-pallet-parachain-system = { workspace = true }
 cumulus-pallet-session-benchmarking = { workspace = true }
+cumulus-pallet-weight-reclaim = { workspace = true }
 cumulus-pallet-xcm = { workspace = true }
 cumulus-pallet-xcmp-queue = { workspace = true }
 cumulus-primitives-aura = { workspace = true }
 cumulus-primitives-core = { workspace = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true }
 cumulus-primitives-utility = { workspace = true }
 pallet-collator-selection = { workspace = true }
 parachain-info = { workspace = true }
@@ -89,11 +89,11 @@ std = [
 	"cumulus-pallet-aura-ext/std",
 	"cumulus-pallet-parachain-system/std",
 	"cumulus-pallet-session-benchmarking/std",
+	"cumulus-pallet-weight-reclaim/std",
 	"cumulus-pallet-xcm/std",
 	"cumulus-pallet-xcmp-queue/std",
 	"cumulus-primitives-aura/std",
 	"cumulus-primitives-core/std",
-	"cumulus-primitives-storage-weight-reclaim/std",
 	"cumulus-primitives-utility/std",
 	"enumflags2/std",
 	"frame-benchmarking?/std",
@@ -150,6 +150,7 @@ std = [
 runtime-benchmarks = [
 	"cumulus-pallet-parachain-system/runtime-benchmarks",
 	"cumulus-pallet-session-benchmarking/runtime-benchmarks",
+	"cumulus-pallet-weight-reclaim/runtime-benchmarks",
 	"cumulus-pallet-xcmp-queue/runtime-benchmarks",
 	"cumulus-primitives-core/runtime-benchmarks",
 	"cumulus-primitives-utility/runtime-benchmarks",
@@ -182,6 +183,7 @@ runtime-benchmarks = [
 try-runtime = [
 	"cumulus-pallet-aura-ext/try-runtime",
 	"cumulus-pallet-parachain-system/try-runtime",
+	"cumulus-pallet-weight-reclaim/try-runtime",
 	"cumulus-pallet-xcm/try-runtime",
 	"cumulus-pallet-xcmp-queue/try-runtime",
 	"frame-executive/try-runtime",
diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs
index ef3c90ace8262fc7b60f50695556490218eef2bd..ffdd86c500e5b4da5eb56a3fb7f16c16083745cb 100644
--- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs
@@ -92,17 +92,19 @@ pub type SignedBlock = generic::SignedBlock<Block>;
 pub type BlockId = generic::BlockId<Block>;
 
 /// The TransactionExtension to the basic transaction logic.
-pub type TxExtension = (
-	frame_system::CheckNonZeroSender<Runtime>,
-	frame_system::CheckSpecVersion<Runtime>,
-	frame_system::CheckTxVersion<Runtime>,
-	frame_system::CheckGenesis<Runtime>,
-	frame_system::CheckEra<Runtime>,
-	frame_system::CheckNonce<Runtime>,
-	frame_system::CheckWeight<Runtime>,
-	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
-	cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim<Runtime>,
-);
+pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+	Runtime,
+	(
+		frame_system::CheckNonZeroSender<Runtime>,
+		frame_system::CheckSpecVersion<Runtime>,
+		frame_system::CheckTxVersion<Runtime>,
+		frame_system::CheckGenesis<Runtime>,
+		frame_system::CheckEra<Runtime>,
+		frame_system::CheckNonce<Runtime>,
+		frame_system::CheckWeight<Runtime>,
+		pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+	),
+>;
 
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
@@ -196,6 +198,10 @@ impl frame_system::Config for Runtime {
 	type MultiBlockMigrator = MultiBlockMigrations;
 }
 
+impl cumulus_pallet_weight_reclaim::Config for Runtime {
+	type WeightInfo = weights::cumulus_pallet_weight_reclaim::WeightInfo<Runtime>;
+}
+
 impl pallet_timestamp::Config for Runtime {
 	/// A timestamp: milliseconds since the unix epoch.
 	type Moment = u64;
@@ -567,6 +573,7 @@ construct_runtime!(
 		ParachainSystem: cumulus_pallet_parachain_system = 1,
 		Timestamp: pallet_timestamp = 2,
 		ParachainInfo: parachain_info = 3,
+		WeightReclaim: cumulus_pallet_weight_reclaim = 4,
 
 		// Monetary stuff.
 		Balances: pallet_balances = 10,
@@ -626,6 +633,7 @@ mod benches {
 		[pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>]
 		[pallet_xcm_benchmarks::fungible, XcmBalances]
 		[pallet_xcm_benchmarks::generic, XcmGeneric]
+		[cumulus_pallet_weight_reclaim, WeightReclaim]
 	);
 }
 
diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/cumulus_pallet_weight_reclaim.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/cumulus_pallet_weight_reclaim.rs
new file mode 100644
index 0000000000000000000000000000000000000000..439855f857192a7c729f5aa49e2b90a1aabd7407
--- /dev/null
+++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/cumulus_pallet_weight_reclaim.rs
@@ -0,0 +1,67 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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.
+
+// Cumulus 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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Autogenerated weights for `cumulus_pallet_weight_reclaim`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-rococo-dev")`, DB CACHE: 1024
+
+// Executed Command:
+// target/production/polkadot-parachain
+// benchmark
+// pallet
+// --steps=50
+// --repeat=20
+// --extrinsic=*
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
+// --pallet=cumulus_pallet_weight_reclaim
+// --chain=people-rococo-dev
+// --header=./cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/people/people-rococo/src/weights/
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::Weight};
+use core::marker::PhantomData;
+
+/// Weight functions for `cumulus_pallet_weight_reclaim`.
+pub struct WeightInfo<T>(PhantomData<T>);
+impl<T: frame_system::Config> cumulus_pallet_weight_reclaim::WeightInfo for WeightInfo<T> {
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:0)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	fn storage_weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1533`
+		// Minimum execution time: 7_097_000 picoseconds.
+		Weight::from_parts(7_419_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
+}
diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/frame_system_extensions.rs
index fb2b69e23e82b690e225517377aafd54fc72a240..3f12b25540ea669dff95ba4e8c9c87429a372af0 100644
--- a/cumulus/parachains/runtimes/people/people-rococo/src/weights/frame_system_extensions.rs
+++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/frame_system_extensions.rs
@@ -129,4 +129,18 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1533`
+		// Minimum execution time: 3_687_000 picoseconds.
+		Weight::from_parts(6_192_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(2))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
 }
diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/mod.rs
index fab3c629ab3f31363233cf289c2abd1b96a59997..81906a11fe1c9ea7a9fde28cea1734bd2dd97252 100644
--- a/cumulus/parachains/runtimes/people/people-rococo/src/weights/mod.rs
+++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/mod.rs
@@ -17,6 +17,7 @@
 
 pub mod block_weights;
 pub mod cumulus_pallet_parachain_system;
+pub mod cumulus_pallet_weight_reclaim;
 pub mod cumulus_pallet_xcmp_queue;
 pub mod extrinsic_weights;
 pub mod frame_system;
diff --git a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml
index 65bc8264934f65f9037ff041640d431f99e67ae4..fae0fd2e33324e500d75983ce09db276450fa79c 100644
--- a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml
@@ -68,11 +68,11 @@ xcm-runtime-apis = { workspace = true }
 cumulus-pallet-aura-ext = { workspace = true }
 cumulus-pallet-parachain-system = { workspace = true }
 cumulus-pallet-session-benchmarking = { workspace = true }
+cumulus-pallet-weight-reclaim = { workspace = true }
 cumulus-pallet-xcm = { workspace = true }
 cumulus-pallet-xcmp-queue = { workspace = true }
 cumulus-primitives-aura = { workspace = true }
 cumulus-primitives-core = { workspace = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true }
 cumulus-primitives-utility = { workspace = true }
 pallet-collator-selection = { workspace = true }
 parachain-info = { workspace = true }
@@ -89,11 +89,11 @@ std = [
 	"cumulus-pallet-aura-ext/std",
 	"cumulus-pallet-parachain-system/std",
 	"cumulus-pallet-session-benchmarking/std",
+	"cumulus-pallet-weight-reclaim/std",
 	"cumulus-pallet-xcm/std",
 	"cumulus-pallet-xcmp-queue/std",
 	"cumulus-primitives-aura/std",
 	"cumulus-primitives-core/std",
-	"cumulus-primitives-storage-weight-reclaim/std",
 	"cumulus-primitives-utility/std",
 	"enumflags2/std",
 	"frame-benchmarking?/std",
@@ -150,6 +150,7 @@ std = [
 runtime-benchmarks = [
 	"cumulus-pallet-parachain-system/runtime-benchmarks",
 	"cumulus-pallet-session-benchmarking/runtime-benchmarks",
+	"cumulus-pallet-weight-reclaim/runtime-benchmarks",
 	"cumulus-pallet-xcmp-queue/runtime-benchmarks",
 	"cumulus-primitives-core/runtime-benchmarks",
 	"cumulus-primitives-utility/runtime-benchmarks",
@@ -182,6 +183,7 @@ runtime-benchmarks = [
 try-runtime = [
 	"cumulus-pallet-aura-ext/try-runtime",
 	"cumulus-pallet-parachain-system/try-runtime",
+	"cumulus-pallet-weight-reclaim/try-runtime",
 	"cumulus-pallet-xcm/try-runtime",
 	"cumulus-pallet-xcmp-queue/try-runtime",
 	"frame-executive/try-runtime",
diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs
index ebf8fcb33bd8fc4f9f24f8795d3f7bb27841f941..ee6b0db55b91ad02155225bf8f72f6c00123886b 100644
--- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs
@@ -92,17 +92,19 @@ pub type SignedBlock = generic::SignedBlock<Block>;
 pub type BlockId = generic::BlockId<Block>;
 
 /// The transactionExtension to the basic transaction logic.
-pub type TxExtension = (
-	frame_system::CheckNonZeroSender<Runtime>,
-	frame_system::CheckSpecVersion<Runtime>,
-	frame_system::CheckTxVersion<Runtime>,
-	frame_system::CheckGenesis<Runtime>,
-	frame_system::CheckEra<Runtime>,
-	frame_system::CheckNonce<Runtime>,
-	frame_system::CheckWeight<Runtime>,
-	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
-	cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim<Runtime>,
-);
+pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+	Runtime,
+	(
+		frame_system::CheckNonZeroSender<Runtime>,
+		frame_system::CheckSpecVersion<Runtime>,
+		frame_system::CheckTxVersion<Runtime>,
+		frame_system::CheckGenesis<Runtime>,
+		frame_system::CheckEra<Runtime>,
+		frame_system::CheckNonce<Runtime>,
+		frame_system::CheckWeight<Runtime>,
+		pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+	),
+>;
 
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
@@ -195,6 +197,10 @@ impl frame_system::Config for Runtime {
 	type MultiBlockMigrator = MultiBlockMigrations;
 }
 
+impl cumulus_pallet_weight_reclaim::Config for Runtime {
+	type WeightInfo = weights::cumulus_pallet_weight_reclaim::WeightInfo<Runtime>;
+}
+
 impl pallet_timestamp::Config for Runtime {
 	/// A timestamp: milliseconds since the unix epoch.
 	type Moment = u64;
@@ -566,6 +572,7 @@ construct_runtime!(
 		ParachainSystem: cumulus_pallet_parachain_system = 1,
 		Timestamp: pallet_timestamp = 2,
 		ParachainInfo: parachain_info = 3,
+		WeightReclaim: cumulus_pallet_weight_reclaim = 4,
 
 		// Monetary stuff.
 		Balances: pallet_balances = 10,
@@ -624,6 +631,7 @@ mod benches {
 		[pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>]
 		[pallet_xcm_benchmarks::fungible, XcmBalances]
 		[pallet_xcm_benchmarks::generic, XcmGeneric]
+		[cumulus_pallet_weight_reclaim, WeightReclaim]
 	);
 }
 
diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/cumulus_pallet_weight_reclaim.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/cumulus_pallet_weight_reclaim.rs
new file mode 100644
index 0000000000000000000000000000000000000000..fd3018ec9740111167a2e66189820aff72765ddd
--- /dev/null
+++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/cumulus_pallet_weight_reclaim.rs
@@ -0,0 +1,67 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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.
+
+// Cumulus 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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Autogenerated weights for `cumulus_pallet_weight_reclaim`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-westend-dev")`, DB CACHE: 1024
+
+// Executed Command:
+// target/production/polkadot-parachain
+// benchmark
+// pallet
+// --steps=50
+// --repeat=20
+// --extrinsic=*
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
+// --pallet=cumulus_pallet_weight_reclaim
+// --chain=people-westend-dev
+// --header=./cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/people/people-westend/src/weights/
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::Weight};
+use core::marker::PhantomData;
+
+/// Weight functions for `cumulus_pallet_weight_reclaim`.
+pub struct WeightInfo<T>(PhantomData<T>);
+impl<T: frame_system::Config> cumulus_pallet_weight_reclaim::WeightInfo for WeightInfo<T> {
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	/// Storage: `System::ExtrinsicWeightReclaimed` (r:1 w:1)
+	/// Proof: `System::ExtrinsicWeightReclaimed` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`)
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:0)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	fn storage_weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1533`
+		// Minimum execution time: 7_006_000 picoseconds.
+		Weight::from_parts(7_269_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
+}
diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/frame_system_extensions.rs
index 0a4b9e8e26812bfe82aaaccd3dc19221d7327e37..422b8566ad08a58a6f26f7c87e975d235305b3b2 100644
--- a/cumulus/parachains/runtimes/people/people-westend/src/weights/frame_system_extensions.rs
+++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/frame_system_extensions.rs
@@ -129,4 +129,18 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	/// Storage: `System::BlockWeight` (r:1 w:1)
+	/// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`)
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1533`
+		// Minimum execution time: 3_687_000 picoseconds.
+		Weight::from_parts(6_192_000, 0)
+			.saturating_add(Weight::from_parts(0, 1533))
+			.saturating_add(T::DbWeight::get().reads(2))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
 }
diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/mod.rs
index fab3c629ab3f31363233cf289c2abd1b96a59997..81906a11fe1c9ea7a9fde28cea1734bd2dd97252 100644
--- a/cumulus/parachains/runtimes/people/people-westend/src/weights/mod.rs
+++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/mod.rs
@@ -17,6 +17,7 @@
 
 pub mod block_weights;
 pub mod cumulus_pallet_parachain_system;
+pub mod cumulus_pallet_weight_reclaim;
 pub mod cumulus_pallet_xcmp_queue;
 pub mod extrinsic_weights;
 pub mod frame_system;
diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs
index 51dc95bf2c712db794a58d6bf6ee30931b9966f6..38ddf3bc1991b4e9541d111a6ec2c1fcf77dca88 100644
--- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs
+++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs
@@ -140,6 +140,7 @@ pub type TxExtension = (
 	frame_system::CheckNonce<Runtime>,
 	frame_system::CheckWeight<Runtime>,
 	pallet_asset_tx_payment::ChargeAssetTxPayment<Runtime>,
+	frame_system::WeightReclaim<Runtime>,
 );
 
 /// Unchecked extrinsic type as expected by this runtime.
diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml
index e8761445f161e1f82682b40e51e35b00d37d6ca3..826a2e9764fc1f788e9b6e62d977565d95630e00 100644
--- a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml
+++ b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml
@@ -51,12 +51,12 @@ xcm-executor = { workspace = true }
 # Cumulus
 cumulus-pallet-aura-ext = { workspace = true }
 cumulus-pallet-parachain-system = { workspace = true }
+cumulus-pallet-weight-reclaim = { workspace = true }
 cumulus-pallet-xcm = { workspace = true }
 cumulus-pallet-xcmp-queue = { workspace = true }
 cumulus-ping = { workspace = true }
 cumulus-primitives-aura = { workspace = true }
 cumulus-primitives-core = { workspace = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true }
 cumulus-primitives-utility = { workspace = true }
 pallet-message-queue = { workspace = true }
 parachain-info = { workspace = true }
@@ -72,12 +72,12 @@ std = [
 	"codec/std",
 	"cumulus-pallet-aura-ext/std",
 	"cumulus-pallet-parachain-system/std",
+	"cumulus-pallet-weight-reclaim/std",
 	"cumulus-pallet-xcm/std",
 	"cumulus-pallet-xcmp-queue/std",
 	"cumulus-ping/std",
 	"cumulus-primitives-aura/std",
 	"cumulus-primitives-core/std",
-	"cumulus-primitives-storage-weight-reclaim/std",
 	"cumulus-primitives-utility/std",
 	"frame-benchmarking?/std",
 	"frame-executive/std",
@@ -117,6 +117,7 @@ std = [
 ]
 runtime-benchmarks = [
 	"cumulus-pallet-parachain-system/runtime-benchmarks",
+	"cumulus-pallet-weight-reclaim/runtime-benchmarks",
 	"cumulus-pallet-xcmp-queue/runtime-benchmarks",
 	"cumulus-primitives-core/runtime-benchmarks",
 	"cumulus-primitives-utility/runtime-benchmarks",
diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs
index 42556e0b493cd6fb413742a67f7ce08012775213..89cd17d5450ac2af19f6c550e2a4b62abd298dbf 100644
--- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs
+++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs
@@ -226,6 +226,10 @@ impl frame_system::Config for Runtime {
 	type MaxConsumers = frame_support::traits::ConstU32<16>;
 }
 
+impl cumulus_pallet_weight_reclaim::Config for Runtime {
+	type WeightInfo = ();
+}
+
 impl pallet_timestamp::Config for Runtime {
 	/// A timestamp: milliseconds since the unix epoch.
 	type Moment = u64;
@@ -617,6 +621,7 @@ construct_runtime! {
 		Timestamp: pallet_timestamp,
 		Sudo: pallet_sudo,
 		TransactionPayment: pallet_transaction_payment,
+		WeightReclaim: cumulus_pallet_weight_reclaim,
 
 		ParachainSystem: cumulus_pallet_parachain_system = 20,
 		ParachainInfo: parachain_info = 21,
@@ -657,17 +662,20 @@ pub type SignedBlock = generic::SignedBlock<Block>;
 /// BlockId type as expected by this runtime.
 pub type BlockId = generic::BlockId<Block>;
 /// The extension to the basic transaction logic.
-pub type TxExtension = (
-	frame_system::CheckNonZeroSender<Runtime>,
-	frame_system::CheckSpecVersion<Runtime>,
-	frame_system::CheckTxVersion<Runtime>,
-	frame_system::CheckGenesis<Runtime>,
-	frame_system::CheckEra<Runtime>,
-	frame_system::CheckNonce<Runtime>,
-	frame_system::CheckWeight<Runtime>,
-	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
-	cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim<Runtime>,
-);
+pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+	Runtime,
+	(
+		frame_system::CheckNonZeroSender<Runtime>,
+		frame_system::CheckSpecVersion<Runtime>,
+		frame_system::CheckTxVersion<Runtime>,
+		frame_system::CheckGenesis<Runtime>,
+		frame_system::CheckEra<Runtime>,
+		frame_system::CheckNonce<Runtime>,
+		frame_system::CheckWeight<Runtime>,
+		pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+	),
+>;
+
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
 	generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
diff --git a/cumulus/primitives/storage-weight-reclaim/src/lib.rs b/cumulus/primitives/storage-weight-reclaim/src/lib.rs
index 5cbe662e2700924c55814680cda4d0428ad0c450..62ff60811904525c1e6af944776bfaac77b926fa 100644
--- a/cumulus/primitives/storage-weight-reclaim/src/lib.rs
+++ b/cumulus/primitives/storage-weight-reclaim/src/lib.rs
@@ -100,15 +100,30 @@ pub fn get_proof_size() -> Option<u64> {
 	(proof_size != PROOF_RECORDING_DISABLED).then_some(proof_size)
 }
 
-/// Storage weight reclaim mechanism.
-///
-/// This extension checks the size of the node-side storage proof
-/// before and after executing a given extrinsic. The difference between
-/// benchmarked and spent weight can be reclaimed.
-#[derive(Encode, Decode, Clone, Eq, PartialEq, Default, TypeInfo)]
-#[scale_info(skip_type_params(T))]
-pub struct StorageWeightReclaim<T: Config + Send + Sync>(PhantomData<T>);
+// Encapsulate into a mod so that macro generated code doesn't trigger a warning about deprecated
+// usage.
+#[allow(deprecated)]
+mod allow_deprecated {
+	use super::*;
+
+	/// Storage weight reclaim mechanism.
+	///
+	/// This extension checks the size of the node-side storage proof
+	/// before and after executing a given extrinsic. The difference between
+	/// benchmarked and spent weight can be reclaimed.
+	#[deprecated(note = "This extension doesn't provide accurate reclaim for storage intensive \
+		transaction extension pipeline; it ignores the validation and preparation of extensions prior \
+		to itself and ignores the post dispatch logic for extensions subsequent to itself, it also
+		doesn't provide weight information. \
+		Use `StorageWeightReclaim` in the `cumulus-pallet-weight-reclaim` crate")]
+	#[derive(Encode, Decode, Clone, Eq, PartialEq, Default, TypeInfo)]
+	#[scale_info(skip_type_params(T))]
+	pub struct StorageWeightReclaim<T: Config + Send + Sync>(pub(super) PhantomData<T>);
+}
+#[allow(deprecated)]
+pub use allow_deprecated::StorageWeightReclaim;
 
+#[allow(deprecated)]
 impl<T: Config + Send + Sync> StorageWeightReclaim<T> {
 	/// Create a new `StorageWeightReclaim` instance.
 	pub fn new() -> Self {
@@ -116,6 +131,7 @@ impl<T: Config + Send + Sync> StorageWeightReclaim<T> {
 	}
 }
 
+#[allow(deprecated)]
 impl<T: Config + Send + Sync> core::fmt::Debug for StorageWeightReclaim<T> {
 	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
 		let _ = write!(f, "StorageWeightReclaim");
@@ -123,6 +139,7 @@ impl<T: Config + Send + Sync> core::fmt::Debug for StorageWeightReclaim<T> {
 	}
 }
 
+#[allow(deprecated)]
 impl<T: Config + Send + Sync> TransactionExtension<T::RuntimeCall> for StorageWeightReclaim<T>
 where
 	T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
diff --git a/cumulus/primitives/storage-weight-reclaim/src/tests.rs b/cumulus/primitives/storage-weight-reclaim/src/tests.rs
index ab83762cc0db1fb0947a6414089a0e3be463adcc..379b39afee0c1b33fdcf85aaea099de3190e8387 100644
--- a/cumulus/primitives/storage-weight-reclaim/src/tests.rs
+++ b/cumulus/primitives/storage-weight-reclaim/src/tests.rs
@@ -74,6 +74,7 @@ fn get_storage_weight() -> PerDispatchClass<Weight> {
 }
 
 #[test]
+#[allow(deprecated)]
 fn basic_refund() {
 	// The real cost will be 100 bytes of storage size
 	let mut test_ext = setup_test_externalities(&[0, 100]);
@@ -109,6 +110,7 @@ fn basic_refund() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn underestimating_refund() {
 	// We fixed a bug where `pre dispatch info weight > consumed weight > post info weight`
 	// resulted in error.
@@ -149,6 +151,7 @@ fn underestimating_refund() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn sets_to_node_storage_proof_if_higher() {
 	// The storage proof reported by the proof recorder is higher than what is stored on
 	// the runtime side.
@@ -240,6 +243,7 @@ fn sets_to_node_storage_proof_if_higher() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn does_nothing_without_extension() {
 	let mut test_ext = new_test_ext();
 
@@ -274,6 +278,7 @@ fn does_nothing_without_extension() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn negative_refund_is_added_to_weight() {
 	let mut test_ext = setup_test_externalities(&[100, 300]);
 
@@ -310,6 +315,7 @@ fn negative_refund_is_added_to_weight() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn test_zero_proof_size() {
 	let mut test_ext = setup_test_externalities(&[0, 0]);
 
@@ -340,6 +346,7 @@ fn test_zero_proof_size() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn test_larger_pre_dispatch_proof_size() {
 	let mut test_ext = setup_test_externalities(&[300, 100]);
 
@@ -374,6 +381,7 @@ fn test_larger_pre_dispatch_proof_size() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn test_incorporates_check_weight_unspent_weight() {
 	let mut test_ext = setup_test_externalities(&[100, 300]);
 
@@ -415,6 +423,7 @@ fn test_incorporates_check_weight_unspent_weight() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn test_incorporates_check_weight_unspent_weight_on_negative() {
 	let mut test_ext = setup_test_externalities(&[100, 300]);
 
@@ -456,6 +465,7 @@ fn test_incorporates_check_weight_unspent_weight_on_negative() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn test_nothing_relcaimed() {
 	let mut test_ext = setup_test_externalities(&[0, 100]);
 
@@ -505,6 +515,7 @@ fn test_nothing_relcaimed() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn test_incorporates_check_weight_unspent_weight_reverse_order() {
 	let mut test_ext = setup_test_externalities(&[100, 300]);
 
@@ -548,6 +559,7 @@ fn test_incorporates_check_weight_unspent_weight_reverse_order() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn test_incorporates_check_weight_unspent_weight_on_negative_reverse_order() {
 	let mut test_ext = setup_test_externalities(&[100, 300]);
 
@@ -616,6 +628,7 @@ fn storage_size_disabled_reported_correctly() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn test_reclaim_helper() {
 	let mut test_ext = setup_test_externalities(&[1000, 1300, 1800]);
 
@@ -635,6 +648,7 @@ fn test_reclaim_helper() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn test_reclaim_helper_does_not_reclaim_negative() {
 	// Benchmarked weight does not change at all
 	let mut test_ext = setup_test_externalities(&[1000, 1300]);
@@ -669,6 +683,7 @@ fn get_benched_weight() -> Weight {
 /// Just here for doc purposes
 fn do_work() {}
 
+#[allow(deprecated)]
 #[docify::export_content(simple_reclaimer_example)]
 fn reclaim_with_weight_meter() {
 	let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(10, 10));
diff --git a/cumulus/test/client/Cargo.toml b/cumulus/test/client/Cargo.toml
index 2c72ca98f35a07a8c148559530ad2e7ee327a958..f64ee832ace3be5343a53e7b68d3634e79021bef 100644
--- a/cumulus/test/client/Cargo.toml
+++ b/cumulus/test/client/Cargo.toml
@@ -39,16 +39,17 @@ polkadot-parachain-primitives = { workspace = true, default-features = true }
 polkadot-primitives = { workspace = true, default-features = true }
 
 # Cumulus
+cumulus-pallet-weight-reclaim = { workspace = true, default-features = true }
 cumulus-primitives-core = { workspace = true, default-features = true }
 cumulus-primitives-parachain-inherent = { workspace = true, default-features = true }
 cumulus-primitives-proof-size-hostfunction = { workspace = true, default-features = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true, default-features = true }
 cumulus-test-relay-sproof-builder = { workspace = true, default-features = true }
 cumulus-test-runtime = { workspace = true }
 cumulus-test-service = { workspace = true }
 
 [features]
 runtime-benchmarks = [
+	"cumulus-pallet-weight-reclaim/runtime-benchmarks",
 	"cumulus-primitives-core/runtime-benchmarks",
 	"cumulus-test-service/runtime-benchmarks",
 	"frame-system/runtime-benchmarks",
diff --git a/cumulus/test/client/src/lib.rs b/cumulus/test/client/src/lib.rs
index 26cf02b3dea94734f2bdd58f7a16c9ef3640a3c1..7861a42372a6519f57ccf84383b8383e4cb40b85 100644
--- a/cumulus/test/client/src/lib.rs
+++ b/cumulus/test/client/src/lib.rs
@@ -143,7 +143,6 @@ pub fn generate_extrinsic_with_pair(
 		frame_system::CheckNonce::<Runtime>::from(nonce),
 		frame_system::CheckWeight::<Runtime>::new(),
 		pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
-		cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::<Runtime>::new(),
 	)
 		.into();
 
@@ -152,7 +151,7 @@ pub fn generate_extrinsic_with_pair(
 	let raw_payload = SignedPayload::from_raw(
 		function.clone(),
 		tx_ext.clone(),
-		((), VERSION.spec_version, genesis_block, current_block_hash, (), (), (), ()),
+		((), VERSION.spec_version, genesis_block, current_block_hash, (), (), ()),
 	);
 	let signature = raw_payload.using_encoded(|e| origin.sign(e));
 
diff --git a/cumulus/test/runtime/Cargo.toml b/cumulus/test/runtime/Cargo.toml
index 150838e5e96e774961a004ba699f6db10fc62f49..4cc4f483c0287903f12c76a88d9c0bacdbc5ec0e 100644
--- a/cumulus/test/runtime/Cargo.toml
+++ b/cumulus/test/runtime/Cargo.toml
@@ -44,9 +44,9 @@ sp-version = { workspace = true }
 # Cumulus
 cumulus-pallet-aura-ext = { workspace = true }
 cumulus-pallet-parachain-system = { workspace = true }
+cumulus-pallet-weight-reclaim = { workspace = true }
 cumulus-primitives-aura = { workspace = true }
 cumulus-primitives-core = { workspace = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true }
 pallet-collator-selection = { workspace = true }
 parachain-info = { workspace = true }
 
@@ -59,9 +59,9 @@ std = [
 	"codec/std",
 	"cumulus-pallet-aura-ext/std",
 	"cumulus-pallet-parachain-system/std",
+	"cumulus-pallet-weight-reclaim/std",
 	"cumulus-primitives-aura/std",
 	"cumulus-primitives-core/std",
-	"cumulus-primitives-storage-weight-reclaim/std",
 	"frame-executive/std",
 	"frame-support/std",
 	"frame-system-rpc-runtime-api/std",
diff --git a/cumulus/test/runtime/src/lib.rs b/cumulus/test/runtime/src/lib.rs
index 4abc10276af1852f8fcd272ae3ea3486355dab93..01ce3427c1f19b21663bd7b940c1fa95e212c48b 100644
--- a/cumulus/test/runtime/src/lib.rs
+++ b/cumulus/test/runtime/src/lib.rs
@@ -232,6 +232,10 @@ impl frame_system::Config for Runtime {
 	type MaxConsumers = frame_support::traits::ConstU32<16>;
 }
 
+impl cumulus_pallet_weight_reclaim::Config for Runtime {
+	type WeightInfo = ();
+}
+
 parameter_types! {
 	pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
 	pub const PotId: PalletId = PalletId(*b"PotStake");
@@ -347,6 +351,7 @@ construct_runtime! {
 		Glutton: pallet_glutton,
 		Aura: pallet_aura,
 		AuraExt: cumulus_pallet_aura_ext,
+		WeightReclaim: cumulus_pallet_weight_reclaim,
 	}
 }
 
@@ -377,16 +382,18 @@ pub type SignedBlock = generic::SignedBlock<Block>;
 /// BlockId type as expected by this runtime.
 pub type BlockId = generic::BlockId<Block>;
 /// The extension to the basic transaction logic.
-pub type TxExtension = (
-	frame_system::CheckNonZeroSender<Runtime>,
-	frame_system::CheckSpecVersion<Runtime>,
-	frame_system::CheckGenesis<Runtime>,
-	frame_system::CheckEra<Runtime>,
-	frame_system::CheckNonce<Runtime>,
-	frame_system::CheckWeight<Runtime>,
-	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
-	cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim<Runtime>,
-);
+pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+	Runtime,
+	(
+		frame_system::CheckNonZeroSender<Runtime>,
+		frame_system::CheckSpecVersion<Runtime>,
+		frame_system::CheckGenesis<Runtime>,
+		frame_system::CheckEra<Runtime>,
+		frame_system::CheckNonce<Runtime>,
+		frame_system::CheckWeight<Runtime>,
+		pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+	),
+>;
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
 	generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
diff --git a/cumulus/test/service/Cargo.toml b/cumulus/test/service/Cargo.toml
index b3d92444c7d1ff90e8ac02423c9dc2b7509cbf72..794007532621e196066ada89fdae09f9e4f09247 100644
--- a/cumulus/test/service/Cargo.toml
+++ b/cumulus/test/service/Cargo.toml
@@ -81,8 +81,8 @@ cumulus-client-parachain-inherent = { workspace = true, default-features = true
 cumulus-client-pov-recovery = { workspace = true, default-features = true }
 cumulus-client-service = { workspace = true, default-features = true }
 cumulus-pallet-parachain-system = { workspace = true }
+cumulus-pallet-weight-reclaim = { workspace = true, default-features = true }
 cumulus-primitives-core = { workspace = true, default-features = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true, default-features = true }
 cumulus-relay-chain-inprocess-interface = { workspace = true, default-features = true }
 cumulus-relay-chain-interface = { workspace = true, default-features = true }
 cumulus-relay-chain-minimal-node = { workspace = true, default-features = true }
@@ -107,6 +107,7 @@ substrate-test-utils = { workspace = true }
 [features]
 runtime-benchmarks = [
 	"cumulus-pallet-parachain-system/runtime-benchmarks",
+	"cumulus-pallet-weight-reclaim/runtime-benchmarks",
 	"cumulus-primitives-core/runtime-benchmarks",
 	"cumulus-test-client/runtime-benchmarks",
 	"frame-system/runtime-benchmarks",
diff --git a/cumulus/test/service/src/lib.rs b/cumulus/test/service/src/lib.rs
index 2c13d20333a73f007ff01ea1a037cbdc2f6082ad..f3f04cbb63835fb2dc2926b1e3b50a320e39794d 100644
--- a/cumulus/test/service/src/lib.rs
+++ b/cumulus/test/service/src/lib.rs
@@ -976,13 +976,12 @@ pub fn construct_extrinsic(
 		frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
 		frame_system::CheckWeight::<runtime::Runtime>::new(),
 		pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(tip),
-		cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::<runtime::Runtime>::new(),
 	)
 		.into();
 	let raw_payload = runtime::SignedPayload::from_raw(
 		function.clone(),
 		tx_ext.clone(),
-		((), runtime::VERSION.spec_version, genesis_block, current_block_hash, (), (), (), ()),
+		((), runtime::VERSION.spec_version, genesis_block, current_block_hash, (), (), ()),
 	);
 	let signature = raw_payload.using_encoded(|e| caller.sign(e));
 	runtime::UncheckedExtrinsic::new_signed(
diff --git a/docs/sdk/Cargo.toml b/docs/sdk/Cargo.toml
index a856e94f42b51ea3417775e6a694e688134d70ab..f526c07796ea5bd918a477b777cf30bb9b974137 100644
--- a/docs/sdk/Cargo.toml
+++ b/docs/sdk/Cargo.toml
@@ -68,8 +68,8 @@ substrate-wasm-builder = { workspace = true, default-features = true }
 cumulus-client-service = { workspace = true, default-features = true }
 cumulus-pallet-aura-ext = { workspace = true, default-features = true }
 cumulus-pallet-parachain-system = { workspace = true, default-features = true }
+cumulus-pallet-weight-reclaim = { workspace = true, default-features = true }
 cumulus-primitives-proof-size-hostfunction = { workspace = true, default-features = true }
-cumulus-primitives-storage-weight-reclaim = { workspace = true, default-features = true }
 parachain-info = { workspace = true, default-features = true }
 
 # Omni Node
diff --git a/docs/sdk/src/guides/enable_pov_reclaim.rs b/docs/sdk/src/guides/enable_pov_reclaim.rs
index cb6960b3df4ef1b5a507eb083baba808c9e99a0f..71abeacd18c8e024369159e3a10ee3f846df842b 100644
--- a/docs/sdk/src/guides/enable_pov_reclaim.rs
+++ b/docs/sdk/src/guides/enable_pov_reclaim.rs
@@ -62,8 +62,10 @@
 //!
 //! In your runtime, you will find a list of TransactionExtensions.
 //! To enable the reclaiming,
-//! add [`StorageWeightReclaim`](cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim)
-//! to that list. For maximum efficiency, make sure that `StorageWeightReclaim` is last in the list.
+//! set [`StorageWeightReclaim`](cumulus_pallet_weight_reclaim::StorageWeightReclaim)
+//! as a warpper of that list.
+//! It is necessary that this extension wraps all the other transaction extensions in order to catch
+//! the whole PoV size of the transactions.
 //! The extension will check the size of the storage proof before and after an extrinsic execution.
 //! It reclaims the difference between the calculated size and the benchmarked size.
 #![doc = docify::embed!("../../templates/parachain/runtime/src/lib.rs", template_signed_extra)]
diff --git a/docs/sdk/src/reference_docs/transaction_extensions.rs b/docs/sdk/src/reference_docs/transaction_extensions.rs
index 0f8198e8372d35975f69d811d545bf20b900407f..fe213458b25c0400a8aef014398fa6d04b7a2f2b 100644
--- a/docs/sdk/src/reference_docs/transaction_extensions.rs
+++ b/docs/sdk/src/reference_docs/transaction_extensions.rs
@@ -47,9 +47,11 @@
 //!   to include the so-called metadata hash. This is required by chains to support the generic
 //!   Ledger application and other similar offline wallets.
 //!
-//! - [`StorageWeightReclaim`](cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim): A
-//!   transaction extension for parachains that reclaims unused storage weight after executing a
-//!   transaction.
+//! - [`WeightReclaim`](frame_system::WeightReclaim): A transaction extension for the relay chain
+//!   that reclaims unused weight after executing a transaction.
+//!
+//! - [`StorageWeightReclaim`](cumulus_pallet_weight_reclaim::StorageWeightReclaim): A transaction
+//!   extension for parachains that reclaims unused storage weight after executing a transaction.
 //!
 //! For more information about these extensions, follow the link to the type documentation.
 //!
diff --git a/polkadot/node/service/src/benchmarking.rs b/polkadot/node/service/src/benchmarking.rs
index 0cf16edc03cc9c79f6163d3c1249be6a65fe2605..5b814a22d2f877d2772790188ee81ba8877ae1cb 100644
--- a/polkadot/node/service/src/benchmarking.rs
+++ b/polkadot/node/service/src/benchmarking.rs
@@ -155,6 +155,7 @@ fn westend_sign_call(
 		frame_system::CheckWeight::<runtime::Runtime>::new(),
 		pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
 		frame_metadata_hash_extension::CheckMetadataHash::<runtime::Runtime>::new(false),
+		frame_system::WeightReclaim::<runtime::Runtime>::new(),
 	)
 		.into();
 
@@ -171,6 +172,7 @@ fn westend_sign_call(
 			(),
 			(),
 			None,
+			(),
 		),
 	);
 
@@ -210,6 +212,7 @@ fn rococo_sign_call(
 		frame_system::CheckWeight::<runtime::Runtime>::new(),
 		pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
 		frame_metadata_hash_extension::CheckMetadataHash::<runtime::Runtime>::new(false),
+		frame_system::WeightReclaim::<runtime::Runtime>::new(),
 	)
 		.into();
 
@@ -226,6 +229,7 @@ fn rococo_sign_call(
 			(),
 			(),
 			None,
+			(),
 		),
 	);
 
diff --git a/polkadot/node/test/service/src/lib.rs b/polkadot/node/test/service/src/lib.rs
index f34bb62a7cf082aa5b51e9f027bbabd7dcb2eaa2..75fd0d9af3013c944a7feaf85a884ba212f42f23 100644
--- a/polkadot/node/test/service/src/lib.rs
+++ b/polkadot/node/test/service/src/lib.rs
@@ -423,6 +423,7 @@ pub fn construct_extrinsic(
 		frame_system::CheckNonce::<Runtime>::from(nonce),
 		frame_system::CheckWeight::<Runtime>::new(),
 		pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
+		frame_system::WeightReclaim::<Runtime>::new(),
 	)
 		.into();
 	let raw_payload = SignedPayload::from_raw(
@@ -437,6 +438,7 @@ pub fn construct_extrinsic(
 			(),
 			(),
 			(),
+			(),
 		),
 	);
 	let signature = raw_payload.using_encoded(|e| caller.sign(e));
diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs
index 4034f8bc1431a4b3d7f4ddad6084fbc2252add3e..cab4394eb5a8db1313550a7364704114211aab71 100644
--- a/polkadot/runtime/rococo/src/lib.rs
+++ b/polkadot/runtime/rococo/src/lib.rs
@@ -674,6 +674,7 @@ where
 			frame_system::CheckWeight::<Runtime>::new(),
 			pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
 			frame_metadata_hash_extension::CheckMetadataHash::new(true),
+			frame_system::WeightReclaim::<Runtime>::new(),
 		)
 			.into();
 		let raw_payload = SignedPayload::new(call, tx_ext)
@@ -1617,6 +1618,7 @@ pub type TxExtension = (
 	frame_system::CheckWeight<Runtime>,
 	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
 	frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+	frame_system::WeightReclaim<Runtime>,
 );
 
 /// Unchecked extrinsic type as expected by this runtime.
diff --git a/polkadot/runtime/rococo/src/weights/frame_system_extensions.rs b/polkadot/runtime/rococo/src/weights/frame_system_extensions.rs
index 99dac1ba75f06f8d8e5e9b835a48f3b5f2974d90..88596a37cc01bbb00d630e84d761e35419b51369 100644
--- a/polkadot/runtime/rococo/src/weights/frame_system_extensions.rs
+++ b/polkadot/runtime/rococo/src/weights/frame_system_extensions.rs
@@ -17,25 +17,23 @@
 //! Autogenerated weights for `frame_system_extensions`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024
 
 // Executed Command:
-// ./target/production/polkadot
+// target/production/polkadot
 // benchmark
 // pallet
-// --chain=rococo-dev
 // --steps=50
 // --repeat=20
-// --no-storage-info
-// --no-median-slopes
-// --no-min-squares
-// --pallet=frame_system_extensions
 // --extrinsic=*
-// --execution=wasm
 // --wasm-execution=compiled
+// --heap-pages=4096
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
+// --pallet=frame_system_extensions
+// --chain=rococo-dev
 // --header=./polkadot/file_header.txt
 // --output=./polkadot/runtime/rococo/src/weights/
 
@@ -50,45 +48,36 @@ use core::marker::PhantomData;
 /// Weight functions for `frame_system_extensions`.
 pub struct WeightInfo<T>(PhantomData<T>);
 impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<T> {
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_genesis() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `54`
-		//  Estimated: `3509`
-		// Minimum execution time: 3_262_000 picoseconds.
-		Weight::from_parts(3_497_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Measured:  `30`
+		//  Estimated: `0`
+		// Minimum execution time: 3_528_000 picoseconds.
+		Weight::from_parts(3_657_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_mortality_mortal_transaction() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `92`
-		//  Estimated: `3509`
-		// Minimum execution time: 5_416_000 picoseconds.
-		Weight::from_parts(5_690_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Measured:  `68`
+		//  Estimated: `0`
+		// Minimum execution time: 6_456_000 picoseconds.
+		Weight::from_parts(6_706_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_mortality_immortal_transaction() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `92`
-		//  Estimated: `3509`
-		// Minimum execution time: 5_416_000 picoseconds.
-		Weight::from_parts(5_690_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Measured:  `68`
+		//  Estimated: `0`
+		// Minimum execution time: 6_210_000 picoseconds.
+		Weight::from_parts(6_581_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
 	fn check_non_zero_sender() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 471_000 picoseconds.
-		Weight::from_parts(552_000, 0)
+		// Minimum execution time: 529_000 picoseconds.
+		Weight::from_parts(561_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	/// Storage: `System::Account` (r:1 w:1)
@@ -97,8 +86,8 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `101`
 		//  Estimated: `3593`
-		// Minimum execution time: 4_847_000 picoseconds.
-		Weight::from_parts(5_091_000, 0)
+		// Minimum execution time: 6_935_000 picoseconds.
+		Weight::from_parts(7_264_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -107,28 +96,32 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 388_000 picoseconds.
-		Weight::from_parts(421_000, 0)
+		// Minimum execution time: 452_000 picoseconds.
+		Weight::from_parts(474_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	fn check_tx_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 378_000 picoseconds.
-		Weight::from_parts(440_000, 0)
+		// Minimum execution time: 422_000 picoseconds.
+		Weight::from_parts(460_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
-	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
-	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
 	fn check_weight() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `24`
-		//  Estimated: `1489`
-		// Minimum execution time: 3_402_000 picoseconds.
-		Weight::from_parts(3_627_000, 0)
-			.saturating_add(Weight::from_parts(0, 1489))
-			.saturating_add(T::DbWeight::get().reads(1))
-			.saturating_add(T::DbWeight::get().writes(1))
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 3_632_000 picoseconds.
+		Weight::from_parts(3_784_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
+	}
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 2_209_000 picoseconds.
+		Weight::from_parts(2_335_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
 }
diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs
index d4031f7ac57ae0b5fac0884405e709a8409e176d..82564d5c278caa4f391d87f185ad9c6c3a35626b 100644
--- a/polkadot/runtime/test-runtime/src/lib.rs
+++ b/polkadot/runtime/test-runtime/src/lib.rs
@@ -443,6 +443,7 @@ where
 			frame_system::CheckNonce::<Runtime>::from(nonce),
 			frame_system::CheckWeight::<Runtime>::new(),
 			pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
+			frame_system::WeightReclaim::<Runtime>::new(),
 		)
 			.into();
 		let raw_payload = SignedPayload::new(call, tx_ext)
@@ -834,6 +835,7 @@ pub type TxExtension = (
 	frame_system::CheckNonce<Runtime>,
 	frame_system::CheckWeight<Runtime>,
 	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+	frame_system::WeightReclaim<Runtime>,
 );
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs
index cd8eb4d2505a48ba7266f063d148cde7a8ba8280..166f3fc42eefe6d3937a23ccce824680158b5060 100644
--- a/polkadot/runtime/westend/src/lib.rs
+++ b/polkadot/runtime/westend/src/lib.rs
@@ -923,6 +923,7 @@ where
 			frame_system::CheckWeight::<Runtime>::new(),
 			pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
 			frame_metadata_hash_extension::CheckMetadataHash::<Runtime>::new(true),
+			frame_system::WeightReclaim::<Runtime>::new(),
 		)
 			.into();
 		let raw_payload = SignedPayload::new(call, tx_ext)
@@ -1814,6 +1815,7 @@ pub type TxExtension = (
 	frame_system::CheckWeight<Runtime>,
 	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
 	frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+	frame_system::WeightReclaim<Runtime>,
 );
 
 parameter_types! {
diff --git a/polkadot/runtime/westend/src/weights/frame_system_extensions.rs b/polkadot/runtime/westend/src/weights/frame_system_extensions.rs
index 048f23fbcb91329eadfd721dd2ae63e1f218a89e..75f4f6d00b562dc589173c003b0e325e77f1b65f 100644
--- a/polkadot/runtime/westend/src/weights/frame_system_extensions.rs
+++ b/polkadot/runtime/westend/src/weights/frame_system_extensions.rs
@@ -17,24 +17,25 @@
 //! Autogenerated weights for `frame_system_extensions`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-09-12, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2024-12-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor`
+//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024
 
 // Executed Command:
-// ./target/debug/polkadot
+// target/production/polkadot
 // benchmark
 // pallet
-// --steps=2
-// --repeat=2
+// --steps=50
+// --repeat=20
 // --extrinsic=*
 // --wasm-execution=compiled
 // --heap-pages=4096
-// --pallet=frame-system-extensions
+// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
+// --pallet=frame_system_extensions
 // --chain=westend-dev
-// --output=./polkadot/runtime/westend/src/weights/
 // --header=./polkadot/file_header.txt
+// --output=./polkadot/runtime/westend/src/weights/
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
@@ -47,45 +48,36 @@ use core::marker::PhantomData;
 /// Weight functions for `frame_system_extensions`.
 pub struct WeightInfo<T>(PhantomData<T>);
 impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<T> {
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_genesis() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `54`
-		//  Estimated: `3509`
-		// Minimum execution time: 75_764_000 picoseconds.
-		Weight::from_parts(85_402_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Measured:  `30`
+		//  Estimated: `0`
+		// Minimum execution time: 3_357_000 picoseconds.
+		Weight::from_parts(3_484_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_mortality_mortal_transaction() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `92`
-		//  Estimated: `3509`
-		// Minimum execution time: 118_233_000 picoseconds.
-		Weight::from_parts(126_539_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Measured:  `68`
+		//  Estimated: `0`
+		// Minimum execution time: 6_242_000 picoseconds.
+		Weight::from_parts(6_566_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
-	/// Storage: `System::BlockHash` (r:1 w:0)
-	/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
 	fn check_mortality_immortal_transaction() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `92`
-		//  Estimated: `3509`
-		// Minimum execution time: 118_233_000 picoseconds.
-		Weight::from_parts(126_539_000, 0)
-			.saturating_add(Weight::from_parts(0, 3509))
-			.saturating_add(T::DbWeight::get().reads(1))
+		//  Measured:  `68`
+		//  Estimated: `0`
+		// Minimum execution time: 6_268_000 picoseconds.
+		Weight::from_parts(6_631_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
 	fn check_non_zero_sender() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 7_885_000 picoseconds.
-		Weight::from_parts(12_784_000, 0)
+		// Minimum execution time: 567_000 picoseconds.
+		Weight::from_parts(617_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	/// Storage: `System::Account` (r:1 w:1)
@@ -94,8 +86,8 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `101`
 		//  Estimated: `3593`
-		// Minimum execution time: 104_237_000 picoseconds.
-		Weight::from_parts(110_910_000, 0)
+		// Minimum execution time: 6_990_000 picoseconds.
+		Weight::from_parts(7_343_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -104,28 +96,32 @@ impl<T: frame_system::Config> frame_system::ExtensionsWeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 6_141_000 picoseconds.
-		Weight::from_parts(11_502_000, 0)
+		// Minimum execution time: 422_000 picoseconds.
+		Weight::from_parts(475_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
 	fn check_tx_version() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 6_192_000 picoseconds.
-		Weight::from_parts(11_481_000, 0)
+		// Minimum execution time: 434_000 picoseconds.
+		Weight::from_parts(519_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 	}
-	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
-	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
 	fn check_weight() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `24`
-		//  Estimated: `1489`
-		// Minimum execution time: 87_616_000 picoseconds.
-		Weight::from_parts(93_607_000, 0)
-			.saturating_add(Weight::from_parts(0, 1489))
-			.saturating_add(T::DbWeight::get().reads(1))
-			.saturating_add(T::DbWeight::get().writes(1))
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 3_524_000 picoseconds.
+		Weight::from_parts(3_706_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
+	}
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 2_216_000 picoseconds.
+		Weight::from_parts(2_337_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
 	}
 }
diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs
index 26ea226313f068d9203bd8057790d3665bae2d11..6ebf6476f7e570f15a37908c40ea53c9810b2875 100644
--- a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs
+++ b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs
@@ -37,6 +37,7 @@ pub type TxExtension = (
 	frame_system::CheckMortality<Test>,
 	frame_system::CheckNonce<Test>,
 	frame_system::CheckWeight<Test>,
+	frame_system::WeightReclaim<Test>,
 );
 pub type Address = sp_runtime::MultiAddress<AccountId, AccountIndex>;
 pub type UncheckedExtrinsic =
diff --git a/polkadot/xcm/xcm-runtime-apis/tests/mock.rs b/polkadot/xcm/xcm-runtime-apis/tests/mock.rs
index fb5d1ae7c0e5ad92a77f201869ac9b4e5da09698..56a77094f177433cf23f32bf943ba2257f932df1 100644
--- a/polkadot/xcm/xcm-runtime-apis/tests/mock.rs
+++ b/polkadot/xcm/xcm-runtime-apis/tests/mock.rs
@@ -60,7 +60,8 @@ construct_runtime! {
 	}
 }
 
-pub type TxExtension = (frame_system::CheckWeight<TestRuntime>,);
+pub type TxExtension =
+	(frame_system::CheckWeight<TestRuntime>, frame_system::WeightReclaim<TestRuntime>);
 
 // we only use the hash type from this, so using the mock should be fine.
 pub(crate) type Extrinsic = sp_runtime::generic::UncheckedExtrinsic<
diff --git a/prdoc/pr_6140.prdoc b/prdoc/pr_6140.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..7e2bd3802cd7cc8b25abfefb1d98d4528c5c0b06
--- /dev/null
+++ b/prdoc/pr_6140.prdoc
@@ -0,0 +1,95 @@
+title: Accurate weight reclaim with frame_system::WeightReclaim and cumulus `StorageWeightReclaim` transaction extensions
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      Since the introduction of transaction extension, the transaction extension weight is no longer part of base extrinsic weight. As a consequence some weight of transaction extensions are missed when calculating post dispatch weight and reclaiming unused block weight.
+
+      For solo chains, in order to reclaim the weight accurately `frame_system::WeightReclaim` transaction extension must be used at the end of the transaction extension pipeline.
+
+      For para chains `StorageWeightReclaim` in `cumulus-primitives-storage-weight-reclaim` is deprecated.
+      A new transaction extension `StorageWeightReclaim` in `cumulus-pallet-weight-reclaim` is introduced.
+      `StorageWeightReclaim` is meant to be used as a wrapping of the whole transaction extension pipeline, and will take into account all proof size accurately.
+
+      The new wrapping transaction extension is used like this:
+      ```rust
+      /// The TransactionExtension to the basic transaction logic.
+      pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+             Runtime,
+             (
+                     frame_system::CheckNonZeroSender<Runtime>,
+                     frame_system::CheckSpecVersion<Runtime>,
+                     frame_system::CheckTxVersion<Runtime>,
+                     frame_system::CheckGenesis<Runtime>,
+                     frame_system::CheckEra<Runtime>,
+                     frame_system::CheckNonce<Runtime>,
+                     pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+                     BridgeRejectObsoleteHeadersAndMessages,
+                     (bridge_to_rococo_config::OnBridgeHubWestendRefundBridgeHubRococoMessages,),
+                     frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+                     frame_system::CheckWeight<Runtime>,
+             ),
+      >;
+      ```
+
+      NOTE: prior to transaction extension, `StorageWeightReclaim` also missed the some proof size used by other transaction extension prior to itself. This is also fixed by the wrapping `StorageWeightReclaim`.
+
+crates:
+- name: cumulus-primitives-storage-weight-reclaim
+  bump: minor
+- name: sp-runtime
+  bump: patch
+- name: polkadot-sdk
+  bump: minor
+- name: asset-hub-rococo-runtime
+  bump: major
+- name: asset-hub-westend-runtime
+  bump: major
+- name: bridge-hub-rococo-runtime
+  bump: major
+- name: bridge-hub-westend-runtime
+  bump: major
+- name: collectives-westend-runtime
+  bump: major
+- name: coretime-rococo-runtime
+  bump: major
+- name: coretime-westend-runtime
+  bump: major
+- name: people-rococo-runtime
+  bump: major
+- name: people-westend-runtime
+  bump: major
+- name: contracts-rococo-runtime
+  bump: major
+- name: frame-support
+  bump: minor
+- name: frame-executive
+  bump: patch
+- name: frame-system
+  bump: major
+- name: staging-xcm-builder
+  bump: patch
+- name: xcm-runtime-apis
+  bump: patch
+- name: cumulus-pallet-weight-reclaim
+  bump: major
+- name: polkadot-service
+  bump: major
+- name: westend-runtime
+  bump: major
+- name: frame-metadata-hash-extension
+  bump: patch
+- name: frame-system-benchmarking
+  bump: major
+- name: polkadot-sdk-frame
+  bump: major
+- name: rococo-runtime
+  bump: major
+- name: cumulus-pov-validator
+  bump: patch
+- name: penpal-runtime
+  bump: major
+- name: glutton-westend-runtime
+  bump: major
+- name: rococo-parachain-runtime
+  bump: major
diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs
index 5f6806c235f6f9c1753df533c9c111bf6ca85f44..e531097dbb5e8adf16d7e8f7de60cba980fe27be 100644
--- a/substrate/bin/node/cli/src/service.rs
+++ b/substrate/bin/node/cli/src/service.rs
@@ -138,6 +138,7 @@ pub fn create_extrinsic(
 				>::from(tip, None),
 			),
 			frame_metadata_hash_extension::CheckMetadataHash::new(false),
+			frame_system::WeightReclaim::<kitchensink_runtime::Runtime>::new(),
 		);
 
 	let raw_payload = kitchensink_runtime::SignedPayload::from_raw(
@@ -153,6 +154,7 @@ pub fn create_extrinsic(
 			(),
 			(),
 			None,
+			(),
 		),
 	);
 	let signature = raw_payload.using_encoded(|e| sender.sign(e));
@@ -1060,6 +1062,7 @@ mod tests {
 				let tx_payment = pallet_skip_feeless_payment::SkipCheckIfFeeless::from(
 					pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::from(0, None),
 				);
+				let weight_reclaim = frame_system::WeightReclaim::new();
 				let metadata_hash = frame_metadata_hash_extension::CheckMetadataHash::new(false);
 				let tx_ext: TxExtension = (
 					check_non_zero_sender,
@@ -1071,6 +1074,7 @@ mod tests {
 					check_weight,
 					tx_payment,
 					metadata_hash,
+					weight_reclaim,
 				);
 				let raw_payload = SignedPayload::from_raw(
 					function,
@@ -1085,6 +1089,7 @@ mod tests {
 						(),
 						(),
 						None,
+						(),
 					),
 				);
 				let signature = raw_payload.using_encoded(|payload| signer.sign(payload));
diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index 45ae378cc00e22ede350aff7d449d82dafd0f7cc..93b134e8165ffc93561034325fbd88dd752b39b4 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -1532,6 +1532,7 @@ where
 				),
 			),
 			frame_metadata_hash_extension::CheckMetadataHash::new(false),
+			frame_system::WeightReclaim::<Runtime>::new(),
 		);
 
 		let raw_payload = SignedPayload::new(call, tx_ext)
@@ -2674,6 +2675,7 @@ pub type TxExtension = (
 		pallet_asset_conversion_tx_payment::ChargeAssetTxPayment<Runtime>,
 	>,
 	frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+	frame_system::WeightReclaim<Runtime>,
 );
 
 #[derive(Clone, PartialEq, Eq, Debug)]
@@ -2695,6 +2697,7 @@ impl EthExtra for EthExtraImpl {
 			pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::<Runtime>::from(tip, None)
 				.into(),
 			frame_metadata_hash_extension::CheckMetadataHash::<Runtime>::new(false),
+			frame_system::WeightReclaim::<Runtime>::new(),
 		)
 	}
 }
diff --git a/substrate/bin/node/testing/src/keyring.rs b/substrate/bin/node/testing/src/keyring.rs
index e5b0299f01a83b2756e50aae44fc781aa35c6ee3..08d6ad6dcc35d95740f2ac684ed5c6265d023c6a 100644
--- a/substrate/bin/node/testing/src/keyring.rs
+++ b/substrate/bin/node/testing/src/keyring.rs
@@ -86,6 +86,7 @@ pub fn tx_ext(nonce: Nonce, extra_fee: Balance) -> TxExtension {
 			pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::from(extra_fee, None),
 		),
 		frame_metadata_hash_extension::CheckMetadataHash::new(false),
+		frame_system::WeightReclaim::new(),
 	)
 }
 
diff --git a/substrate/frame/executive/src/tests.rs b/substrate/frame/executive/src/tests.rs
index 3841b010325b28c832ed197ac55c479c724c9afc..882d875f3d804901d09be10d9a4d186501c568fb 100644
--- a/substrate/frame/executive/src/tests.rs
+++ b/substrate/frame/executive/src/tests.rs
@@ -335,6 +335,9 @@ impl frame_system::ExtensionsWeightInfo for MockExtensionsWeights {
 	fn check_weight() -> Weight {
 		Weight::from_parts(10, 0)
 	}
+	fn weight_reclaim() -> Weight {
+		Weight::zero()
+	}
 }
 
 #[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
@@ -452,6 +455,7 @@ type TxExtension = (
 	frame_system::CheckNonce<Runtime>,
 	frame_system::CheckWeight<Runtime>,
 	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+	frame_system::WeightReclaim<Runtime>,
 );
 type UncheckedXt = sp_runtime::generic::UncheckedExtrinsic<
 	u64,
@@ -560,6 +564,7 @@ fn tx_ext(nonce: u64, fee: Balance) -> TxExtension {
 		frame_system::CheckNonce::from(nonce),
 		frame_system::CheckWeight::new(),
 		pallet_transaction_payment::ChargeTransactionPayment::from(fee),
+		frame_system::WeightReclaim::new(),
 	)
 		.into()
 }
diff --git a/substrate/frame/metadata-hash-extension/src/tests.rs b/substrate/frame/metadata-hash-extension/src/tests.rs
index 11a3345ee15ce2b7217f6070704f6bfbdabf78b9..7a6966f4629027dfe25cc65a866b415a3d9d45ea 100644
--- a/substrate/frame/metadata-hash-extension/src/tests.rs
+++ b/substrate/frame/metadata-hash-extension/src/tests.rs
@@ -144,6 +144,7 @@ mod docs {
 			// Add the `CheckMetadataHash` extension.
 			// The position in this list is not important, so we could also add it to beginning.
 			frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+			frame_system::WeightReclaim<Runtime>,
 		);
 
 		/// In your runtime this will be your real address type.
diff --git a/substrate/frame/src/lib.rs b/substrate/frame/src/lib.rs
index b3e340cbcbffaece0002437c314ac64cc75a140b..b0338b682314650ebfcbe5cf0a26a5296815c1de 100644
--- a/substrate/frame/src/lib.rs
+++ b/substrate/frame/src/lib.rs
@@ -495,6 +495,7 @@ pub mod runtime {
 			frame_system::CheckEra<T>,
 			frame_system::CheckNonce<T>,
 			frame_system::CheckWeight<T>,
+			frame_system::WeightReclaim<T>,
 		);
 	}
 
diff --git a/substrate/frame/support/src/dispatch.rs b/substrate/frame/support/src/dispatch.rs
index 483a3dce77f6a8b510f9c36b7d74805103ae8d8a..990996830030ce1a12ea165ffbe77052661e6edc 100644
--- a/substrate/frame/support/src/dispatch.rs
+++ b/substrate/frame/support/src/dispatch.rs
@@ -308,6 +308,19 @@ impl PostDispatchInfo {
 	/// Calculate how much weight was actually spent by the `Dispatchable`.
 	pub fn calc_actual_weight(&self, info: &DispatchInfo) -> Weight {
 		if let Some(actual_weight) = self.actual_weight {
+			let info_total_weight = info.total_weight();
+			if actual_weight.any_gt(info_total_weight) {
+				log::error!(
+					target: crate::LOG_TARGET,
+					"Post dispatch weight is greater than pre dispatch weight. \
+					Pre dispatch weight may underestimating the actual weight. \
+					Greater post dispatch weight components are ignored.
+					Pre dispatch weight: {:?},
+					Post dispatch weight: {:?}",
+					actual_weight,
+					info_total_weight,
+				);
+			}
 			actual_weight.min(info.total_weight())
 		} else {
 			info.total_weight()
diff --git a/substrate/frame/system/benchmarking/src/extensions.rs b/substrate/frame/system/benchmarking/src/extensions.rs
index 01e4687bc4bceecd21f9d9c097e65db4f7305105..25d6ea03557887d1554a2a417d781aaa2c79bee7 100644
--- a/substrate/frame/system/benchmarking/src/extensions.rs
+++ b/substrate/frame/system/benchmarking/src/extensions.rs
@@ -29,7 +29,7 @@ use frame_support::{
 use frame_system::{
 	pallet_prelude::*, CheckGenesis, CheckMortality, CheckNonZeroSender, CheckNonce,
 	CheckSpecVersion, CheckTxVersion, CheckWeight, Config, ExtensionsWeightInfo, Pallet as System,
-	RawOrigin,
+	RawOrigin, WeightReclaim,
 };
 use sp_runtime::{
 	generic::Era,
@@ -254,5 +254,49 @@ mod benchmarks {
 		Ok(())
 	}
 
+	#[benchmark]
+	fn weight_reclaim() -> Result<(), BenchmarkError> {
+		let caller = account("caller", 0, 0);
+		let base_extrinsic = <T as frame_system::Config>::BlockWeights::get()
+			.get(DispatchClass::Normal)
+			.base_extrinsic;
+		let extension_weight = <T as frame_system::Config>::ExtensionsWeightInfo::weight_reclaim();
+		let info = DispatchInfo {
+			call_weight: Weight::from_parts(base_extrinsic.ref_time() * 5, 0),
+			extension_weight,
+			class: DispatchClass::Normal,
+			..Default::default()
+		};
+		let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into();
+		let post_info = PostDispatchInfo {
+			actual_weight: Some(Weight::from_parts(base_extrinsic.ref_time() * 2, 0)),
+			pays_fee: Default::default(),
+		};
+		let len = 0_usize;
+		let ext = WeightReclaim::<T>::new();
+
+		let initial_block_weight = Weight::from_parts(base_extrinsic.ref_time() * 2, 0);
+		frame_system::BlockWeight::<T>::mutate(|current_weight| {
+			current_weight.set(Weight::zero(), DispatchClass::Mandatory);
+			current_weight.set(initial_block_weight, DispatchClass::Normal);
+			current_weight.accrue(base_extrinsic + info.total_weight(), DispatchClass::Normal);
+		});
+
+		#[block]
+		{
+			ext.test_run(RawOrigin::Signed(caller).into(), &call, &info, len, 0, |_| Ok(post_info))
+				.unwrap()
+				.unwrap();
+		}
+
+		assert_eq!(
+			System::<T>::block_weight().total(),
+			initial_block_weight +
+				base_extrinsic +
+				post_info.actual_weight.unwrap().saturating_add(extension_weight),
+		);
+		Ok(())
+	}
+
 	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test,);
 }
diff --git a/substrate/frame/system/benchmarking/src/mock.rs b/substrate/frame/system/benchmarking/src/mock.rs
index 6b126619ce5bfab57882868e19c936cbdec0eb27..61b5b885ec623f190c4bc618e033517b1e74f2ac 100644
--- a/substrate/frame/system/benchmarking/src/mock.rs
+++ b/substrate/frame/system/benchmarking/src/mock.rs
@@ -65,6 +65,10 @@ impl frame_system::ExtensionsWeightInfo for MockWeights {
 	fn check_weight() -> Weight {
 		Weight::from_parts(10, 0)
 	}
+
+	fn weight_reclaim() -> Weight {
+		Weight::from_parts(10, 0)
+	}
 }
 
 #[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
diff --git a/substrate/frame/system/src/extensions/check_weight.rs b/substrate/frame/system/src/extensions/check_weight.rs
index ee91478b90f314ddce0c7afffe5ab292abebc2ce..de0303defd0c3e8c9fc502d3017127e1c08c54ac 100644
--- a/substrate/frame/system/src/extensions/check_weight.rs
+++ b/substrate/frame/system/src/extensions/check_weight.rs
@@ -135,30 +135,12 @@ where
 		Ok(())
 	}
 
+	#[deprecated(note = "Use `frame_system::Pallet::reclaim_weight` instead.")]
 	pub fn do_post_dispatch(
 		info: &DispatchInfoOf<T::RuntimeCall>,
 		post_info: &PostDispatchInfoOf<T::RuntimeCall>,
 	) -> Result<(), TransactionValidityError> {
-		let unspent = post_info.calc_unspent(info);
-		if unspent.any_gt(Weight::zero()) {
-			crate::BlockWeight::<T>::mutate(|current_weight| {
-				current_weight.reduce(unspent, info.class);
-			})
-		}
-
-		log::trace!(
-			target: LOG_TARGET,
-			"Used block weight: {:?}",
-			crate::BlockWeight::<T>::get(),
-		);
-
-		log::trace!(
-			target: LOG_TARGET,
-			"Used block length: {:?}",
-			Pallet::<T>::all_extrinsics_len(),
-		);
-
-		Ok(())
+		crate::Pallet::<T>::reclaim_weight(info, post_info)
 	}
 }
 
@@ -279,8 +261,7 @@ where
 		_len: usize,
 		_result: &DispatchResult,
 	) -> Result<Weight, TransactionValidityError> {
-		Self::do_post_dispatch(info, post_info)?;
-		Ok(Weight::zero())
+		crate::Pallet::<T>::reclaim_weight(info, post_info).map(|()| Weight::zero())
 	}
 
 	fn bare_validate(
@@ -306,7 +287,7 @@ where
 		_len: usize,
 		_result: &DispatchResult,
 	) -> Result<(), TransactionValidityError> {
-		Self::do_post_dispatch(info, post_info)
+		crate::Pallet::<T>::reclaim_weight(info, post_info)
 	}
 }
 
@@ -744,6 +725,121 @@ mod tests {
 		})
 	}
 
+	#[test]
+	fn extrinsic_already_refunded_more_precisely() {
+		new_test_ext().execute_with(|| {
+			// This is half of the max block weight
+			let info =
+				DispatchInfo { call_weight: Weight::from_parts(512, 0), ..Default::default() };
+			let post_info = PostDispatchInfo {
+				actual_weight: Some(Weight::from_parts(128, 0)),
+				pays_fee: Default::default(),
+			};
+			let prior_block_weight = Weight::from_parts(64, 0);
+			let accurate_refund = Weight::from_parts(510, 0);
+			let len = 0_usize;
+			let base_extrinsic = block_weights().get(DispatchClass::Normal).base_extrinsic;
+
+			// Set initial info
+			BlockWeight::<Test>::mutate(|current_weight| {
+				current_weight.set(Weight::zero(), DispatchClass::Mandatory);
+				current_weight.set(prior_block_weight, DispatchClass::Normal);
+			});
+
+			// Validate and prepare extrinsic
+			let pre = CheckWeight::<Test>(PhantomData)
+				.validate_and_prepare(Some(1).into(), CALL, &info, len, 0)
+				.unwrap()
+				.0;
+
+			assert_eq!(
+				BlockWeight::<Test>::get().total(),
+				info.total_weight() + prior_block_weight + base_extrinsic
+			);
+
+			// Refund more accurately than the benchmark
+			BlockWeight::<Test>::mutate(|current_weight| {
+				current_weight.reduce(accurate_refund, DispatchClass::Normal);
+			});
+			crate::ExtrinsicWeightReclaimed::<Test>::put(accurate_refund);
+
+			// Do the post dispatch
+			assert_ok!(CheckWeight::<Test>::post_dispatch_details(
+				pre,
+				&info,
+				&post_info,
+				len,
+				&Ok(())
+			));
+
+			// Ensure the accurate refund is used
+			assert_eq!(crate::ExtrinsicWeightReclaimed::<Test>::get(), accurate_refund);
+			assert_eq!(
+				BlockWeight::<Test>::get().total(),
+				info.total_weight() - accurate_refund + prior_block_weight + base_extrinsic
+			);
+		})
+	}
+
+	#[test]
+	fn extrinsic_already_refunded_less_precisely() {
+		new_test_ext().execute_with(|| {
+			// This is half of the max block weight
+			let info =
+				DispatchInfo { call_weight: Weight::from_parts(512, 0), ..Default::default() };
+			let post_info = PostDispatchInfo {
+				actual_weight: Some(Weight::from_parts(128, 0)),
+				pays_fee: Default::default(),
+			};
+			let prior_block_weight = Weight::from_parts(64, 0);
+			let inaccurate_refund = Weight::from_parts(110, 0);
+			let len = 0_usize;
+			let base_extrinsic = block_weights().get(DispatchClass::Normal).base_extrinsic;
+
+			// Set initial info
+			BlockWeight::<Test>::mutate(|current_weight| {
+				current_weight.set(Weight::zero(), DispatchClass::Mandatory);
+				current_weight.set(prior_block_weight, DispatchClass::Normal);
+			});
+
+			// Validate and prepare extrinsic
+			let pre = CheckWeight::<Test>(PhantomData)
+				.validate_and_prepare(Some(1).into(), CALL, &info, len, 0)
+				.unwrap()
+				.0;
+
+			assert_eq!(
+				BlockWeight::<Test>::get().total(),
+				info.total_weight() + prior_block_weight + base_extrinsic
+			);
+
+			// Refund less accurately than the benchmark
+			BlockWeight::<Test>::mutate(|current_weight| {
+				current_weight.reduce(inaccurate_refund, DispatchClass::Normal);
+			});
+			crate::ExtrinsicWeightReclaimed::<Test>::put(inaccurate_refund);
+
+			// Do the post dispatch
+			assert_ok!(CheckWeight::<Test>::post_dispatch_details(
+				pre,
+				&info,
+				&post_info,
+				len,
+				&Ok(())
+			));
+
+			// Ensure the accurate refund from benchmark is used
+			assert_eq!(
+				crate::ExtrinsicWeightReclaimed::<Test>::get(),
+				post_info.calc_unspent(&info)
+			);
+			assert_eq!(
+				BlockWeight::<Test>::get().total(),
+				post_info.actual_weight.unwrap() + prior_block_weight + base_extrinsic
+			);
+		})
+	}
+
 	#[test]
 	fn zero_weight_extrinsic_still_has_base_weight() {
 		new_test_ext().execute_with(|| {
diff --git a/substrate/frame/system/src/extensions/mod.rs b/substrate/frame/system/src/extensions/mod.rs
index d79104d224035450f9ca69ba7d4b502b9ff0289d..66a8b17d30ae15b09a4af20a9dd703a52d18de9a 100644
--- a/substrate/frame/system/src/extensions/mod.rs
+++ b/substrate/frame/system/src/extensions/mod.rs
@@ -22,6 +22,7 @@ pub mod check_nonce;
 pub mod check_spec_version;
 pub mod check_tx_version;
 pub mod check_weight;
+pub mod weight_reclaim;
 pub mod weights;
 
 pub use weights::WeightInfo;
diff --git a/substrate/frame/system/src/extensions/weight_reclaim.rs b/substrate/frame/system/src/extensions/weight_reclaim.rs
new file mode 100644
index 0000000000000000000000000000000000000000..0c37422a843bb7595497e8c2cc939ac39dee1c5e
--- /dev/null
+++ b/substrate/frame/system/src/extensions/weight_reclaim.rs
@@ -0,0 +1,401 @@
+// This file is part of Substrate.
+
+// 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::Config;
+use codec::{Decode, Encode};
+use frame_support::dispatch::{DispatchInfo, PostDispatchInfo};
+use scale_info::TypeInfo;
+use sp_runtime::{
+	traits::{
+		DispatchInfoOf, Dispatchable, PostDispatchInfoOf, TransactionExtension, ValidateResult,
+	},
+	transaction_validity::{TransactionSource, TransactionValidityError, ValidTransaction},
+	DispatchResult,
+};
+use sp_weights::Weight;
+
+/// Reclaim the unused weight using the post dispatch information
+///
+/// After the dispatch of the extrinsic, calculate the unused weight using the post dispatch
+/// information and update the block consumed weight according to the new calculated extrinsic
+/// weight.
+#[derive(Encode, Decode, Clone, Eq, PartialEq, Default, TypeInfo)]
+#[scale_info(skip_type_params(T))]
+pub struct WeightReclaim<T: Config + Send + Sync>(core::marker::PhantomData<T>);
+
+impl<T: Config + Send + Sync> WeightReclaim<T>
+where
+	T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
+{
+	/// Creates new `TransactionExtension` to recalculate the extrinsic weight after dispatch.
+	pub fn new() -> Self {
+		Self(Default::default())
+	}
+}
+
+impl<T: Config + Send + Sync> TransactionExtension<T::RuntimeCall> for WeightReclaim<T>
+where
+	T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
+{
+	const IDENTIFIER: &'static str = "WeightReclaim";
+	type Implicit = ();
+	type Pre = ();
+	type Val = ();
+
+	fn weight(&self, _: &T::RuntimeCall) -> Weight {
+		<T::ExtensionsWeightInfo as super::WeightInfo>::weight_reclaim()
+	}
+
+	fn validate(
+		&self,
+		origin: T::RuntimeOrigin,
+		_call: &T::RuntimeCall,
+		_info: &DispatchInfoOf<T::RuntimeCall>,
+		_len: usize,
+		_self_implicit: Self::Implicit,
+		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
+	) -> ValidateResult<Self::Val, T::RuntimeCall> {
+		Ok((ValidTransaction::default(), (), origin))
+	}
+
+	fn prepare(
+		self,
+		_val: Self::Val,
+		_origin: &T::RuntimeOrigin,
+		_call: &T::RuntimeCall,
+		_info: &DispatchInfoOf<T::RuntimeCall>,
+		_len: usize,
+	) -> Result<Self::Pre, TransactionValidityError> {
+		Ok(())
+	}
+
+	fn post_dispatch_details(
+		_pre: Self::Pre,
+		info: &DispatchInfoOf<T::RuntimeCall>,
+		post_info: &PostDispatchInfoOf<T::RuntimeCall>,
+		_len: usize,
+		_result: &DispatchResult,
+	) -> Result<Weight, TransactionValidityError> {
+		crate::Pallet::<T>::reclaim_weight(info, post_info).map(|()| Weight::zero())
+	}
+
+	fn bare_validate(
+		_call: &T::RuntimeCall,
+		_info: &DispatchInfoOf<T::RuntimeCall>,
+		_len: usize,
+	) -> frame_support::pallet_prelude::TransactionValidity {
+		Ok(ValidTransaction::default())
+	}
+
+	fn bare_validate_and_prepare(
+		_call: &T::RuntimeCall,
+		_info: &DispatchInfoOf<T::RuntimeCall>,
+		_len: usize,
+	) -> Result<(), TransactionValidityError> {
+		Ok(())
+	}
+
+	fn bare_post_dispatch(
+		info: &DispatchInfoOf<T::RuntimeCall>,
+		post_info: &mut PostDispatchInfoOf<T::RuntimeCall>,
+		_len: usize,
+		_result: &DispatchResult,
+	) -> Result<(), TransactionValidityError> {
+		crate::Pallet::<T>::reclaim_weight(info, post_info)
+	}
+}
+
+impl<T: Config + Send + Sync> core::fmt::Debug for WeightReclaim<T>
+where
+	T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
+{
+	fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+		write!(f, "{}", Self::IDENTIFIER)
+	}
+}
+
+#[cfg(test)]
+mod tests {
+	use super::*;
+	use crate::{
+		mock::{new_test_ext, Test},
+		BlockWeight, DispatchClass,
+	};
+	use frame_support::{assert_ok, weights::Weight};
+
+	fn block_weights() -> crate::limits::BlockWeights {
+		<Test as crate::Config>::BlockWeights::get()
+	}
+
+	#[test]
+	fn extrinsic_already_refunded_more_precisely() {
+		new_test_ext().execute_with(|| {
+			// This is half of the max block weight
+			let info =
+				DispatchInfo { call_weight: Weight::from_parts(512, 0), ..Default::default() };
+			let post_info = PostDispatchInfo {
+				actual_weight: Some(Weight::from_parts(128, 0)),
+				pays_fee: Default::default(),
+			};
+			let prior_block_weight = Weight::from_parts(64, 0);
+			let accurate_refund = Weight::from_parts(510, 0);
+			let len = 0_usize;
+			let base_extrinsic = block_weights().get(DispatchClass::Normal).base_extrinsic;
+
+			// Set initial info
+			BlockWeight::<Test>::mutate(|current_weight| {
+				current_weight.set(prior_block_weight, DispatchClass::Normal);
+				current_weight.accrue(
+					base_extrinsic + info.total_weight() - accurate_refund,
+					DispatchClass::Normal,
+				);
+			});
+			crate::ExtrinsicWeightReclaimed::<Test>::put(accurate_refund);
+
+			// Do the post dispatch
+			assert_ok!(WeightReclaim::<Test>::post_dispatch_details(
+				(),
+				&info,
+				&post_info,
+				len,
+				&Ok(())
+			));
+
+			// Ensure the accurate refund is used
+			assert_eq!(crate::ExtrinsicWeightReclaimed::<Test>::get(), accurate_refund);
+			assert_eq!(
+				*BlockWeight::<Test>::get().get(DispatchClass::Normal),
+				info.total_weight() - accurate_refund + prior_block_weight + base_extrinsic
+			);
+		})
+	}
+
+	#[test]
+	fn extrinsic_already_refunded_less_precisely() {
+		new_test_ext().execute_with(|| {
+			// This is half of the max block weight
+			let info =
+				DispatchInfo { call_weight: Weight::from_parts(512, 0), ..Default::default() };
+			let post_info = PostDispatchInfo {
+				actual_weight: Some(Weight::from_parts(128, 0)),
+				pays_fee: Default::default(),
+			};
+			let prior_block_weight = Weight::from_parts(64, 0);
+			let inaccurate_refund = Weight::from_parts(110, 0);
+			let len = 0_usize;
+			let base_extrinsic = block_weights().get(DispatchClass::Normal).base_extrinsic;
+
+			// Set initial info
+			BlockWeight::<Test>::mutate(|current_weight| {
+				current_weight.set(prior_block_weight, DispatchClass::Normal);
+				current_weight.accrue(
+					base_extrinsic + info.total_weight() - inaccurate_refund,
+					DispatchClass::Normal,
+				);
+			});
+			crate::ExtrinsicWeightReclaimed::<Test>::put(inaccurate_refund);
+
+			// Do the post dispatch
+			assert_ok!(WeightReclaim::<Test>::post_dispatch_details(
+				(),
+				&info,
+				&post_info,
+				len,
+				&Ok(())
+			));
+
+			// Ensure the accurate refund from benchmark is used
+			assert_eq!(
+				crate::ExtrinsicWeightReclaimed::<Test>::get(),
+				post_info.calc_unspent(&info)
+			);
+			assert_eq!(
+				*BlockWeight::<Test>::get().get(DispatchClass::Normal),
+				post_info.actual_weight.unwrap() + prior_block_weight + base_extrinsic
+			);
+		})
+	}
+
+	#[test]
+	fn extrinsic_not_refunded_before() {
+		new_test_ext().execute_with(|| {
+			// This is half of the max block weight
+			let info =
+				DispatchInfo { call_weight: Weight::from_parts(512, 0), ..Default::default() };
+			let post_info = PostDispatchInfo {
+				actual_weight: Some(Weight::from_parts(128, 0)),
+				pays_fee: Default::default(),
+			};
+			let prior_block_weight = Weight::from_parts(64, 0);
+			let len = 0_usize;
+			let base_extrinsic = block_weights().get(DispatchClass::Normal).base_extrinsic;
+
+			// Set initial info
+			BlockWeight::<Test>::mutate(|current_weight| {
+				current_weight.set(prior_block_weight, DispatchClass::Normal);
+				current_weight.accrue(base_extrinsic + info.total_weight(), DispatchClass::Normal);
+			});
+
+			// Do the post dispatch
+			assert_ok!(WeightReclaim::<Test>::post_dispatch_details(
+				(),
+				&info,
+				&post_info,
+				len,
+				&Ok(())
+			));
+
+			// Ensure the accurate refund from benchmark is used
+			assert_eq!(
+				crate::ExtrinsicWeightReclaimed::<Test>::get(),
+				post_info.calc_unspent(&info)
+			);
+			assert_eq!(
+				*BlockWeight::<Test>::get().get(DispatchClass::Normal),
+				post_info.actual_weight.unwrap() + prior_block_weight + base_extrinsic
+			);
+		})
+	}
+
+	#[test]
+	fn no_actual_post_dispatch_weight() {
+		new_test_ext().execute_with(|| {
+			// This is half of the max block weight
+			let info =
+				DispatchInfo { call_weight: Weight::from_parts(512, 0), ..Default::default() };
+			let post_info = PostDispatchInfo { actual_weight: None, pays_fee: Default::default() };
+			let prior_block_weight = Weight::from_parts(64, 0);
+			let len = 0_usize;
+			let base_extrinsic = block_weights().get(DispatchClass::Normal).base_extrinsic;
+
+			// Set initial info
+			BlockWeight::<Test>::mutate(|current_weight| {
+				current_weight.set(prior_block_weight, DispatchClass::Normal);
+				current_weight.accrue(base_extrinsic + info.total_weight(), DispatchClass::Normal);
+			});
+
+			// Do the post dispatch
+			assert_ok!(WeightReclaim::<Test>::post_dispatch_details(
+				(),
+				&info,
+				&post_info,
+				len,
+				&Ok(())
+			));
+
+			// Ensure the accurate refund from benchmark is used
+			assert_eq!(
+				crate::ExtrinsicWeightReclaimed::<Test>::get(),
+				post_info.calc_unspent(&info)
+			);
+			assert_eq!(
+				*BlockWeight::<Test>::get().get(DispatchClass::Normal),
+				info.total_weight() + prior_block_weight + base_extrinsic
+			);
+		})
+	}
+
+	#[test]
+	fn different_dispatch_class() {
+		new_test_ext().execute_with(|| {
+			// This is half of the max block weight
+			let info = DispatchInfo {
+				call_weight: Weight::from_parts(512, 0),
+				class: DispatchClass::Operational,
+				..Default::default()
+			};
+			let post_info = PostDispatchInfo {
+				actual_weight: Some(Weight::from_parts(128, 0)),
+				pays_fee: Default::default(),
+			};
+			let prior_block_weight = Weight::from_parts(64, 0);
+			let len = 0_usize;
+			let base_extrinsic = block_weights().get(DispatchClass::Operational).base_extrinsic;
+
+			// Set initial info
+			BlockWeight::<Test>::mutate(|current_weight| {
+				current_weight.set(prior_block_weight, DispatchClass::Operational);
+				current_weight
+					.accrue(base_extrinsic + info.total_weight(), DispatchClass::Operational);
+			});
+
+			// Do the post dispatch
+			assert_ok!(WeightReclaim::<Test>::post_dispatch_details(
+				(),
+				&info,
+				&post_info,
+				len,
+				&Ok(())
+			));
+
+			// Ensure the accurate refund from benchmark is used
+			assert_eq!(
+				crate::ExtrinsicWeightReclaimed::<Test>::get(),
+				post_info.calc_unspent(&info)
+			);
+			assert_eq!(
+				*BlockWeight::<Test>::get().get(DispatchClass::Operational),
+				post_info.actual_weight.unwrap() + prior_block_weight + base_extrinsic
+			);
+		})
+	}
+
+	#[test]
+	fn bare_also_works() {
+		new_test_ext().execute_with(|| {
+			// This is half of the max block weight
+			let info = DispatchInfo {
+				call_weight: Weight::from_parts(512, 0),
+				class: DispatchClass::Operational,
+				..Default::default()
+			};
+			let post_info = PostDispatchInfo {
+				actual_weight: Some(Weight::from_parts(128, 0)),
+				pays_fee: Default::default(),
+			};
+			let prior_block_weight = Weight::from_parts(64, 0);
+			let len = 0_usize;
+			let base_extrinsic = block_weights().get(DispatchClass::Operational).base_extrinsic;
+
+			// Set initial info
+			BlockWeight::<Test>::mutate(|current_weight| {
+				current_weight.set(prior_block_weight, DispatchClass::Operational);
+				current_weight
+					.accrue(base_extrinsic + info.total_weight(), DispatchClass::Operational);
+			});
+
+			// Do the bare post dispatch
+			assert_ok!(WeightReclaim::<Test>::bare_post_dispatch(
+				&info,
+				&mut post_info.clone(),
+				len,
+				&Ok(())
+			));
+
+			// Ensure the accurate refund from benchmark is used
+			assert_eq!(
+				crate::ExtrinsicWeightReclaimed::<Test>::get(),
+				post_info.calc_unspent(&info)
+			);
+			assert_eq!(
+				*BlockWeight::<Test>::get().get(DispatchClass::Operational),
+				post_info.actual_weight.unwrap() + prior_block_weight + base_extrinsic
+			);
+		})
+	}
+}
diff --git a/substrate/frame/system/src/extensions/weights.rs b/substrate/frame/system/src/extensions/weights.rs
index b3c296899be52e8d308dd48fdeb662327be26dfb..670bb9a0e6fab2165cc29e04d757300a2eeae4a4 100644
--- a/substrate/frame/system/src/extensions/weights.rs
+++ b/substrate/frame/system/src/extensions/weights.rs
@@ -59,6 +59,7 @@ pub trait WeightInfo {
 	fn check_spec_version() -> Weight;
 	fn check_tx_version() -> Weight;
 	fn check_weight() -> Weight;
+	fn weight_reclaim() -> Weight;
 }
 
 /// Weights for `frame_system_extensions` using the Substrate node and recommended hardware.
@@ -133,6 +134,17 @@ impl<T: crate::Config> WeightInfo for SubstrateWeight<T> {
 		// Minimum execution time: 2_887_000 picoseconds.
 		Weight::from_parts(3_006_000, 0)
 	}
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1489`
+		// Minimum execution time: 4_375_000 picoseconds.
+		Weight::from_parts(4_747_000, 1489)
+			.saturating_add(RocksDbWeight::get().reads(1_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
 }
 
 // For backwards compatibility and tests.
@@ -206,4 +218,15 @@ impl WeightInfo for () {
 		// Minimum execution time: 2_887_000 picoseconds.
 		Weight::from_parts(3_006_000, 0)
 	}
+	/// Storage: `System::AllExtrinsicsLen` (r:1 w:1)
+	/// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+	fn weight_reclaim() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `24`
+		//  Estimated: `1489`
+		// Minimum execution time: 4_375_000 picoseconds.
+		Weight::from_parts(4_747_000, 1489)
+			.saturating_add(RocksDbWeight::get().reads(1_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
 }
diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs
index 862fb4cf9faf8c23c57bbbc713894d6e31325155..4fc69c8755f3c276a97c3bcb237ce7f2c2be1509 100644
--- a/substrate/frame/system/src/lib.rs
+++ b/substrate/frame/system/src/lib.rs
@@ -146,6 +146,10 @@ use frame_support::{
 };
 use scale_info::TypeInfo;
 use sp_core::storage::well_known_keys;
+use sp_runtime::{
+	traits::{DispatchInfoOf, PostDispatchInfoOf},
+	transaction_validity::TransactionValidityError,
+};
 use sp_weights::{RuntimeDbWeight, Weight};
 
 #[cfg(any(feature = "std", test))]
@@ -170,7 +174,7 @@ pub use extensions::{
 	check_genesis::CheckGenesis, check_mortality::CheckMortality,
 	check_non_zero_sender::CheckNonZeroSender, check_nonce::CheckNonce,
 	check_spec_version::CheckSpecVersion, check_tx_version::CheckTxVersion,
-	check_weight::CheckWeight, WeightInfo as ExtensionsWeightInfo,
+	check_weight::CheckWeight, weight_reclaim::WeightReclaim, WeightInfo as ExtensionsWeightInfo,
 };
 // Backward compatible re-export.
 pub use extensions::check_mortality::CheckMortality as CheckEra;
@@ -1039,6 +1043,17 @@ pub mod pallet {
 	pub(super) type AuthorizedUpgrade<T: Config> =
 		StorageValue<_, CodeUpgradeAuthorization<T>, OptionQuery>;
 
+	/// The weight reclaimed for the extrinsic.
+	///
+	/// This information is available until the end of the extrinsic execution.
+	/// More precisely this information is removed in `note_applied_extrinsic`.
+	///
+	/// Logic doing some post dispatch weight reduction must update this storage to avoid duplicate
+	/// reduction.
+	#[pallet::storage]
+	#[pallet::whitelist_storage]
+	pub type ExtrinsicWeightReclaimed<T: Config> = StorageValue<_, Weight, ValueQuery>;
+
 	#[derive(frame_support::DefaultNoBound)]
 	#[pallet::genesis_config]
 	pub struct GenesisConfig<T: Config> {
@@ -2073,10 +2088,23 @@ impl<T: Config> Pallet<T> {
 			},
 		});
 
+		log::trace!(
+			target: LOG_TARGET,
+			"Used block weight: {:?}",
+			BlockWeight::<T>::get(),
+		);
+
+		log::trace!(
+			target: LOG_TARGET,
+			"Used block length: {:?}",
+			Pallet::<T>::all_extrinsics_len(),
+		);
+
 		let next_extrinsic_index = Self::extrinsic_index().unwrap_or_default() + 1u32;
 
 		storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &next_extrinsic_index);
 		ExecutionPhase::<T>::put(Phase::ApplyExtrinsic(next_extrinsic_index));
+		ExtrinsicWeightReclaimed::<T>::kill();
 	}
 
 	/// To be called immediately after `note_applied_extrinsic` of the last extrinsic of the block
@@ -2174,6 +2202,32 @@ impl<T: Config> Pallet<T> {
 		}
 		Ok(actual_hash)
 	}
+
+	/// Reclaim the weight for the extrinsic given info and post info.
+	///
+	/// This function will check the already reclaimed weight, and reclaim more if the
+	/// difference between pre dispatch and post dispatch weight is higher.
+	pub fn reclaim_weight(
+		info: &DispatchInfoOf<T::RuntimeCall>,
+		post_info: &PostDispatchInfoOf<T::RuntimeCall>,
+	) -> Result<(), TransactionValidityError>
+	where
+		T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
+	{
+		let already_reclaimed = crate::ExtrinsicWeightReclaimed::<T>::get();
+		let unspent = post_info.calc_unspent(info);
+		let accurate_reclaim = already_reclaimed.max(unspent);
+		// Saturation never happens, we took the maximum above.
+		let to_reclaim_more = accurate_reclaim.saturating_sub(already_reclaimed);
+		if to_reclaim_more != Weight::zero() {
+			crate::BlockWeight::<T>::mutate(|current_weight| {
+				current_weight.reduce(to_reclaim_more, info.class);
+			});
+			crate::ExtrinsicWeightReclaimed::<T>::put(accurate_reclaim);
+		}
+
+		Ok(())
+	}
 }
 
 /// Returns a 32 byte datum which is guaranteed to be universally unique. `entropy` is provided
diff --git a/substrate/frame/system/src/tests.rs b/substrate/frame/system/src/tests.rs
index 6b903f5b7e79eccbeacc6180e2828ea74897f72d..6415380b2848564cf3c3ed4a95642d147db539c9 100644
--- a/substrate/frame/system/src/tests.rs
+++ b/substrate/frame/system/src/tests.rs
@@ -892,3 +892,67 @@ fn test_default_account_nonce() {
 		assert_eq!(System::account_nonce(&1), 5u64.into());
 	});
 }
+
+#[test]
+fn extrinsic_weight_refunded_is_cleaned() {
+	new_test_ext().execute_with(|| {
+		crate::ExtrinsicWeightReclaimed::<Test>::put(Weight::from_parts(1, 2));
+		assert_eq!(crate::ExtrinsicWeightReclaimed::<Test>::get(), Weight::from_parts(1, 2));
+		System::note_applied_extrinsic(&Ok(().into()), Default::default());
+		assert_eq!(crate::ExtrinsicWeightReclaimed::<Test>::get(), Weight::zero());
+
+		crate::ExtrinsicWeightReclaimed::<Test>::put(Weight::from_parts(1, 2));
+		assert_eq!(crate::ExtrinsicWeightReclaimed::<Test>::get(), Weight::from_parts(1, 2));
+		System::note_applied_extrinsic(&Err(DispatchError::BadOrigin.into()), Default::default());
+		assert_eq!(crate::ExtrinsicWeightReclaimed::<Test>::get(), Weight::zero());
+	});
+}
+
+#[test]
+fn reclaim_works() {
+	new_test_ext().execute_with(|| {
+		let info = DispatchInfo { call_weight: Weight::from_parts(100, 200), ..Default::default() };
+		crate::Pallet::<Test>::reclaim_weight(
+			&info,
+			&PostDispatchInfo {
+				actual_weight: Some(Weight::from_parts(50, 100)),
+				..Default::default()
+			},
+		)
+		.unwrap();
+		assert_eq!(crate::ExtrinsicWeightReclaimed::<Test>::get(), Weight::from_parts(50, 100));
+
+		crate::Pallet::<Test>::reclaim_weight(
+			&info,
+			&PostDispatchInfo {
+				actual_weight: Some(Weight::from_parts(25, 200)),
+				..Default::default()
+			},
+		)
+		.unwrap();
+		assert_eq!(crate::ExtrinsicWeightReclaimed::<Test>::get(), Weight::from_parts(75, 100));
+
+		crate::Pallet::<Test>::reclaim_weight(
+			&info,
+			&PostDispatchInfo {
+				actual_weight: Some(Weight::from_parts(300, 50)),
+				..Default::default()
+			},
+		)
+		.unwrap();
+		assert_eq!(crate::ExtrinsicWeightReclaimed::<Test>::get(), Weight::from_parts(75, 150));
+
+		crate::Pallet::<Test>::reclaim_weight(
+			&info,
+			&PostDispatchInfo {
+				actual_weight: Some(Weight::from_parts(300, 300)),
+				..Default::default()
+			},
+		)
+		.unwrap();
+		assert_eq!(crate::ExtrinsicWeightReclaimed::<Test>::get(), Weight::from_parts(75, 150));
+
+		System::note_applied_extrinsic(&Ok(().into()), Default::default());
+		assert_eq!(crate::ExtrinsicWeightReclaimed::<Test>::get(), Weight::zero());
+	});
+}
diff --git a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs
index 1842b1631621a9158f09422cb744dc54d27df935..dec818598472334214ba7e8b228530d5259583d0 100644
--- a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs
+++ b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs
@@ -85,7 +85,6 @@ where
 		match self.format {
 			ExtrinsicFormat::Bare => {
 				let inherent_validation = I::validate_unsigned(source, &self.function)?;
-				#[allow(deprecated)]
 				let legacy_validation = Extension::bare_validate(&self.function, info, len)?;
 				Ok(legacy_validation.combine_with(inherent_validation))
 			},
diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs b/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs
index 27f33acb69cce1d53b6dc4058772ba0303b44e21..4d95e5e6f3a4f03602a83a4dd3152c3430f311c4 100644
--- a/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs
+++ b/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs
@@ -487,7 +487,7 @@ pub trait TransactionExtension<Call: Dispatchable>:
 #[macro_export]
 macro_rules! impl_tx_ext_default {
 	($call:ty ; , $( $rest:tt )*) => {
-		impl_tx_ext_default!{$call ; $( $rest )*}
+		$crate::impl_tx_ext_default!{$call ; $( $rest )*}
 	};
 	($call:ty ; validate $( $rest:tt )*) => {
 		fn validate(
@@ -502,7 +502,7 @@ macro_rules! impl_tx_ext_default {
 		) -> $crate::traits::ValidateResult<Self::Val, $call> {
 			Ok((Default::default(), Default::default(), origin))
 		}
-		impl_tx_ext_default!{$call ; $( $rest )*}
+		$crate::impl_tx_ext_default!{$call ; $( $rest )*}
 	};
 	($call:ty ; prepare $( $rest:tt )*) => {
 		fn prepare(
@@ -515,13 +515,13 @@ macro_rules! impl_tx_ext_default {
 		) -> Result<Self::Pre, $crate::transaction_validity::TransactionValidityError> {
 			Ok(Default::default())
 		}
-		impl_tx_ext_default!{$call ; $( $rest )*}
+		$crate::impl_tx_ext_default!{$call ; $( $rest )*}
 	};
 	($call:ty ; weight $( $rest:tt )*) => {
 		fn weight(&self, _call: &$call) -> $crate::Weight {
 			$crate::Weight::zero()
 		}
-		impl_tx_ext_default!{$call ; $( $rest )*}
+		$crate::impl_tx_ext_default!{$call ; $( $rest )*}
 	};
 	($call:ty ;) => {};
 }
diff --git a/substrate/test-utils/runtime/src/extrinsic.rs b/substrate/test-utils/runtime/src/extrinsic.rs
index 491086bef49792fe25eff1a88b910549cb12f893..49dc6ba035c9e929d172d67d39b7ee7a97ac2f07 100644
--- a/substrate/test-utils/runtime/src/extrinsic.rs
+++ b/substrate/test-utils/runtime/src/extrinsic.rs
@@ -212,6 +212,7 @@ impl ExtrinsicBuilder {
 				self.metadata_hash
 					.map(CheckMetadataHash::new_with_custom_hash)
 					.unwrap_or_else(|| CheckMetadataHash::new(false)),
+				frame_system::WeightReclaim::new(),
 			);
 			let raw_payload = SignedPayload::from_raw(
 				self.function.clone(),
diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs
index 666776865316be6c818fcc23b81937959d25b8b2..4d24354f99a7eb8f55e499205a8038eec0ccc4e0 100644
--- a/substrate/test-utils/runtime/src/lib.rs
+++ b/substrate/test-utils/runtime/src/lib.rs
@@ -155,6 +155,7 @@ pub type TxExtension = (
 	(CheckNonce<Runtime>, CheckWeight<Runtime>),
 	CheckSubstrateCall,
 	frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+	frame_system::WeightReclaim<Runtime>,
 );
 /// The payload being signed in transactions.
 pub type SignedPayload = sp_runtime::generic::SignedPayload<RuntimeCall, TxExtension>;
diff --git a/templates/minimal/runtime/src/lib.rs b/templates/minimal/runtime/src/lib.rs
index 72eded5bfd135c9a779f3e85b9328bbb69b17457..972c7500f3993f5a362e422e300262025146ce1c 100644
--- a/templates/minimal/runtime/src/lib.rs
+++ b/templates/minimal/runtime/src/lib.rs
@@ -118,6 +118,10 @@ type TxExtension = (
 	// Ensures that the sender has enough funds to pay for the transaction
 	// and deducts the fee from the sender's account.
 	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+	// Reclaim the unused weight from the block using post dispatch information.
+	// It must be last in the pipeline in order to catch the refund in previous transaction
+	// extensions
+	frame_system::WeightReclaim<Runtime>,
 );
 
 // Composes the runtime by adding all the used pallets and deriving necessary types.
diff --git a/templates/parachain/runtime/Cargo.toml b/templates/parachain/runtime/Cargo.toml
index 9a0548106ed7b93d5f750396b98f3acdc7d69662..83d7bf4c9b72d60e37977411f0b5f8c6d5363c16 100644
--- a/templates/parachain/runtime/Cargo.toml
+++ b/templates/parachain/runtime/Cargo.toml
@@ -48,11 +48,11 @@ polkadot-sdk = { workspace = true, default-features = false, features = [
 
 	"cumulus-pallet-aura-ext",
 	"cumulus-pallet-session-benchmarking",
+	"cumulus-pallet-weight-reclaim",
 	"cumulus-pallet-xcm",
 	"cumulus-pallet-xcmp-queue",
 	"cumulus-primitives-aura",
 	"cumulus-primitives-core",
-	"cumulus-primitives-storage-weight-reclaim",
 	"cumulus-primitives-utility",
 	"pallet-collator-selection",
 	"parachains-common",
diff --git a/templates/parachain/runtime/src/benchmarks.rs b/templates/parachain/runtime/src/benchmarks.rs
index aae50e7258c0616248a5b11d3efab88e4258dba9..ca9d423bf856b12f8226e3f9a81ade4f059939f4 100644
--- a/templates/parachain/runtime/src/benchmarks.rs
+++ b/templates/parachain/runtime/src/benchmarks.rs
@@ -33,4 +33,5 @@ polkadot_sdk::frame_benchmarking::define_benchmarks!(
 	[pallet_collator_selection, CollatorSelection]
 	[cumulus_pallet_parachain_system, ParachainSystem]
 	[cumulus_pallet_xcmp_queue, XcmpQueue]
+	[cumulus_pallet_weight_reclaim, WeightReclaim]
 );
diff --git a/templates/parachain/runtime/src/configs/mod.rs b/templates/parachain/runtime/src/configs/mod.rs
index ba4c71c7f218705c4e5035d1fcac67fce10e2485..1e9155f59a57a8c9f5f34ef946fd3b39113e7a74 100644
--- a/templates/parachain/runtime/src/configs/mod.rs
+++ b/templates/parachain/runtime/src/configs/mod.rs
@@ -129,6 +129,11 @@ impl frame_system::Config for Runtime {
 	type MaxConsumers = frame_support::traits::ConstU32<16>;
 }
 
+/// Configure the palelt weight reclaim tx.
+impl cumulus_pallet_weight_reclaim::Config for Runtime {
+	type WeightInfo = ();
+}
+
 impl pallet_timestamp::Config for Runtime {
 	/// A timestamp: milliseconds since the unix epoch.
 	type Moment = u64;
diff --git a/templates/parachain/runtime/src/lib.rs b/templates/parachain/runtime/src/lib.rs
index 9669237af785af680e1c912e5775d613f023d2e1..0be27ecce73945a6fbda409f7d19994493d9be0f 100644
--- a/templates/parachain/runtime/src/lib.rs
+++ b/templates/parachain/runtime/src/lib.rs
@@ -75,18 +75,20 @@ pub type BlockId = generic::BlockId<Block>;
 
 /// The extension to the basic transaction logic.
 #[docify::export(template_signed_extra)]
-pub type TxExtension = (
-	frame_system::CheckNonZeroSender<Runtime>,
-	frame_system::CheckSpecVersion<Runtime>,
-	frame_system::CheckTxVersion<Runtime>,
-	frame_system::CheckGenesis<Runtime>,
-	frame_system::CheckEra<Runtime>,
-	frame_system::CheckNonce<Runtime>,
-	frame_system::CheckWeight<Runtime>,
-	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
-	cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim<Runtime>,
-	frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
-);
+pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
+	Runtime,
+	(
+		frame_system::CheckNonZeroSender<Runtime>,
+		frame_system::CheckSpecVersion<Runtime>,
+		frame_system::CheckTxVersion<Runtime>,
+		frame_system::CheckGenesis<Runtime>,
+		frame_system::CheckEra<Runtime>,
+		frame_system::CheckNonce<Runtime>,
+		frame_system::CheckWeight<Runtime>,
+		pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+		frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+	),
+>;
 
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
@@ -272,6 +274,8 @@ mod runtime {
 	pub type Timestamp = pallet_timestamp;
 	#[runtime::pallet_index(3)]
 	pub type ParachainInfo = parachain_info;
+	#[runtime::pallet_index(4)]
+	pub type WeightReclaim = cumulus_pallet_weight_reclaim;
 
 	// Monetary stuff.
 	#[runtime::pallet_index(10)]
diff --git a/templates/solochain/node/src/benchmarking.rs b/templates/solochain/node/src/benchmarking.rs
index 0d60230cd19c0347ca54bd0feae8a5ca7f2da66c..467cad4c0aaa50c3445e5370a2fbc12ba4482e97 100644
--- a/templates/solochain/node/src/benchmarking.rs
+++ b/templates/solochain/node/src/benchmarking.rs
@@ -122,6 +122,7 @@ pub fn create_benchmark_extrinsic(
 		frame_system::CheckWeight::<runtime::Runtime>::new(),
 		pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
 		frame_metadata_hash_extension::CheckMetadataHash::<runtime::Runtime>::new(false),
+		frame_system::WeightReclaim::<runtime::Runtime>::new(),
 	);
 
 	let raw_payload = runtime::SignedPayload::from_raw(
@@ -137,6 +138,7 @@ pub fn create_benchmark_extrinsic(
 			(),
 			(),
 			None,
+			(),
 		),
 	);
 	let signature = raw_payload.using_encoded(|e| sender.sign(e));
diff --git a/templates/solochain/runtime/src/lib.rs b/templates/solochain/runtime/src/lib.rs
index ae0ea16ae42ef6122d1472677f5a23fe769e465d..6a2149ec8b637c2b253a9327abd81260259cf150 100644
--- a/templates/solochain/runtime/src/lib.rs
+++ b/templates/solochain/runtime/src/lib.rs
@@ -157,6 +157,7 @@ pub type TxExtension = (
 	frame_system::CheckWeight<Runtime>,
 	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
 	frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
+	frame_system::WeightReclaim<Runtime>,
 );
 
 /// Unchecked extrinsic type as expected by this runtime.
diff --git a/umbrella/Cargo.toml b/umbrella/Cargo.toml
index d2a47ade7f8754f4c9ef068722c22d920f5103e1..17a7c02e82592c5765f7290183e8ee6711e44aff 100644
--- a/umbrella/Cargo.toml
+++ b/umbrella/Cargo.toml
@@ -29,6 +29,7 @@ std = [
 	"cumulus-pallet-parachain-system?/std",
 	"cumulus-pallet-session-benchmarking?/std",
 	"cumulus-pallet-solo-to-para?/std",
+	"cumulus-pallet-weight-reclaim?/std",
 	"cumulus-pallet-xcm?/std",
 	"cumulus-pallet-xcmp-queue?/std",
 	"cumulus-ping?/std",
@@ -239,6 +240,7 @@ runtime-benchmarks = [
 	"cumulus-pallet-dmp-queue?/runtime-benchmarks",
 	"cumulus-pallet-parachain-system?/runtime-benchmarks",
 	"cumulus-pallet-session-benchmarking?/runtime-benchmarks",
+	"cumulus-pallet-weight-reclaim?/runtime-benchmarks",
 	"cumulus-pallet-xcmp-queue?/runtime-benchmarks",
 	"cumulus-primitives-core?/runtime-benchmarks",
 	"cumulus-primitives-utility?/runtime-benchmarks",
@@ -369,6 +371,7 @@ try-runtime = [
 	"cumulus-pallet-dmp-queue?/try-runtime",
 	"cumulus-pallet-parachain-system?/try-runtime",
 	"cumulus-pallet-solo-to-para?/try-runtime",
+	"cumulus-pallet-weight-reclaim?/try-runtime",
 	"cumulus-pallet-xcm?/try-runtime",
 	"cumulus-pallet-xcmp-queue?/try-runtime",
 	"cumulus-ping?/try-runtime",
@@ -540,7 +543,7 @@ with-tracing = [
 	"sp-tracing?/with-tracing",
 	"sp-tracing?/with-tracing",
 ]
-runtime-full = ["assets-common", "binary-merkle-tree", "bp-header-chain", "bp-messages", "bp-parachains", "bp-polkadot", "bp-polkadot-core", "bp-relayers", "bp-runtime", "bp-test-utils", "bp-xcm-bridge-hub", "bp-xcm-bridge-hub-router", "bridge-hub-common", "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", "cumulus-pallet-parachain-system-proc-macro", "cumulus-pallet-session-benchmarking", "cumulus-pallet-solo-to-para", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-ping", "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-primitives-proof-size-hostfunction", "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-timestamp", "cumulus-primitives-utility", "frame-benchmarking", "frame-benchmarking-pallet-pov", "frame-election-provider-solution-type", "frame-election-provider-support", "frame-executive", "frame-metadata-hash-extension", "frame-support", "frame-support-procedural", "frame-support-procedural-tools-derive", "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", "pallet-alliance", "pallet-asset-conversion", "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", "pallet-asset-tx-payment", "pallet-assets", "pallet-assets-freezer", "pallet-atomic-swap", "pallet-aura", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", "pallet-bags-list", "pallet-balances", "pallet-beefy", "pallet-beefy-mmr", "pallet-bounties", "pallet-bridge-grandpa", "pallet-bridge-messages", "pallet-bridge-parachains", "pallet-bridge-relayers", "pallet-broker", "pallet-child-bounties", "pallet-collator-selection", "pallet-collective", "pallet-collective-content", "pallet-contracts", "pallet-contracts-proc-macro", "pallet-contracts-uapi", "pallet-conviction-voting", "pallet-core-fellowship", "pallet-delegated-staking", "pallet-democracy", "pallet-dev-mode", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", "pallet-fast-unstake", "pallet-glutton", "pallet-grandpa", "pallet-identity", "pallet-im-online", "pallet-indices", "pallet-insecure-randomness-collective-flip", "pallet-lottery", "pallet-membership", "pallet-message-queue", "pallet-migrations", "pallet-mixnet", "pallet-mmr", "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-nis", "pallet-node-authorization", "pallet-nomination-pools", "pallet-nomination-pools-benchmarking", "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", "pallet-paged-list", "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", "pallet-recovery", "pallet-referenda", "pallet-remark", "pallet-revive", "pallet-revive-proc-macro", "pallet-revive-uapi", "pallet-root-offences", "pallet-root-testing", "pallet-safe-mode", "pallet-salary", "pallet-scheduler", "pallet-scored-pool", "pallet-session", "pallet-session-benchmarking", "pallet-skip-feeless-payment", "pallet-society", "pallet-staking", "pallet-staking-reward-curve", "pallet-staking-reward-fn", "pallet-staking-runtime-api", "pallet-state-trie-migration", "pallet-statement", "pallet-sudo", "pallet-timestamp", "pallet-tips", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", "pallet-tx-pause", "pallet-uniques", "pallet-utility", "pallet-verify-signature", "pallet-vesting", "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-bridge-hub", "pallet-xcm-bridge-hub-router", "parachains-common", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-metrics", "polkadot-runtime-parachains", "polkadot-sdk-frame", "sc-chain-spec-derive", "sc-tracing-proc-macro", "slot-range-helper", "snowbridge-beacon-primitives", "snowbridge-core", "snowbridge-ethereum", "snowbridge-outbound-queue-merkle-tree", "snowbridge-outbound-queue-runtime-api", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-ethereum-client-fixtures", "snowbridge-pallet-inbound-queue", "snowbridge-pallet-inbound-queue-fixtures", "snowbridge-pallet-outbound-queue", "snowbridge-pallet-system", "snowbridge-router-primitives", "snowbridge-runtime-common", "snowbridge-system-runtime-api", "sp-api", "sp-api-proc-macro", "sp-application-crypto", "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", "sp-consensus-pow", "sp-consensus-slots", "sp-core", "sp-crypto-ec-utils", "sp-crypto-hashing", "sp-crypto-hashing-proc-macro", "sp-debug-derive", "sp-externalities", "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keyring", "sp-keystore", "sp-metadata-ir", "sp-mixnet", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", "sp-runtime", "sp-runtime-interface", "sp-runtime-interface-proc-macro", "sp-session", "sp-staking", "sp-state-machine", "sp-statement-store", "sp-std", "sp-storage", "sp-timestamp", "sp-tracing", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", "sp-version", "sp-version-proc-macro", "sp-wasm-interface", "sp-weights", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", "substrate-bip39", "testnet-parachains-constants", "tracing-gum-proc-macro", "xcm-procedural", "xcm-runtime-apis"]
+runtime-full = ["assets-common", "binary-merkle-tree", "bp-header-chain", "bp-messages", "bp-parachains", "bp-polkadot", "bp-polkadot-core", "bp-relayers", "bp-runtime", "bp-test-utils", "bp-xcm-bridge-hub", "bp-xcm-bridge-hub-router", "bridge-hub-common", "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", "cumulus-pallet-parachain-system-proc-macro", "cumulus-pallet-session-benchmarking", "cumulus-pallet-solo-to-para", "cumulus-pallet-weight-reclaim", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-ping", "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-primitives-proof-size-hostfunction", "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-timestamp", "cumulus-primitives-utility", "frame-benchmarking", "frame-benchmarking-pallet-pov", "frame-election-provider-solution-type", "frame-election-provider-support", "frame-executive", "frame-metadata-hash-extension", "frame-support", "frame-support-procedural", "frame-support-procedural-tools-derive", "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", "pallet-alliance", "pallet-asset-conversion", "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", "pallet-asset-tx-payment", "pallet-assets", "pallet-assets-freezer", "pallet-atomic-swap", "pallet-aura", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", "pallet-bags-list", "pallet-balances", "pallet-beefy", "pallet-beefy-mmr", "pallet-bounties", "pallet-bridge-grandpa", "pallet-bridge-messages", "pallet-bridge-parachains", "pallet-bridge-relayers", "pallet-broker", "pallet-child-bounties", "pallet-collator-selection", "pallet-collective", "pallet-collective-content", "pallet-contracts", "pallet-contracts-proc-macro", "pallet-contracts-uapi", "pallet-conviction-voting", "pallet-core-fellowship", "pallet-delegated-staking", "pallet-democracy", "pallet-dev-mode", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", "pallet-fast-unstake", "pallet-glutton", "pallet-grandpa", "pallet-identity", "pallet-im-online", "pallet-indices", "pallet-insecure-randomness-collective-flip", "pallet-lottery", "pallet-membership", "pallet-message-queue", "pallet-migrations", "pallet-mixnet", "pallet-mmr", "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-nis", "pallet-node-authorization", "pallet-nomination-pools", "pallet-nomination-pools-benchmarking", "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", "pallet-paged-list", "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", "pallet-recovery", "pallet-referenda", "pallet-remark", "pallet-revive", "pallet-revive-proc-macro", "pallet-revive-uapi", "pallet-root-offences", "pallet-root-testing", "pallet-safe-mode", "pallet-salary", "pallet-scheduler", "pallet-scored-pool", "pallet-session", "pallet-session-benchmarking", "pallet-skip-feeless-payment", "pallet-society", "pallet-staking", "pallet-staking-reward-curve", "pallet-staking-reward-fn", "pallet-staking-runtime-api", "pallet-state-trie-migration", "pallet-statement", "pallet-sudo", "pallet-timestamp", "pallet-tips", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", "pallet-tx-pause", "pallet-uniques", "pallet-utility", "pallet-verify-signature", "pallet-vesting", "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-bridge-hub", "pallet-xcm-bridge-hub-router", "parachains-common", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-metrics", "polkadot-runtime-parachains", "polkadot-sdk-frame", "sc-chain-spec-derive", "sc-tracing-proc-macro", "slot-range-helper", "snowbridge-beacon-primitives", "snowbridge-core", "snowbridge-ethereum", "snowbridge-outbound-queue-merkle-tree", "snowbridge-outbound-queue-runtime-api", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-ethereum-client-fixtures", "snowbridge-pallet-inbound-queue", "snowbridge-pallet-inbound-queue-fixtures", "snowbridge-pallet-outbound-queue", "snowbridge-pallet-system", "snowbridge-router-primitives", "snowbridge-runtime-common", "snowbridge-system-runtime-api", "sp-api", "sp-api-proc-macro", "sp-application-crypto", "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", "sp-consensus-pow", "sp-consensus-slots", "sp-core", "sp-crypto-ec-utils", "sp-crypto-hashing", "sp-crypto-hashing-proc-macro", "sp-debug-derive", "sp-externalities", "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keyring", "sp-keystore", "sp-metadata-ir", "sp-mixnet", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", "sp-runtime", "sp-runtime-interface", "sp-runtime-interface-proc-macro", "sp-session", "sp-staking", "sp-state-machine", "sp-statement-store", "sp-std", "sp-storage", "sp-timestamp", "sp-tracing", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", "sp-version", "sp-version-proc-macro", "sp-wasm-interface", "sp-weights", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", "substrate-bip39", "testnet-parachains-constants", "tracing-gum-proc-macro", "xcm-procedural", "xcm-runtime-apis"]
 runtime = [
 	"frame-benchmarking",
 	"frame-benchmarking-pallet-pov",
@@ -722,6 +725,11 @@ default-features = false
 optional = true
 path = "../cumulus/pallets/solo-to-para"
 
+[dependencies.cumulus-pallet-weight-reclaim]
+default-features = false
+optional = true
+path = "../cumulus/pallets/weight-reclaim"
+
 [dependencies.cumulus-pallet-xcm]
 default-features = false
 optional = true
diff --git a/umbrella/src/lib.rs b/umbrella/src/lib.rs
index 7b3c869588f00bee358c25bfe7b159c3daa3bae1..3504f081f2957b5a9a8eccaea15343281ee98292 100644
--- a/umbrella/src/lib.rs
+++ b/umbrella/src/lib.rs
@@ -141,6 +141,10 @@ pub use cumulus_pallet_session_benchmarking;
 #[cfg(feature = "cumulus-pallet-solo-to-para")]
 pub use cumulus_pallet_solo_to_para;
 
+/// pallet and transaction extensions for accurate proof size reclaim.
+#[cfg(feature = "cumulus-pallet-weight-reclaim")]
+pub use cumulus_pallet_weight_reclaim;
+
 /// Pallet for stuff specific to parachains' usage of XCM.
 #[cfg(feature = "cumulus-pallet-xcm")]
 pub use cumulus_pallet_xcm;