From 7a2c9d4a9ae495e9165975da234ff4b67f5bfeb4 Mon Sep 17 00:00:00 2001
From: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Date: Wed, 17 Apr 2024 18:52:00 +0300
Subject: [PATCH] Fix nostd build of several crates (#4060)

Preparation for https://github.com/paritytech/polkadot-sdk/pull/3935

Changes:
- Add some `default-features = false` for the case that a crate and that
dependency both support nostd builds.
- Shuffle files around of some benchmarking-only crates. These
conditionally disabled the `cfg_attr` for nostd and pulled in libstd.
Example [here](https://github.com/ggwpez/zepter/pull/95). The actual
logic is moved into a `inner.rs` to preserve nostd capability of the
crate in case the benchmarking feature is disabled.
- Add some `use sp_std::vec` where needed.
- Remove some `optional = true` in cases where it was not optional.
- Removed one superfluous `cfg_attr(not(feature = "std"), no_std..`.

All in all this should be logical no-op.

---------

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
---
 .../pallets/session-benchmarking/src/inner.rs |  42 +
 .../pallets/session-benchmarking/src/lib.rs   |  34 +-
 .../assets/asset-hub-rococo/Cargo.toml        |  10 +-
 .../assets/asset-hub-rococo/src/lib.rs        |  19 -
 .../glutton/glutton-westend/Cargo.toml        |   4 +-
 .../primitives/parachain-inherent/Cargo.toml  |   6 +-
 polkadot/primitives/Cargo.toml                |   3 +-
 polkadot/runtime/parachains/Cargo.toml        |   3 +-
 .../xcm-executor/integration-tests/src/lib.rs |   1 -
 prdoc/pr_4060.prdoc                           |  54 ++
 substrate/frame/Cargo.toml                    |   2 +-
 substrate/frame/atomic-swap/src/lib.rs        |   1 +
 .../benchmarking/src/inner.rs                 |  89 ++
 .../benchmarking/src/lib.rs                   |  74 +-
 substrate/frame/examples/dev-mode/src/lib.rs  |   1 +
 .../frame/examples/offchain-worker/Cargo.toml |   2 +-
 substrate/frame/indices/Cargo.toml            |   3 +-
 substrate/frame/nomination-pools/Cargo.toml   |   4 +-
 .../benchmarking/src/inner.rs                 | 846 ++++++++++++++++++
 .../nomination-pools/benchmarking/src/lib.rs  | 835 +----------------
 .../frame/offences/benchmarking/src/inner.rs  | 250 ++++++
 .../frame/offences/benchmarking/src/lib.rs    | 238 +----
 .../frame/offences/benchmarking/src/mock.rs   |   5 +-
 substrate/frame/root-offences/Cargo.toml      |   5 +-
 substrate/frame/root-offences/src/lib.rs      |   5 +-
 .../frame/session/benchmarking/src/inner.rs   | 162 ++++
 .../frame/session/benchmarking/src/lib.rs     | 152 +---
 substrate/frame/src/lib.rs                    |   4 +-
 .../frame/system/benchmarking/src/inner.rs    | 230 +++++
 .../frame/system/benchmarking/src/lib.rs      | 220 +----
 substrate/frame/try-runtime/src/inner.rs      |  50 ++
 substrate/frame/try-runtime/src/lib.rs        |  35 +-
 .../primitives/consensus/babe/Cargo.toml      |   2 +-
 substrate/primitives/core/Cargo.toml          |   2 +-
 substrate/primitives/session/Cargo.toml       |   4 +-
 .../transaction-storage-proof/Cargo.toml      |   4 +-
 36 files changed, 1800 insertions(+), 1601 deletions(-)
 create mode 100644 cumulus/pallets/session-benchmarking/src/inner.rs
 create mode 100644 prdoc/pr_4060.prdoc
 create mode 100644 substrate/frame/election-provider-support/benchmarking/src/inner.rs
 create mode 100644 substrate/frame/nomination-pools/benchmarking/src/inner.rs
 create mode 100644 substrate/frame/offences/benchmarking/src/inner.rs
 create mode 100644 substrate/frame/session/benchmarking/src/inner.rs
 create mode 100644 substrate/frame/system/benchmarking/src/inner.rs
 create mode 100644 substrate/frame/try-runtime/src/inner.rs

diff --git a/cumulus/pallets/session-benchmarking/src/inner.rs b/cumulus/pallets/session-benchmarking/src/inner.rs
new file mode 100644
index 00000000000..cffd0776f3d
--- /dev/null
+++ b/cumulus/pallets/session-benchmarking/src/inner.rs
@@ -0,0 +1,42 @@
+// 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.
+
+//! Benchmarking setup for pallet-session.
+
+use sp_std::{prelude::*, vec};
+
+use frame_benchmarking::{benchmarks, whitelisted_caller};
+use frame_system::RawOrigin;
+use pallet_session::*;
+use parity_scale_codec::Decode;
+pub struct Pallet<T: Config>(pallet_session::Pallet<T>);
+pub trait Config: pallet_session::Config {}
+
+benchmarks! {
+	set_keys {
+		let caller: T::AccountId = whitelisted_caller();
+		frame_system::Pallet::<T>::inc_providers(&caller);
+		let keys = T::Keys::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()).unwrap();
+		let proof: Vec<u8> = vec![0,1,2,3];
+	}: _(RawOrigin::Signed(caller), keys, proof)
+
+	purge_keys {
+		let caller: T::AccountId = whitelisted_caller();
+		frame_system::Pallet::<T>::inc_providers(&caller);
+		let keys = T::Keys::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()).unwrap();
+		let proof: Vec<u8> = vec![0,1,2,3];
+		let _t = pallet_session::Pallet::<T>::set_keys(RawOrigin::Signed(caller.clone()).into(), keys, proof);
+	}: _(RawOrigin::Signed(caller))
+}
diff --git a/cumulus/pallets/session-benchmarking/src/lib.rs b/cumulus/pallets/session-benchmarking/src/lib.rs
index f474def6b13..a95d6fb7d59 100644
--- a/cumulus/pallets/session-benchmarking/src/lib.rs
+++ b/cumulus/pallets/session-benchmarking/src/lib.rs
@@ -1,3 +1,5 @@
+// This file is part of Substrate.
+
 // Copyright (C) Parity Technologies (UK) Ltd.
 // SPDX-License-Identifier: Apache-2.0
 
@@ -13,31 +15,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//! Benchmarking setup for pallet-session
-#![cfg_attr(not(feature = "std"), no_std)]
-#![cfg(feature = "runtime-benchmarks")]
-use sp_std::{prelude::*, vec};
+//! Benchmarks for the Session Pallet.
+// This is separated into its own crate due to cyclic dependency issues.
 
-use frame_benchmarking::{benchmarks, whitelisted_caller};
-use frame_system::RawOrigin;
-use pallet_session::*;
-use parity_scale_codec::Decode;
-pub struct Pallet<T: Config>(pallet_session::Pallet<T>);
-pub trait Config: pallet_session::Config {}
+#![cfg_attr(not(feature = "std"), no_std)]
 
-benchmarks! {
-	set_keys {
-		let caller: T::AccountId = whitelisted_caller();
-		frame_system::Pallet::<T>::inc_providers(&caller);
-		let keys = T::Keys::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()).unwrap();
-		let proof: Vec<u8> = vec![0,1,2,3];
-	}: _(RawOrigin::Signed(caller), keys, proof)
+#[cfg(feature = "runtime-benchmarks")]
+pub mod inner;
 
-	purge_keys {
-		let caller: T::AccountId = whitelisted_caller();
-		frame_system::Pallet::<T>::inc_providers(&caller);
-		let keys = T::Keys::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()).unwrap();
-		let proof: Vec<u8> = vec![0,1,2,3];
-		let _t = pallet_session::Pallet::<T>::set_keys(RawOrigin::Signed(caller.clone()).into(), keys, proof);
-	}: _(RawOrigin::Signed(caller))
-}
+#[cfg(feature = "runtime-benchmarks")]
+pub use inner::*;
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml
index e8be734214f..47574783810 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml
@@ -37,7 +37,7 @@ pallet-nfts = { path = "../../../../../substrate/frame/nfts", default-features =
 pallet-nfts-runtime-api = { path = "../../../../../substrate/frame/nfts/runtime-api", default-features = false }
 pallet-proxy = { path = "../../../../../substrate/frame/proxy", default-features = false }
 pallet-session = { path = "../../../../../substrate/frame/session", default-features = false }
-pallet-state-trie-migration = { path = "../../../../../substrate/frame/state-trie-migration", default-features = false, optional = true }
+pallet-state-trie-migration = { path = "../../../../../substrate/frame/state-trie-migration", default-features = false }
 pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false }
 pallet-transaction-payment = { path = "../../../../../substrate/frame/transaction-payment", default-features = false }
 pallet-transaction-payment-rpc-runtime-api = { path = "../../../../../substrate/frame/transaction-payment/rpc/runtime-api", default-features = false }
@@ -102,14 +102,6 @@ substrate-wasm-builder = { path = "../../../../../substrate/utils/wasm-builder",
 
 [features]
 default = ["std"]
-# When enabled the `state_version` is set to `1`.
-# This means that the chain will start using the new state format. The migration is lazy, so
-# it requires to write a storage value to use the new state format. To migrate all the other
-# storage values that aren't touched the state migration pallet is added as well.
-# This pallet will migrate the entire state, controlled through some account.
-#
-# This feature should be removed when the main-net will be migrated.
-state-trie-version-1 = ["pallet-state-trie-migration"]
 runtime-benchmarks = [
 	"assets-common/runtime-benchmarks",
 	"cumulus-pallet-parachain-system/runtime-benchmarks",
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 30e211a8f1d..5cb29343a1c 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs
@@ -107,7 +107,6 @@ impl_opaque_keys! {
 	}
 }
 
-#[cfg(feature = "state-trie-version-1")]
 #[sp_version::runtime_version]
 pub const VERSION: RuntimeVersion = RuntimeVersion {
 	spec_name: create_runtime_str!("statemine"),
@@ -120,19 +119,6 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
 	state_version: 1,
 };
 
-#[cfg(not(feature = "state-trie-version-1"))]
-#[sp_version::runtime_version]
-pub const VERSION: RuntimeVersion = RuntimeVersion {
-	spec_name: create_runtime_str!("statemine"),
-	impl_name: create_runtime_str!("statemine"),
-	authoring_version: 1,
-	spec_version: 1_010_000,
-	impl_version: 0,
-	apis: RUNTIME_API_VERSIONS,
-	transaction_version: 14,
-	state_version: 0,
-};
-
 /// The version information used to identify this runtime when compiled natively.
 #[cfg(feature = "std")]
 pub fn native_version() -> NativeVersion {
@@ -953,7 +939,6 @@ construct_runtime!(
 		PoolAssets: pallet_assets::<Instance3> = 55,
 		AssetConversion: pallet_asset_conversion = 56,
 
-		#[cfg(feature = "state-trie-version-1")]
 		StateTrieMigration: pallet_state_trie_migration = 70,
 
 		// TODO: the pallet instance should be removed once all pools have migrated
@@ -1695,7 +1680,6 @@ cumulus_pallet_parachain_system::register_validate_block! {
 	BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
 }
 
-#[cfg(feature = "state-trie-version-1")]
 parameter_types! {
 	// The deposit configuration for the singed migration. Specially if you want to allow any signed account to do the migration (see `SignedFilter`, these deposits should be high)
 	pub const MigrationSignedDepositPerItem: Balance = CENTS;
@@ -1703,7 +1687,6 @@ parameter_types! {
 	pub const MigrationMaxKeyLen: u32 = 512;
 }
 
-#[cfg(feature = "state-trie-version-1")]
 impl pallet_state_trie_migration::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
 	type Currency = Balances;
@@ -1721,13 +1704,11 @@ impl pallet_state_trie_migration::Config for Runtime {
 	type MaxKeyLen = MigrationMaxKeyLen;
 }
 
-#[cfg(feature = "state-trie-version-1")]
 frame_support::ord_parameter_types! {
 	pub const MigController: AccountId = AccountId::from(hex_literal::hex!("8458ed39dc4b6f6c7255f7bc42be50c2967db126357c999d44e12ca7ac80dc52"));
 	pub const RootMigController: AccountId = AccountId::from(hex_literal::hex!("8458ed39dc4b6f6c7255f7bc42be50c2967db126357c999d44e12ca7ac80dc52"));
 }
 
-#[cfg(feature = "state-trie-version-1")]
 #[test]
 fn ensure_key_ss58() {
 	use frame_support::traits::SortedMembers;
diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml b/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml
index fe9cd25841b..808bed38732 100644
--- a/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml
@@ -22,8 +22,8 @@ frame-system-rpc-runtime-api = { path = "../../../../../substrate/frame/system/r
 frame-system-benchmarking = { path = "../../../../../substrate/frame/system/benchmarking", default-features = false, optional = true }
 frame-try-runtime = { path = "../../../../../substrate/frame/try-runtime", default-features = false, optional = true }
 pallet-aura = { path = "../../../../../substrate/frame/aura", default-features = false }
-pallet-glutton = { path = "../../../../../substrate/frame/glutton", default-features = false, optional = true }
-pallet-sudo = { path = "../../../../../substrate/frame/sudo", default-features = false, optional = true }
+pallet-glutton = { path = "../../../../../substrate/frame/glutton", default-features = false }
+pallet-sudo = { path = "../../../../../substrate/frame/sudo", default-features = false }
 pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false }
 sp-api = { path = "../../../../../substrate/primitives/api", default-features = false }
 sp-block-builder = { path = "../../../../../substrate/primitives/block-builder", default-features = false }
diff --git a/cumulus/primitives/parachain-inherent/Cargo.toml b/cumulus/primitives/parachain-inherent/Cargo.toml
index fcf4c93bc2f..4da561661b6 100644
--- a/cumulus/primitives/parachain-inherent/Cargo.toml
+++ b/cumulus/primitives/parachain-inherent/Cargo.toml
@@ -17,8 +17,8 @@ scale-info = { version = "2.11.1", default-features = false, features = ["derive
 # Substrate
 sp-core = { path = "../../../substrate/primitives/core", default-features = false }
 sp-inherents = { path = "../../../substrate/primitives/inherents", default-features = false }
-sp-runtime = { path = "../../../substrate/primitives/runtime", optional = true }
-sp-state-machine = { path = "../../../substrate/primitives/state-machine", optional = true }
+sp-runtime = { path = "../../../substrate/primitives/runtime", optional = true, default-features = false }
+sp-state-machine = { path = "../../../substrate/primitives/state-machine", optional = true, default-features = false }
 sp-std = { path = "../../../substrate/primitives/std", default-features = false }
 sp-trie = { path = "../../../substrate/primitives/trie", default-features = false }
 
@@ -34,6 +34,8 @@ std = [
 	"scale-info/std",
 	"sp-core/std",
 	"sp-inherents/std",
+	"sp-runtime?/std",
+	"sp-state-machine?/std",
 	"sp-std/std",
 	"sp-trie/std",
 ]
diff --git a/polkadot/primitives/Cargo.toml b/polkadot/primitives/Cargo.toml
index 004fa62acf3..99800afc37f 100644
--- a/polkadot/primitives/Cargo.toml
+++ b/polkadot/primitives/Cargo.toml
@@ -26,7 +26,7 @@ sp-arithmetic = { path = "../../substrate/primitives/arithmetic", default-featur
 sp-authority-discovery = { path = "../../substrate/primitives/authority-discovery", default-features = false, features = ["serde"] }
 sp-consensus-slots = { path = "../../substrate/primitives/consensus/slots", default-features = false, features = ["serde"] }
 sp-io = { path = "../../substrate/primitives/io", default-features = false }
-sp-keystore = { path = "../../substrate/primitives/keystore", optional = true }
+sp-keystore = { path = "../../substrate/primitives/keystore", optional = true, default-features = false }
 sp-staking = { path = "../../substrate/primitives/staking", default-features = false, features = ["serde"] }
 sp-std = { package = "sp-std", path = "../../substrate/primitives/std", default-features = false }
 
@@ -53,6 +53,7 @@ std = [
 	"sp-consensus-slots/std",
 	"sp-io/std",
 	"sp-keystore",
+	"sp-keystore?/std",
 	"sp-staking/std",
 	"sp-std/std",
 ]
diff --git a/polkadot/runtime/parachains/Cargo.toml b/polkadot/runtime/parachains/Cargo.toml
index dff8549f29f..402c6e487a1 100644
--- a/polkadot/runtime/parachains/Cargo.toml
+++ b/polkadot/runtime/parachains/Cargo.toml
@@ -28,7 +28,7 @@ sp-runtime = { path = "../../../substrate/primitives/runtime", default-features
 sp-session = { path = "../../../substrate/primitives/session", default-features = false }
 sp-staking = { path = "../../../substrate/primitives/staking", default-features = false, features = ["serde"] }
 sp-core = { path = "../../../substrate/primitives/core", default-features = false, features = ["serde"] }
-sp-keystore = { path = "../../../substrate/primitives/keystore", optional = true }
+sp-keystore = { path = "../../../substrate/primitives/keystore", optional = true, default-features = false }
 sp-application-crypto = { path = "../../../substrate/primitives/application-crypto", default-features = false, optional = true }
 sp-tracing = { path = "../../../substrate/primitives/tracing", default-features = false, optional = true }
 sp-arithmetic = { path = "../../../substrate/primitives/arithmetic", default-features = false }
@@ -108,6 +108,7 @@ std = [
 	"sp-core/std",
 	"sp-io/std",
 	"sp-keystore",
+	"sp-keystore?/std",
 	"sp-runtime/std",
 	"sp-session/std",
 	"sp-staking/std",
diff --git a/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs b/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs
index 1d1ee40d092..279d7118f8c 100644
--- a/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs
+++ b/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs
@@ -14,7 +14,6 @@
 // You should have received a copy of the GNU General Public License
 // along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
 
-#![cfg_attr(not(feature = "std"), no_std)]
 #![cfg(test)]
 
 use codec::Encode;
diff --git a/prdoc/pr_4060.prdoc b/prdoc/pr_4060.prdoc
new file mode 100644
index 00000000000..621620a4489
--- /dev/null
+++ b/prdoc/pr_4060.prdoc
@@ -0,0 +1,54 @@
+title: "Fix nostd build of several crates"
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      Fixes feature and dependency configuration of several crate. This should allow for better no-std build capabilities.
+
+crates:
+  - name: cumulus-pallet-session-benchmarking
+    bump: patch
+  - name: asset-hub-rococo-runtime
+    bump: patch
+  - name: glutton-westend-runtime
+    bump: patch
+  - name: cumulus-primitives-parachain-inherent
+    bump: patch
+  - name: polkadot-primitives
+    bump: patch
+  - name: polkadot-runtime-parachains
+    bump: patch
+  - name: xcm-executor-integration-tests
+    bump: patch
+  - name: pallet-atomic-swap
+    bump: patch
+  - name: pallet-election-provider-support-benchmarking
+    bump: patch
+  - name: pallet-dev-mode
+    bump: patch
+  - name: pallet-example-offchain-worker
+    bump: patch
+  - name: pallet-indices
+    bump: patch
+  - name: pallet-nomination-pools
+    bump: patch
+  - name: pallet-nomination-pools-benchmarking
+    bump: patch
+  - name: pallet-offences-benchmarking
+    bump: patch
+  - name: pallet-root-offences
+    bump: patch
+  - name: pallet-session-benchmarking
+    bump: patch
+  - name: frame-system-benchmarking
+    bump: patch
+  - name: sp-consensus-babe
+    bump: patch
+  - name: sp-consensus-babe
+    bump: patch
+  - name: sp-core
+    bump: patch
+  - name: sp-session
+    bump: patch
+  - name: sp-transaction-storage-proof
+    bump: patch
diff --git a/substrate/frame/Cargo.toml b/substrate/frame/Cargo.toml
index 919d6d17ce8..84bab86581c 100644
--- a/substrate/frame/Cargo.toml
+++ b/substrate/frame/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
 license = "Apache-2.0"
 homepage = "paritytech.github.io"
 repository.workspace = true
-description = "The single package to get you started with building frame pallets and runtimes"
+description = "Experimental: The single package to get you started with building frame pallets and runtimes"
 publish = false
 
 [lints]
diff --git a/substrate/frame/atomic-swap/src/lib.rs b/substrate/frame/atomic-swap/src/lib.rs
index 609903e67e3..dc0300dc1a5 100644
--- a/substrate/frame/atomic-swap/src/lib.rs
+++ b/substrate/frame/atomic-swap/src/lib.rs
@@ -58,6 +58,7 @@ use frame_system::pallet_prelude::BlockNumberFor;
 use scale_info::TypeInfo;
 use sp_io::hashing::blake2_256;
 use sp_runtime::RuntimeDebug;
+use sp_std::vec::Vec;
 
 /// Pending atomic swap operation.
 #[derive(Clone, Eq, PartialEq, RuntimeDebugNoBound, Encode, Decode, TypeInfo, MaxEncodedLen)]
diff --git a/substrate/frame/election-provider-support/benchmarking/src/inner.rs b/substrate/frame/election-provider-support/benchmarking/src/inner.rs
new file mode 100644
index 00000000000..4722680cfcc
--- /dev/null
+++ b/substrate/frame/election-provider-support/benchmarking/src/inner.rs
@@ -0,0 +1,89 @@
+// 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.
+
+//! Election provider support pallet benchmarking.
+//! This is separated into its own crate to avoid bloating the size of the runtime.
+
+use codec::Decode;
+use frame_benchmarking::v1::benchmarks;
+use frame_election_provider_support::{NposSolver, PhragMMS, SequentialPhragmen};
+use sp_std::vec::Vec;
+
+pub struct Pallet<T: Config>(frame_system::Pallet<T>);
+pub trait Config: frame_system::Config {}
+
+const VOTERS: [u32; 2] = [1_000, 2_000];
+const TARGETS: [u32; 2] = [500, 1_000];
+const VOTES_PER_VOTER: [u32; 2] = [5, 16];
+
+const SEED: u32 = 999;
+fn set_up_voters_targets<AccountId: Decode + Clone>(
+	voters_len: u32,
+	targets_len: u32,
+	degree: usize,
+) -> (Vec<(AccountId, u64, impl IntoIterator<Item = AccountId>)>, Vec<AccountId>) {
+	// fill targets.
+	let mut targets = (0..targets_len)
+		.map(|i| frame_benchmarking::account::<AccountId>("Target", i, SEED))
+		.collect::<Vec<_>>();
+	assert!(targets.len() > degree, "we should always have enough voters to fill");
+	targets.truncate(degree);
+
+	// fill voters.
+	let voters = (0..voters_len)
+		.map(|i| {
+			let voter = frame_benchmarking::account::<AccountId>("Voter", i, SEED);
+			(voter, 1_000, targets.clone())
+		})
+		.collect::<Vec<_>>();
+
+	(voters, targets)
+}
+
+benchmarks! {
+	phragmen {
+		// number of votes in snapshot.
+		let v in (VOTERS[0]) .. VOTERS[1];
+		// number of targets in snapshot.
+		let t in (TARGETS[0]) .. TARGETS[1];
+		// number of votes per voter (ie the degree).
+		let d in (VOTES_PER_VOTER[0]) .. VOTES_PER_VOTER[1];
+
+		let (voters, targets) = set_up_voters_targets::<T::AccountId>(v, t, d as usize);
+	}: {
+		assert!(
+			SequentialPhragmen::<T::AccountId, sp_runtime::Perbill>
+				::solve(d as usize, targets, voters).is_ok()
+		);
+	}
+
+	phragmms {
+		// number of votes in snapshot.
+		let v in (VOTERS[0]) .. VOTERS[1];
+		// number of targets in snapshot.
+		let t in (TARGETS[0]) .. TARGETS[1];
+		// number of votes per voter (ie the degree).
+		let d in (VOTES_PER_VOTER[0]) .. VOTES_PER_VOTER[1];
+
+		let (voters, targets) = set_up_voters_targets::<T::AccountId>(v, t, d as usize);
+	}: {
+		assert!(
+			PhragMMS::<T::AccountId, sp_runtime::Perbill>
+				::solve(d as usize, targets, voters).is_ok()
+		);
+	}
+}
diff --git a/substrate/frame/election-provider-support/benchmarking/src/lib.rs b/substrate/frame/election-provider-support/benchmarking/src/lib.rs
index 6c75aed0a91..78b226e52af 100644
--- a/substrate/frame/election-provider-support/benchmarking/src/lib.rs
+++ b/substrate/frame/election-provider-support/benchmarking/src/lib.rs
@@ -16,77 +16,11 @@
 // limitations under the License.
 
 //! Election provider support pallet benchmarking.
-//! This is separated into its own crate to avoid bloating the size of the runtime.
 
-#![cfg(feature = "runtime-benchmarks")]
 #![cfg_attr(not(feature = "std"), no_std)]
 
-use codec::Decode;
-use frame_benchmarking::v1::benchmarks;
-use frame_election_provider_support::{NposSolver, PhragMMS, SequentialPhragmen};
-use sp_std::vec::Vec;
+#[cfg(feature = "runtime-benchmarks")]
+pub mod inner;
 
-pub struct Pallet<T: Config>(frame_system::Pallet<T>);
-pub trait Config: frame_system::Config {}
-
-const VOTERS: [u32; 2] = [1_000, 2_000];
-const TARGETS: [u32; 2] = [500, 1_000];
-const VOTES_PER_VOTER: [u32; 2] = [5, 16];
-
-const SEED: u32 = 999;
-fn set_up_voters_targets<AccountId: Decode + Clone>(
-	voters_len: u32,
-	targets_len: u32,
-	degree: usize,
-) -> (Vec<(AccountId, u64, impl IntoIterator<Item = AccountId>)>, Vec<AccountId>) {
-	// fill targets.
-	let mut targets = (0..targets_len)
-		.map(|i| frame_benchmarking::account::<AccountId>("Target", i, SEED))
-		.collect::<Vec<_>>();
-	assert!(targets.len() > degree, "we should always have enough voters to fill");
-	targets.truncate(degree);
-
-	// fill voters.
-	let voters = (0..voters_len)
-		.map(|i| {
-			let voter = frame_benchmarking::account::<AccountId>("Voter", i, SEED);
-			(voter, 1_000, targets.clone())
-		})
-		.collect::<Vec<_>>();
-
-	(voters, targets)
-}
-
-benchmarks! {
-	phragmen {
-		// number of votes in snapshot.
-		let v in (VOTERS[0]) .. VOTERS[1];
-		// number of targets in snapshot.
-		let t in (TARGETS[0]) .. TARGETS[1];
-		// number of votes per voter (ie the degree).
-		let d in (VOTES_PER_VOTER[0]) .. VOTES_PER_VOTER[1];
-
-		let (voters, targets) = set_up_voters_targets::<T::AccountId>(v, t, d as usize);
-	}: {
-		assert!(
-			SequentialPhragmen::<T::AccountId, sp_runtime::Perbill>
-				::solve(d as usize, targets, voters).is_ok()
-		);
-	}
-
-	phragmms {
-		// number of votes in snapshot.
-		let v in (VOTERS[0]) .. VOTERS[1];
-		// number of targets in snapshot.
-		let t in (TARGETS[0]) .. TARGETS[1];
-		// number of votes per voter (ie the degree).
-		let d in (VOTES_PER_VOTER[0]) .. VOTES_PER_VOTER[1];
-
-		let (voters, targets) = set_up_voters_targets::<T::AccountId>(v, t, d as usize);
-	}: {
-		assert!(
-			PhragMMS::<T::AccountId, sp_runtime::Perbill>
-				::solve(d as usize, targets, voters).is_ok()
-		);
-	}
-}
+#[cfg(feature = "runtime-benchmarks")]
+pub use inner::*;
diff --git a/substrate/frame/examples/dev-mode/src/lib.rs b/substrate/frame/examples/dev-mode/src/lib.rs
index d57e7a5b76b..15f1a4b5d61 100644
--- a/substrate/frame/examples/dev-mode/src/lib.rs
+++ b/substrate/frame/examples/dev-mode/src/lib.rs
@@ -30,6 +30,7 @@
 
 use frame_support::dispatch::DispatchResult;
 use frame_system::ensure_signed;
+use sp_std::{vec, vec::Vec};
 
 // Re-export pallet items so that they can be accessed from the crate namespace.
 pub use pallet::*;
diff --git a/substrate/frame/examples/offchain-worker/Cargo.toml b/substrate/frame/examples/offchain-worker/Cargo.toml
index 468af0345ca..9363f753352 100644
--- a/substrate/frame/examples/offchain-worker/Cargo.toml
+++ b/substrate/frame/examples/offchain-worker/Cargo.toml
@@ -24,7 +24,7 @@ frame-support = { path = "../../support", default-features = false }
 frame-system = { path = "../../system", default-features = false }
 sp-core = { path = "../../../primitives/core", default-features = false }
 sp-io = { path = "../../../primitives/io", default-features = false }
-sp-keystore = { path = "../../../primitives/keystore", optional = true }
+sp-keystore = { path = "../../../primitives/keystore", optional = true, default-features = false }
 sp-runtime = { path = "../../../primitives/runtime", default-features = false }
 sp-std = { path = "../../../primitives/std", default-features = false }
 
diff --git a/substrate/frame/indices/Cargo.toml b/substrate/frame/indices/Cargo.toml
index 7b14bf358f1..8684f347270 100644
--- a/substrate/frame/indices/Cargo.toml
+++ b/substrate/frame/indices/Cargo.toml
@@ -23,7 +23,7 @@ frame-support = { path = "../support", default-features = false }
 frame-system = { path = "../system", default-features = false }
 sp-core = { path = "../../primitives/core", default-features = false }
 sp-io = { path = "../../primitives/io", default-features = false }
-sp-keyring = { path = "../../primitives/keyring", optional = true }
+sp-keyring = { path = "../../primitives/keyring", optional = true, default-features = false }
 sp-runtime = { path = "../../primitives/runtime", default-features = false }
 sp-std = { path = "../../primitives/std", default-features = false }
 
@@ -42,6 +42,7 @@ std = [
 	"sp-core/std",
 	"sp-io/std",
 	"sp-keyring",
+	"sp-keyring?/std",
 	"sp-runtime/std",
 	"sp-std/std",
 ]
diff --git a/substrate/frame/nomination-pools/Cargo.toml b/substrate/frame/nomination-pools/Cargo.toml
index 55e9ef6fbd3..eddcc8e4e1d 100644
--- a/substrate/frame/nomination-pools/Cargo.toml
+++ b/substrate/frame/nomination-pools/Cargo.toml
@@ -34,8 +34,8 @@ sp-io = { path = "../../primitives/io", default-features = false }
 log = { workspace = true }
 
 # Optional: use for testing and/or fuzzing
-pallet-balances = { path = "../balances", optional = true }
-sp-tracing = { path = "../../primitives/tracing", optional = true }
+pallet-balances = { path = "../balances", optional = true, default-features = false }
+sp-tracing = { path = "../../primitives/tracing", optional = true, default-features = false }
 
 [dev-dependencies]
 pallet-balances = { path = "../balances" }
diff --git a/substrate/frame/nomination-pools/benchmarking/src/inner.rs b/substrate/frame/nomination-pools/benchmarking/src/inner.rs
new file mode 100644
index 00000000000..277060e7f64
--- /dev/null
+++ b/substrate/frame/nomination-pools/benchmarking/src/inner.rs
@@ -0,0 +1,846 @@
+// 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.
+
+//! Benchmarks for the nomination pools coupled with the staking and bags list pallets.
+
+use frame_benchmarking::v1::{account, whitelist_account};
+use frame_election_provider_support::SortedListProvider;
+use frame_support::{
+	assert_ok, ensure,
+	traits::{
+		fungible::{Inspect, Mutate, Unbalanced},
+		Get,
+	},
+};
+use frame_system::RawOrigin as RuntimeOrigin;
+use pallet_nomination_pools::{
+	BalanceOf, BondExtra, BondedPoolInner, BondedPools, ClaimPermission, ClaimPermissions,
+	Commission, CommissionChangeRate, CommissionClaimPermission, ConfigOp, GlobalMaxCommission,
+	MaxPoolMembers, MaxPoolMembersPerPool, MaxPools, Metadata, MinCreateBond, MinJoinBond,
+	Pallet as Pools, PoolMembers, PoolRoles, PoolState, RewardPools, SubPoolsStorage,
+};
+use pallet_staking::MaxNominationsOf;
+use sp_runtime::{
+	traits::{Bounded, StaticLookup, Zero},
+	Perbill,
+};
+use sp_staking::{EraIndex, StakingInterface};
+use sp_std::{vec, vec::Vec};
+// `frame_benchmarking::benchmarks!` macro needs this
+use pallet_nomination_pools::Call;
+
+type CurrencyOf<T> = <T as pallet_nomination_pools::Config>::Currency;
+
+const USER_SEED: u32 = 0;
+const MAX_SPANS: u32 = 100;
+
+pub(crate) type VoterBagsListInstance = pallet_bags_list::Instance1;
+pub trait Config:
+	pallet_nomination_pools::Config
+	+ pallet_staking::Config
+	+ pallet_bags_list::Config<VoterBagsListInstance>
+{
+}
+
+pub struct Pallet<T: Config>(Pools<T>);
+
+fn create_funded_user_with_balance<T: pallet_nomination_pools::Config>(
+	string: &'static str,
+	n: u32,
+	balance: BalanceOf<T>,
+) -> T::AccountId {
+	let user = account(string, n, USER_SEED);
+	T::Currency::set_balance(&user, balance);
+	user
+}
+
+// Create a bonded pool account, bonding `balance` and giving the account `balance * 2` free
+// balance.
+fn create_pool_account<T: pallet_nomination_pools::Config>(
+	n: u32,
+	balance: BalanceOf<T>,
+	commission: Option<Perbill>,
+) -> (T::AccountId, T::AccountId) {
+	let ed = CurrencyOf::<T>::minimum_balance();
+	let pool_creator: T::AccountId =
+		create_funded_user_with_balance::<T>("pool_creator", n, ed + balance * 2u32.into());
+	let pool_creator_lookup = T::Lookup::unlookup(pool_creator.clone());
+
+	Pools::<T>::create(
+		RuntimeOrigin::Signed(pool_creator.clone()).into(),
+		balance,
+		pool_creator_lookup.clone(),
+		pool_creator_lookup.clone(),
+		pool_creator_lookup,
+	)
+	.unwrap();
+
+	if let Some(c) = commission {
+		let pool_id = pallet_nomination_pools::LastPoolId::<T>::get();
+		Pools::<T>::set_commission(
+			RuntimeOrigin::Signed(pool_creator.clone()).into(),
+			pool_id,
+			Some((c, pool_creator.clone())),
+		)
+		.expect("pool just created, commission can be set by root; qed");
+	}
+
+	let pool_account = pallet_nomination_pools::BondedPools::<T>::iter()
+		.find(|(_, bonded_pool)| bonded_pool.roles.depositor == pool_creator)
+		.map(|(pool_id, _)| Pools::<T>::create_bonded_account(pool_id))
+		.expect("pool_creator created a pool above");
+
+	(pool_creator, pool_account)
+}
+
+fn vote_to_balance<T: pallet_nomination_pools::Config>(
+	vote: u64,
+) -> Result<BalanceOf<T>, &'static str> {
+	vote.try_into().map_err(|_| "could not convert u64 to Balance")
+}
+
+#[allow(unused)]
+struct ListScenario<T: pallet_nomination_pools::Config> {
+	/// Stash/Controller that is expected to be moved.
+	origin1: T::AccountId,
+	creator1: T::AccountId,
+	dest_weight: BalanceOf<T>,
+	origin1_member: Option<T::AccountId>,
+}
+
+impl<T: Config> ListScenario<T> {
+	/// An expensive scenario for bags-list implementation:
+	///
+	/// - the node to be updated (r) is the head of a bag that has at least one other node. The bag
+	///   itself will need to be read and written to update its head. The node pointed to by r.next
+	///   will need to be read and written as it will need to have its prev pointer updated. Note
+	///   that there are two other worst case scenarios for bag removal: 1) the node is a tail and
+	///   2) the node is a middle node with prev and next; all scenarios end up with the same number
+	///   of storage reads and writes.
+	///
+	/// - the destination bag has at least one node, which will need its next pointer updated.
+	pub(crate) fn new(
+		origin_weight: BalanceOf<T>,
+		is_increase: bool,
+	) -> Result<Self, &'static str> {
+		ensure!(!origin_weight.is_zero(), "origin weight must be greater than 0");
+
+		ensure!(
+			pallet_nomination_pools::MaxPools::<T>::get().unwrap_or(0) >= 3,
+			"must allow at least three pools for benchmarks"
+		);
+
+		// Burn the entire issuance.
+		CurrencyOf::<T>::set_total_issuance(Zero::zero());
+
+		// Create accounts with the origin weight
+		let (pool_creator1, pool_origin1) =
+			create_pool_account::<T>(USER_SEED + 1, origin_weight, Some(Perbill::from_percent(50)));
+
+		T::Staking::nominate(
+			&pool_origin1,
+			// NOTE: these don't really need to be validators.
+			vec![account("random_validator", 0, USER_SEED)],
+		)?;
+
+		let (_, pool_origin2) =
+			create_pool_account::<T>(USER_SEED + 2, origin_weight, Some(Perbill::from_percent(50)));
+
+		T::Staking::nominate(
+			&pool_origin2,
+			vec![account("random_validator", 0, USER_SEED)].clone(),
+		)?;
+
+		// Find a destination weight that will trigger the worst case scenario
+		let dest_weight_as_vote = <T as pallet_staking::Config>::VoterList::score_update_worst_case(
+			&pool_origin1,
+			is_increase,
+		);
+
+		let dest_weight: BalanceOf<T> =
+			dest_weight_as_vote.try_into().map_err(|_| "could not convert u64 to Balance")?;
+
+		// Create an account with the worst case destination weight
+		let (_, pool_dest1) =
+			create_pool_account::<T>(USER_SEED + 3, dest_weight, Some(Perbill::from_percent(50)));
+
+		T::Staking::nominate(&pool_dest1, vec![account("random_validator", 0, USER_SEED)])?;
+
+		let weight_of = pallet_staking::Pallet::<T>::weight_of_fn();
+		assert_eq!(vote_to_balance::<T>(weight_of(&pool_origin1)).unwrap(), origin_weight);
+		assert_eq!(vote_to_balance::<T>(weight_of(&pool_origin2)).unwrap(), origin_weight);
+		assert_eq!(vote_to_balance::<T>(weight_of(&pool_dest1)).unwrap(), dest_weight);
+
+		Ok(ListScenario {
+			origin1: pool_origin1,
+			creator1: pool_creator1,
+			dest_weight,
+			origin1_member: None,
+		})
+	}
+
+	fn add_joiner(mut self, amount: BalanceOf<T>) -> Self {
+		let amount = MinJoinBond::<T>::get()
+			.max(CurrencyOf::<T>::minimum_balance())
+			// Max `amount` with minimum thresholds for account balance and joining a pool
+			// to ensure 1) the user can be created and 2) can join the pool
+			.max(amount);
+
+		let joiner: T::AccountId = account("joiner", USER_SEED, 0);
+		self.origin1_member = Some(joiner.clone());
+		CurrencyOf::<T>::set_balance(&joiner, amount * 2u32.into());
+
+		let original_bonded = T::Staking::active_stake(&self.origin1).unwrap();
+
+		// Unbond `amount` from the underlying pool account so when the member joins
+		// we will maintain `current_bonded`.
+		T::Staking::unbond(&self.origin1, amount).expect("the pool was created in `Self::new`.");
+
+		// Account pool points for the unbonded balance.
+		BondedPools::<T>::mutate(&1, |maybe_pool| {
+			maybe_pool.as_mut().map(|pool| pool.points -= amount)
+		});
+
+		Pools::<T>::join(RuntimeOrigin::Signed(joiner.clone()).into(), amount, 1).unwrap();
+
+		// check that the vote weight is still the same as the original bonded
+		let weight_of = pallet_staking::Pallet::<T>::weight_of_fn();
+		assert_eq!(vote_to_balance::<T>(weight_of(&self.origin1)).unwrap(), original_bonded);
+
+		// check the member was added correctly
+		let member = PoolMembers::<T>::get(&joiner).unwrap();
+		assert_eq!(member.points, amount);
+		assert_eq!(member.pool_id, 1);
+
+		self
+	}
+}
+
+frame_benchmarking::benchmarks! {
+	join {
+		let origin_weight = Pools::<T>::depositor_min_bond() * 2u32.into();
+
+		// setup the worst case list scenario.
+		let scenario = ListScenario::<T>::new(origin_weight, true)?;
+		assert_eq!(
+			T::Staking::active_stake(&scenario.origin1).unwrap(),
+			origin_weight
+		);
+
+		let max_additional = scenario.dest_weight - origin_weight;
+		let joiner_free = CurrencyOf::<T>::minimum_balance() + max_additional;
+
+		let joiner: T::AccountId
+			= create_funded_user_with_balance::<T>("joiner", 0, joiner_free);
+
+		whitelist_account!(joiner);
+	}: _(RuntimeOrigin::Signed(joiner.clone()), max_additional, 1)
+	verify {
+		assert_eq!(CurrencyOf::<T>::balance(&joiner), joiner_free - max_additional);
+		assert_eq!(
+			T::Staking::active_stake(&scenario.origin1).unwrap(),
+			scenario.dest_weight
+		);
+	}
+
+	bond_extra_transfer {
+		let origin_weight = Pools::<T>::depositor_min_bond() * 2u32.into();
+		let scenario = ListScenario::<T>::new(origin_weight, true)?;
+		let extra = scenario.dest_weight - origin_weight;
+
+		// creator of the src pool will bond-extra, bumping itself to dest bag.
+
+	}: bond_extra(RuntimeOrigin::Signed(scenario.creator1.clone()), BondExtra::FreeBalance(extra))
+	verify {
+		assert!(
+			T::Staking::active_stake(&scenario.origin1).unwrap() >=
+			scenario.dest_weight
+		);
+	}
+
+	bond_extra_other {
+		let claimer: T::AccountId = account("claimer", USER_SEED + 4, 0);
+
+		let origin_weight = Pools::<T>::depositor_min_bond() * 2u32.into();
+		let scenario = ListScenario::<T>::new(origin_weight, true)?;
+		let extra = (scenario.dest_weight - origin_weight).max(CurrencyOf::<T>::minimum_balance());
+
+		// set claim preferences to `PermissionlessAll` to any account to bond extra on member's behalf.
+		let _ = Pools::<T>::set_claim_permission(RuntimeOrigin::Signed(scenario.creator1.clone()).into(), ClaimPermission::PermissionlessAll);
+
+		// transfer exactly `extra` to the depositor of the src pool (1),
+		let reward_account1 = Pools::<T>::create_reward_account(1);
+		assert!(extra >= CurrencyOf::<T>::minimum_balance());
+		let _ = CurrencyOf::<T>::mint_into(&reward_account1, extra);
+
+	}: _(RuntimeOrigin::Signed(claimer), T::Lookup::unlookup(scenario.creator1.clone()), BondExtra::Rewards)
+	verify {
+		 // commission of 50% deducted here.
+		assert!(
+			T::Staking::active_stake(&scenario.origin1).unwrap() >=
+			scenario.dest_weight / 2u32.into()
+		);
+	}
+
+	claim_payout {
+		let claimer: T::AccountId = account("claimer", USER_SEED + 4, 0);
+		let commission = Perbill::from_percent(50);
+		let origin_weight = Pools::<T>::depositor_min_bond() * 2u32.into();
+		let ed = CurrencyOf::<T>::minimum_balance();
+		let (depositor, pool_account) = create_pool_account::<T>(0, origin_weight, Some(commission));
+		let reward_account = Pools::<T>::create_reward_account(1);
+
+		// Send funds to the reward account of the pool
+		CurrencyOf::<T>::set_balance(&reward_account, ed + origin_weight);
+
+		// set claim preferences to `PermissionlessAll` so any account can claim rewards on member's
+		// behalf.
+		let _ = Pools::<T>::set_claim_permission(RuntimeOrigin::Signed(depositor.clone()).into(), ClaimPermission::PermissionlessAll);
+
+		// Sanity check
+		assert_eq!(
+			CurrencyOf::<T>::balance(&depositor),
+			origin_weight
+		);
+
+		whitelist_account!(depositor);
+	}:claim_payout_other(RuntimeOrigin::Signed(claimer), depositor.clone())
+	verify {
+		assert_eq!(
+			CurrencyOf::<T>::balance(&depositor),
+			origin_weight + commission * origin_weight
+		);
+		assert_eq!(
+			CurrencyOf::<T>::balance(&reward_account),
+			ed + commission * origin_weight
+		);
+	}
+
+
+	unbond {
+		// The weight the nominator will start at. The value used here is expected to be
+		// significantly higher than the first position in a list (e.g. the first bag threshold).
+		let origin_weight = Pools::<T>::depositor_min_bond() * 200u32.into();
+		let scenario = ListScenario::<T>::new(origin_weight, false)?;
+		let amount = origin_weight - scenario.dest_weight;
+
+		let scenario = scenario.add_joiner(amount);
+		let member_id = scenario.origin1_member.unwrap().clone();
+		let member_id_lookup = T::Lookup::unlookup(member_id.clone());
+		let all_points = PoolMembers::<T>::get(&member_id).unwrap().points;
+		whitelist_account!(member_id);
+	}: _(RuntimeOrigin::Signed(member_id.clone()), member_id_lookup, all_points)
+	verify {
+		let bonded_after = T::Staking::active_stake(&scenario.origin1).unwrap();
+		// We at least went down to the destination bag
+		assert!(bonded_after <= scenario.dest_weight);
+		let member = PoolMembers::<T>::get(
+			&member_id
+		)
+		.unwrap();
+		assert_eq!(
+			member.unbonding_eras.keys().cloned().collect::<Vec<_>>(),
+			vec![0 + T::Staking::bonding_duration()]
+		);
+		assert_eq!(
+			member.unbonding_eras.values().cloned().collect::<Vec<_>>(),
+			vec![all_points]
+		);
+	}
+
+	pool_withdraw_unbonded {
+		let s in 0 .. MAX_SPANS;
+
+		let min_create_bond = Pools::<T>::depositor_min_bond();
+		let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
+
+		// Add a new member
+		let min_join_bond = MinJoinBond::<T>::get().max(CurrencyOf::<T>::minimum_balance());
+		let joiner = create_funded_user_with_balance::<T>("joiner", 0, min_join_bond * 2u32.into());
+		Pools::<T>::join(RuntimeOrigin::Signed(joiner.clone()).into(), min_join_bond, 1)
+			.unwrap();
+
+		// Sanity check join worked
+		assert_eq!(
+			T::Staking::active_stake(&pool_account).unwrap(),
+			min_create_bond + min_join_bond
+		);
+		assert_eq!(CurrencyOf::<T>::balance(&joiner), min_join_bond);
+
+		// Unbond the new member
+		Pools::<T>::fully_unbond(RuntimeOrigin::Signed(joiner.clone()).into(), joiner.clone()).unwrap();
+
+		// Sanity check that unbond worked
+		assert_eq!(
+			T::Staking::active_stake(&pool_account).unwrap(),
+			min_create_bond
+		);
+		assert_eq!(pallet_staking::Ledger::<T>::get(&pool_account).unwrap().unlocking.len(), 1);
+		// Set the current era
+		pallet_staking::CurrentEra::<T>::put(EraIndex::max_value());
+
+		// Add `s` count of slashing spans to storage.
+		pallet_staking::benchmarking::add_slashing_spans::<T>(&pool_account, s);
+		whitelist_account!(pool_account);
+	}: _(RuntimeOrigin::Signed(pool_account.clone()), 1, s)
+	verify {
+		// The joiners funds didn't change
+		assert_eq!(CurrencyOf::<T>::balance(&joiner), min_join_bond);
+		// The unlocking chunk was removed
+		assert_eq!(pallet_staking::Ledger::<T>::get(pool_account).unwrap().unlocking.len(), 0);
+	}
+
+	withdraw_unbonded_update {
+		let s in 0 .. MAX_SPANS;
+
+		let min_create_bond = Pools::<T>::depositor_min_bond();
+		let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
+
+		// Add a new member
+		let min_join_bond = MinJoinBond::<T>::get().max(CurrencyOf::<T>::minimum_balance());
+		let joiner = create_funded_user_with_balance::<T>("joiner", 0, min_join_bond * 2u32.into());
+		let joiner_lookup = T::Lookup::unlookup(joiner.clone());
+		Pools::<T>::join(RuntimeOrigin::Signed(joiner.clone()).into(), min_join_bond, 1)
+			.unwrap();
+
+		// Sanity check join worked
+		assert_eq!(
+			T::Staking::active_stake(&pool_account).unwrap(),
+			min_create_bond + min_join_bond
+		);
+		assert_eq!(CurrencyOf::<T>::balance(&joiner), min_join_bond);
+
+		// Unbond the new member
+		pallet_staking::CurrentEra::<T>::put(0);
+		Pools::<T>::fully_unbond(RuntimeOrigin::Signed(joiner.clone()).into(), joiner.clone()).unwrap();
+
+		// Sanity check that unbond worked
+		assert_eq!(
+			T::Staking::active_stake(&pool_account).unwrap(),
+			min_create_bond
+		);
+		assert_eq!(pallet_staking::Ledger::<T>::get(&pool_account).unwrap().unlocking.len(), 1);
+
+		// Set the current era to ensure we can withdraw unbonded funds
+		pallet_staking::CurrentEra::<T>::put(EraIndex::max_value());
+
+		pallet_staking::benchmarking::add_slashing_spans::<T>(&pool_account, s);
+		whitelist_account!(joiner);
+	}: withdraw_unbonded(RuntimeOrigin::Signed(joiner.clone()), joiner_lookup, s)
+	verify {
+		assert_eq!(
+			CurrencyOf::<T>::balance(&joiner), min_join_bond * 2u32.into()
+		);
+		// The unlocking chunk was removed
+		assert_eq!(pallet_staking::Ledger::<T>::get(&pool_account).unwrap().unlocking.len(), 0);
+	}
+
+	withdraw_unbonded_kill {
+		let s in 0 .. MAX_SPANS;
+
+		let min_create_bond = Pools::<T>::depositor_min_bond();
+		let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
+		let depositor_lookup = T::Lookup::unlookup(depositor.clone());
+
+		// We set the pool to the destroying state so the depositor can leave
+		BondedPools::<T>::try_mutate(&1, |maybe_bonded_pool| {
+			maybe_bonded_pool.as_mut().ok_or(()).map(|bonded_pool| {
+				bonded_pool.state = PoolState::Destroying;
+			})
+		})
+		.unwrap();
+
+		// Unbond the creator
+		pallet_staking::CurrentEra::<T>::put(0);
+		// Simulate some rewards so we can check if the rewards storage is cleaned up. We check this
+		// here to ensure the complete flow for destroying a pool works - the reward pool account
+		// should never exist by time the depositor withdraws so we test that it gets cleaned
+		// up when unbonding.
+		let reward_account = Pools::<T>::create_reward_account(1);
+		assert!(frame_system::Account::<T>::contains_key(&reward_account));
+		Pools::<T>::fully_unbond(RuntimeOrigin::Signed(depositor.clone()).into(), depositor.clone()).unwrap();
+
+		// Sanity check that unbond worked
+		assert_eq!(
+			T::Staking::active_stake(&pool_account).unwrap(),
+			Zero::zero()
+		);
+		assert_eq!(
+			CurrencyOf::<T>::balance(&pool_account),
+			min_create_bond
+		);
+		assert_eq!(pallet_staking::Ledger::<T>::get(&pool_account).unwrap().unlocking.len(), 1);
+
+		// Set the current era to ensure we can withdraw unbonded funds
+		pallet_staking::CurrentEra::<T>::put(EraIndex::max_value());
+
+		// Some last checks that storage items we expect to get cleaned up are present
+		assert!(pallet_staking::Ledger::<T>::contains_key(&pool_account));
+		assert!(BondedPools::<T>::contains_key(&1));
+		assert!(SubPoolsStorage::<T>::contains_key(&1));
+		assert!(RewardPools::<T>::contains_key(&1));
+		assert!(PoolMembers::<T>::contains_key(&depositor));
+		assert!(frame_system::Account::<T>::contains_key(&reward_account));
+
+		whitelist_account!(depositor);
+	}: withdraw_unbonded(RuntimeOrigin::Signed(depositor.clone()), depositor_lookup, s)
+	verify {
+		// Pool removal worked
+		assert!(!pallet_staking::Ledger::<T>::contains_key(&pool_account));
+		assert!(!BondedPools::<T>::contains_key(&1));
+		assert!(!SubPoolsStorage::<T>::contains_key(&1));
+		assert!(!RewardPools::<T>::contains_key(&1));
+		assert!(!PoolMembers::<T>::contains_key(&depositor));
+		assert!(!frame_system::Account::<T>::contains_key(&pool_account));
+		assert!(!frame_system::Account::<T>::contains_key(&reward_account));
+
+		// Funds where transferred back correctly
+		assert_eq!(
+			CurrencyOf::<T>::balance(&depositor),
+			// gets bond back + rewards collecting when unbonding
+			min_create_bond * 2u32.into() + CurrencyOf::<T>::minimum_balance()
+		);
+	}
+
+	create {
+		let min_create_bond = Pools::<T>::depositor_min_bond();
+		let depositor: T::AccountId = account("depositor", USER_SEED, 0);
+		let depositor_lookup = T::Lookup::unlookup(depositor.clone());
+
+		// Give the depositor some balance to bond
+		CurrencyOf::<T>::set_balance(&depositor, min_create_bond * 2u32.into());
+
+		// Make sure no Pools exist at a pre-condition for our verify checks
+		assert_eq!(RewardPools::<T>::count(), 0);
+		assert_eq!(BondedPools::<T>::count(), 0);
+
+		whitelist_account!(depositor);
+	}: _(
+			RuntimeOrigin::Signed(depositor.clone()),
+			min_create_bond,
+			depositor_lookup.clone(),
+			depositor_lookup.clone(),
+			depositor_lookup
+		)
+	verify {
+		assert_eq!(RewardPools::<T>::count(), 1);
+		assert_eq!(BondedPools::<T>::count(), 1);
+		let (_, new_pool) = BondedPools::<T>::iter().next().unwrap();
+		assert_eq!(
+			new_pool,
+			BondedPoolInner {
+				commission: Commission::default(),
+				member_counter: 1,
+				points: min_create_bond,
+				roles: PoolRoles {
+					depositor: depositor.clone(),
+					root: Some(depositor.clone()),
+					nominator: Some(depositor.clone()),
+					bouncer: Some(depositor.clone()),
+				},
+				state: PoolState::Open,
+			}
+		);
+		assert_eq!(
+			T::Staking::active_stake(&Pools::<T>::create_bonded_account(1)),
+			Ok(min_create_bond)
+		);
+	}
+
+	nominate {
+		let n in 1 .. MaxNominationsOf::<T>::get();
+
+		// Create a pool
+		let min_create_bond = Pools::<T>::depositor_min_bond() * 2u32.into();
+		let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
+
+		// Create some accounts to nominate. For the sake of benchmarking they don't need to be
+		// actual validators
+		 let validators: Vec<_> = (0..n)
+			.map(|i| account("stash", USER_SEED, i))
+			.collect();
+
+		whitelist_account!(depositor);
+	}:_(RuntimeOrigin::Signed(depositor.clone()), 1, validators)
+	verify {
+		assert_eq!(RewardPools::<T>::count(), 1);
+		assert_eq!(BondedPools::<T>::count(), 1);
+		let (_, new_pool) = BondedPools::<T>::iter().next().unwrap();
+		assert_eq!(
+			new_pool,
+			BondedPoolInner {
+				commission: Commission::default(),
+				member_counter: 1,
+				points: min_create_bond,
+				roles: PoolRoles {
+					depositor: depositor.clone(),
+					root: Some(depositor.clone()),
+					nominator: Some(depositor.clone()),
+					bouncer: Some(depositor.clone()),
+				},
+				state: PoolState::Open,
+			}
+		);
+		assert_eq!(
+			T::Staking::active_stake(&Pools::<T>::create_bonded_account(1)),
+			Ok(min_create_bond)
+		);
+	}
+
+	set_state {
+		// Create a pool
+		let min_create_bond = Pools::<T>::depositor_min_bond();
+		let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
+		BondedPools::<T>::mutate(&1, |maybe_pool| {
+			// Force the pool into an invalid state
+			maybe_pool.as_mut().map(|pool| pool.points = min_create_bond * 10u32.into());
+		});
+
+		let caller = account("caller", 0, USER_SEED);
+		whitelist_account!(caller);
+	}:_(RuntimeOrigin::Signed(caller), 1, PoolState::Destroying)
+	verify {
+		assert_eq!(BondedPools::<T>::get(1).unwrap().state, PoolState::Destroying);
+	}
+
+	set_metadata {
+		let n in 1 .. <T as pallet_nomination_pools::Config>::MaxMetadataLen::get();
+
+		// Create a pool
+		let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
+
+		// Create metadata of the max possible size
+		let metadata: Vec<u8> = (0..n).map(|_| 42).collect();
+
+		whitelist_account!(depositor);
+	}:_(RuntimeOrigin::Signed(depositor), 1, metadata.clone())
+	verify {
+		assert_eq!(Metadata::<T>::get(&1), metadata);
+	}
+
+	set_configs {
+	}:_(
+		RuntimeOrigin::Root,
+		ConfigOp::Set(BalanceOf::<T>::max_value()),
+		ConfigOp::Set(BalanceOf::<T>::max_value()),
+		ConfigOp::Set(u32::MAX),
+		ConfigOp::Set(u32::MAX),
+		ConfigOp::Set(u32::MAX),
+		ConfigOp::Set(Perbill::max_value())
+	) verify {
+		assert_eq!(MinJoinBond::<T>::get(), BalanceOf::<T>::max_value());
+		assert_eq!(MinCreateBond::<T>::get(), BalanceOf::<T>::max_value());
+		assert_eq!(MaxPools::<T>::get(), Some(u32::MAX));
+		assert_eq!(MaxPoolMembers::<T>::get(), Some(u32::MAX));
+		assert_eq!(MaxPoolMembersPerPool::<T>::get(), Some(u32::MAX));
+		assert_eq!(GlobalMaxCommission::<T>::get(), Some(Perbill::max_value()));
+	}
+
+	update_roles {
+		let first_id = pallet_nomination_pools::LastPoolId::<T>::get() + 1;
+		let (root, _) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
+		let random: T::AccountId = account("but is anything really random in computers..?", 0, USER_SEED);
+	}:_(
+		RuntimeOrigin::Signed(root.clone()),
+		first_id,
+		ConfigOp::Set(random.clone()),
+		ConfigOp::Set(random.clone()),
+		ConfigOp::Set(random.clone())
+	) verify {
+		assert_eq!(
+			pallet_nomination_pools::BondedPools::<T>::get(first_id).unwrap().roles,
+			pallet_nomination_pools::PoolRoles {
+				depositor: root,
+				nominator: Some(random.clone()),
+				bouncer: Some(random.clone()),
+				root: Some(random),
+			},
+		)
+	}
+
+	chill {
+		// Create a pool
+		let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
+
+		// Nominate with the pool.
+		 let validators: Vec<_> = (0..MaxNominationsOf::<T>::get())
+			.map(|i| account("stash", USER_SEED, i))
+			.collect();
+
+		assert_ok!(T::Staking::nominate(&pool_account, validators));
+		assert!(T::Staking::nominations(&Pools::<T>::create_bonded_account(1)).is_some());
+
+		whitelist_account!(depositor);
+	}:_(RuntimeOrigin::Signed(depositor.clone()), 1)
+	verify {
+		assert!(T::Staking::nominations(&Pools::<T>::create_bonded_account(1)).is_none());
+	}
+
+	set_commission {
+		// Create a pool - do not set a commission yet.
+		let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
+		// set a max commission
+		Pools::<T>::set_commission_max(RuntimeOrigin::Signed(depositor.clone()).into(), 1u32.into(), Perbill::from_percent(50)).unwrap();
+		// set a change rate
+		Pools::<T>::set_commission_change_rate(RuntimeOrigin::Signed(depositor.clone()).into(), 1u32.into(), CommissionChangeRate {
+			max_increase: Perbill::from_percent(20),
+			min_delay: 0u32.into(),
+		}).unwrap();
+		// set a claim permission to an account.
+		Pools::<T>::set_commission_claim_permission(
+			RuntimeOrigin::Signed(depositor.clone()).into(),
+			1u32.into(),
+			Some(CommissionClaimPermission::Account(depositor.clone()))
+		).unwrap();
+
+	}:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into(), Some((Perbill::from_percent(20), depositor.clone())))
+	verify {
+		assert_eq!(BondedPools::<T>::get(1).unwrap().commission, Commission {
+			current: Some((Perbill::from_percent(20), depositor.clone())),
+			max: Some(Perbill::from_percent(50)),
+			change_rate: Some(CommissionChangeRate {
+					max_increase: Perbill::from_percent(20),
+					min_delay: 0u32.into()
+			}),
+			throttle_from: Some(1u32.into()),
+			claim_permission: Some(CommissionClaimPermission::Account(depositor)),
+		});
+	}
+
+	set_commission_max {
+		// Create a pool, setting a commission that will update when max commission is set.
+		let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), Some(Perbill::from_percent(50)));
+	}:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into(), Perbill::from_percent(50))
+	verify {
+		assert_eq!(
+			BondedPools::<T>::get(1).unwrap().commission, Commission {
+			current: Some((Perbill::from_percent(50), depositor)),
+			max: Some(Perbill::from_percent(50)),
+			change_rate: None,
+			throttle_from: Some(0u32.into()),
+			claim_permission: None,
+		});
+	}
+
+	set_commission_change_rate {
+		// Create a pool
+		let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
+	}:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into(), CommissionChangeRate {
+		max_increase: Perbill::from_percent(50),
+		min_delay: 1000u32.into(),
+	})
+	verify {
+		assert_eq!(
+			BondedPools::<T>::get(1).unwrap().commission, Commission {
+			current: None,
+			max: None,
+			change_rate: Some(CommissionChangeRate {
+				max_increase: Perbill::from_percent(50),
+				min_delay: 1000u32.into(),
+			}),
+			throttle_from: Some(1_u32.into()),
+			claim_permission: None,
+		});
+  }
+
+	set_commission_claim_permission {
+		// Create a pool.
+		let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
+	}:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into(), Some(CommissionClaimPermission::Account(depositor.clone())))
+	verify {
+		assert_eq!(
+			BondedPools::<T>::get(1).unwrap().commission, Commission {
+			current: None,
+			max: None,
+			change_rate: None,
+			throttle_from: None,
+			claim_permission: Some(CommissionClaimPermission::Account(depositor)),
+		});
+	}
+
+	set_claim_permission {
+		// Create a pool
+		let min_create_bond = Pools::<T>::depositor_min_bond();
+		let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
+
+		// Join pool
+		let min_join_bond = MinJoinBond::<T>::get().max(CurrencyOf::<T>::minimum_balance());
+		let joiner = create_funded_user_with_balance::<T>("joiner", 0, min_join_bond * 4u32.into());
+		let joiner_lookup = T::Lookup::unlookup(joiner.clone());
+		Pools::<T>::join(RuntimeOrigin::Signed(joiner.clone()).into(), min_join_bond, 1)
+			.unwrap();
+
+		// Sanity check join worked
+		assert_eq!(
+			T::Staking::active_stake(&pool_account).unwrap(),
+			min_create_bond + min_join_bond
+		);
+	}:_(RuntimeOrigin::Signed(joiner.clone()), ClaimPermission::Permissioned)
+	verify {
+		assert_eq!(ClaimPermissions::<T>::get(joiner), ClaimPermission::Permissioned);
+	}
+
+	claim_commission {
+		let claimer: T::AccountId = account("claimer_member", USER_SEED + 4, 0);
+		let commission = Perbill::from_percent(50);
+		let origin_weight = Pools::<T>::depositor_min_bond() * 2u32.into();
+		let ed = CurrencyOf::<T>::minimum_balance();
+		let (depositor, pool_account) = create_pool_account::<T>(0, origin_weight, Some(commission));
+		let reward_account = Pools::<T>::create_reward_account(1);
+		CurrencyOf::<T>::set_balance(&reward_account, ed + origin_weight);
+
+		// member claims a payout to make some commission available.
+		let _ = Pools::<T>::claim_payout(RuntimeOrigin::Signed(claimer.clone()).into());
+		// set a claim permission to an account.
+		let _ = Pools::<T>::set_commission_claim_permission(
+			RuntimeOrigin::Signed(depositor.clone()).into(),
+			1u32.into(),
+			Some(CommissionClaimPermission::Account(claimer))
+		);
+		whitelist_account!(depositor);
+	}:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into())
+	verify {
+		assert_eq!(
+			CurrencyOf::<T>::balance(&depositor),
+			origin_weight + commission * origin_weight
+		);
+		assert_eq!(
+			CurrencyOf::<T>::balance(&reward_account),
+			ed + commission * origin_weight
+		);
+	}
+
+	adjust_pool_deposit {
+		// Create a pool
+		let (depositor, _) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
+
+		// Remove ed freeze to create a scenario where the ed deposit needs to be adjusted.
+		let _ = Pools::<T>::unfreeze_pool_deposit(&Pools::<T>::create_reward_account(1));
+		assert!(&Pools::<T>::check_ed_imbalance().is_err());
+
+		whitelist_account!(depositor);
+	}:_(RuntimeOrigin::Signed(depositor), 1)
+	verify {
+		assert!(&Pools::<T>::check_ed_imbalance().is_ok());
+	}
+
+	impl_benchmark_test_suite!(
+		Pallet,
+		crate::mock::new_test_ext(),
+		crate::mock::Runtime
+	);
+}
diff --git a/substrate/frame/nomination-pools/benchmarking/src/lib.rs b/substrate/frame/nomination-pools/benchmarking/src/lib.rs
index f7df173ec04..45e8f1f27e9 100644
--- a/substrate/frame/nomination-pools/benchmarking/src/lib.rs
+++ b/substrate/frame/nomination-pools/benchmarking/src/lib.rs
@@ -17,836 +17,13 @@
 
 //! Benchmarks for the nomination pools coupled with the staking and bags list pallets.
 
-#![cfg(feature = "runtime-benchmarks")]
 #![cfg_attr(not(feature = "std"), no_std)]
 
-#[cfg(test)]
-mod mock;
+#[cfg(feature = "runtime-benchmarks")]
+pub mod inner;
 
-use frame_benchmarking::v1::{account, whitelist_account};
-use frame_election_provider_support::SortedListProvider;
-use frame_support::{
-	assert_ok, ensure,
-	traits::{
-		fungible::{Inspect, Mutate, Unbalanced},
-		Get,
-	},
-};
-use frame_system::RawOrigin as RuntimeOrigin;
-use pallet_nomination_pools::{
-	BalanceOf, BondExtra, BondedPoolInner, BondedPools, ClaimPermission, ClaimPermissions,
-	Commission, CommissionChangeRate, CommissionClaimPermission, ConfigOp, GlobalMaxCommission,
-	MaxPoolMembers, MaxPoolMembersPerPool, MaxPools, Metadata, MinCreateBond, MinJoinBond,
-	Pallet as Pools, PoolMembers, PoolRoles, PoolState, RewardPools, SubPoolsStorage,
-};
-use pallet_staking::MaxNominationsOf;
-use sp_runtime::{
-	traits::{Bounded, StaticLookup, Zero},
-	Perbill,
-};
-use sp_staking::{EraIndex, StakingInterface};
-use sp_std::{vec, vec::Vec};
-// `frame_benchmarking::benchmarks!` macro needs this
-use pallet_nomination_pools::Call;
+#[cfg(feature = "runtime-benchmarks")]
+pub use inner::*;
 
-type CurrencyOf<T> = <T as pallet_nomination_pools::Config>::Currency;
-
-const USER_SEED: u32 = 0;
-const MAX_SPANS: u32 = 100;
-
-type VoterBagsListInstance = pallet_bags_list::Instance1;
-pub trait Config:
-	pallet_nomination_pools::Config
-	+ pallet_staking::Config
-	+ pallet_bags_list::Config<VoterBagsListInstance>
-{
-}
-
-pub struct Pallet<T: Config>(Pools<T>);
-
-fn create_funded_user_with_balance<T: pallet_nomination_pools::Config>(
-	string: &'static str,
-	n: u32,
-	balance: BalanceOf<T>,
-) -> T::AccountId {
-	let user = account(string, n, USER_SEED);
-	T::Currency::set_balance(&user, balance);
-	user
-}
-
-// Create a bonded pool account, bonding `balance` and giving the account `balance * 2` free
-// balance.
-fn create_pool_account<T: pallet_nomination_pools::Config>(
-	n: u32,
-	balance: BalanceOf<T>,
-	commission: Option<Perbill>,
-) -> (T::AccountId, T::AccountId) {
-	let ed = CurrencyOf::<T>::minimum_balance();
-	let pool_creator: T::AccountId =
-		create_funded_user_with_balance::<T>("pool_creator", n, ed + balance * 2u32.into());
-	let pool_creator_lookup = T::Lookup::unlookup(pool_creator.clone());
-
-	Pools::<T>::create(
-		RuntimeOrigin::Signed(pool_creator.clone()).into(),
-		balance,
-		pool_creator_lookup.clone(),
-		pool_creator_lookup.clone(),
-		pool_creator_lookup,
-	)
-	.unwrap();
-
-	if let Some(c) = commission {
-		let pool_id = pallet_nomination_pools::LastPoolId::<T>::get();
-		Pools::<T>::set_commission(
-			RuntimeOrigin::Signed(pool_creator.clone()).into(),
-			pool_id,
-			Some((c, pool_creator.clone())),
-		)
-		.expect("pool just created, commission can be set by root; qed");
-	}
-
-	let pool_account = pallet_nomination_pools::BondedPools::<T>::iter()
-		.find(|(_, bonded_pool)| bonded_pool.roles.depositor == pool_creator)
-		.map(|(pool_id, _)| Pools::<T>::create_bonded_account(pool_id))
-		.expect("pool_creator created a pool above");
-
-	(pool_creator, pool_account)
-}
-
-fn vote_to_balance<T: pallet_nomination_pools::Config>(
-	vote: u64,
-) -> Result<BalanceOf<T>, &'static str> {
-	vote.try_into().map_err(|_| "could not convert u64 to Balance")
-}
-
-#[allow(unused)]
-struct ListScenario<T: pallet_nomination_pools::Config> {
-	/// Stash/Controller that is expected to be moved.
-	origin1: T::AccountId,
-	creator1: T::AccountId,
-	dest_weight: BalanceOf<T>,
-	origin1_member: Option<T::AccountId>,
-}
-
-impl<T: Config> ListScenario<T> {
-	/// An expensive scenario for bags-list implementation:
-	///
-	/// - the node to be updated (r) is the head of a bag that has at least one other node. The bag
-	///   itself will need to be read and written to update its head. The node pointed to by r.next
-	///   will need to be read and written as it will need to have its prev pointer updated. Note
-	///   that there are two other worst case scenarios for bag removal: 1) the node is a tail and
-	///   2) the node is a middle node with prev and next; all scenarios end up with the same number
-	///   of storage reads and writes.
-	///
-	/// - the destination bag has at least one node, which will need its next pointer updated.
-	pub(crate) fn new(
-		origin_weight: BalanceOf<T>,
-		is_increase: bool,
-	) -> Result<Self, &'static str> {
-		ensure!(!origin_weight.is_zero(), "origin weight must be greater than 0");
-
-		ensure!(
-			pallet_nomination_pools::MaxPools::<T>::get().unwrap_or(0) >= 3,
-			"must allow at least three pools for benchmarks"
-		);
-
-		// Burn the entire issuance.
-		CurrencyOf::<T>::set_total_issuance(Zero::zero());
-
-		// Create accounts with the origin weight
-		let (pool_creator1, pool_origin1) =
-			create_pool_account::<T>(USER_SEED + 1, origin_weight, Some(Perbill::from_percent(50)));
-
-		T::Staking::nominate(
-			&pool_origin1,
-			// NOTE: these don't really need to be validators.
-			vec![account("random_validator", 0, USER_SEED)],
-		)?;
-
-		let (_, pool_origin2) =
-			create_pool_account::<T>(USER_SEED + 2, origin_weight, Some(Perbill::from_percent(50)));
-
-		T::Staking::nominate(
-			&pool_origin2,
-			vec![account("random_validator", 0, USER_SEED)].clone(),
-		)?;
-
-		// Find a destination weight that will trigger the worst case scenario
-		let dest_weight_as_vote = <T as pallet_staking::Config>::VoterList::score_update_worst_case(
-			&pool_origin1,
-			is_increase,
-		);
-
-		let dest_weight: BalanceOf<T> =
-			dest_weight_as_vote.try_into().map_err(|_| "could not convert u64 to Balance")?;
-
-		// Create an account with the worst case destination weight
-		let (_, pool_dest1) =
-			create_pool_account::<T>(USER_SEED + 3, dest_weight, Some(Perbill::from_percent(50)));
-
-		T::Staking::nominate(&pool_dest1, vec![account("random_validator", 0, USER_SEED)])?;
-
-		let weight_of = pallet_staking::Pallet::<T>::weight_of_fn();
-		assert_eq!(vote_to_balance::<T>(weight_of(&pool_origin1)).unwrap(), origin_weight);
-		assert_eq!(vote_to_balance::<T>(weight_of(&pool_origin2)).unwrap(), origin_weight);
-		assert_eq!(vote_to_balance::<T>(weight_of(&pool_dest1)).unwrap(), dest_weight);
-
-		Ok(ListScenario {
-			origin1: pool_origin1,
-			creator1: pool_creator1,
-			dest_weight,
-			origin1_member: None,
-		})
-	}
-
-	fn add_joiner(mut self, amount: BalanceOf<T>) -> Self {
-		let amount = MinJoinBond::<T>::get()
-			.max(CurrencyOf::<T>::minimum_balance())
-			// Max `amount` with minimum thresholds for account balance and joining a pool
-			// to ensure 1) the user can be created and 2) can join the pool
-			.max(amount);
-
-		let joiner: T::AccountId = account("joiner", USER_SEED, 0);
-		self.origin1_member = Some(joiner.clone());
-		CurrencyOf::<T>::set_balance(&joiner, amount * 2u32.into());
-
-		let original_bonded = T::Staking::active_stake(&self.origin1).unwrap();
-
-		// Unbond `amount` from the underlying pool account so when the member joins
-		// we will maintain `current_bonded`.
-		T::Staking::unbond(&self.origin1, amount).expect("the pool was created in `Self::new`.");
-
-		// Account pool points for the unbonded balance.
-		BondedPools::<T>::mutate(&1, |maybe_pool| {
-			maybe_pool.as_mut().map(|pool| pool.points -= amount)
-		});
-
-		Pools::<T>::join(RuntimeOrigin::Signed(joiner.clone()).into(), amount, 1).unwrap();
-
-		// check that the vote weight is still the same as the original bonded
-		let weight_of = pallet_staking::Pallet::<T>::weight_of_fn();
-		assert_eq!(vote_to_balance::<T>(weight_of(&self.origin1)).unwrap(), original_bonded);
-
-		// check the member was added correctly
-		let member = PoolMembers::<T>::get(&joiner).unwrap();
-		assert_eq!(member.points, amount);
-		assert_eq!(member.pool_id, 1);
-
-		self
-	}
-}
-
-frame_benchmarking::benchmarks! {
-	join {
-		let origin_weight = Pools::<T>::depositor_min_bond() * 2u32.into();
-
-		// setup the worst case list scenario.
-		let scenario = ListScenario::<T>::new(origin_weight, true)?;
-		assert_eq!(
-			T::Staking::active_stake(&scenario.origin1).unwrap(),
-			origin_weight
-		);
-
-		let max_additional = scenario.dest_weight - origin_weight;
-		let joiner_free = CurrencyOf::<T>::minimum_balance() + max_additional;
-
-		let joiner: T::AccountId
-			= create_funded_user_with_balance::<T>("joiner", 0, joiner_free);
-
-		whitelist_account!(joiner);
-	}: _(RuntimeOrigin::Signed(joiner.clone()), max_additional, 1)
-	verify {
-		assert_eq!(CurrencyOf::<T>::balance(&joiner), joiner_free - max_additional);
-		assert_eq!(
-			T::Staking::active_stake(&scenario.origin1).unwrap(),
-			scenario.dest_weight
-		);
-	}
-
-	bond_extra_transfer {
-		let origin_weight = Pools::<T>::depositor_min_bond() * 2u32.into();
-		let scenario = ListScenario::<T>::new(origin_weight, true)?;
-		let extra = scenario.dest_weight - origin_weight;
-
-		// creator of the src pool will bond-extra, bumping itself to dest bag.
-
-	}: bond_extra(RuntimeOrigin::Signed(scenario.creator1.clone()), BondExtra::FreeBalance(extra))
-	verify {
-		assert!(
-			T::Staking::active_stake(&scenario.origin1).unwrap() >=
-			scenario.dest_weight
-		);
-	}
-
-	bond_extra_other {
-		let claimer: T::AccountId = account("claimer", USER_SEED + 4, 0);
-
-		let origin_weight = Pools::<T>::depositor_min_bond() * 2u32.into();
-		let scenario = ListScenario::<T>::new(origin_weight, true)?;
-		let extra = (scenario.dest_weight - origin_weight).max(CurrencyOf::<T>::minimum_balance());
-
-		// set claim preferences to `PermissionlessAll` to any account to bond extra on member's behalf.
-		let _ = Pools::<T>::set_claim_permission(RuntimeOrigin::Signed(scenario.creator1.clone()).into(), ClaimPermission::PermissionlessAll);
-
-		// transfer exactly `extra` to the depositor of the src pool (1),
-		let reward_account1 = Pools::<T>::create_reward_account(1);
-		assert!(extra >= CurrencyOf::<T>::minimum_balance());
-		let _ = CurrencyOf::<T>::mint_into(&reward_account1, extra);
-
-	}: _(RuntimeOrigin::Signed(claimer), T::Lookup::unlookup(scenario.creator1.clone()), BondExtra::Rewards)
-	verify {
-		 // commission of 50% deducted here.
-		assert!(
-			T::Staking::active_stake(&scenario.origin1).unwrap() >=
-			scenario.dest_weight / 2u32.into()
-		);
-	}
-
-	claim_payout {
-		let claimer: T::AccountId = account("claimer", USER_SEED + 4, 0);
-		let commission = Perbill::from_percent(50);
-		let origin_weight = Pools::<T>::depositor_min_bond() * 2u32.into();
-		let ed = CurrencyOf::<T>::minimum_balance();
-		let (depositor, pool_account) = create_pool_account::<T>(0, origin_weight, Some(commission));
-		let reward_account = Pools::<T>::create_reward_account(1);
-
-		// Send funds to the reward account of the pool
-		CurrencyOf::<T>::set_balance(&reward_account, ed + origin_weight);
-
-		// set claim preferences to `PermissionlessAll` so any account can claim rewards on member's
-		// behalf.
-		let _ = Pools::<T>::set_claim_permission(RuntimeOrigin::Signed(depositor.clone()).into(), ClaimPermission::PermissionlessAll);
-
-		// Sanity check
-		assert_eq!(
-			CurrencyOf::<T>::balance(&depositor),
-			origin_weight
-		);
-
-		whitelist_account!(depositor);
-	}:claim_payout_other(RuntimeOrigin::Signed(claimer), depositor.clone())
-	verify {
-		assert_eq!(
-			CurrencyOf::<T>::balance(&depositor),
-			origin_weight + commission * origin_weight
-		);
-		assert_eq!(
-			CurrencyOf::<T>::balance(&reward_account),
-			ed + commission * origin_weight
-		);
-	}
-
-
-	unbond {
-		// The weight the nominator will start at. The value used here is expected to be
-		// significantly higher than the first position in a list (e.g. the first bag threshold).
-		let origin_weight = Pools::<T>::depositor_min_bond() * 200u32.into();
-		let scenario = ListScenario::<T>::new(origin_weight, false)?;
-		let amount = origin_weight - scenario.dest_weight;
-
-		let scenario = scenario.add_joiner(amount);
-		let member_id = scenario.origin1_member.unwrap().clone();
-		let member_id_lookup = T::Lookup::unlookup(member_id.clone());
-		let all_points = PoolMembers::<T>::get(&member_id).unwrap().points;
-		whitelist_account!(member_id);
-	}: _(RuntimeOrigin::Signed(member_id.clone()), member_id_lookup, all_points)
-	verify {
-		let bonded_after = T::Staking::active_stake(&scenario.origin1).unwrap();
-		// We at least went down to the destination bag
-		assert!(bonded_after <= scenario.dest_weight);
-		let member = PoolMembers::<T>::get(
-			&member_id
-		)
-		.unwrap();
-		assert_eq!(
-			member.unbonding_eras.keys().cloned().collect::<Vec<_>>(),
-			vec![0 + T::Staking::bonding_duration()]
-		);
-		assert_eq!(
-			member.unbonding_eras.values().cloned().collect::<Vec<_>>(),
-			vec![all_points]
-		);
-	}
-
-	pool_withdraw_unbonded {
-		let s in 0 .. MAX_SPANS;
-
-		let min_create_bond = Pools::<T>::depositor_min_bond();
-		let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
-
-		// Add a new member
-		let min_join_bond = MinJoinBond::<T>::get().max(CurrencyOf::<T>::minimum_balance());
-		let joiner = create_funded_user_with_balance::<T>("joiner", 0, min_join_bond * 2u32.into());
-		Pools::<T>::join(RuntimeOrigin::Signed(joiner.clone()).into(), min_join_bond, 1)
-			.unwrap();
-
-		// Sanity check join worked
-		assert_eq!(
-			T::Staking::active_stake(&pool_account).unwrap(),
-			min_create_bond + min_join_bond
-		);
-		assert_eq!(CurrencyOf::<T>::balance(&joiner), min_join_bond);
-
-		// Unbond the new member
-		Pools::<T>::fully_unbond(RuntimeOrigin::Signed(joiner.clone()).into(), joiner.clone()).unwrap();
-
-		// Sanity check that unbond worked
-		assert_eq!(
-			T::Staking::active_stake(&pool_account).unwrap(),
-			min_create_bond
-		);
-		assert_eq!(pallet_staking::Ledger::<T>::get(&pool_account).unwrap().unlocking.len(), 1);
-		// Set the current era
-		pallet_staking::CurrentEra::<T>::put(EraIndex::max_value());
-
-		// Add `s` count of slashing spans to storage.
-		pallet_staking::benchmarking::add_slashing_spans::<T>(&pool_account, s);
-		whitelist_account!(pool_account);
-	}: _(RuntimeOrigin::Signed(pool_account.clone()), 1, s)
-	verify {
-		// The joiners funds didn't change
-		assert_eq!(CurrencyOf::<T>::balance(&joiner), min_join_bond);
-		// The unlocking chunk was removed
-		assert_eq!(pallet_staking::Ledger::<T>::get(pool_account).unwrap().unlocking.len(), 0);
-	}
-
-	withdraw_unbonded_update {
-		let s in 0 .. MAX_SPANS;
-
-		let min_create_bond = Pools::<T>::depositor_min_bond();
-		let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
-
-		// Add a new member
-		let min_join_bond = MinJoinBond::<T>::get().max(CurrencyOf::<T>::minimum_balance());
-		let joiner = create_funded_user_with_balance::<T>("joiner", 0, min_join_bond * 2u32.into());
-		let joiner_lookup = T::Lookup::unlookup(joiner.clone());
-		Pools::<T>::join(RuntimeOrigin::Signed(joiner.clone()).into(), min_join_bond, 1)
-			.unwrap();
-
-		// Sanity check join worked
-		assert_eq!(
-			T::Staking::active_stake(&pool_account).unwrap(),
-			min_create_bond + min_join_bond
-		);
-		assert_eq!(CurrencyOf::<T>::balance(&joiner), min_join_bond);
-
-		// Unbond the new member
-		pallet_staking::CurrentEra::<T>::put(0);
-		Pools::<T>::fully_unbond(RuntimeOrigin::Signed(joiner.clone()).into(), joiner.clone()).unwrap();
-
-		// Sanity check that unbond worked
-		assert_eq!(
-			T::Staking::active_stake(&pool_account).unwrap(),
-			min_create_bond
-		);
-		assert_eq!(pallet_staking::Ledger::<T>::get(&pool_account).unwrap().unlocking.len(), 1);
-
-		// Set the current era to ensure we can withdraw unbonded funds
-		pallet_staking::CurrentEra::<T>::put(EraIndex::max_value());
-
-		pallet_staking::benchmarking::add_slashing_spans::<T>(&pool_account, s);
-		whitelist_account!(joiner);
-	}: withdraw_unbonded(RuntimeOrigin::Signed(joiner.clone()), joiner_lookup, s)
-	verify {
-		assert_eq!(
-			CurrencyOf::<T>::balance(&joiner), min_join_bond * 2u32.into()
-		);
-		// The unlocking chunk was removed
-		assert_eq!(pallet_staking::Ledger::<T>::get(&pool_account).unwrap().unlocking.len(), 0);
-	}
-
-	withdraw_unbonded_kill {
-		let s in 0 .. MAX_SPANS;
-
-		let min_create_bond = Pools::<T>::depositor_min_bond();
-		let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
-		let depositor_lookup = T::Lookup::unlookup(depositor.clone());
-
-		// We set the pool to the destroying state so the depositor can leave
-		BondedPools::<T>::try_mutate(&1, |maybe_bonded_pool| {
-			maybe_bonded_pool.as_mut().ok_or(()).map(|bonded_pool| {
-				bonded_pool.state = PoolState::Destroying;
-			})
-		})
-		.unwrap();
-
-		// Unbond the creator
-		pallet_staking::CurrentEra::<T>::put(0);
-		// Simulate some rewards so we can check if the rewards storage is cleaned up. We check this
-		// here to ensure the complete flow for destroying a pool works - the reward pool account
-		// should never exist by time the depositor withdraws so we test that it gets cleaned
-		// up when unbonding.
-		let reward_account = Pools::<T>::create_reward_account(1);
-		assert!(frame_system::Account::<T>::contains_key(&reward_account));
-		Pools::<T>::fully_unbond(RuntimeOrigin::Signed(depositor.clone()).into(), depositor.clone()).unwrap();
-
-		// Sanity check that unbond worked
-		assert_eq!(
-			T::Staking::active_stake(&pool_account).unwrap(),
-			Zero::zero()
-		);
-		assert_eq!(
-			CurrencyOf::<T>::balance(&pool_account),
-			min_create_bond
-		);
-		assert_eq!(pallet_staking::Ledger::<T>::get(&pool_account).unwrap().unlocking.len(), 1);
-
-		// Set the current era to ensure we can withdraw unbonded funds
-		pallet_staking::CurrentEra::<T>::put(EraIndex::max_value());
-
-		// Some last checks that storage items we expect to get cleaned up are present
-		assert!(pallet_staking::Ledger::<T>::contains_key(&pool_account));
-		assert!(BondedPools::<T>::contains_key(&1));
-		assert!(SubPoolsStorage::<T>::contains_key(&1));
-		assert!(RewardPools::<T>::contains_key(&1));
-		assert!(PoolMembers::<T>::contains_key(&depositor));
-		assert!(frame_system::Account::<T>::contains_key(&reward_account));
-
-		whitelist_account!(depositor);
-	}: withdraw_unbonded(RuntimeOrigin::Signed(depositor.clone()), depositor_lookup, s)
-	verify {
-		// Pool removal worked
-		assert!(!pallet_staking::Ledger::<T>::contains_key(&pool_account));
-		assert!(!BondedPools::<T>::contains_key(&1));
-		assert!(!SubPoolsStorage::<T>::contains_key(&1));
-		assert!(!RewardPools::<T>::contains_key(&1));
-		assert!(!PoolMembers::<T>::contains_key(&depositor));
-		assert!(!frame_system::Account::<T>::contains_key(&pool_account));
-		assert!(!frame_system::Account::<T>::contains_key(&reward_account));
-
-		// Funds where transferred back correctly
-		assert_eq!(
-			CurrencyOf::<T>::balance(&depositor),
-			// gets bond back + rewards collecting when unbonding
-			min_create_bond * 2u32.into() + CurrencyOf::<T>::minimum_balance()
-		);
-	}
-
-	create {
-		let min_create_bond = Pools::<T>::depositor_min_bond();
-		let depositor: T::AccountId = account("depositor", USER_SEED, 0);
-		let depositor_lookup = T::Lookup::unlookup(depositor.clone());
-
-		// Give the depositor some balance to bond
-		CurrencyOf::<T>::set_balance(&depositor, min_create_bond * 2u32.into());
-
-		// Make sure no Pools exist at a pre-condition for our verify checks
-		assert_eq!(RewardPools::<T>::count(), 0);
-		assert_eq!(BondedPools::<T>::count(), 0);
-
-		whitelist_account!(depositor);
-	}: _(
-			RuntimeOrigin::Signed(depositor.clone()),
-			min_create_bond,
-			depositor_lookup.clone(),
-			depositor_lookup.clone(),
-			depositor_lookup
-		)
-	verify {
-		assert_eq!(RewardPools::<T>::count(), 1);
-		assert_eq!(BondedPools::<T>::count(), 1);
-		let (_, new_pool) = BondedPools::<T>::iter().next().unwrap();
-		assert_eq!(
-			new_pool,
-			BondedPoolInner {
-				commission: Commission::default(),
-				member_counter: 1,
-				points: min_create_bond,
-				roles: PoolRoles {
-					depositor: depositor.clone(),
-					root: Some(depositor.clone()),
-					nominator: Some(depositor.clone()),
-					bouncer: Some(depositor.clone()),
-				},
-				state: PoolState::Open,
-			}
-		);
-		assert_eq!(
-			T::Staking::active_stake(&Pools::<T>::create_bonded_account(1)),
-			Ok(min_create_bond)
-		);
-	}
-
-	nominate {
-		let n in 1 .. MaxNominationsOf::<T>::get();
-
-		// Create a pool
-		let min_create_bond = Pools::<T>::depositor_min_bond() * 2u32.into();
-		let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
-
-		// Create some accounts to nominate. For the sake of benchmarking they don't need to be
-		// actual validators
-		 let validators: Vec<_> = (0..n)
-			.map(|i| account("stash", USER_SEED, i))
-			.collect();
-
-		whitelist_account!(depositor);
-	}:_(RuntimeOrigin::Signed(depositor.clone()), 1, validators)
-	verify {
-		assert_eq!(RewardPools::<T>::count(), 1);
-		assert_eq!(BondedPools::<T>::count(), 1);
-		let (_, new_pool) = BondedPools::<T>::iter().next().unwrap();
-		assert_eq!(
-			new_pool,
-			BondedPoolInner {
-				commission: Commission::default(),
-				member_counter: 1,
-				points: min_create_bond,
-				roles: PoolRoles {
-					depositor: depositor.clone(),
-					root: Some(depositor.clone()),
-					nominator: Some(depositor.clone()),
-					bouncer: Some(depositor.clone()),
-				},
-				state: PoolState::Open,
-			}
-		);
-		assert_eq!(
-			T::Staking::active_stake(&Pools::<T>::create_bonded_account(1)),
-			Ok(min_create_bond)
-		);
-	}
-
-	set_state {
-		// Create a pool
-		let min_create_bond = Pools::<T>::depositor_min_bond();
-		let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
-		BondedPools::<T>::mutate(&1, |maybe_pool| {
-			// Force the pool into an invalid state
-			maybe_pool.as_mut().map(|pool| pool.points = min_create_bond * 10u32.into());
-		});
-
-		let caller = account("caller", 0, USER_SEED);
-		whitelist_account!(caller);
-	}:_(RuntimeOrigin::Signed(caller), 1, PoolState::Destroying)
-	verify {
-		assert_eq!(BondedPools::<T>::get(1).unwrap().state, PoolState::Destroying);
-	}
-
-	set_metadata {
-		let n in 1 .. <T as pallet_nomination_pools::Config>::MaxMetadataLen::get();
-
-		// Create a pool
-		let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
-
-		// Create metadata of the max possible size
-		let metadata: Vec<u8> = (0..n).map(|_| 42).collect();
-
-		whitelist_account!(depositor);
-	}:_(RuntimeOrigin::Signed(depositor), 1, metadata.clone())
-	verify {
-		assert_eq!(Metadata::<T>::get(&1), metadata);
-	}
-
-	set_configs {
-	}:_(
-		RuntimeOrigin::Root,
-		ConfigOp::Set(BalanceOf::<T>::max_value()),
-		ConfigOp::Set(BalanceOf::<T>::max_value()),
-		ConfigOp::Set(u32::MAX),
-		ConfigOp::Set(u32::MAX),
-		ConfigOp::Set(u32::MAX),
-		ConfigOp::Set(Perbill::max_value())
-	) verify {
-		assert_eq!(MinJoinBond::<T>::get(), BalanceOf::<T>::max_value());
-		assert_eq!(MinCreateBond::<T>::get(), BalanceOf::<T>::max_value());
-		assert_eq!(MaxPools::<T>::get(), Some(u32::MAX));
-		assert_eq!(MaxPoolMembers::<T>::get(), Some(u32::MAX));
-		assert_eq!(MaxPoolMembersPerPool::<T>::get(), Some(u32::MAX));
-		assert_eq!(GlobalMaxCommission::<T>::get(), Some(Perbill::max_value()));
-	}
-
-	update_roles {
-		let first_id = pallet_nomination_pools::LastPoolId::<T>::get() + 1;
-		let (root, _) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
-		let random: T::AccountId = account("but is anything really random in computers..?", 0, USER_SEED);
-	}:_(
-		RuntimeOrigin::Signed(root.clone()),
-		first_id,
-		ConfigOp::Set(random.clone()),
-		ConfigOp::Set(random.clone()),
-		ConfigOp::Set(random.clone())
-	) verify {
-		assert_eq!(
-			pallet_nomination_pools::BondedPools::<T>::get(first_id).unwrap().roles,
-			pallet_nomination_pools::PoolRoles {
-				depositor: root,
-				nominator: Some(random.clone()),
-				bouncer: Some(random.clone()),
-				root: Some(random),
-			},
-		)
-	}
-
-	chill {
-		// Create a pool
-		let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
-
-		// Nominate with the pool.
-		 let validators: Vec<_> = (0..MaxNominationsOf::<T>::get())
-			.map(|i| account("stash", USER_SEED, i))
-			.collect();
-
-		assert_ok!(T::Staking::nominate(&pool_account, validators));
-		assert!(T::Staking::nominations(&Pools::<T>::create_bonded_account(1)).is_some());
-
-		whitelist_account!(depositor);
-	}:_(RuntimeOrigin::Signed(depositor.clone()), 1)
-	verify {
-		assert!(T::Staking::nominations(&Pools::<T>::create_bonded_account(1)).is_none());
-	}
-
-	set_commission {
-		// Create a pool - do not set a commission yet.
-		let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
-		// set a max commission
-		Pools::<T>::set_commission_max(RuntimeOrigin::Signed(depositor.clone()).into(), 1u32.into(), Perbill::from_percent(50)).unwrap();
-		// set a change rate
-		Pools::<T>::set_commission_change_rate(RuntimeOrigin::Signed(depositor.clone()).into(), 1u32.into(), CommissionChangeRate {
-			max_increase: Perbill::from_percent(20),
-			min_delay: 0u32.into(),
-		}).unwrap();
-		// set a claim permission to an account.
-		Pools::<T>::set_commission_claim_permission(
-			RuntimeOrigin::Signed(depositor.clone()).into(),
-			1u32.into(),
-			Some(CommissionClaimPermission::Account(depositor.clone()))
-		).unwrap();
-
-	}:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into(), Some((Perbill::from_percent(20), depositor.clone())))
-	verify {
-		assert_eq!(BondedPools::<T>::get(1).unwrap().commission, Commission {
-			current: Some((Perbill::from_percent(20), depositor.clone())),
-			max: Some(Perbill::from_percent(50)),
-			change_rate: Some(CommissionChangeRate {
-					max_increase: Perbill::from_percent(20),
-					min_delay: 0u32.into()
-			}),
-			throttle_from: Some(1u32.into()),
-			claim_permission: Some(CommissionClaimPermission::Account(depositor)),
-		});
-	}
-
-	set_commission_max {
-		// Create a pool, setting a commission that will update when max commission is set.
-		let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), Some(Perbill::from_percent(50)));
-	}:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into(), Perbill::from_percent(50))
-	verify {
-		assert_eq!(
-			BondedPools::<T>::get(1).unwrap().commission, Commission {
-			current: Some((Perbill::from_percent(50), depositor)),
-			max: Some(Perbill::from_percent(50)),
-			change_rate: None,
-			throttle_from: Some(0u32.into()),
-			claim_permission: None,
-		});
-	}
-
-	set_commission_change_rate {
-		// Create a pool
-		let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
-	}:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into(), CommissionChangeRate {
-		max_increase: Perbill::from_percent(50),
-		min_delay: 1000u32.into(),
-	})
-	verify {
-		assert_eq!(
-			BondedPools::<T>::get(1).unwrap().commission, Commission {
-			current: None,
-			max: None,
-			change_rate: Some(CommissionChangeRate {
-				max_increase: Perbill::from_percent(50),
-				min_delay: 1000u32.into(),
-			}),
-			throttle_from: Some(1_u32.into()),
-			claim_permission: None,
-		});
-  }
-
-	set_commission_claim_permission {
-		// Create a pool.
-		let (depositor, pool_account) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
-	}:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into(), Some(CommissionClaimPermission::Account(depositor.clone())))
-	verify {
-		assert_eq!(
-			BondedPools::<T>::get(1).unwrap().commission, Commission {
-			current: None,
-			max: None,
-			change_rate: None,
-			throttle_from: None,
-			claim_permission: Some(CommissionClaimPermission::Account(depositor)),
-		});
-	}
-
-	set_claim_permission {
-		// Create a pool
-		let min_create_bond = Pools::<T>::depositor_min_bond();
-		let (depositor, pool_account) = create_pool_account::<T>(0, min_create_bond, None);
-
-		// Join pool
-		let min_join_bond = MinJoinBond::<T>::get().max(CurrencyOf::<T>::minimum_balance());
-		let joiner = create_funded_user_with_balance::<T>("joiner", 0, min_join_bond * 4u32.into());
-		let joiner_lookup = T::Lookup::unlookup(joiner.clone());
-		Pools::<T>::join(RuntimeOrigin::Signed(joiner.clone()).into(), min_join_bond, 1)
-			.unwrap();
-
-		// Sanity check join worked
-		assert_eq!(
-			T::Staking::active_stake(&pool_account).unwrap(),
-			min_create_bond + min_join_bond
-		);
-	}:_(RuntimeOrigin::Signed(joiner.clone()), ClaimPermission::Permissioned)
-	verify {
-		assert_eq!(ClaimPermissions::<T>::get(joiner), ClaimPermission::Permissioned);
-	}
-
-	claim_commission {
-		let claimer: T::AccountId = account("claimer_member", USER_SEED + 4, 0);
-		let commission = Perbill::from_percent(50);
-		let origin_weight = Pools::<T>::depositor_min_bond() * 2u32.into();
-		let ed = CurrencyOf::<T>::minimum_balance();
-		let (depositor, pool_account) = create_pool_account::<T>(0, origin_weight, Some(commission));
-		let reward_account = Pools::<T>::create_reward_account(1);
-		CurrencyOf::<T>::set_balance(&reward_account, ed + origin_weight);
-
-		// member claims a payout to make some commission available.
-		let _ = Pools::<T>::claim_payout(RuntimeOrigin::Signed(claimer.clone()).into());
-		// set a claim permission to an account.
-		let _ = Pools::<T>::set_commission_claim_permission(
-			RuntimeOrigin::Signed(depositor.clone()).into(),
-			1u32.into(),
-			Some(CommissionClaimPermission::Account(claimer))
-		);
-		whitelist_account!(depositor);
-	}:_(RuntimeOrigin::Signed(depositor.clone()), 1u32.into())
-	verify {
-		assert_eq!(
-			CurrencyOf::<T>::balance(&depositor),
-			origin_weight + commission * origin_weight
-		);
-		assert_eq!(
-			CurrencyOf::<T>::balance(&reward_account),
-			ed + commission * origin_weight
-		);
-	}
-
-	adjust_pool_deposit {
-		// Create a pool
-		let (depositor, _) = create_pool_account::<T>(0, Pools::<T>::depositor_min_bond() * 2u32.into(), None);
-
-		// Remove ed freeze to create a scenario where the ed deposit needs to be adjusted.
-		let _ = Pools::<T>::unfreeze_pool_deposit(&Pools::<T>::create_reward_account(1));
-		assert!(&Pools::<T>::check_ed_imbalance().is_err());
-
-		whitelist_account!(depositor);
-	}:_(RuntimeOrigin::Signed(depositor), 1)
-	verify {
-		assert!(&Pools::<T>::check_ed_imbalance().is_ok());
-	}
-
-	impl_benchmark_test_suite!(
-		Pallet,
-		crate::mock::new_test_ext(),
-		crate::mock::Runtime
-	);
-}
+#[cfg(all(feature = "runtime-benchmarks", test))]
+pub(crate) mod mock;
diff --git a/substrate/frame/offences/benchmarking/src/inner.rs b/substrate/frame/offences/benchmarking/src/inner.rs
new file mode 100644
index 00000000000..9aa88f7a0d6
--- /dev/null
+++ b/substrate/frame/offences/benchmarking/src/inner.rs
@@ -0,0 +1,250 @@
+// 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.
+
+//! Offences pallet benchmarking.
+
+use sp_std::{prelude::*, vec};
+
+use frame_benchmarking::v1::{account, benchmarks};
+use frame_support::traits::{Currency, Get};
+use frame_system::{Config as SystemConfig, Pallet as System, RawOrigin};
+
+use sp_runtime::{
+	traits::{Convert, Saturating, StaticLookup},
+	Perbill,
+};
+use sp_staking::offence::ReportOffence;
+
+use pallet_babe::EquivocationOffence as BabeEquivocationOffence;
+use pallet_balances::Config as BalancesConfig;
+use pallet_grandpa::{
+	EquivocationOffence as GrandpaEquivocationOffence, TimeSlot as GrandpaTimeSlot,
+};
+use pallet_offences::{Config as OffencesConfig, Pallet as Offences};
+use pallet_session::{
+	historical::{Config as HistoricalConfig, IdentificationTuple},
+	Config as SessionConfig, Pallet as Session, SessionManager,
+};
+use pallet_staking::{
+	Config as StakingConfig, Exposure, IndividualExposure, MaxNominationsOf, Pallet as Staking,
+	RewardDestination, ValidatorPrefs,
+};
+
+const SEED: u32 = 0;
+
+const MAX_NOMINATORS: u32 = 100;
+
+pub struct Pallet<T: Config>(Offences<T>);
+
+pub trait Config:
+	SessionConfig
+	+ StakingConfig
+	+ OffencesConfig
+	+ HistoricalConfig
+	+ BalancesConfig
+	+ IdTupleConvert<Self>
+{
+}
+
+/// A helper trait to make sure we can convert `IdentificationTuple` coming from historical
+/// and the one required by offences.
+pub trait IdTupleConvert<T: HistoricalConfig + OffencesConfig> {
+	/// Convert identification tuple from `historical` trait to the one expected by `offences`.
+	fn convert(id: IdentificationTuple<T>) -> <T as OffencesConfig>::IdentificationTuple;
+}
+
+impl<T: HistoricalConfig + OffencesConfig> IdTupleConvert<T> for T
+where
+	<T as OffencesConfig>::IdentificationTuple: From<IdentificationTuple<T>>,
+{
+	fn convert(id: IdentificationTuple<T>) -> <T as OffencesConfig>::IdentificationTuple {
+		id.into()
+	}
+}
+
+type LookupSourceOf<T> = <<T as SystemConfig>::Lookup as StaticLookup>::Source;
+type BalanceOf<T> =
+	<<T as StakingConfig>::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance;
+
+struct Offender<T: Config> {
+	pub controller: T::AccountId,
+	#[allow(dead_code)]
+	pub stash: T::AccountId,
+	#[allow(dead_code)]
+	pub nominator_stashes: Vec<T::AccountId>,
+}
+
+fn bond_amount<T: Config>() -> BalanceOf<T> {
+	T::Currency::minimum_balance().saturating_mul(10_000u32.into())
+}
+
+fn create_offender<T: Config>(n: u32, nominators: u32) -> Result<Offender<T>, &'static str> {
+	let stash: T::AccountId = account("stash", n, SEED);
+	let stash_lookup: LookupSourceOf<T> = T::Lookup::unlookup(stash.clone());
+	let reward_destination = RewardDestination::Staked;
+	let amount = bond_amount::<T>();
+	// add twice as much balance to prevent the account from being killed.
+	let free_amount = amount.saturating_mul(2u32.into());
+	T::Currency::make_free_balance_be(&stash, free_amount);
+	Staking::<T>::bond(
+		RawOrigin::Signed(stash.clone()).into(),
+		amount,
+		reward_destination.clone(),
+	)?;
+
+	let validator_prefs =
+		ValidatorPrefs { commission: Perbill::from_percent(50), ..Default::default() };
+	Staking::<T>::validate(RawOrigin::Signed(stash.clone()).into(), validator_prefs)?;
+
+	let mut individual_exposures = vec![];
+	let mut nominator_stashes = vec![];
+	// Create n nominators
+	for i in 0..nominators {
+		let nominator_stash: T::AccountId =
+			account("nominator stash", n * MAX_NOMINATORS + i, SEED);
+		T::Currency::make_free_balance_be(&nominator_stash, free_amount);
+
+		Staking::<T>::bond(
+			RawOrigin::Signed(nominator_stash.clone()).into(),
+			amount,
+			reward_destination.clone(),
+		)?;
+
+		let selected_validators: Vec<LookupSourceOf<T>> = vec![stash_lookup.clone()];
+		Staking::<T>::nominate(
+			RawOrigin::Signed(nominator_stash.clone()).into(),
+			selected_validators,
+		)?;
+
+		individual_exposures
+			.push(IndividualExposure { who: nominator_stash.clone(), value: amount });
+		nominator_stashes.push(nominator_stash.clone());
+	}
+
+	let exposure = Exposure { total: amount * n.into(), own: amount, others: individual_exposures };
+	let current_era = 0u32;
+	Staking::<T>::add_era_stakers(current_era, stash.clone(), exposure);
+
+	Ok(Offender { controller: stash.clone(), stash, nominator_stashes })
+}
+
+fn make_offenders<T: Config>(
+	num_offenders: u32,
+	num_nominators: u32,
+) -> Result<(Vec<IdentificationTuple<T>>, Vec<Offender<T>>), &'static str> {
+	Staking::<T>::new_session(0);
+
+	let mut offenders = vec![];
+	for i in 0..num_offenders {
+		let offender = create_offender::<T>(i + 1, num_nominators)?;
+		offenders.push(offender);
+	}
+
+	Staking::<T>::start_session(0);
+
+	let id_tuples = offenders
+		.iter()
+		.map(|offender| {
+			<T as SessionConfig>::ValidatorIdOf::convert(offender.controller.clone())
+				.expect("failed to get validator id from account id")
+		})
+		.map(|validator_id| {
+			<T as HistoricalConfig>::FullIdentificationOf::convert(validator_id.clone())
+				.map(|full_id| (validator_id, full_id))
+				.expect("failed to convert validator id to full identification")
+		})
+		.collect::<Vec<IdentificationTuple<T>>>();
+	Ok((id_tuples, offenders))
+}
+
+benchmarks! {
+	report_offence_grandpa {
+		let n in 0 .. MAX_NOMINATORS.min(MaxNominationsOf::<T>::get());
+
+		// for grandpa equivocation reports the number of reporters
+		// and offenders is always 1
+		let reporters = vec![account("reporter", 1, SEED)];
+
+		// make sure reporters actually get rewarded
+		Staking::<T>::set_slash_reward_fraction(Perbill::one());
+
+		let (mut offenders, raw_offenders) = make_offenders::<T>(1, n)?;
+		let validator_set_count = Session::<T>::validators().len() as u32;
+
+		let offence = GrandpaEquivocationOffence {
+			time_slot: GrandpaTimeSlot { set_id: 0, round: 0 },
+			session_index: 0,
+			validator_set_count,
+			offender: T::convert(offenders.pop().unwrap()),
+		};
+		assert_eq!(System::<T>::event_count(), 0);
+	}: {
+		let _ = Offences::<T>::report_offence(reporters, offence);
+	}
+	verify {
+		// make sure that all slashes have been applied
+		#[cfg(test)]
+		assert_eq!(
+			System::<T>::event_count(), 0
+			+ 1 // offence
+			+ 3 // reporter (reward + endowment)
+			+ 1 // offenders reported
+			+ 3 // offenders slashed
+			+ 1 // offenders chilled
+			+ 3 * n // nominators slashed
+		);
+	}
+
+	report_offence_babe {
+		let n in 0 .. MAX_NOMINATORS.min(MaxNominationsOf::<T>::get());
+
+		// for babe equivocation reports the number of reporters
+		// and offenders is always 1
+		let reporters = vec![account("reporter", 1, SEED)];
+
+		// make sure reporters actually get rewarded
+		Staking::<T>::set_slash_reward_fraction(Perbill::one());
+
+		let (mut offenders, raw_offenders) = make_offenders::<T>(1, n)?;
+		let validator_set_count = Session::<T>::validators().len() as u32;
+
+		let offence = BabeEquivocationOffence {
+			slot: 0u64.into(),
+			session_index: 0,
+			validator_set_count,
+			offender: T::convert(offenders.pop().unwrap()),
+		};
+		assert_eq!(System::<T>::event_count(), 0);
+	}: {
+		let _ = Offences::<T>::report_offence(reporters, offence);
+	}
+	verify {
+		// make sure that all slashes have been applied
+		#[cfg(test)]
+		assert_eq!(
+			System::<T>::event_count(), 0
+			+ 1 // offence
+			+ 3 // reporter (reward + endowment)
+			+ 1 // offenders reported
+			+ 3 // offenders slashed
+			+ 1 // offenders chilled
+			+ 3 * n // nominators slashed
+		);
+	}
+
+	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
+}
diff --git a/substrate/frame/offences/benchmarking/src/lib.rs b/substrate/frame/offences/benchmarking/src/lib.rs
index 563aa4755ce..b08955a1332 100644
--- a/substrate/frame/offences/benchmarking/src/lib.rs
+++ b/substrate/frame/offences/benchmarking/src/lib.rs
@@ -17,239 +17,13 @@
 
 //! Offences pallet benchmarking.
 
-#![cfg(feature = "runtime-benchmarks")]
 #![cfg_attr(not(feature = "std"), no_std)]
 
-mod mock;
+#[cfg(feature = "runtime-benchmarks")]
+pub mod inner;
 
-use sp_std::{prelude::*, vec};
+#[cfg(feature = "runtime-benchmarks")]
+pub use inner::*;
 
-use frame_benchmarking::v1::{account, benchmarks};
-use frame_support::traits::{Currency, Get};
-use frame_system::{Config as SystemConfig, Pallet as System, RawOrigin};
-
-use sp_runtime::{
-	traits::{Convert, Saturating, StaticLookup},
-	Perbill,
-};
-use sp_staking::offence::ReportOffence;
-
-use pallet_babe::EquivocationOffence as BabeEquivocationOffence;
-use pallet_balances::Config as BalancesConfig;
-use pallet_grandpa::{
-	EquivocationOffence as GrandpaEquivocationOffence, TimeSlot as GrandpaTimeSlot,
-};
-use pallet_offences::{Config as OffencesConfig, Pallet as Offences};
-use pallet_session::{
-	historical::{Config as HistoricalConfig, IdentificationTuple},
-	Config as SessionConfig, Pallet as Session, SessionManager,
-};
-use pallet_staking::{
-	Config as StakingConfig, Exposure, IndividualExposure, MaxNominationsOf, Pallet as Staking,
-	RewardDestination, ValidatorPrefs,
-};
-
-const SEED: u32 = 0;
-
-const MAX_NOMINATORS: u32 = 100;
-
-pub struct Pallet<T: Config>(Offences<T>);
-
-pub trait Config:
-	SessionConfig
-	+ StakingConfig
-	+ OffencesConfig
-	+ HistoricalConfig
-	+ BalancesConfig
-	+ IdTupleConvert<Self>
-{
-}
-
-/// A helper trait to make sure we can convert `IdentificationTuple` coming from historical
-/// and the one required by offences.
-pub trait IdTupleConvert<T: HistoricalConfig + OffencesConfig> {
-	/// Convert identification tuple from `historical` trait to the one expected by `offences`.
-	fn convert(id: IdentificationTuple<T>) -> <T as OffencesConfig>::IdentificationTuple;
-}
-
-impl<T: HistoricalConfig + OffencesConfig> IdTupleConvert<T> for T
-where
-	<T as OffencesConfig>::IdentificationTuple: From<IdentificationTuple<T>>,
-{
-	fn convert(id: IdentificationTuple<T>) -> <T as OffencesConfig>::IdentificationTuple {
-		id.into()
-	}
-}
-
-type LookupSourceOf<T> = <<T as SystemConfig>::Lookup as StaticLookup>::Source;
-type BalanceOf<T> =
-	<<T as StakingConfig>::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance;
-
-struct Offender<T: Config> {
-	pub controller: T::AccountId,
-	#[allow(dead_code)]
-	pub stash: T::AccountId,
-	#[allow(dead_code)]
-	pub nominator_stashes: Vec<T::AccountId>,
-}
-
-fn bond_amount<T: Config>() -> BalanceOf<T> {
-	T::Currency::minimum_balance().saturating_mul(10_000u32.into())
-}
-
-fn create_offender<T: Config>(n: u32, nominators: u32) -> Result<Offender<T>, &'static str> {
-	let stash: T::AccountId = account("stash", n, SEED);
-	let stash_lookup: LookupSourceOf<T> = T::Lookup::unlookup(stash.clone());
-	let reward_destination = RewardDestination::Staked;
-	let amount = bond_amount::<T>();
-	// add twice as much balance to prevent the account from being killed.
-	let free_amount = amount.saturating_mul(2u32.into());
-	T::Currency::make_free_balance_be(&stash, free_amount);
-	Staking::<T>::bond(
-		RawOrigin::Signed(stash.clone()).into(),
-		amount,
-		reward_destination.clone(),
-	)?;
-
-	let validator_prefs =
-		ValidatorPrefs { commission: Perbill::from_percent(50), ..Default::default() };
-	Staking::<T>::validate(RawOrigin::Signed(stash.clone()).into(), validator_prefs)?;
-
-	let mut individual_exposures = vec![];
-	let mut nominator_stashes = vec![];
-	// Create n nominators
-	for i in 0..nominators {
-		let nominator_stash: T::AccountId =
-			account("nominator stash", n * MAX_NOMINATORS + i, SEED);
-		T::Currency::make_free_balance_be(&nominator_stash, free_amount);
-
-		Staking::<T>::bond(
-			RawOrigin::Signed(nominator_stash.clone()).into(),
-			amount,
-			reward_destination.clone(),
-		)?;
-
-		let selected_validators: Vec<LookupSourceOf<T>> = vec![stash_lookup.clone()];
-		Staking::<T>::nominate(
-			RawOrigin::Signed(nominator_stash.clone()).into(),
-			selected_validators,
-		)?;
-
-		individual_exposures
-			.push(IndividualExposure { who: nominator_stash.clone(), value: amount });
-		nominator_stashes.push(nominator_stash.clone());
-	}
-
-	let exposure = Exposure { total: amount * n.into(), own: amount, others: individual_exposures };
-	let current_era = 0u32;
-	Staking::<T>::add_era_stakers(current_era, stash.clone(), exposure);
-
-	Ok(Offender { controller: stash.clone(), stash, nominator_stashes })
-}
-
-fn make_offenders<T: Config>(
-	num_offenders: u32,
-	num_nominators: u32,
-) -> Result<(Vec<IdentificationTuple<T>>, Vec<Offender<T>>), &'static str> {
-	Staking::<T>::new_session(0);
-
-	let mut offenders = vec![];
-	for i in 0..num_offenders {
-		let offender = create_offender::<T>(i + 1, num_nominators)?;
-		offenders.push(offender);
-	}
-
-	Staking::<T>::start_session(0);
-
-	let id_tuples = offenders
-		.iter()
-		.map(|offender| {
-			<T as SessionConfig>::ValidatorIdOf::convert(offender.controller.clone())
-				.expect("failed to get validator id from account id")
-		})
-		.map(|validator_id| {
-			<T as HistoricalConfig>::FullIdentificationOf::convert(validator_id.clone())
-				.map(|full_id| (validator_id, full_id))
-				.expect("failed to convert validator id to full identification")
-		})
-		.collect::<Vec<IdentificationTuple<T>>>();
-	Ok((id_tuples, offenders))
-}
-
-benchmarks! {
-	report_offence_grandpa {
-		let n in 0 .. MAX_NOMINATORS.min(MaxNominationsOf::<T>::get());
-
-		// for grandpa equivocation reports the number of reporters
-		// and offenders is always 1
-		let reporters = vec![account("reporter", 1, SEED)];
-
-		// make sure reporters actually get rewarded
-		Staking::<T>::set_slash_reward_fraction(Perbill::one());
-
-		let (mut offenders, raw_offenders) = make_offenders::<T>(1, n)?;
-		let validator_set_count = Session::<T>::validators().len() as u32;
-
-		let offence = GrandpaEquivocationOffence {
-			time_slot: GrandpaTimeSlot { set_id: 0, round: 0 },
-			session_index: 0,
-			validator_set_count,
-			offender: T::convert(offenders.pop().unwrap()),
-		};
-		assert_eq!(System::<T>::event_count(), 0);
-	}: {
-		let _ = Offences::<T>::report_offence(reporters, offence);
-	}
-	verify {
-		// make sure that all slashes have been applied
-		#[cfg(test)]
-		assert_eq!(
-			System::<T>::event_count(), 0
-			+ 1 // offence
-			+ 3 // reporter (reward + endowment)
-			+ 1 // offenders reported
-			+ 3 // offenders slashed
-			+ 1 // offenders chilled
-			+ 3 * n // nominators slashed
-		);
-	}
-
-	report_offence_babe {
-		let n in 0 .. MAX_NOMINATORS.min(MaxNominationsOf::<T>::get());
-
-		// for babe equivocation reports the number of reporters
-		// and offenders is always 1
-		let reporters = vec![account("reporter", 1, SEED)];
-
-		// make sure reporters actually get rewarded
-		Staking::<T>::set_slash_reward_fraction(Perbill::one());
-
-		let (mut offenders, raw_offenders) = make_offenders::<T>(1, n)?;
-		let validator_set_count = Session::<T>::validators().len() as u32;
-
-		let offence = BabeEquivocationOffence {
-			slot: 0u64.into(),
-			session_index: 0,
-			validator_set_count,
-			offender: T::convert(offenders.pop().unwrap()),
-		};
-		assert_eq!(System::<T>::event_count(), 0);
-	}: {
-		let _ = Offences::<T>::report_offence(reporters, offence);
-	}
-	verify {
-		// make sure that all slashes have been applied
-		#[cfg(test)]
-		assert_eq!(
-			System::<T>::event_count(), 0
-			+ 1 // offence
-			+ 3 // reporter (reward + endowment)
-			+ 1 // offenders reported
-			+ 3 // offenders slashed
-			+ 1 // offenders chilled
-			+ 3 * n // nominators slashed
-		);
-	}
-
-	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
-}
+#[cfg(all(feature = "runtime-benchmarks", test))]
+pub(crate) mod mock;
diff --git a/substrate/frame/offences/benchmarking/src/mock.rs b/substrate/frame/offences/benchmarking/src/mock.rs
index ea2e9e93ed6..27129e73c71 100644
--- a/substrate/frame/offences/benchmarking/src/mock.rs
+++ b/substrate/frame/offences/benchmarking/src/mock.rs
@@ -17,9 +17,6 @@
 
 //! Mock file for offences benchmarking.
 
-#![cfg(test)]
-
-use super::*;
 use frame_election_provider_support::{
 	bounds::{ElectionBounds, ElectionBoundsBuilder},
 	onchain, SequentialPhragmen,
@@ -33,7 +30,7 @@ use pallet_session::historical as pallet_session_historical;
 use sp_runtime::{
 	testing::{Header, UintAuthorityId},
 	traits::IdentityLookup,
-	BuildStorage,
+	BuildStorage, Perbill,
 };
 
 type AccountId = u64;
diff --git a/substrate/frame/root-offences/Cargo.toml b/substrate/frame/root-offences/Cargo.toml
index ad3dcf1f90e..f4d83c237b9 100644
--- a/substrate/frame/root-offences/Cargo.toml
+++ b/substrate/frame/root-offences/Cargo.toml
@@ -24,7 +24,7 @@ pallet-staking = { path = "../staking", default-features = false }
 
 frame-support = { path = "../support", default-features = false }
 frame-system = { path = "../system", default-features = false }
-sp-runtime = { path = "../../primitives/runtime" }
+sp-runtime = { path = "../../primitives/runtime", default-features = false }
 sp-staking = { path = "../../primitives/staking", default-features = false }
 
 [dev-dependencies]
@@ -34,7 +34,7 @@ pallet-staking-reward-curve = { path = "../staking/reward-curve" }
 
 sp-core = { path = "../../primitives/core" }
 sp-io = { path = "../../primitives/io", default-features = false }
-sp-std = { path = "../../primitives/std", default-features = false }
+sp-std = { path = "../../primitives/std" }
 
 frame-election-provider-support = { path = "../election-provider-support" }
 
@@ -74,5 +74,4 @@ std = [
 	"sp-io/std",
 	"sp-runtime/std",
 	"sp-staking/std",
-	"sp-std/std",
 ]
diff --git a/substrate/frame/root-offences/src/lib.rs b/substrate/frame/root-offences/src/lib.rs
index e6bb5bb1881..24d259ed1d4 100644
--- a/substrate/frame/root-offences/src/lib.rs
+++ b/substrate/frame/root-offences/src/lib.rs
@@ -27,6 +27,9 @@ mod mock;
 #[cfg(test)]
 mod tests;
 
+extern crate alloc;
+
+use alloc::vec::Vec;
 use pallet_session::historical::IdentificationTuple;
 use pallet_staking::{BalanceOf, Exposure, ExposureOf, Pallet as Staking};
 use sp_runtime::Perbill;
@@ -112,7 +115,7 @@ pub mod pallet {
 				.into_iter()
 				.map(|(o, _)| OffenceDetails::<T> {
 					offender: (o.clone(), Staking::<T>::eras_stakers(now, &o)),
-					reporters: vec![],
+					reporters: Default::default(),
 				})
 				.collect())
 		}
diff --git a/substrate/frame/session/benchmarking/src/inner.rs b/substrate/frame/session/benchmarking/src/inner.rs
new file mode 100644
index 00000000000..d86c5d9ad27
--- /dev/null
+++ b/substrate/frame/session/benchmarking/src/inner.rs
@@ -0,0 +1,162 @@
+// 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.
+
+//! Benchmarks for the Session Pallet.
+// This is separated into its own crate due to cyclic dependency issues.
+
+use sp_runtime::traits::{One, StaticLookup, TrailingZeroInput};
+use sp_std::{prelude::*, vec};
+
+use codec::Decode;
+use frame_benchmarking::v1::benchmarks;
+use frame_support::traits::{Get, KeyOwnerProofSystem, OnInitialize};
+use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin};
+use pallet_session::{historical::Pallet as Historical, Pallet as Session, *};
+use pallet_staking::{
+	benchmarking::create_validator_with_nominators, testing_utils::create_validators,
+	MaxNominationsOf, RewardDestination,
+};
+
+const MAX_VALIDATORS: u32 = 1000;
+
+pub struct Pallet<T: Config>(pallet_session::Pallet<T>);
+pub trait Config:
+	pallet_session::Config + pallet_session::historical::Config + pallet_staking::Config
+{
+}
+
+impl<T: Config> OnInitialize<BlockNumberFor<T>> for Pallet<T> {
+	fn on_initialize(n: BlockNumberFor<T>) -> frame_support::weights::Weight {
+		pallet_session::Pallet::<T>::on_initialize(n)
+	}
+}
+
+benchmarks! {
+	set_keys {
+		let n = MaxNominationsOf::<T>::get();
+		let (v_stash, _) = create_validator_with_nominators::<T>(
+			n,
+			MaxNominationsOf::<T>::get(),
+			false,
+			true,
+			RewardDestination::Staked,
+		)?;
+		let v_controller = pallet_staking::Pallet::<T>::bonded(&v_stash).ok_or("not stash")?;
+
+		let keys = T::Keys::decode(&mut TrailingZeroInput::zeroes()).unwrap();
+		let proof: Vec<u8> = vec![0,1,2,3];
+		// Whitelist controller account from further DB operations.
+		let v_controller_key = frame_system::Account::<T>::hashed_key_for(&v_controller);
+		frame_benchmarking::benchmarking::add_to_whitelist(v_controller_key.into());
+	}: _(RawOrigin::Signed(v_controller), keys, proof)
+
+	purge_keys {
+		let n = MaxNominationsOf::<T>::get();
+		let (v_stash, _) = create_validator_with_nominators::<T>(
+			n,
+			MaxNominationsOf::<T>::get(),
+			false,
+			true,
+			RewardDestination::Staked,
+		)?;
+		let v_controller = pallet_staking::Pallet::<T>::bonded(&v_stash).ok_or("not stash")?;
+		let keys = T::Keys::decode(&mut TrailingZeroInput::zeroes()).unwrap();
+		let proof: Vec<u8> = vec![0,1,2,3];
+		Session::<T>::set_keys(RawOrigin::Signed(v_controller.clone()).into(), keys, proof)?;
+		// Whitelist controller account from further DB operations.
+		let v_controller_key = frame_system::Account::<T>::hashed_key_for(&v_controller);
+		frame_benchmarking::benchmarking::add_to_whitelist(v_controller_key.into());
+	}: _(RawOrigin::Signed(v_controller))
+
+	#[extra]
+	check_membership_proof_current_session {
+		let n in 2 .. MAX_VALIDATORS as u32;
+
+		let (key, key_owner_proof1) = check_membership_proof_setup::<T>(n);
+		let key_owner_proof2 = key_owner_proof1.clone();
+	}: {
+		Historical::<T>::check_proof(key, key_owner_proof1);
+	}
+	verify {
+		assert!(Historical::<T>::check_proof(key, key_owner_proof2).is_some());
+	}
+
+	#[extra]
+	check_membership_proof_historical_session {
+		let n in 2 .. MAX_VALIDATORS as u32;
+
+		let (key, key_owner_proof1) = check_membership_proof_setup::<T>(n);
+
+		// skip to the next session so that the session is historical
+		// and the membership merkle proof must be checked.
+		Session::<T>::rotate_session();
+
+		let key_owner_proof2 = key_owner_proof1.clone();
+	}: {
+		Historical::<T>::check_proof(key, key_owner_proof1);
+	}
+	verify {
+		assert!(Historical::<T>::check_proof(key, key_owner_proof2).is_some());
+	}
+
+	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test, extra = false);
+}
+
+/// Sets up the benchmark for checking a membership proof. It creates the given
+/// number of validators, sets random session keys and then creates a membership
+/// proof for the first authority and returns its key and the proof.
+fn check_membership_proof_setup<T: Config>(
+	n: u32,
+) -> ((sp_runtime::KeyTypeId, &'static [u8; 32]), sp_session::MembershipProof) {
+	pallet_staking::ValidatorCount::<T>::put(n);
+
+	// create validators and set random session keys
+	for (n, who) in create_validators::<T>(n, 1000).unwrap().into_iter().enumerate() {
+		use rand::{RngCore, SeedableRng};
+
+		let validator = T::Lookup::lookup(who).unwrap();
+		let controller = pallet_staking::Pallet::<T>::bonded(&validator).unwrap();
+
+		let keys = {
+			let mut keys = [0u8; 128];
+
+			// we keep the keys for the first validator as 0x00000...
+			if n > 0 {
+				let mut rng = rand::rngs::StdRng::seed_from_u64(n as u64);
+				rng.fill_bytes(&mut keys);
+			}
+
+			keys
+		};
+
+		let keys: T::Keys = Decode::decode(&mut &keys[..]).unwrap();
+		let proof: Vec<u8> = vec![];
+
+		Session::<T>::set_keys(RawOrigin::Signed(controller).into(), keys, proof).unwrap();
+	}
+
+	Pallet::<T>::on_initialize(frame_system::pallet_prelude::BlockNumberFor::<T>::one());
+
+	// skip sessions until the new validator set is enacted
+	while Session::<T>::validators().len() < n as usize {
+		Session::<T>::rotate_session();
+	}
+
+	let key = (sp_runtime::KeyTypeId(*b"babe"), &[0u8; 32]);
+
+	(key, Historical::<T>::prove(key).unwrap())
+}
diff --git a/substrate/frame/session/benchmarking/src/lib.rs b/substrate/frame/session/benchmarking/src/lib.rs
index 84258d84994..b08955a1332 100644
--- a/substrate/frame/session/benchmarking/src/lib.rs
+++ b/substrate/frame/session/benchmarking/src/lib.rs
@@ -15,153 +15,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//! Benchmarks for the Session Pallet.
-// This is separated into its own crate due to cyclic dependency issues.
+//! Offences pallet benchmarking.
 
-#![cfg(feature = "runtime-benchmarks")]
 #![cfg_attr(not(feature = "std"), no_std)]
 
-mod mock;
+#[cfg(feature = "runtime-benchmarks")]
+pub mod inner;
 
-use sp_runtime::traits::{One, StaticLookup, TrailingZeroInput};
-use sp_std::{prelude::*, vec};
+#[cfg(feature = "runtime-benchmarks")]
+pub use inner::*;
 
-use codec::Decode;
-use frame_benchmarking::v1::benchmarks;
-use frame_support::traits::{Get, KeyOwnerProofSystem, OnInitialize};
-use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin};
-use pallet_session::{historical::Pallet as Historical, Pallet as Session, *};
-use pallet_staking::{
-	benchmarking::create_validator_with_nominators, testing_utils::create_validators,
-	MaxNominationsOf, RewardDestination,
-};
-
-const MAX_VALIDATORS: u32 = 1000;
-
-pub struct Pallet<T: Config>(pallet_session::Pallet<T>);
-pub trait Config:
-	pallet_session::Config + pallet_session::historical::Config + pallet_staking::Config
-{
-}
-
-impl<T: Config> OnInitialize<BlockNumberFor<T>> for Pallet<T> {
-	fn on_initialize(n: BlockNumberFor<T>) -> frame_support::weights::Weight {
-		pallet_session::Pallet::<T>::on_initialize(n)
-	}
-}
-
-benchmarks! {
-	set_keys {
-		let n = MaxNominationsOf::<T>::get();
-		let (v_stash, _) = create_validator_with_nominators::<T>(
-			n,
-			MaxNominationsOf::<T>::get(),
-			false,
-			true,
-			RewardDestination::Staked,
-		)?;
-		let v_controller = pallet_staking::Pallet::<T>::bonded(&v_stash).ok_or("not stash")?;
-
-		let keys = T::Keys::decode(&mut TrailingZeroInput::zeroes()).unwrap();
-		let proof: Vec<u8> = vec![0,1,2,3];
-		// Whitelist controller account from further DB operations.
-		let v_controller_key = frame_system::Account::<T>::hashed_key_for(&v_controller);
-		frame_benchmarking::benchmarking::add_to_whitelist(v_controller_key.into());
-	}: _(RawOrigin::Signed(v_controller), keys, proof)
-
-	purge_keys {
-		let n = MaxNominationsOf::<T>::get();
-		let (v_stash, _) = create_validator_with_nominators::<T>(
-			n,
-			MaxNominationsOf::<T>::get(),
-			false,
-			true,
-			RewardDestination::Staked,
-		)?;
-		let v_controller = pallet_staking::Pallet::<T>::bonded(&v_stash).ok_or("not stash")?;
-		let keys = T::Keys::decode(&mut TrailingZeroInput::zeroes()).unwrap();
-		let proof: Vec<u8> = vec![0,1,2,3];
-		Session::<T>::set_keys(RawOrigin::Signed(v_controller.clone()).into(), keys, proof)?;
-		// Whitelist controller account from further DB operations.
-		let v_controller_key = frame_system::Account::<T>::hashed_key_for(&v_controller);
-		frame_benchmarking::benchmarking::add_to_whitelist(v_controller_key.into());
-	}: _(RawOrigin::Signed(v_controller))
-
-	#[extra]
-	check_membership_proof_current_session {
-		let n in 2 .. MAX_VALIDATORS as u32;
-
-		let (key, key_owner_proof1) = check_membership_proof_setup::<T>(n);
-		let key_owner_proof2 = key_owner_proof1.clone();
-	}: {
-		Historical::<T>::check_proof(key, key_owner_proof1);
-	}
-	verify {
-		assert!(Historical::<T>::check_proof(key, key_owner_proof2).is_some());
-	}
-
-	#[extra]
-	check_membership_proof_historical_session {
-		let n in 2 .. MAX_VALIDATORS as u32;
-
-		let (key, key_owner_proof1) = check_membership_proof_setup::<T>(n);
-
-		// skip to the next session so that the session is historical
-		// and the membership merkle proof must be checked.
-		Session::<T>::rotate_session();
-
-		let key_owner_proof2 = key_owner_proof1.clone();
-	}: {
-		Historical::<T>::check_proof(key, key_owner_proof1);
-	}
-	verify {
-		assert!(Historical::<T>::check_proof(key, key_owner_proof2).is_some());
-	}
-
-	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test, extra = false);
-}
-
-/// Sets up the benchmark for checking a membership proof. It creates the given
-/// number of validators, sets random session keys and then creates a membership
-/// proof for the first authority and returns its key and the proof.
-fn check_membership_proof_setup<T: Config>(
-	n: u32,
-) -> ((sp_runtime::KeyTypeId, &'static [u8; 32]), sp_session::MembershipProof) {
-	pallet_staking::ValidatorCount::<T>::put(n);
-
-	// create validators and set random session keys
-	for (n, who) in create_validators::<T>(n, 1000).unwrap().into_iter().enumerate() {
-		use rand::{RngCore, SeedableRng};
-
-		let validator = T::Lookup::lookup(who).unwrap();
-		let controller = pallet_staking::Pallet::<T>::bonded(&validator).unwrap();
-
-		let keys = {
-			let mut keys = [0u8; 128];
-
-			// we keep the keys for the first validator as 0x00000...
-			if n > 0 {
-				let mut rng = rand::rngs::StdRng::seed_from_u64(n as u64);
-				rng.fill_bytes(&mut keys);
-			}
-
-			keys
-		};
-
-		let keys: T::Keys = Decode::decode(&mut &keys[..]).unwrap();
-		let proof: Vec<u8> = vec![];
-
-		Session::<T>::set_keys(RawOrigin::Signed(controller).into(), keys, proof).unwrap();
-	}
-
-	Pallet::<T>::on_initialize(frame_system::pallet_prelude::BlockNumberFor::<T>::one());
-
-	// skip sessions until the new validator set is enacted
-	while Session::<T>::validators().len() < n as usize {
-		Session::<T>::rotate_session();
-	}
-
-	let key = (sp_runtime::KeyTypeId(*b"babe"), &[0u8; 32]);
-
-	(key, Historical::<T>::prove(key).unwrap())
-}
+#[cfg(all(feature = "runtime-benchmarks", test))]
+pub(crate) mod mock;
diff --git a/substrate/frame/src/lib.rs b/substrate/frame/src/lib.rs
index f93f4d31e77..90c446808da 100644
--- a/substrate/frame/src/lib.rs
+++ b/substrate/frame/src/lib.rs
@@ -34,9 +34,9 @@
 //!
 //! See [`polkadot_sdk::frame`](../polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html).
 //!
-//! ## Warning: Experimental
+//! ## WARNING: Experimental
 //!
-//! This crate and all of its content is experimental, and should not yet be used in production.
+//! **This crate and all of its content is experimental, and should not yet be used in production.**
 //!
 //! ## Underlying dependencies
 //!
diff --git a/substrate/frame/system/benchmarking/src/inner.rs b/substrate/frame/system/benchmarking/src/inner.rs
new file mode 100644
index 00000000000..c1631b0a2e3
--- /dev/null
+++ b/substrate/frame/system/benchmarking/src/inner.rs
@@ -0,0 +1,230 @@
+// 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.
+
+//! Frame System benchmarks.
+
+use codec::Encode;
+use frame_benchmarking::v2::*;
+use frame_support::{dispatch::DispatchClass, storage, traits::Get};
+use frame_system::{Call, Pallet as System, RawOrigin};
+use sp_core::storage::well_known_keys;
+use sp_runtime::traits::Hash;
+use sp_std::{prelude::*, vec};
+
+pub struct Pallet<T: Config>(System<T>);
+pub trait Config: frame_system::Config {
+	/// Adds ability to the Runtime to test against their sample code.
+	///
+	/// Default is `../res/kitchensink_runtime.compact.compressed.wasm`.
+	fn prepare_set_code_data() -> Vec<u8> {
+		include_bytes!("../res/kitchensink_runtime.compact.compressed.wasm").to_vec()
+	}
+
+	/// Adds ability to the Runtime to prepare/initialize before running benchmark `set_code`.
+	fn setup_set_code_requirements(_code: &Vec<u8>) -> Result<(), BenchmarkError> {
+		Ok(())
+	}
+
+	/// Adds ability to the Runtime to do custom validation after benchmark.
+	///
+	/// Default is checking for `CodeUpdated` event .
+	fn verify_set_code() {
+		System::<Self>::assert_last_event(frame_system::Event::<Self>::CodeUpdated.into());
+	}
+}
+
+#[benchmarks]
+mod benchmarks {
+	use super::*;
+
+	#[benchmark]
+	fn remark(
+		b: Linear<0, { *T::BlockLength::get().max.get(DispatchClass::Normal) as u32 }>,
+	) -> Result<(), BenchmarkError> {
+		let remark_message = vec![1; b as usize];
+		let caller = whitelisted_caller();
+
+		#[extrinsic_call]
+		remark(RawOrigin::Signed(caller), remark_message);
+
+		Ok(())
+	}
+
+	#[benchmark]
+	fn remark_with_event(
+		b: Linear<0, { *T::BlockLength::get().max.get(DispatchClass::Normal) as u32 }>,
+	) -> Result<(), BenchmarkError> {
+		let remark_message = vec![1; b as usize];
+		let caller: T::AccountId = whitelisted_caller();
+		let hash = T::Hashing::hash(&remark_message[..]);
+
+		#[extrinsic_call]
+		remark_with_event(RawOrigin::Signed(caller.clone()), remark_message);
+
+		System::<T>::assert_last_event(
+			frame_system::Event::<T>::Remarked { sender: caller, hash }.into(),
+		);
+		Ok(())
+	}
+
+	#[benchmark]
+	fn set_heap_pages() -> Result<(), BenchmarkError> {
+		#[extrinsic_call]
+		set_heap_pages(RawOrigin::Root, Default::default());
+
+		Ok(())
+	}
+
+	#[benchmark]
+	fn set_code() -> Result<(), BenchmarkError> {
+		let runtime_blob = T::prepare_set_code_data();
+		T::setup_set_code_requirements(&runtime_blob)?;
+
+		#[extrinsic_call]
+		set_code(RawOrigin::Root, runtime_blob);
+
+		T::verify_set_code();
+		Ok(())
+	}
+
+	#[benchmark(extra)]
+	fn set_code_without_checks() -> Result<(), BenchmarkError> {
+		// Assume Wasm ~4MB
+		let code = vec![1; 4_000_000 as usize];
+		T::setup_set_code_requirements(&code)?;
+
+		#[block]
+		{
+			System::<T>::set_code_without_checks(RawOrigin::Root.into(), code)?;
+		}
+
+		let current_code =
+			storage::unhashed::get_raw(well_known_keys::CODE).ok_or("Code not stored.")?;
+		assert_eq!(current_code.len(), 4_000_000 as usize);
+		Ok(())
+	}
+
+	#[benchmark(skip_meta)]
+	fn set_storage(i: Linear<0, { 1_000 }>) -> Result<(), BenchmarkError> {
+		// Set up i items to add
+		let mut items = Vec::new();
+		for j in 0..i {
+			let hash = (i, j).using_encoded(T::Hashing::hash).as_ref().to_vec();
+			items.push((hash.clone(), hash.clone()));
+		}
+
+		let items_to_verify = items.clone();
+
+		#[extrinsic_call]
+		set_storage(RawOrigin::Root, items);
+
+		// Verify that they're actually in the storage.
+		for (item, _) in items_to_verify {
+			let value = storage::unhashed::get_raw(&item).ok_or("No value stored")?;
+			assert_eq!(value, *item);
+		}
+		Ok(())
+	}
+
+	#[benchmark(skip_meta)]
+	fn kill_storage(i: Linear<0, { 1_000 }>) -> Result<(), BenchmarkError> {
+		// Add i items to storage
+		let mut items = Vec::with_capacity(i as usize);
+		for j in 0..i {
+			let hash = (i, j).using_encoded(T::Hashing::hash).as_ref().to_vec();
+			storage::unhashed::put_raw(&hash, &hash);
+			items.push(hash);
+		}
+
+		// Verify that they're actually in the storage.
+		for item in &items {
+			let value = storage::unhashed::get_raw(item).ok_or("No value stored")?;
+			assert_eq!(value, *item);
+		}
+
+		let items_to_verify = items.clone();
+
+		#[extrinsic_call]
+		kill_storage(RawOrigin::Root, items);
+
+		// Verify that they're not in the storage anymore.
+		for item in items_to_verify {
+			assert!(storage::unhashed::get_raw(&item).is_none());
+		}
+		Ok(())
+	}
+
+	#[benchmark(skip_meta)]
+	fn kill_prefix(p: Linear<0, { 1_000 }>) -> Result<(), BenchmarkError> {
+		let prefix = p.using_encoded(T::Hashing::hash).as_ref().to_vec();
+		let mut items = Vec::with_capacity(p as usize);
+		// add p items that share a prefix
+		for i in 0..p {
+			let hash = (p, i).using_encoded(T::Hashing::hash).as_ref().to_vec();
+			let key = [&prefix[..], &hash[..]].concat();
+			storage::unhashed::put_raw(&key, &key);
+			items.push(key);
+		}
+
+		// Verify that they're actually in the storage.
+		for item in &items {
+			let value = storage::unhashed::get_raw(item).ok_or("No value stored")?;
+			assert_eq!(value, *item);
+		}
+
+		#[extrinsic_call]
+		kill_prefix(RawOrigin::Root, prefix, p);
+
+		// Verify that they're not in the storage anymore.
+		for item in items {
+			assert!(storage::unhashed::get_raw(&item).is_none());
+		}
+		Ok(())
+	}
+
+	#[benchmark]
+	fn authorize_upgrade() -> Result<(), BenchmarkError> {
+		let runtime_blob = T::prepare_set_code_data();
+		T::setup_set_code_requirements(&runtime_blob)?;
+		let hash = T::Hashing::hash(&runtime_blob);
+
+		#[extrinsic_call]
+		authorize_upgrade(RawOrigin::Root, hash);
+
+		assert!(System::<T>::authorized_upgrade().is_some());
+		Ok(())
+	}
+
+	#[benchmark]
+	fn apply_authorized_upgrade() -> Result<(), BenchmarkError> {
+		let runtime_blob = T::prepare_set_code_data();
+		T::setup_set_code_requirements(&runtime_blob)?;
+		let hash = T::Hashing::hash(&runtime_blob);
+		// Will be heavier when it needs to do verification (i.e. don't use `...without_checks`).
+		System::<T>::authorize_upgrade(RawOrigin::Root.into(), hash)?;
+
+		#[extrinsic_call]
+		apply_authorized_upgrade(RawOrigin::Root, runtime_blob);
+
+		// Can't check for `CodeUpdated` in parachain upgrades. Just check that the authorization is
+		// gone.
+		assert!(System::<T>::authorized_upgrade().is_none());
+		Ok(())
+	}
+
+	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
+}
diff --git a/substrate/frame/system/benchmarking/src/lib.rs b/substrate/frame/system/benchmarking/src/lib.rs
index 29100faa751..e55038aeb95 100644
--- a/substrate/frame/system/benchmarking/src/lib.rs
+++ b/substrate/frame/system/benchmarking/src/lib.rs
@@ -15,221 +15,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Benchmarks for Utility Pallet
+//! Frame System benchmarks.
 
 #![cfg_attr(not(feature = "std"), no_std)]
-#![cfg(feature = "runtime-benchmarks")]
 
-use codec::Encode;
-use frame_benchmarking::v2::*;
-use frame_support::{dispatch::DispatchClass, storage, traits::Get};
-use frame_system::{Call, Pallet as System, RawOrigin};
-use sp_core::storage::well_known_keys;
-use sp_runtime::traits::Hash;
-use sp_std::{prelude::*, vec};
+#[cfg(feature = "runtime-benchmarks")]
+pub mod inner;
 
-mod mock;
+#[cfg(feature = "runtime-benchmarks")]
+pub use inner::*;
 
-pub struct Pallet<T: Config>(System<T>);
-pub trait Config: frame_system::Config {
-	/// Adds ability to the Runtime to test against their sample code.
-	///
-	/// Default is `../res/kitchensink_runtime.compact.compressed.wasm`.
-	fn prepare_set_code_data() -> Vec<u8> {
-		include_bytes!("../res/kitchensink_runtime.compact.compressed.wasm").to_vec()
-	}
-
-	/// Adds ability to the Runtime to prepare/initialize before running benchmark `set_code`.
-	fn setup_set_code_requirements(_code: &Vec<u8>) -> Result<(), BenchmarkError> {
-		Ok(())
-	}
-
-	/// Adds ability to the Runtime to do custom validation after benchmark.
-	///
-	/// Default is checking for `CodeUpdated` event .
-	fn verify_set_code() {
-		System::<Self>::assert_last_event(frame_system::Event::<Self>::CodeUpdated.into());
-	}
-}
-
-#[benchmarks]
-mod benchmarks {
-	use super::*;
-
-	#[benchmark]
-	fn remark(
-		b: Linear<0, { *T::BlockLength::get().max.get(DispatchClass::Normal) as u32 }>,
-	) -> Result<(), BenchmarkError> {
-		let remark_message = vec![1; b as usize];
-		let caller = whitelisted_caller();
-
-		#[extrinsic_call]
-		remark(RawOrigin::Signed(caller), remark_message);
-
-		Ok(())
-	}
-
-	#[benchmark]
-	fn remark_with_event(
-		b: Linear<0, { *T::BlockLength::get().max.get(DispatchClass::Normal) as u32 }>,
-	) -> Result<(), BenchmarkError> {
-		let remark_message = vec![1; b as usize];
-		let caller: T::AccountId = whitelisted_caller();
-		let hash = T::Hashing::hash(&remark_message[..]);
-
-		#[extrinsic_call]
-		remark_with_event(RawOrigin::Signed(caller.clone()), remark_message);
-
-		System::<T>::assert_last_event(
-			frame_system::Event::<T>::Remarked { sender: caller, hash }.into(),
-		);
-		Ok(())
-	}
-
-	#[benchmark]
-	fn set_heap_pages() -> Result<(), BenchmarkError> {
-		#[extrinsic_call]
-		set_heap_pages(RawOrigin::Root, Default::default());
-
-		Ok(())
-	}
-
-	#[benchmark]
-	fn set_code() -> Result<(), BenchmarkError> {
-		let runtime_blob = T::prepare_set_code_data();
-		T::setup_set_code_requirements(&runtime_blob)?;
-
-		#[extrinsic_call]
-		set_code(RawOrigin::Root, runtime_blob);
-
-		T::verify_set_code();
-		Ok(())
-	}
-
-	#[benchmark(extra)]
-	fn set_code_without_checks() -> Result<(), BenchmarkError> {
-		// Assume Wasm ~4MB
-		let code = vec![1; 4_000_000 as usize];
-		T::setup_set_code_requirements(&code)?;
-
-		#[block]
-		{
-			System::<T>::set_code_without_checks(RawOrigin::Root.into(), code)?;
-		}
-
-		let current_code =
-			storage::unhashed::get_raw(well_known_keys::CODE).ok_or("Code not stored.")?;
-		assert_eq!(current_code.len(), 4_000_000 as usize);
-		Ok(())
-	}
-
-	#[benchmark(skip_meta)]
-	fn set_storage(i: Linear<0, { 1_000 }>) -> Result<(), BenchmarkError> {
-		// Set up i items to add
-		let mut items = Vec::new();
-		for j in 0..i {
-			let hash = (i, j).using_encoded(T::Hashing::hash).as_ref().to_vec();
-			items.push((hash.clone(), hash.clone()));
-		}
-
-		let items_to_verify = items.clone();
-
-		#[extrinsic_call]
-		set_storage(RawOrigin::Root, items);
-
-		// Verify that they're actually in the storage.
-		for (item, _) in items_to_verify {
-			let value = storage::unhashed::get_raw(&item).ok_or("No value stored")?;
-			assert_eq!(value, *item);
-		}
-		Ok(())
-	}
-
-	#[benchmark(skip_meta)]
-	fn kill_storage(i: Linear<0, { 1_000 }>) -> Result<(), BenchmarkError> {
-		// Add i items to storage
-		let mut items = Vec::with_capacity(i as usize);
-		for j in 0..i {
-			let hash = (i, j).using_encoded(T::Hashing::hash).as_ref().to_vec();
-			storage::unhashed::put_raw(&hash, &hash);
-			items.push(hash);
-		}
-
-		// Verify that they're actually in the storage.
-		for item in &items {
-			let value = storage::unhashed::get_raw(item).ok_or("No value stored")?;
-			assert_eq!(value, *item);
-		}
-
-		let items_to_verify = items.clone();
-
-		#[extrinsic_call]
-		kill_storage(RawOrigin::Root, items);
-
-		// Verify that they're not in the storage anymore.
-		for item in items_to_verify {
-			assert!(storage::unhashed::get_raw(&item).is_none());
-		}
-		Ok(())
-	}
-
-	#[benchmark(skip_meta)]
-	fn kill_prefix(p: Linear<0, { 1_000 }>) -> Result<(), BenchmarkError> {
-		let prefix = p.using_encoded(T::Hashing::hash).as_ref().to_vec();
-		let mut items = Vec::with_capacity(p as usize);
-		// add p items that share a prefix
-		for i in 0..p {
-			let hash = (p, i).using_encoded(T::Hashing::hash).as_ref().to_vec();
-			let key = [&prefix[..], &hash[..]].concat();
-			storage::unhashed::put_raw(&key, &key);
-			items.push(key);
-		}
-
-		// Verify that they're actually in the storage.
-		for item in &items {
-			let value = storage::unhashed::get_raw(item).ok_or("No value stored")?;
-			assert_eq!(value, *item);
-		}
-
-		#[extrinsic_call]
-		kill_prefix(RawOrigin::Root, prefix, p);
-
-		// Verify that they're not in the storage anymore.
-		for item in items {
-			assert!(storage::unhashed::get_raw(&item).is_none());
-		}
-		Ok(())
-	}
-
-	#[benchmark]
-	fn authorize_upgrade() -> Result<(), BenchmarkError> {
-		let runtime_blob = T::prepare_set_code_data();
-		T::setup_set_code_requirements(&runtime_blob)?;
-		let hash = T::Hashing::hash(&runtime_blob);
-
-		#[extrinsic_call]
-		authorize_upgrade(RawOrigin::Root, hash);
-
-		assert!(System::<T>::authorized_upgrade().is_some());
-		Ok(())
-	}
-
-	#[benchmark]
-	fn apply_authorized_upgrade() -> Result<(), BenchmarkError> {
-		let runtime_blob = T::prepare_set_code_data();
-		T::setup_set_code_requirements(&runtime_blob)?;
-		let hash = T::Hashing::hash(&runtime_blob);
-		// Will be heavier when it needs to do verification (i.e. don't use `...without_checks`).
-		System::<T>::authorize_upgrade(RawOrigin::Root.into(), hash)?;
-
-		#[extrinsic_call]
-		apply_authorized_upgrade(RawOrigin::Root, runtime_blob);
-
-		// Can't check for `CodeUpdated` in parachain upgrades. Just check that the authorization is
-		// gone.
-		assert!(System::<T>::authorized_upgrade().is_none());
-		Ok(())
-	}
-
-	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
-}
+#[cfg(all(feature = "runtime-benchmarks", test))]
+pub(crate) mod mock;
diff --git a/substrate/frame/try-runtime/src/inner.rs b/substrate/frame/try-runtime/src/inner.rs
new file mode 100644
index 00000000000..591124e2ad9
--- /dev/null
+++ b/substrate/frame/try-runtime/src/inner.rs
@@ -0,0 +1,50 @@
+// 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.
+
+//! Supporting types for try-runtime, testing and dry-running commands.
+
+pub use frame_support::traits::{TryStateSelect, UpgradeCheckSelect};
+use frame_support::weights::Weight;
+
+sp_api::decl_runtime_apis! {
+	/// Runtime api for testing the execution of a runtime upgrade.
+	pub trait TryRuntime {
+		/// dry-run runtime upgrades, returning the total weight consumed.
+		///
+		/// This should do EXACTLY the same operations as the runtime would have done in the case of
+		/// a runtime upgrade (e.g. pallet ordering must be the same)
+		///
+		/// Returns the consumed weight of the migration in case of a successful one, combined with
+		/// the total allowed block weight of the runtime.
+		///
+		/// If `checks` is `true`, `pre_migrate` and `post_migrate` of each migration and
+		/// `try_state` of all pallets will be executed. Else, no. If checks are executed, the PoV
+		/// tracking is likely inaccurate.
+		fn on_runtime_upgrade(checks: UpgradeCheckSelect) -> (Weight, Weight);
+
+		/// Execute the given block, but optionally disable state-root and signature checks.
+		///
+		/// Optionally, a number of `try_state` hooks can also be executed after the block
+		/// execution.
+		fn execute_block(
+			block: Block,
+			state_root_check: bool,
+			signature_check: bool,
+			try_state: TryStateSelect,
+		) -> Weight;
+	}
+}
diff --git a/substrate/frame/try-runtime/src/lib.rs b/substrate/frame/try-runtime/src/lib.rs
index 43292efe210..9da2dd18ca2 100644
--- a/substrate/frame/try-runtime/src/lib.rs
+++ b/substrate/frame/try-runtime/src/lib.rs
@@ -18,36 +18,9 @@
 //! Supporting types for try-runtime, testing and dry-running commands.
 
 #![cfg_attr(not(feature = "std"), no_std)]
-#![cfg(feature = "try-runtime")]
 
-pub use frame_support::traits::{TryStateSelect, UpgradeCheckSelect};
-use frame_support::weights::Weight;
+#[cfg(feature = "try-runtime")]
+pub mod inner;
 
-sp_api::decl_runtime_apis! {
-	/// Runtime api for testing the execution of a runtime upgrade.
-	pub trait TryRuntime {
-		/// dry-run runtime upgrades, returning the total weight consumed.
-		///
-		/// This should do EXACTLY the same operations as the runtime would have done in the case of
-		/// a runtime upgrade (e.g. pallet ordering must be the same)
-		///
-		/// Returns the consumed weight of the migration in case of a successful one, combined with
-		/// the total allowed block weight of the runtime.
-		///
-		/// If `checks` is `true`, `pre_migrate` and `post_migrate` of each migration and
-		/// `try_state` of all pallets will be executed. Else, no. If checks are executed, the PoV
-		/// tracking is likely inaccurate.
-		fn on_runtime_upgrade(checks: UpgradeCheckSelect) -> (Weight, Weight);
-
-		/// Execute the given block, but optionally disable state-root and signature checks.
-		///
-		/// Optionally, a number of `try_state` hooks can also be executed after the block
-		/// execution.
-		fn execute_block(
-			block: Block,
-			state_root_check: bool,
-			signature_check: bool,
-			try_state: TryStateSelect,
-		) -> Weight;
-	}
-}
+#[cfg(feature = "try-runtime")]
+pub use inner::*;
diff --git a/substrate/primitives/consensus/babe/Cargo.toml b/substrate/primitives/consensus/babe/Cargo.toml
index 2420f48b1f4..799d474aebe 100644
--- a/substrate/primitives/consensus/babe/Cargo.toml
+++ b/substrate/primitives/consensus/babe/Cargo.toml
@@ -26,7 +26,7 @@ sp-consensus-slots = { path = "../slots", default-features = false }
 sp-core = { path = "../../core", default-features = false }
 sp-inherents = { path = "../../inherents", default-features = false }
 sp-runtime = { path = "../../runtime", default-features = false }
-sp-timestamp = { path = "../../timestamp", optional = true }
+sp-timestamp = { path = "../../timestamp", optional = true, default-features = false }
 
 [features]
 default = ["std"]
diff --git a/substrate/primitives/core/Cargo.toml b/substrate/primitives/core/Cargo.toml
index 833b2af95cd..8437497b02b 100644
--- a/substrate/primitives/core/Cargo.toml
+++ b/substrate/primitives/core/Cargo.toml
@@ -37,7 +37,7 @@ ss58-registry = { version = "1.34.0", default-features = false }
 sp-std = { path = "../std", default-features = false }
 sp-debug-derive = { path = "../debug-derive", default-features = false }
 sp-storage = { path = "../storage", default-features = false }
-sp-externalities = { path = "../externalities", optional = true }
+sp-externalities = { path = "../externalities", optional = true, default-features = false }
 futures = { version = "0.3.30", optional = true }
 dyn-clonable = { version = "0.9.0", optional = true }
 thiserror = { optional = true, workspace = true }
diff --git a/substrate/primitives/session/Cargo.toml b/substrate/primitives/session/Cargo.toml
index cdee4fb03e1..5314ccd6d96 100644
--- a/substrate/primitives/session/Cargo.toml
+++ b/substrate/primitives/session/Cargo.toml
@@ -20,9 +20,9 @@ codec = { package = "parity-scale-codec", version = "3.6.1", default-features =
 scale-info = { version = "2.11.1", default-features = false, features = ["derive"] }
 sp-api = { path = "../api", default-features = false }
 sp-core = { path = "../core", default-features = false }
-sp-runtime = { path = "../runtime", optional = true }
+sp-runtime = { path = "../runtime", optional = true, default-features = false }
 sp-staking = { path = "../staking", default-features = false }
-sp-keystore = { path = "../keystore", optional = true }
+sp-keystore = { path = "../keystore", optional = true, default-features = false }
 
 [features]
 default = ["std"]
diff --git a/substrate/primitives/transaction-storage-proof/Cargo.toml b/substrate/primitives/transaction-storage-proof/Cargo.toml
index 137a232fce7..6cce469d3f9 100644
--- a/substrate/primitives/transaction-storage-proof/Cargo.toml
+++ b/substrate/primitives/transaction-storage-proof/Cargo.toml
@@ -19,10 +19,10 @@ targets = ["x86_64-unknown-linux-gnu"]
 async-trait = { version = "0.1.79", optional = true }
 codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] }
 scale-info = { version = "2.11.1", default-features = false, features = ["derive"] }
-sp-core = { path = "../core", optional = true }
+sp-core = { path = "../core", optional = true, default-features = false }
 sp-inherents = { path = "../inherents", default-features = false }
 sp-runtime = { path = "../runtime", default-features = false }
-sp-trie = { path = "../trie", optional = true }
+sp-trie = { path = "../trie", optional = true, default-features = false }
 
 [features]
 default = ["std"]
-- 
GitLab