diff --git a/.github/workflows/review-trigger.yml b/.github/workflows/review-trigger.yml
index 061cf4ab09ed919f6de0a83f74a22c2062c3a258..7f7d9d362782c9738e108de0f7f949aaab3eb8c6 100644
--- a/.github/workflows/review-trigger.yml
+++ b/.github/workflows/review-trigger.yml
@@ -21,25 +21,30 @@ jobs:
       - name: Skip merge queue
         if: ${{ contains(github.ref, 'gh-readonly-queue') }}
         run: exit 0
-      - name: Get comments
+      - name: Get PR data
         id: comments
-        run: echo "bodies=$(gh pr view ${{ github.event.number }} --repo ${{ github.repository }} --json comments --jq '[.comments[].body]')" >> "$GITHUB_OUTPUT"
+        run: |
+          echo "bodies=$(gh pr view ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --json comments --jq '[.comments[].body]')" >> "$GITHUB_OUTPUT"
+          echo "reviews=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews --jq '[.[].state]')" >> "$GITHUB_OUTPUT"
         env:
           GH_TOKEN: ${{ github.token }}
       - name: Fail when author pushes new code
         # Require new reviews when the author is pushing and he is not a member
         if: |
+          contains(fromJson(steps.comments.outputs.reviews), 'APPROVED') &&
           github.event_name == 'pull_request_target' &&
           github.event.action == 'synchronize' && 
           github.event.sender.login == github.event.pull_request.user.login && 
+          github.event.pull_request.author_association != 'CONTRIBUTOR' && 
           github.event.pull_request.author_association != 'MEMBER'
         run: |
+          echo "User's association is ${{ github.event.pull_request.author_association }}"
           # We get the list of reviewers who approved the PR
-          REVIEWERS=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.number }}/reviews \
+          REVIEWERS=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews \
           --jq '{reviewers: [.[] | select(.state == "APPROVED") | .user.login]}')
 
           # We request them to review again
-          echo $REVIEWERS | gh api --method POST repos/${{ github.repository }}/pulls/${{ github.event.number }}/requested_reviewers --input -
+          echo $REVIEWERS | gh api --method POST repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/requested_reviewers --input -
           
           echo "::error::Project needs to be reviewed again"
           exit 1
@@ -49,7 +54,7 @@ jobs:
         # If the previous step failed and github-actions hasn't commented yet we comment instructions
         if: failure() && !contains(fromJson(steps.comments.outputs.bodies), 'Review required! Latest push from author must always be reviewed')
         run: |          
-          gh pr comment ${{ github.event.number }} --repo ${{ github.repository }} --body "Review required! Latest push from author must always be reviewed"
+          gh pr comment ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --body "Review required! Latest push from author must always be reviewed"
         env:
           GH_TOKEN: ${{ github.token }}
           COMMENTS: ${{ steps.comments.outputs.users }}
diff --git a/Cargo.lock b/Cargo.lock
index 32dee11171fdc57382fbd8c0d64e40a006064c13..ff28d842a23ed38a7723563984ea4e697cb0ed25 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -820,6 +820,7 @@ dependencies = [
  "assert_matches",
  "asset-hub-rococo-runtime",
  "asset-test-utils",
+ "cumulus-pallet-parachain-system",
  "emulated-integration-tests-common",
  "frame-support",
  "pallet-asset-conversion",
@@ -827,11 +828,15 @@ dependencies = [
  "pallet-assets",
  "pallet-balances",
  "pallet-message-queue",
+ "pallet-treasury",
+ "pallet-utility",
  "pallet-xcm",
  "parachains-common",
  "parity-scale-codec",
  "penpal-runtime",
+ "polkadot-runtime-common",
  "rococo-runtime",
+ "rococo-runtime-constants",
  "rococo-system-emulated-network",
  "sp-runtime",
  "staging-xcm",
@@ -2834,6 +2839,36 @@ dependencies = [
  "testnet-parachains-constants",
 ]
 
+[[package]]
+name = "collectives-westend-integration-tests"
+version = "1.0.0"
+dependencies = [
+ "assert_matches",
+ "asset-hub-westend-runtime",
+ "collectives-westend-runtime",
+ "cumulus-pallet-parachain-system",
+ "cumulus-pallet-xcmp-queue",
+ "emulated-integration-tests-common",
+ "frame-support",
+ "pallet-asset-rate",
+ "pallet-assets",
+ "pallet-balances",
+ "pallet-message-queue",
+ "pallet-treasury",
+ "pallet-utility",
+ "pallet-xcm",
+ "parachains-common",
+ "parity-scale-codec",
+ "polkadot-runtime-common",
+ "sp-runtime",
+ "staging-xcm",
+ "staging-xcm-executor",
+ "testnet-parachains-constants",
+ "westend-runtime",
+ "westend-runtime-constants",
+ "westend-system-emulated-network",
+]
+
 [[package]]
 name = "collectives-westend-runtime"
 version = "3.0.0"
diff --git a/Cargo.toml b/Cargo.toml
index a020bfa694a237dbef0b2133118cd2ca2ca5a925..ab7b8ee4baf40dd9bd9ec2f1f9993fa5ae618757 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -103,6 +103,7 @@ members = [
 	"cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend",
 	"cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo",
 	"cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend",
+	"cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend",
 	"cumulus/parachains/integration-tests/emulated/tests/people/people-rococo",
 	"cumulus/parachains/integration-tests/emulated/tests/people/people-westend",
 	"cumulus/parachains/pallets/collective-content",
diff --git a/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/src/lib.rs
index 379a29d697bcb564b670eadb638f7088f042137a..7a3a936ec972f0a8c99e3b472c7cce9e9914e29c 100644
--- a/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/src/lib.rs
+++ b/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/src/lib.rs
@@ -39,6 +39,8 @@ decl_test_relay_chains! {
 			Hrmp: rococo_runtime::Hrmp,
 			Identity: rococo_runtime::Identity,
 			IdentityMigrator: rococo_runtime::IdentityMigrator,
+			Treasury: rococo_runtime::Treasury,
+			AssetRate: rococo_runtime::AssetRate,
 		}
 	},
 }
diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml
index 64fee0241a4da2d987d4906918677fe1acbd91e3..230f7a9c359b922070f507355a74a708d80096e5 100644
--- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml
+++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml
@@ -22,15 +22,20 @@ pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-
 pallet-asset-conversion = { path = "../../../../../../../substrate/frame/asset-conversion", default-features = false }
 pallet-asset-rewards = { path = "../../../../../../../substrate/frame/asset-rewards", default-features = false }
 pallet-message-queue = { path = "../../../../../../../substrate/frame/message-queue", default-features = false }
+pallet-treasury = { path = "../../../../../../../substrate/frame/treasury", default-features = false }
+pallet-utility = { path = "../../../../../../../substrate/frame/utility", default-features = false }
 
 # Polkadot
 xcm = { package = "staging-xcm", path = "../../../../../../../polkadot/xcm", default-features = false }
 pallet-xcm = { path = "../../../../../../../polkadot/xcm/pallet-xcm", default-features = false }
 xcm-executor = { package = "staging-xcm-executor", path = "../../../../../../../polkadot/xcm/xcm-executor", default-features = false }
 rococo-runtime = { path = "../../../../../../../polkadot/runtime/rococo" }
+polkadot-runtime-common = { path = "../../../../../../../polkadot/runtime/common" }
+rococo-runtime-constants = { path = "../../../../../../../polkadot/runtime/rococo/constants" }
 
 # Cumulus
 asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" }
+cumulus-pallet-parachain-system = { path = "../../../../../../pallets/parachain-system", default-features = false }
 parachains-common = { path = "../../../../../common" }
 asset-hub-rococo-runtime = { path = "../../../../../runtimes/assets/asset-hub-rococo" }
 penpal-runtime = { path = "../../../../../runtimes/testing/penpal" }
diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs
index dfe0a7561d509717647744d2ede358a45840b284..89f32ccdfb51c0f85c4b1da18914d30281ad6780 100644
--- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs
+++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs
@@ -20,3 +20,4 @@ mod set_xcm_versions;
 mod swap;
 mod teleport;
 mod treasury_asset_reward_pool;
+mod treasury;
diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs
new file mode 100644
index 0000000000000000000000000000000000000000..01bf40ae8fdf2cf87092c83ef604ef25427e2939
--- /dev/null
+++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs
@@ -0,0 +1,270 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::imports::*;
+use emulated_integration_tests_common::accounts::{ALICE, BOB};
+use frame_support::{
+	dispatch::RawOrigin,
+	sp_runtime::traits::Dispatchable,
+	traits::{
+		fungible::Inspect,
+		fungibles::{Create, Inspect as FungiblesInspect, Mutate},
+	},
+};
+use parachains_common::AccountId;
+use polkadot_runtime_common::impls::VersionedLocatableAsset;
+use rococo_runtime::OriginCaller;
+use rococo_runtime_constants::currency::GRAND;
+use xcm_executor::traits::ConvertLocation;
+
+// Fund Treasury account on Asset Hub from Treasury account on Relay Chain with ROCs.
+#[test]
+fn spend_roc_on_asset_hub() {
+	// initial treasury balance on Asset Hub in ROCs.
+	let treasury_balance = 9_000 * GRAND;
+	// the balance spend on Asset Hub.
+	let treasury_spend_balance = 1_000 * GRAND;
+
+	let init_alice_balance = AssetHubRococo::execute_with(|| {
+		<<AssetHubRococo as AssetHubRococoPallet>::Balances as Inspect<_>>::balance(
+			&AssetHubRococo::account_id_of(ALICE),
+		)
+	});
+
+	Rococo::execute_with(|| {
+		type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
+		type RuntimeCall = <Rococo as Chain>::RuntimeCall;
+		type Runtime = <Rococo as Chain>::Runtime;
+		type Balances = <Rococo as RococoPallet>::Balances;
+		type Treasury = <Rococo as RococoPallet>::Treasury;
+
+		// Fund Treasury account on Asset Hub with ROCs.
+
+		let root = <Rococo as Chain>::RuntimeOrigin::root();
+		let treasury_account = Treasury::account_id();
+
+		// Mint assets to Treasury account on Relay Chain.
+		assert_ok!(Balances::force_set_balance(
+			root.clone(),
+			treasury_account.clone().into(),
+			treasury_balance * 2,
+		));
+
+		let native_asset = Location::here();
+		let asset_hub_location: Location = [Parachain(1000)].into();
+		let treasury_location: Location = (Parent, PalletInstance(18)).into();
+
+		let teleport_call = RuntimeCall::Utility(pallet_utility::Call::<Runtime>::dispatch_as {
+			as_origin: bx!(OriginCaller::system(RawOrigin::Signed(treasury_account))),
+			call: bx!(RuntimeCall::XcmPallet(pallet_xcm::Call::<Runtime>::teleport_assets {
+				dest: bx!(VersionedLocation::V4(asset_hub_location.clone())),
+				beneficiary: bx!(VersionedLocation::V4(treasury_location)),
+				assets: bx!(VersionedAssets::V4(
+					Asset { id: native_asset.clone().into(), fun: treasury_balance.into() }.into()
+				)),
+				fee_asset_item: 0,
+			})),
+		});
+
+		// Dispatched from Root to `despatch_as` `Signed(treasury_account)`.
+		assert_ok!(teleport_call.dispatch(root));
+
+		assert_expected_events!(
+			Rococo,
+			vec![
+				RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
+			]
+		);
+	});
+
+	Rococo::execute_with(|| {
+		type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
+		type RuntimeCall = <Rococo as Chain>::RuntimeCall;
+		type RuntimeOrigin = <Rococo as Chain>::RuntimeOrigin;
+		type Runtime = <Rococo as Chain>::Runtime;
+		type Treasury = <Rococo as RococoPallet>::Treasury;
+
+		// Fund Alice account from Rococo Treasury account on Asset Hub.
+
+		let treasury_origin: RuntimeOrigin =
+			rococo_runtime::governance::pallet_custom_origins::Origin::Treasurer.into();
+
+		let alice_location: Location =
+			[Junction::AccountId32 { network: None, id: Rococo::account_id_of(ALICE).into() }]
+				.into();
+		let asset_hub_location: Location = [Parachain(1000)].into();
+		let native_asset = Location::parent();
+
+		let treasury_spend_call = RuntimeCall::Treasury(pallet_treasury::Call::<Runtime>::spend {
+			asset_kind: bx!(VersionedLocatableAsset::V4 {
+				location: asset_hub_location.clone(),
+				asset_id: native_asset.into(),
+			}),
+			amount: treasury_spend_balance,
+			beneficiary: bx!(VersionedLocation::V4(alice_location)),
+			valid_from: None,
+		});
+
+		assert_ok!(treasury_spend_call.dispatch(treasury_origin));
+
+		// Claim the spend.
+
+		let bob_signed = RuntimeOrigin::signed(Rococo::account_id_of(BOB));
+		assert_ok!(Treasury::payout(bob_signed.clone(), 0));
+
+		assert_expected_events!(
+			Rococo,
+			vec![
+				RuntimeEvent::Treasury(pallet_treasury::Event::AssetSpendApproved { .. }) => {},
+				RuntimeEvent::Treasury(pallet_treasury::Event::Paid { .. }) => {},
+			]
+		);
+	});
+
+	AssetHubRococo::execute_with(|| {
+		type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
+		type Balances = <AssetHubRococo as AssetHubRococoPallet>::Balances;
+
+		// Ensure that the funds deposited to Alice account.
+
+		let alice_account = AssetHubRococo::account_id_of(ALICE);
+		assert_eq!(
+			<Balances as Inspect<_>>::balance(&alice_account),
+			treasury_spend_balance + init_alice_balance
+		);
+
+		// Assert events triggered by xcm pay program:
+		// 1. treasury asset transferred to spend beneficiary;
+		// 2. response to Relay Chain Treasury pallet instance sent back;
+		// 3. XCM program completed;
+		assert_expected_events!(
+			AssetHubRococo,
+			vec![
+				RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => {},
+				RuntimeEvent::ParachainSystem(cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }) => {},
+				RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {},
+			]
+		);
+	});
+}
+
+#[test]
+fn create_and_claim_treasury_spend_in_usdt() {
+	const ASSET_ID: u32 = 1984;
+	const SPEND_AMOUNT: u128 = 1_000_000;
+	// treasury location from a sibling parachain.
+	let treasury_location: Location = Location::new(1, PalletInstance(18));
+	// treasury account on a sibling parachain.
+	let treasury_account =
+		asset_hub_rococo_runtime::xcm_config::LocationToAccountId::convert_location(
+			&treasury_location,
+		)
+		.unwrap();
+	let asset_hub_location =
+		v3::Location::new(0, v3::Junction::Parachain(AssetHubRococo::para_id().into()));
+	let root = <Rococo as Chain>::RuntimeOrigin::root();
+	// asset kind to be spend from the treasury.
+	let asset_kind = VersionedLocatableAsset::V3 {
+		location: asset_hub_location,
+		asset_id: v3::AssetId::Concrete(
+			(v3::Junction::PalletInstance(50), v3::Junction::GeneralIndex(ASSET_ID.into())).into(),
+		),
+	};
+	// treasury spend beneficiary.
+	let alice: AccountId = Rococo::account_id_of(ALICE);
+	let bob: AccountId = Rococo::account_id_of(BOB);
+	let bob_signed = <Rococo as Chain>::RuntimeOrigin::signed(bob.clone());
+
+	AssetHubRococo::execute_with(|| {
+		type Assets = <AssetHubRococo as AssetHubRococoPallet>::Assets;
+
+		// create an asset class and mint some assets to the treasury account.
+		assert_ok!(<Assets as Create<_>>::create(
+			ASSET_ID,
+			treasury_account.clone(),
+			true,
+			SPEND_AMOUNT / 2
+		));
+		assert_ok!(<Assets as Mutate<_>>::mint_into(ASSET_ID, &treasury_account, SPEND_AMOUNT * 4));
+		// beneficiary has zero balance.
+		assert_eq!(<Assets as FungiblesInspect<_>>::balance(ASSET_ID, &alice,), 0u128,);
+	});
+
+	Rococo::execute_with(|| {
+		type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
+		type Treasury = <Rococo as RococoPallet>::Treasury;
+		type AssetRate = <Rococo as RococoPallet>::AssetRate;
+
+		// create a conversion rate from `asset_kind` to the native currency.
+		assert_ok!(AssetRate::create(root.clone(), Box::new(asset_kind.clone()), 2.into()));
+
+		// create and approve a treasury spend.
+		assert_ok!(Treasury::spend(
+			root,
+			Box::new(asset_kind),
+			SPEND_AMOUNT,
+			Box::new(Location::new(0, Into::<[u8; 32]>::into(alice.clone())).into()),
+			None,
+		));
+		// claim the spend.
+		assert_ok!(Treasury::payout(bob_signed.clone(), 0));
+
+		assert_expected_events!(
+			Rococo,
+			vec![
+				RuntimeEvent::Treasury(pallet_treasury::Event::Paid { .. }) => {},
+			]
+		);
+	});
+
+	AssetHubRococo::execute_with(|| {
+		type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
+		type Assets = <AssetHubRococo as AssetHubRococoPallet>::Assets;
+
+		// assert events triggered by xcm pay program
+		// 1. treasury asset transferred to spend beneficiary
+		// 2. response to Relay Chain treasury pallet instance sent back
+		// 3. XCM program completed
+		assert_expected_events!(
+			AssetHubRococo,
+			vec![
+				RuntimeEvent::Assets(pallet_assets::Event::Transferred { asset_id: id, from, to, amount }) => {
+					id: id == &ASSET_ID,
+					from: from == &treasury_account,
+					to: to == &alice,
+					amount: amount == &SPEND_AMOUNT,
+				},
+				RuntimeEvent::ParachainSystem(cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }) => {},
+				RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {},
+			]
+		);
+		// beneficiary received the assets from the treasury.
+		assert_eq!(<Assets as FungiblesInspect<_>>::balance(ASSET_ID, &alice,), SPEND_AMOUNT,);
+	});
+
+	Rococo::execute_with(|| {
+		type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
+		type Treasury = <Rococo as RococoPallet>::Treasury;
+
+		// check the payment status to ensure the response from the AssetHub was received.
+		assert_ok!(Treasury::check_status(bob_signed, 0));
+		assert_expected_events!(
+			Rococo,
+			vec![
+				RuntimeEvent::Treasury(pallet_treasury::Event::SpendProcessed { .. }) => {},
+			]
+		);
+	});
+}
diff --git a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/Cargo.toml
new file mode 100644
index 0000000000000000000000000000000000000000..d1dbef9fc4156c08b2c52f54a3759de763c959e0
--- /dev/null
+++ b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/Cargo.toml
@@ -0,0 +1,43 @@
+[package]
+name = "collectives-westend-integration-tests"
+version = "1.0.0"
+authors.workspace = true
+edition.workspace = true
+license = "Apache-2.0"
+description = "Collectives Westend runtime integration tests with xcm-emulator"
+publish = false
+
+[lints]
+workspace = true
+
+[dependencies]
+codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false }
+assert_matches = "1.5.0"
+
+# Substrate
+sp-runtime = { path = "../../../../../../../substrate/primitives/runtime", default-features = false }
+frame-support = { path = "../../../../../../../substrate/frame/support", default-features = false }
+pallet-balances = { path = "../../../../../../../substrate/frame/balances", default-features = false }
+pallet-asset-rate = { path = "../../../../../../../substrate/frame/asset-rate", default-features = false }
+pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-features = false }
+pallet-treasury = { path = "../../../../../../../substrate/frame/treasury", default-features = false }
+pallet-message-queue = { path = "../../../../../../../substrate/frame/message-queue", default-features = false }
+pallet-utility = { path = "../../../../../../../substrate/frame/utility", default-features = false }
+
+# Polkadot
+polkadot-runtime-common = { path = "../../../../../../../polkadot/runtime/common" }
+xcm = { package = "staging-xcm", path = "../../../../../../../polkadot/xcm", default-features = false }
+xcm-executor = { package = "staging-xcm-executor", path = "../../../../../../../polkadot/xcm/xcm-executor", default-features = false }
+pallet-xcm = { path = "../../../../../../../polkadot/xcm/pallet-xcm", default-features = false }
+westend-runtime = { path = "../../../../../../../polkadot/runtime/westend" }
+westend-runtime-constants = { path = "../../../../../../../polkadot/runtime/westend/constants" }
+
+# Cumulus
+parachains-common = { path = "../../../../../../parachains/common" }
+testnet-parachains-constants = { path = "../../../../../runtimes/constants", features = ["westend"] }
+asset-hub-westend-runtime = { path = "../../../../../runtimes/assets/asset-hub-westend" }
+collectives-westend-runtime = { path = "../../../../../runtimes/collectives/collectives-westend" }
+cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../../pallets/xcmp-queue" }
+cumulus-pallet-parachain-system = { default-features = false, path = "../../../../../../pallets/parachain-system" }
+emulated-integration-tests-common = { path = "../../../common", default-features = false }
+westend-system-emulated-network = { path = "../../../networks/westend-system" }
diff --git a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/lib.rs
new file mode 100644
index 0000000000000000000000000000000000000000..97239330216ac8f66a7684811d1de30b13f56f7e
--- /dev/null
+++ b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/lib.rs
@@ -0,0 +1,30 @@
+// 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.
+
+pub use xcm::{prelude::*, v3};
+
+pub use emulated_integration_tests_common::xcm_emulator::{
+	assert_expected_events, bx, Chain, RelayChain as Relay, TestExt,
+};
+pub use westend_system_emulated_network::{
+	asset_hub_westend_emulated_chain::AssetHubWestendParaPallet as AssetHubWestendPallet,
+	collectives_westend_emulated_chain::CollectivesWestendParaPallet as CollectivesWestendPallet,
+	westend_emulated_chain::WestendRelayPallet as WestendPallet,
+	AssetHubWestendPara as AssetHubWestend, CollectivesWestendPara as CollectivesWestend,
+	WestendRelay as Westend,
+};
+
+#[cfg(test)]
+mod tests;
diff --git a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs
new file mode 100644
index 0000000000000000000000000000000000000000..bde1220e2495bc544e507be1a8b40d77fcbde894
--- /dev/null
+++ b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs
@@ -0,0 +1,236 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::*;
+use asset_hub_westend_runtime::xcm_config::LocationToAccountId as AssetHubLocationToAccountId;
+use emulated_integration_tests_common::accounts::ALICE;
+use frame_support::{
+	assert_ok, dispatch::RawOrigin, instances::Instance1, sp_runtime::traits::Dispatchable,
+	traits::fungible::Inspect,
+};
+use polkadot_runtime_common::impls::VersionedLocatableAsset;
+use westend_runtime::OriginCaller;
+use westend_runtime_constants::currency::UNITS;
+use xcm_executor::traits::ConvertLocation;
+
+// Fund Fellowship Treasury from Westend Treasury and spend from Fellowship Treasury.
+#[test]
+fn fellowship_treasury_spend() {
+	// initial treasury balance on Asset Hub in WNDs.
+	let treasury_balance = 20_000_000 * UNITS;
+	// target fellowship balance on Asset Hub in WNDs.
+	let fellowship_treasury_balance = 1_000_000 * UNITS;
+	// fellowship first spend balance in WNDs.
+	let fellowship_spend_balance = 10_000 * UNITS;
+
+	let init_alice_balance = AssetHubWestend::execute_with(|| {
+		<<AssetHubWestend as AssetHubWestendPallet>::Balances as Inspect<_>>::balance(
+			&AssetHubWestend::account_id_of(ALICE),
+		)
+	});
+
+	Westend::execute_with(|| {
+		type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
+		type RuntimeCall = <Westend as Chain>::RuntimeCall;
+		type Runtime = <Westend as Chain>::Runtime;
+		type Balances = <Westend as WestendPallet>::Balances;
+		type Treasury = <Westend as WestendPallet>::Treasury;
+
+		// Fund Treasury account on Asset Hub with WNDs.
+
+		let root = <Westend as Chain>::RuntimeOrigin::root();
+		let treasury_account = Treasury::account_id();
+
+		// Mist assets to Treasury account on Relay Chain.
+		assert_ok!(Balances::force_set_balance(
+			root.clone(),
+			treasury_account.clone().into(),
+			treasury_balance * 2,
+		));
+
+		let native_asset = Location::here();
+		let asset_hub_location: Location = [Parachain(1000)].into();
+		let treasury_location: Location = (Parent, PalletInstance(37)).into();
+
+		let teleport_call = RuntimeCall::Utility(pallet_utility::Call::<Runtime>::dispatch_as {
+			as_origin: bx!(OriginCaller::system(RawOrigin::Signed(treasury_account))),
+			call: bx!(RuntimeCall::XcmPallet(pallet_xcm::Call::<Runtime>::teleport_assets {
+				dest: bx!(VersionedLocation::V4(asset_hub_location.clone())),
+				beneficiary: bx!(VersionedLocation::V4(treasury_location)),
+				assets: bx!(VersionedAssets::V4(
+					Asset { id: native_asset.clone().into(), fun: treasury_balance.into() }.into()
+				)),
+				fee_asset_item: 0,
+			})),
+		});
+
+		// Dispatched from Root to `dispatch_as` `Signed(treasury_account)`.
+		assert_ok!(teleport_call.dispatch(root));
+
+		assert_expected_events!(
+			Westend,
+			vec![
+				RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
+			]
+		);
+	});
+
+	Westend::execute_with(|| {
+		type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
+		type RuntimeCall = <Westend as Chain>::RuntimeCall;
+		type RuntimeOrigin = <Westend as Chain>::RuntimeOrigin;
+		type Runtime = <Westend as Chain>::Runtime;
+		type Treasury = <Westend as WestendPallet>::Treasury;
+
+		// Fund Fellowship Treasury from Westend Treasury.
+
+		let treasury_origin: RuntimeOrigin =
+			westend_runtime::governance::pallet_custom_origins::Origin::Treasurer.into();
+		let fellowship_treasury_location: Location =
+			Location::new(1, [Parachain(1001), PalletInstance(65)]);
+		let asset_hub_location: Location = [Parachain(1000)].into();
+		let native_asset = Location::parent();
+
+		let treasury_spend_call = RuntimeCall::Treasury(pallet_treasury::Call::<Runtime>::spend {
+			asset_kind: bx!(VersionedLocatableAsset::V4 {
+				location: asset_hub_location.clone(),
+				asset_id: native_asset.into(),
+			}),
+			amount: fellowship_treasury_balance,
+			beneficiary: bx!(VersionedLocation::V4(fellowship_treasury_location)),
+			valid_from: None,
+		});
+
+		assert_ok!(treasury_spend_call.dispatch(treasury_origin));
+
+		// Claim the spend.
+
+		let alice_signed = RuntimeOrigin::signed(Westend::account_id_of(ALICE));
+		assert_ok!(Treasury::payout(alice_signed.clone(), 0));
+
+		assert_expected_events!(
+			Westend,
+			vec![
+				RuntimeEvent::Treasury(pallet_treasury::Event::AssetSpendApproved { .. }) => {},
+				RuntimeEvent::Treasury(pallet_treasury::Event::Paid { .. }) => {},
+			]
+		);
+	});
+
+	AssetHubWestend::execute_with(|| {
+		type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
+		type Balances = <AssetHubWestend as AssetHubWestendPallet>::Balances;
+
+		// Ensure that the funds deposited to the Fellowship Treasury account.
+
+		let fellowship_treasury_location: Location =
+			Location::new(1, [Parachain(1001), PalletInstance(65)]);
+		let fellowship_treasury_account =
+			AssetHubLocationToAccountId::convert_location(&fellowship_treasury_location).unwrap();
+
+		assert_eq!(
+			<Balances as Inspect<_>>::balance(&fellowship_treasury_account),
+			fellowship_treasury_balance
+		);
+
+		// Assert events triggered by xcm pay program:
+		// 1. treasury asset transferred to spend beneficiary;
+		// 2. response to Relay Chain Treasury pallet instance sent back;
+		// 3. XCM program completed;
+		assert_expected_events!(
+			AssetHubWestend,
+			vec![
+				RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => {},
+				RuntimeEvent::ParachainSystem(cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }) => {},
+				RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {},
+			]
+		);
+	});
+
+	CollectivesWestend::execute_with(|| {
+		type RuntimeEvent = <CollectivesWestend as Chain>::RuntimeEvent;
+		type RuntimeCall = <CollectivesWestend as Chain>::RuntimeCall;
+		type RuntimeOrigin = <CollectivesWestend as Chain>::RuntimeOrigin;
+		type Runtime = <CollectivesWestend as Chain>::Runtime;
+		type FellowshipTreasury =
+			<CollectivesWestend as CollectivesWestendPallet>::FellowshipTreasury;
+
+		// Fund Alice account from Fellowship Treasury.
+
+		let fellows_origin: RuntimeOrigin =
+			collectives_westend_runtime::fellowship::pallet_fellowship_origins::Origin::Fellows
+				.into();
+		let asset_hub_location: Location = (Parent, Parachain(1000)).into();
+		let native_asset = Location::parent();
+
+		let alice_location: Location = [Junction::AccountId32 {
+			network: None,
+			id: CollectivesWestend::account_id_of(ALICE).into(),
+		}]
+		.into();
+
+		let fellowship_treasury_spend_call =
+			RuntimeCall::FellowshipTreasury(pallet_treasury::Call::<Runtime, Instance1>::spend {
+				asset_kind: bx!(VersionedLocatableAsset::V4 {
+					location: asset_hub_location,
+					asset_id: native_asset.into(),
+				}),
+				amount: fellowship_spend_balance,
+				beneficiary: bx!(VersionedLocation::V4(alice_location)),
+				valid_from: None,
+			});
+
+		assert_ok!(fellowship_treasury_spend_call.dispatch(fellows_origin));
+
+		// Claim the spend.
+
+		let alice_signed = RuntimeOrigin::signed(CollectivesWestend::account_id_of(ALICE));
+		assert_ok!(FellowshipTreasury::payout(alice_signed.clone(), 0));
+
+		assert_expected_events!(
+			CollectivesWestend,
+			vec![
+				RuntimeEvent::FellowshipTreasury(pallet_treasury::Event::AssetSpendApproved { .. }) => {},
+				RuntimeEvent::FellowshipTreasury(pallet_treasury::Event::Paid { .. }) => {},
+			]
+		);
+	});
+
+	AssetHubWestend::execute_with(|| {
+		type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
+		type Balances = <AssetHubWestend as AssetHubWestendPallet>::Balances;
+
+		// Ensure that the funds deposited to Alice account.
+
+		let alice_account = AssetHubWestend::account_id_of(ALICE);
+		assert_eq!(
+			<Balances as Inspect<_>>::balance(&alice_account),
+			fellowship_spend_balance + init_alice_balance
+		);
+
+		// Assert events triggered by xcm pay program:
+		// 1. treasury asset transferred to spend beneficiary;
+		// 2. response to Relay Chain Treasury pallet instance sent back;
+		// 3. XCM program completed;
+		assert_expected_events!(
+			AssetHubWestend,
+			vec![
+				RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => {},
+				RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
+				RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {},
+			]
+		);
+	});
+}
diff --git a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..a9f65df34b647835b4ce5585be6b53b0489de578
--- /dev/null
+++ b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/mod.rs
@@ -0,0 +1,16 @@
+// 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.
+
+mod fellowship_treasury;
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs
index 3816d2ed848ed51740283ffea31e9f7e53c01f1a..94765287637b57d47c588d9a4359666d1b54f509 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs
@@ -21,13 +21,16 @@ mod tracks;
 use crate::{
 	weights,
 	xcm_config::{FellowshipAdminBodyId, LocationToAccountId, TreasurerBodyId, UsdtAssetHub},
-	AccountId, AssetRate, Balance, Balances, FellowshipReferenda, GovernanceLocation, Preimage,
-	Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Scheduler, WestendTreasuryAccount, DAYS,
+	AccountId, AssetRate, Balance, Balances, FellowshipReferenda, GovernanceLocation,
+	ParachainInfo, Preimage, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Scheduler,
+	WestendTreasuryAccount, DAYS,
 };
+use cumulus_primitives_core::ParaId;
 use frame_support::{
 	parameter_types,
 	traits::{
-		EitherOf, EitherOfDiverse, MapSuccess, NeverEnsureOrigin, OriginTrait, TryWithMorphedArg,
+		tokens::UnityOrOuterConversion, EitherOf, EitherOfDiverse, FromContains, MapSuccess,
+		NeverEnsureOrigin, OriginTrait, TryWithMorphedArg,
 	},
 	PalletId,
 };
@@ -40,10 +43,10 @@ use pallet_ranked_collective::EnsureOfRank;
 use pallet_xcm::{EnsureXcm, IsVoiceOfBody};
 use parachains_common::impls::ToParentTreasury;
 use polkadot_runtime_common::impls::{
-	LocatableAssetConverter, VersionedLocatableAsset, VersionedLocationConverter,
+	ContainsParts, LocatableAssetConverter, VersionedLocatableAsset, VersionedLocationConverter,
 };
 use sp_arithmetic::Permill;
-use sp_core::{ConstU128, ConstU32};
+use sp_core::{ConstU128, ConstU32, ConstU8};
 use sp_runtime::traits::{ConstU16, ConvertToValue, IdentityLookup, Replace, TakeFirst};
 use testnet_parachains_constants::westend::{account, currency::GRAND};
 use westend_runtime_constants::time::HOURS;
@@ -263,6 +266,7 @@ parameter_types! {
 	// The asset's interior location for the paying account. This is the Fellowship Treasury
 	// pallet instance (which sits at index 65).
 	pub FellowshipTreasuryInteriorLocation: InteriorLocation = PalletInstance(65).into();
+	pub SelfParaId: ParaId = ParachainInfo::parachain_id();
 }
 
 #[cfg(feature = "runtime-benchmarks")]
@@ -345,7 +349,15 @@ impl pallet_treasury::Config<FellowshipTreasuryInstance> for Runtime {
 	type Paymaster = FellowshipTreasuryPaymaster;
 	#[cfg(feature = "runtime-benchmarks")]
 	type Paymaster = PayWithEnsure<FellowshipTreasuryPaymaster, OpenHrmpChannel<ConstU32<1000>>>;
-	type BalanceConverter = AssetRate;
+	type BalanceConverter = UnityOrOuterConversion<
+		ContainsParts<
+			FromContains<
+				xcm_builder::IsSiblingSystemParachain<ParaId, SelfParaId>,
+				xcm_builder::IsParentsOnly<ConstU8<1>>,
+			>,
+		>,
+		AssetRate,
+	>;
 	type PayoutPeriod = ConstU32<{ 30 * DAYS }>;
 	#[cfg(feature = "runtime-benchmarks")]
 	type BenchmarkHelper = polkadot_runtime_common::impls::benchmarks::TreasuryArguments<
diff --git a/docs/contributor/prdoc.md b/docs/contributor/prdoc.md
index af0ede5107a6cb1ea31d8b81fe16b06553ef64ac..0c8165af40f4d4f0438ab780c5f87eb5fe2ad62e 100644
--- a/docs/contributor/prdoc.md
+++ b/docs/contributor/prdoc.md
@@ -1,55 +1,31 @@
 # PRDoc
 
-## Intro
-
-With the merge of [PR #1946](https://github.com/paritytech/polkadot-sdk/pull/1946), a new method for
-documenting changes has been introduced: `prdoc`. The [prdoc repository](https://github.com/paritytech/prdoc)
-contains more documentation and tooling.
-
-The current document describes how to quickly get started authoring `PRDoc` files.
+A [prdoc](https://github.com/paritytech/prdoc) is like a changelog but for a Pull Request. We use this approach to
+record changes on a crate level. This information is then processed by the release team to apply the correct crate
+version bumps and to generate the CHANGELOG of the next release.
 
 ## Requirements
 
-When creating a PR, the author needs to decides with the `R0` label whether the change (PR) should
-appear in the release notes or not.
-
-Labelling a PR with `R0` means that no `PRDoc` is required.
-
-A PR without the `R0` label **does** require a valid `PRDoc` file to be introduced in the PR.
-
-## PRDoc how-to
-
-A `.prdoc` file is a YAML file with a defined structure (ie JSON Schema).
-
-For significant changes, a `.prdoc` file is mandatory and the file must meet the following
-requirements:
-- file named `pr_NNNN.prdoc` where `NNNN` is the PR number.
-  For convenience, those file can also contain a short description: `pr_NNNN_foobar.prdoc`.
-- located under the [`prdoc` folder](https://github.com/paritytech/polkadot-sdk/tree/master/prdoc) of the repository
-- compliant with the [JSON schema](https://json-schema.org/) defined in `prdoc/schema_user.json`
-
-Those requirements can be fulfilled manually without any tooling but a text editor.
-
-## Tooling
-
-Users might find the following helpers convenient:
-- Setup VSCode to be aware of the prdoc schema: see [using VSCode](https://github.com/paritytech/prdoc#using-vscode)
-- Using the `prdoc` cli to:
-  - generate a `PRDoc` file from a [template defined in the Polkadot SDK
-    repo](https://github.com/paritytech/polkadot-sdk/blob/master/prdoc/.template.prdoc) simply providing a PR number
-  - check the validity of one or more `PRDoc` files
+When creating a PR, the author needs to decide with the `R0-silent` label whether the PR has to contain a prdoc. The
+`R0` label should only be placed for No-OP changes like correcting a typo in a comment or CI stuff. If unsure, ping
+the [CODEOWNERS](../../.github/CODEOWNERS) for advice.
 
-## `prdoc` cli usage
+## PRDoc How-To
 
-The `prdoc` cli documentation can be found at https://github.com/paritytech/prdoc#prdoc
+A `.prdoc` file is a YAML file with a defined structure (ie JSON Schema). Please follow these steps to generate one:
 
-tldr:
-- `prdoc generate <NNNN>`
-- `prdoc check -n <NNNN>`
+1. Install the [`prdoc` CLI](https://github.com/paritytech/prdoc) by running `cargo install prdoc`.
+1. Open a Pull Request and get the PR number.
+1. Generate the file with `prdoc generate <PR_NUMBER>`. The output filename will be printed.
+1. Optional: Install the `prdoc/schema_user.json` schema in your editor, for example
+[VsCode](https://github.com/paritytech/prdoc?tab=readme-ov-file#schemas).
+1. Edit your `.prdoc` file according to the [Audience](#pick-an-audience) and [SemVer](#record-semver-changes) sections.
+1. Check your prdoc with `prdoc check -n <PR_NUMBER>`. This is optional since the CI will also check it.
 
-where <NNNN> is the PR number.
+> **Tip:** GitHub CLI and jq can be used to provide the number of your PR to generate the correct file:  
+> `prdoc generate $(gh pr view --json number | jq '.number') -o prdoc`
 
-## Pick an audience
+## Pick An Audience
 
 While describing a PR, the author needs to consider which audience(s) need to be addressed.
 The list of valid audiences is described and documented in the JSON schema as follow:
@@ -65,7 +41,41 @@ The list of valid audiences is described and documented in the JSON schema as fo
 
 - `Runtime User`: Anyone using the runtime. This can be a token holder or a dev writing a front end for a chain.
 
-## Tips
+If you have a change that affects multiple audiences, you can either list them all, or write multiple sections and
+re-phrase the changes for each audience.
+
+## Record SemVer Changes
+
+All published crates that got modified need to have an entry in the `crates` section of your `PRDoc`. This entry tells
+the release team how to bump the crate version prior to the next release. It is very important that this information is
+correct, otherwise it could break the code of downstream teams.
+
+The bump can either be `major`, `minor`, `patch` or `none`. The three first options are defined by
+[rust-lang.org](https://doc.rust-lang.org/cargo/reference/semver.html), whereas `None` should be picked if no other
+applies. The `None` option is equivalent to the `R0-silent` label, but on a crate level. Experimental and private APIs
+are exempt from bumping and can be broken at any time. Please read the [Crate Section](../RELEASE.md) of the RELEASE doc
+about them.
+
+> **Note**: There is currently no CI in place to sanity check this information, but should be added soon.
+
+### Example
+
+For example when you modified two crates and record the changes:
+
+```yaml
+crates:
+- name: frame-example
+  bump: major
+- name: frame-example-pallet
+  bump: minor
+```
+
+It means that downstream code using `frame-example-pallet` is still guaranteed to work as before, while code using
+`frame-example` might break.
+
+### Dependencies
 
-The PRDoc schema is defined in each repo and usually is quite restrictive.
-You cannot simply add a new property to a `PRDoc` file unless the Schema allows it.
+A crate that depends on another crate will automatically inherit its `major` bumps. This means that you do not need to
+bump a crate that had a SemVer breaking change only from re-exporting another crate with a breaking change.  
+`minor` an `patch` bumps do not need to be inherited, since `cargo` will automatically update them to the latest
+compatible version.
diff --git a/polkadot/node/core/prospective-parachains/src/fragment_tree.rs b/polkadot/node/core/prospective-parachains/src/fragment_tree/mod.rs
similarity index 50%
rename from polkadot/node/core/prospective-parachains/src/fragment_tree.rs
rename to polkadot/node/core/prospective-parachains/src/fragment_tree/mod.rs
index 8061dc82d8358ae9e7c741e3f785634601eb5d03..86814b976d13424281203aa5bca59b0a918b7251 100644
--- a/polkadot/node/core/prospective-parachains/src/fragment_tree.rs
+++ b/polkadot/node/core/prospective-parachains/src/fragment_tree/mod.rs
@@ -86,6 +86,9 @@
 //! will still perform fairly well under these conditions, despite being somewhat wasteful of
 //! memory.
 
+#[cfg(test)]
+mod tests;
+
 use std::{
 	borrow::Cow,
 	collections::{
@@ -1145,1447 +1148,3 @@ impl FragmentNode {
 		self.children.iter().find(|(_, c)| c == candidate_hash).map(|(p, _)| *p)
 	}
 }
-
-#[cfg(test)]
-mod tests {
-	use super::*;
-	use assert_matches::assert_matches;
-	use polkadot_node_subsystem_util::inclusion_emulator::InboundHrmpLimitations;
-	use polkadot_primitives::{BlockNumber, CandidateCommitments, CandidateDescriptor, HeadData};
-	use polkadot_primitives_test_helpers as test_helpers;
-	use rstest::rstest;
-	use std::iter;
-
-	impl NodePointer {
-		fn unwrap_idx(self) -> usize {
-			match self {
-				NodePointer::Root => panic!("Unexpected root"),
-				NodePointer::Storage(index) => index,
-			}
-		}
-	}
-
-	fn make_constraints(
-		min_relay_parent_number: BlockNumber,
-		valid_watermarks: Vec<BlockNumber>,
-		required_parent: HeadData,
-	) -> Constraints {
-		Constraints {
-			min_relay_parent_number,
-			max_pov_size: 1_000_000,
-			max_code_size: 1_000_000,
-			ump_remaining: 10,
-			ump_remaining_bytes: 1_000,
-			max_ump_num_per_candidate: 10,
-			dmp_remaining_messages: [0; 10].into(),
-			hrmp_inbound: InboundHrmpLimitations { valid_watermarks },
-			hrmp_channels_out: HashMap::new(),
-			max_hrmp_num_per_candidate: 0,
-			required_parent,
-			validation_code_hash: Hash::repeat_byte(42).into(),
-			upgrade_restriction: None,
-			future_validation_code: None,
-		}
-	}
-
-	fn make_committed_candidate(
-		para_id: ParaId,
-		relay_parent: Hash,
-		relay_parent_number: BlockNumber,
-		parent_head: HeadData,
-		para_head: HeadData,
-		hrmp_watermark: BlockNumber,
-	) -> (PersistedValidationData, CommittedCandidateReceipt) {
-		let persisted_validation_data = PersistedValidationData {
-			parent_head,
-			relay_parent_number,
-			relay_parent_storage_root: Hash::repeat_byte(69),
-			max_pov_size: 1_000_000,
-		};
-
-		let candidate = CommittedCandidateReceipt {
-			descriptor: CandidateDescriptor {
-				para_id,
-				relay_parent,
-				collator: test_helpers::dummy_collator(),
-				persisted_validation_data_hash: persisted_validation_data.hash(),
-				pov_hash: Hash::repeat_byte(1),
-				erasure_root: Hash::repeat_byte(1),
-				signature: test_helpers::dummy_collator_signature(),
-				para_head: para_head.hash(),
-				validation_code_hash: Hash::repeat_byte(42).into(),
-			},
-			commitments: CandidateCommitments {
-				upward_messages: Default::default(),
-				horizontal_messages: Default::default(),
-				new_validation_code: None,
-				head_data: para_head,
-				processed_downward_messages: 1,
-				hrmp_watermark,
-			},
-		};
-
-		(persisted_validation_data, candidate)
-	}
-
-	#[test]
-	fn scope_rejects_ancestors_that_skip_blocks() {
-		let para_id = ParaId::from(5u32);
-		let relay_parent = RelayChainBlockInfo {
-			number: 10,
-			hash: Hash::repeat_byte(10),
-			storage_root: Hash::repeat_byte(69),
-		};
-
-		let ancestors = vec![RelayChainBlockInfo {
-			number: 8,
-			hash: Hash::repeat_byte(8),
-			storage_root: Hash::repeat_byte(69),
-		}];
-
-		let max_depth = 2;
-		let base_constraints = make_constraints(8, vec![8, 9], vec![1, 2, 3].into());
-		let pending_availability = Vec::new();
-
-		assert_matches!(
-			Scope::with_ancestors(
-				para_id,
-				relay_parent,
-				base_constraints,
-				pending_availability,
-				max_depth,
-				ancestors
-			),
-			Err(UnexpectedAncestor { number: 8, prev: 10 })
-		);
-	}
-
-	#[test]
-	fn scope_rejects_ancestor_for_0_block() {
-		let para_id = ParaId::from(5u32);
-		let relay_parent = RelayChainBlockInfo {
-			number: 0,
-			hash: Hash::repeat_byte(0),
-			storage_root: Hash::repeat_byte(69),
-		};
-
-		let ancestors = vec![RelayChainBlockInfo {
-			number: 99999,
-			hash: Hash::repeat_byte(99),
-			storage_root: Hash::repeat_byte(69),
-		}];
-
-		let max_depth = 2;
-		let base_constraints = make_constraints(0, vec![], vec![1, 2, 3].into());
-		let pending_availability = Vec::new();
-
-		assert_matches!(
-			Scope::with_ancestors(
-				para_id,
-				relay_parent,
-				base_constraints,
-				pending_availability,
-				max_depth,
-				ancestors,
-			),
-			Err(UnexpectedAncestor { number: 99999, prev: 0 })
-		);
-	}
-
-	#[test]
-	fn scope_only_takes_ancestors_up_to_min() {
-		let para_id = ParaId::from(5u32);
-		let relay_parent = RelayChainBlockInfo {
-			number: 5,
-			hash: Hash::repeat_byte(0),
-			storage_root: Hash::repeat_byte(69),
-		};
-
-		let ancestors = vec![
-			RelayChainBlockInfo {
-				number: 4,
-				hash: Hash::repeat_byte(4),
-				storage_root: Hash::repeat_byte(69),
-			},
-			RelayChainBlockInfo {
-				number: 3,
-				hash: Hash::repeat_byte(3),
-				storage_root: Hash::repeat_byte(69),
-			},
-			RelayChainBlockInfo {
-				number: 2,
-				hash: Hash::repeat_byte(2),
-				storage_root: Hash::repeat_byte(69),
-			},
-		];
-
-		let max_depth = 2;
-		let base_constraints = make_constraints(3, vec![2], vec![1, 2, 3].into());
-		let pending_availability = Vec::new();
-
-		let scope = Scope::with_ancestors(
-			para_id,
-			relay_parent,
-			base_constraints,
-			pending_availability,
-			max_depth,
-			ancestors,
-		)
-		.unwrap();
-
-		assert_eq!(scope.ancestors.len(), 2);
-		assert_eq!(scope.ancestors_by_hash.len(), 2);
-	}
-
-	#[test]
-	fn storage_add_candidate() {
-		let mut storage = CandidateStorage::new();
-		let relay_parent = Hash::repeat_byte(69);
-
-		let (pvd, candidate) = make_committed_candidate(
-			ParaId::from(5u32),
-			relay_parent,
-			8,
-			vec![4, 5, 6].into(),
-			vec![1, 2, 3].into(),
-			7,
-		);
-
-		let candidate_hash = candidate.hash();
-		let parent_head_hash = pvd.parent_head.hash();
-
-		storage.add_candidate(candidate, pvd).unwrap();
-		assert!(storage.contains(&candidate_hash));
-		assert_eq!(storage.iter_para_children(&parent_head_hash).count(), 1);
-
-		assert_eq!(storage.relay_parent_by_candidate_hash(&candidate_hash), Some(relay_parent));
-	}
-
-	#[test]
-	fn storage_retain() {
-		let mut storage = CandidateStorage::new();
-
-		let (pvd, candidate) = make_committed_candidate(
-			ParaId::from(5u32),
-			Hash::repeat_byte(69),
-			8,
-			vec![4, 5, 6].into(),
-			vec![1, 2, 3].into(),
-			7,
-		);
-
-		let candidate_hash = candidate.hash();
-		let output_head_hash = candidate.commitments.head_data.hash();
-		let parent_head_hash = pvd.parent_head.hash();
-
-		storage.add_candidate(candidate, pvd).unwrap();
-		storage.retain(|_| true);
-		assert!(storage.contains(&candidate_hash));
-		assert_eq!(storage.iter_para_children(&parent_head_hash).count(), 1);
-		assert!(storage.head_data_by_hash(&output_head_hash).is_some());
-
-		storage.retain(|_| false);
-		assert!(!storage.contains(&candidate_hash));
-		assert_eq!(storage.iter_para_children(&parent_head_hash).count(), 0);
-		assert!(storage.head_data_by_hash(&output_head_hash).is_none());
-	}
-
-	// [`FragmentTree::populate`] should pick up candidates that build on other candidates.
-	#[test]
-	fn populate_works_recursively() {
-		let mut storage = CandidateStorage::new();
-
-		let para_id = ParaId::from(5u32);
-		let relay_parent_a = Hash::repeat_byte(1);
-		let relay_parent_b = Hash::repeat_byte(2);
-
-		let (pvd_a, candidate_a) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0a].into(),
-			vec![0x0b].into(),
-			0,
-		);
-		let candidate_a_hash = candidate_a.hash();
-
-		let (pvd_b, candidate_b) = make_committed_candidate(
-			para_id,
-			relay_parent_b,
-			1,
-			vec![0x0b].into(),
-			vec![0x0c].into(),
-			1,
-		);
-		let candidate_b_hash = candidate_b.hash();
-
-		let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
-		let pending_availability = Vec::new();
-
-		let ancestors = vec![RelayChainBlockInfo {
-			number: pvd_a.relay_parent_number,
-			hash: relay_parent_a,
-			storage_root: pvd_a.relay_parent_storage_root,
-		}];
-
-		let relay_parent_b_info = RelayChainBlockInfo {
-			number: pvd_b.relay_parent_number,
-			hash: relay_parent_b,
-			storage_root: pvd_b.relay_parent_storage_root,
-		};
-
-		storage.add_candidate(candidate_a, pvd_a).unwrap();
-		storage.add_candidate(candidate_b, pvd_b).unwrap();
-		let scope = Scope::with_ancestors(
-			para_id,
-			relay_parent_b_info,
-			base_constraints,
-			pending_availability,
-			4,
-			ancestors,
-		)
-		.unwrap();
-		let tree = FragmentTree::populate(scope, &storage);
-
-		let candidates: Vec<_> = tree.candidates().collect();
-		assert_eq!(candidates.len(), 2);
-		assert!(candidates.contains(&candidate_a_hash));
-		assert!(candidates.contains(&candidate_b_hash));
-
-		assert_eq!(tree.nodes.len(), 2);
-		assert_eq!(tree.nodes[0].parent, NodePointer::Root);
-		assert_eq!(tree.nodes[0].candidate_hash, candidate_a_hash);
-		assert_eq!(tree.nodes[0].depth, 0);
-
-		assert_eq!(tree.nodes[1].parent, NodePointer::Storage(0));
-		assert_eq!(tree.nodes[1].candidate_hash, candidate_b_hash);
-		assert_eq!(tree.nodes[1].depth, 1);
-	}
-
-	#[test]
-	fn children_of_root_are_contiguous() {
-		let mut storage = CandidateStorage::new();
-
-		let para_id = ParaId::from(5u32);
-		let relay_parent_a = Hash::repeat_byte(1);
-		let relay_parent_b = Hash::repeat_byte(2);
-
-		let (pvd_a, candidate_a) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0a].into(),
-			vec![0x0b].into(),
-			0,
-		);
-
-		let (pvd_b, candidate_b) = make_committed_candidate(
-			para_id,
-			relay_parent_b,
-			1,
-			vec![0x0b].into(),
-			vec![0x0c].into(),
-			1,
-		);
-
-		let (pvd_a2, candidate_a2) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0a].into(),
-			vec![0x0b, 1].into(),
-			0,
-		);
-		let candidate_a2_hash = candidate_a2.hash();
-
-		let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
-		let pending_availability = Vec::new();
-
-		let ancestors = vec![RelayChainBlockInfo {
-			number: pvd_a.relay_parent_number,
-			hash: relay_parent_a,
-			storage_root: pvd_a.relay_parent_storage_root,
-		}];
-
-		let relay_parent_b_info = RelayChainBlockInfo {
-			number: pvd_b.relay_parent_number,
-			hash: relay_parent_b,
-			storage_root: pvd_b.relay_parent_storage_root,
-		};
-
-		storage.add_candidate(candidate_a, pvd_a).unwrap();
-		storage.add_candidate(candidate_b, pvd_b).unwrap();
-		let scope = Scope::with_ancestors(
-			para_id,
-			relay_parent_b_info,
-			base_constraints,
-			pending_availability,
-			4,
-			ancestors,
-		)
-		.unwrap();
-		let mut tree = FragmentTree::populate(scope, &storage);
-
-		storage.add_candidate(candidate_a2, pvd_a2).unwrap();
-		tree.add_and_populate(candidate_a2_hash, &storage);
-		let candidates: Vec<_> = tree.candidates().collect();
-		assert_eq!(candidates.len(), 3);
-
-		assert_eq!(tree.nodes[0].parent, NodePointer::Root);
-		assert_eq!(tree.nodes[1].parent, NodePointer::Root);
-		assert_eq!(tree.nodes[2].parent, NodePointer::Storage(0));
-	}
-
-	#[test]
-	fn add_candidate_child_of_root() {
-		let mut storage = CandidateStorage::new();
-
-		let para_id = ParaId::from(5u32);
-		let relay_parent_a = Hash::repeat_byte(1);
-
-		let (pvd_a, candidate_a) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0a].into(),
-			vec![0x0b].into(),
-			0,
-		);
-
-		let (pvd_b, candidate_b) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0a].into(),
-			vec![0x0c].into(),
-			0,
-		);
-		let candidate_b_hash = candidate_b.hash();
-
-		let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
-		let pending_availability = Vec::new();
-
-		let relay_parent_a_info = RelayChainBlockInfo {
-			number: pvd_a.relay_parent_number,
-			hash: relay_parent_a,
-			storage_root: pvd_a.relay_parent_storage_root,
-		};
-
-		storage.add_candidate(candidate_a, pvd_a).unwrap();
-		let scope = Scope::with_ancestors(
-			para_id,
-			relay_parent_a_info,
-			base_constraints,
-			pending_availability,
-			4,
-			vec![],
-		)
-		.unwrap();
-		let mut tree = FragmentTree::populate(scope, &storage);
-
-		storage.add_candidate(candidate_b, pvd_b).unwrap();
-		tree.add_and_populate(candidate_b_hash, &storage);
-		let candidates: Vec<_> = tree.candidates().collect();
-		assert_eq!(candidates.len(), 2);
-
-		assert_eq!(tree.nodes[0].parent, NodePointer::Root);
-		assert_eq!(tree.nodes[1].parent, NodePointer::Root);
-	}
-
-	#[test]
-	fn add_candidate_child_of_non_root() {
-		let mut storage = CandidateStorage::new();
-
-		let para_id = ParaId::from(5u32);
-		let relay_parent_a = Hash::repeat_byte(1);
-
-		let (pvd_a, candidate_a) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0a].into(),
-			vec![0x0b].into(),
-			0,
-		);
-
-		let (pvd_b, candidate_b) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0b].into(),
-			vec![0x0c].into(),
-			0,
-		);
-		let candidate_b_hash = candidate_b.hash();
-
-		let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
-		let pending_availability = Vec::new();
-
-		let relay_parent_a_info = RelayChainBlockInfo {
-			number: pvd_a.relay_parent_number,
-			hash: relay_parent_a,
-			storage_root: pvd_a.relay_parent_storage_root,
-		};
-
-		storage.add_candidate(candidate_a, pvd_a).unwrap();
-		let scope = Scope::with_ancestors(
-			para_id,
-			relay_parent_a_info,
-			base_constraints,
-			pending_availability,
-			4,
-			vec![],
-		)
-		.unwrap();
-		let mut tree = FragmentTree::populate(scope, &storage);
-
-		storage.add_candidate(candidate_b, pvd_b).unwrap();
-		tree.add_and_populate(candidate_b_hash, &storage);
-		let candidates: Vec<_> = tree.candidates().collect();
-		assert_eq!(candidates.len(), 2);
-
-		assert_eq!(tree.nodes[0].parent, NodePointer::Root);
-		assert_eq!(tree.nodes[1].parent, NodePointer::Storage(0));
-	}
-
-	#[test]
-	fn test_find_ancestor_path_and_find_backable_chain_empty_tree() {
-		let para_id = ParaId::from(5u32);
-		let relay_parent = Hash::repeat_byte(1);
-		let required_parent: HeadData = vec![0xff].into();
-		let max_depth = 10;
-
-		// Empty tree
-		let storage = CandidateStorage::new();
-		let base_constraints = make_constraints(0, vec![0], required_parent.clone());
-
-		let relay_parent_info =
-			RelayChainBlockInfo { number: 0, hash: relay_parent, storage_root: Hash::zero() };
-
-		let scope = Scope::with_ancestors(
-			para_id,
-			relay_parent_info,
-			base_constraints,
-			vec![],
-			max_depth,
-			vec![],
-		)
-		.unwrap();
-		let tree = FragmentTree::populate(scope, &storage);
-		assert_eq!(tree.candidates().collect::<Vec<_>>().len(), 0);
-		assert_eq!(tree.nodes.len(), 0);
-
-		assert_eq!(tree.find_ancestor_path(Ancestors::new()).unwrap(), NodePointer::Root);
-		assert_eq!(tree.find_backable_chain(Ancestors::new(), 2, |_| true), vec![]);
-		// Invalid candidate.
-		let ancestors: Ancestors = [CandidateHash::default()].into_iter().collect();
-		assert_eq!(tree.find_ancestor_path(ancestors.clone()), Some(NodePointer::Root));
-		assert_eq!(tree.find_backable_chain(ancestors, 2, |_| true), vec![]);
-	}
-
-	#[rstest]
-	#[case(true, 13)]
-	#[case(false, 8)]
-	// The tree with no cycles looks like:
-	// Make a tree that looks like this (note that there's no cycle):
-	//         +-(root)-+
-	//         |        |
-	//    +----0---+    7
-	//    |        |
-	//    1----+   5
-	//    |    |
-	//    |    |
-	//    2    6
-	//    |
-	//    3
-	//    |
-	//    4
-	//
-	// The tree with cycles is the same as the first but has a cycle from 4 back to the state
-	// produced by 0 (It's bounded by the max_depth + 1).
-	//         +-(root)-+
-	//         |        |
-	//    +----0---+    7
-	//    |        |
-	//    1----+   5
-	//    |    |
-	//    |    |
-	//    2    6
-	//    |
-	//    3
-	//    |
-	//    4---+
-	//    |   |
-	//    1   5
-	//    |
-	//    2
-	//    |
-	//    3
-	fn test_find_ancestor_path_and_find_backable_chain(
-		#[case] has_cycle: bool,
-		#[case] expected_node_count: usize,
-	) {
-		let para_id = ParaId::from(5u32);
-		let relay_parent = Hash::repeat_byte(1);
-		let required_parent: HeadData = vec![0xff].into();
-		let max_depth = 7;
-		let relay_parent_number = 0;
-		let relay_parent_storage_root = Hash::repeat_byte(69);
-
-		let mut candidates = vec![];
-
-		// Candidate 0
-		candidates.push(make_committed_candidate(
-			para_id,
-			relay_parent,
-			0,
-			required_parent.clone(),
-			vec![0].into(),
-			0,
-		));
-		// Candidate 1
-		candidates.push(make_committed_candidate(
-			para_id,
-			relay_parent,
-			0,
-			vec![0].into(),
-			vec![1].into(),
-			0,
-		));
-		// Candidate 2
-		candidates.push(make_committed_candidate(
-			para_id,
-			relay_parent,
-			0,
-			vec![1].into(),
-			vec![2].into(),
-			0,
-		));
-		// Candidate 3
-		candidates.push(make_committed_candidate(
-			para_id,
-			relay_parent,
-			0,
-			vec![2].into(),
-			vec![3].into(),
-			0,
-		));
-		// Candidate 4
-		candidates.push(make_committed_candidate(
-			para_id,
-			relay_parent,
-			0,
-			vec![3].into(),
-			vec![4].into(),
-			0,
-		));
-		// Candidate 5
-		candidates.push(make_committed_candidate(
-			para_id,
-			relay_parent,
-			0,
-			vec![0].into(),
-			vec![5].into(),
-			0,
-		));
-		// Candidate 6
-		candidates.push(make_committed_candidate(
-			para_id,
-			relay_parent,
-			0,
-			vec![1].into(),
-			vec![6].into(),
-			0,
-		));
-		// Candidate 7
-		candidates.push(make_committed_candidate(
-			para_id,
-			relay_parent,
-			0,
-			required_parent.clone(),
-			vec![7].into(),
-			0,
-		));
-
-		if has_cycle {
-			candidates[4] = make_committed_candidate(
-				para_id,
-				relay_parent,
-				0,
-				vec![3].into(),
-				vec![0].into(), // put the cycle here back to the output state of 0.
-				0,
-			);
-		}
-
-		let base_constraints = make_constraints(0, vec![0], required_parent.clone());
-		let mut storage = CandidateStorage::new();
-
-		let relay_parent_info = RelayChainBlockInfo {
-			number: relay_parent_number,
-			hash: relay_parent,
-			storage_root: relay_parent_storage_root,
-		};
-
-		for (pvd, candidate) in candidates.iter() {
-			storage.add_candidate(candidate.clone(), pvd.clone()).unwrap();
-		}
-		let candidates =
-			candidates.into_iter().map(|(_pvd, candidate)| candidate).collect::<Vec<_>>();
-		let scope = Scope::with_ancestors(
-			para_id,
-			relay_parent_info,
-			base_constraints,
-			vec![],
-			max_depth,
-			vec![],
-		)
-		.unwrap();
-		let tree = FragmentTree::populate(scope, &storage);
-
-		assert_eq!(tree.candidates().collect::<Vec<_>>().len(), candidates.len());
-		assert_eq!(tree.nodes.len(), expected_node_count);
-
-		// Do some common tests on both trees.
-		{
-			// No ancestors supplied.
-			assert_eq!(tree.find_ancestor_path(Ancestors::new()).unwrap(), NodePointer::Root);
-			assert_eq!(
-				tree.find_backable_chain(Ancestors::new(), 4, |_| true),
-				[0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
-			);
-			// Ancestor which is not part of the tree. Will be ignored.
-			let ancestors: Ancestors = [CandidateHash::default()].into_iter().collect();
-			assert_eq!(tree.find_ancestor_path(ancestors.clone()).unwrap(), NodePointer::Root);
-			assert_eq!(
-				tree.find_backable_chain(ancestors, 4, |_| true),
-				[0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
-			);
-			// A chain fork.
-			let ancestors: Ancestors =
-				[(candidates[0].hash()), (candidates[7].hash())].into_iter().collect();
-			assert_eq!(tree.find_ancestor_path(ancestors.clone()), None);
-			assert_eq!(tree.find_backable_chain(ancestors, 1, |_| true), vec![]);
-
-			// Ancestors which are part of the tree but don't form a path. Will be ignored.
-			let ancestors: Ancestors =
-				[candidates[1].hash(), candidates[2].hash()].into_iter().collect();
-			assert_eq!(tree.find_ancestor_path(ancestors.clone()).unwrap(), NodePointer::Root);
-			assert_eq!(
-				tree.find_backable_chain(ancestors, 4, |_| true),
-				[0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
-			);
-
-			// Valid ancestors.
-			let ancestors: Ancestors = [candidates[7].hash()].into_iter().collect();
-			let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
-			let candidate = &tree.nodes[res.unwrap_idx()];
-			assert_eq!(candidate.candidate_hash, candidates[7].hash());
-			assert_eq!(tree.find_backable_chain(ancestors, 1, |_| true), vec![]);
-
-			let ancestors: Ancestors =
-				[candidates[2].hash(), candidates[0].hash(), candidates[1].hash()]
-					.into_iter()
-					.collect();
-			let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
-			let candidate = &tree.nodes[res.unwrap_idx()];
-			assert_eq!(candidate.candidate_hash, candidates[2].hash());
-			assert_eq!(
-				tree.find_backable_chain(ancestors.clone(), 2, |_| true),
-				[3, 4].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
-			);
-
-			// Valid ancestors with candidates which have been omitted due to timeouts
-			let ancestors: Ancestors =
-				[candidates[0].hash(), candidates[2].hash()].into_iter().collect();
-			let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
-			let candidate = &tree.nodes[res.unwrap_idx()];
-			assert_eq!(candidate.candidate_hash, candidates[0].hash());
-			assert_eq!(
-				tree.find_backable_chain(ancestors, 3, |_| true),
-				[1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
-			);
-
-			let ancestors: Ancestors =
-				[candidates[0].hash(), candidates[1].hash(), candidates[3].hash()]
-					.into_iter()
-					.collect();
-			let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
-			let candidate = &tree.nodes[res.unwrap_idx()];
-			assert_eq!(candidate.candidate_hash, candidates[1].hash());
-			if has_cycle {
-				assert_eq!(
-					tree.find_backable_chain(ancestors, 2, |_| true),
-					[2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
-				);
-			} else {
-				assert_eq!(
-					tree.find_backable_chain(ancestors, 4, |_| true),
-					[2, 3, 4].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
-				);
-			}
-
-			let ancestors: Ancestors =
-				[candidates[1].hash(), candidates[2].hash()].into_iter().collect();
-			let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
-			assert_eq!(res, NodePointer::Root);
-			assert_eq!(
-				tree.find_backable_chain(ancestors, 4, |_| true),
-				[0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
-			);
-
-			// Requested count is 0.
-			assert_eq!(tree.find_backable_chain(Ancestors::new(), 0, |_| true), vec![]);
-
-			let ancestors: Ancestors =
-				[candidates[2].hash(), candidates[0].hash(), candidates[1].hash()]
-					.into_iter()
-					.collect();
-			assert_eq!(tree.find_backable_chain(ancestors, 0, |_| true), vec![]);
-
-			let ancestors: Ancestors =
-				[candidates[2].hash(), candidates[0].hash()].into_iter().collect();
-			assert_eq!(tree.find_backable_chain(ancestors, 0, |_| true), vec![]);
-		}
-
-		// Now do some tests only on the tree with cycles
-		if has_cycle {
-			// Exceeds the maximum tree depth. 0-1-2-3-4-1-2-3-4, when the tree stops at
-			// 0-1-2-3-4-1-2-3.
-			let ancestors: Ancestors = [
-				candidates[0].hash(),
-				candidates[1].hash(),
-				candidates[2].hash(),
-				candidates[3].hash(),
-				candidates[4].hash(),
-			]
-			.into_iter()
-			.collect();
-			let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
-			let candidate = &tree.nodes[res.unwrap_idx()];
-			assert_eq!(candidate.candidate_hash, candidates[4].hash());
-			assert_eq!(
-				tree.find_backable_chain(ancestors, 4, |_| true),
-				[1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
-			);
-
-			// 0-1-2.
-			let ancestors: Ancestors =
-				[candidates[0].hash(), candidates[1].hash(), candidates[2].hash()]
-					.into_iter()
-					.collect();
-			let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
-			let candidate = &tree.nodes[res.unwrap_idx()];
-			assert_eq!(candidate.candidate_hash, candidates[2].hash());
-			assert_eq!(
-				tree.find_backable_chain(ancestors.clone(), 1, |_| true),
-				[3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
-			);
-			assert_eq!(
-				tree.find_backable_chain(ancestors, 5, |_| true),
-				[3, 4, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
-			);
-
-			// 0-1
-			let ancestors: Ancestors =
-				[candidates[0].hash(), candidates[1].hash()].into_iter().collect();
-			let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
-			let candidate = &tree.nodes[res.unwrap_idx()];
-			assert_eq!(candidate.candidate_hash, candidates[1].hash());
-			assert_eq!(
-				tree.find_backable_chain(ancestors, 6, |_| true),
-				[2, 3, 4, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>(),
-			);
-
-			// For 0-1-2-3-4-5, there's more than 1 way of finding this path in
-			// the tree. `None` should be returned. The runtime should not have accepted this.
-			let ancestors: Ancestors = [
-				candidates[0].hash(),
-				candidates[1].hash(),
-				candidates[2].hash(),
-				candidates[3].hash(),
-				candidates[4].hash(),
-				candidates[5].hash(),
-			]
-			.into_iter()
-			.collect();
-			let res = tree.find_ancestor_path(ancestors.clone());
-			assert_eq!(res, None);
-			assert_eq!(tree.find_backable_chain(ancestors, 1, |_| true), vec![]);
-		}
-	}
-
-	#[test]
-	fn graceful_cycle_of_0() {
-		let mut storage = CandidateStorage::new();
-
-		let para_id = ParaId::from(5u32);
-		let relay_parent_a = Hash::repeat_byte(1);
-
-		let (pvd_a, candidate_a) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0a].into(),
-			vec![0x0a].into(), // input same as output
-			0,
-		);
-		let candidate_a_hash = candidate_a.hash();
-		let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
-		let pending_availability = Vec::new();
-
-		let relay_parent_a_info = RelayChainBlockInfo {
-			number: pvd_a.relay_parent_number,
-			hash: relay_parent_a,
-			storage_root: pvd_a.relay_parent_storage_root,
-		};
-
-		let max_depth = 4;
-		storage.add_candidate(candidate_a, pvd_a).unwrap();
-		let scope = Scope::with_ancestors(
-			para_id,
-			relay_parent_a_info,
-			base_constraints,
-			pending_availability,
-			max_depth,
-			vec![],
-		)
-		.unwrap();
-		let tree = FragmentTree::populate(scope, &storage);
-
-		let candidates: Vec<_> = tree.candidates().collect();
-		assert_eq!(candidates.len(), 1);
-		assert_eq!(tree.nodes.len(), max_depth + 1);
-
-		assert_eq!(tree.nodes[0].parent, NodePointer::Root);
-		assert_eq!(tree.nodes[1].parent, NodePointer::Storage(0));
-		assert_eq!(tree.nodes[2].parent, NodePointer::Storage(1));
-		assert_eq!(tree.nodes[3].parent, NodePointer::Storage(2));
-		assert_eq!(tree.nodes[4].parent, NodePointer::Storage(3));
-
-		assert_eq!(tree.nodes[0].candidate_hash, candidate_a_hash);
-		assert_eq!(tree.nodes[1].candidate_hash, candidate_a_hash);
-		assert_eq!(tree.nodes[2].candidate_hash, candidate_a_hash);
-		assert_eq!(tree.nodes[3].candidate_hash, candidate_a_hash);
-		assert_eq!(tree.nodes[4].candidate_hash, candidate_a_hash);
-
-		for count in 1..10 {
-			assert_eq!(
-				tree.find_backable_chain(Ancestors::new(), count, |_| true),
-				iter::repeat(candidate_a_hash)
-					.take(std::cmp::min(count as usize, max_depth + 1))
-					.collect::<Vec<_>>()
-			);
-			assert_eq!(
-				tree.find_backable_chain(
-					[candidate_a_hash].into_iter().collect(),
-					count - 1,
-					|_| true
-				),
-				iter::repeat(candidate_a_hash)
-					.take(std::cmp::min(count as usize - 1, max_depth))
-					.collect::<Vec<_>>()
-			);
-		}
-	}
-
-	#[test]
-	fn graceful_cycle_of_1() {
-		let mut storage = CandidateStorage::new();
-
-		let para_id = ParaId::from(5u32);
-		let relay_parent_a = Hash::repeat_byte(1);
-
-		let (pvd_a, candidate_a) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0a].into(),
-			vec![0x0b].into(), // input same as output
-			0,
-		);
-		let candidate_a_hash = candidate_a.hash();
-
-		let (pvd_b, candidate_b) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0b].into(),
-			vec![0x0a].into(), // input same as output
-			0,
-		);
-		let candidate_b_hash = candidate_b.hash();
-
-		let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
-		let pending_availability = Vec::new();
-
-		let relay_parent_a_info = RelayChainBlockInfo {
-			number: pvd_a.relay_parent_number,
-			hash: relay_parent_a,
-			storage_root: pvd_a.relay_parent_storage_root,
-		};
-
-		let max_depth = 4;
-		storage.add_candidate(candidate_a, pvd_a).unwrap();
-		storage.add_candidate(candidate_b, pvd_b).unwrap();
-		let scope = Scope::with_ancestors(
-			para_id,
-			relay_parent_a_info,
-			base_constraints,
-			pending_availability,
-			max_depth,
-			vec![],
-		)
-		.unwrap();
-		let tree = FragmentTree::populate(scope, &storage);
-
-		let candidates: Vec<_> = tree.candidates().collect();
-		assert_eq!(candidates.len(), 2);
-		assert_eq!(tree.nodes.len(), max_depth + 1);
-
-		assert_eq!(tree.nodes[0].parent, NodePointer::Root);
-		assert_eq!(tree.nodes[1].parent, NodePointer::Storage(0));
-		assert_eq!(tree.nodes[2].parent, NodePointer::Storage(1));
-		assert_eq!(tree.nodes[3].parent, NodePointer::Storage(2));
-		assert_eq!(tree.nodes[4].parent, NodePointer::Storage(3));
-
-		assert_eq!(tree.nodes[0].candidate_hash, candidate_a_hash);
-		assert_eq!(tree.nodes[1].candidate_hash, candidate_b_hash);
-		assert_eq!(tree.nodes[2].candidate_hash, candidate_a_hash);
-		assert_eq!(tree.nodes[3].candidate_hash, candidate_b_hash);
-		assert_eq!(tree.nodes[4].candidate_hash, candidate_a_hash);
-
-		assert_eq!(tree.find_backable_chain(Ancestors::new(), 1, |_| true), vec![candidate_a_hash],);
-		assert_eq!(
-			tree.find_backable_chain(Ancestors::new(), 2, |_| true),
-			vec![candidate_a_hash, candidate_b_hash],
-		);
-		assert_eq!(
-			tree.find_backable_chain(Ancestors::new(), 3, |_| true),
-			vec![candidate_a_hash, candidate_b_hash, candidate_a_hash],
-		);
-		assert_eq!(
-			tree.find_backable_chain([candidate_a_hash].into_iter().collect(), 2, |_| true),
-			vec![candidate_b_hash, candidate_a_hash],
-		);
-
-		assert_eq!(
-			tree.find_backable_chain(Ancestors::new(), 6, |_| true),
-			vec![
-				candidate_a_hash,
-				candidate_b_hash,
-				candidate_a_hash,
-				candidate_b_hash,
-				candidate_a_hash
-			],
-		);
-
-		for count in 3..7 {
-			assert_eq!(
-				tree.find_backable_chain(
-					[candidate_a_hash, candidate_b_hash].into_iter().collect(),
-					count,
-					|_| true
-				),
-				vec![candidate_a_hash, candidate_b_hash, candidate_a_hash],
-			);
-		}
-	}
-
-	#[test]
-	fn hypothetical_depths_known_and_unknown() {
-		let mut storage = CandidateStorage::new();
-
-		let para_id = ParaId::from(5u32);
-		let relay_parent_a = Hash::repeat_byte(1);
-
-		let (pvd_a, candidate_a) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0a].into(),
-			vec![0x0b].into(), // input same as output
-			0,
-		);
-		let candidate_a_hash = candidate_a.hash();
-
-		let (pvd_b, candidate_b) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0b].into(),
-			vec![0x0a].into(), // input same as output
-			0,
-		);
-		let candidate_b_hash = candidate_b.hash();
-
-		let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
-		let pending_availability = Vec::new();
-
-		let relay_parent_a_info = RelayChainBlockInfo {
-			number: pvd_a.relay_parent_number,
-			hash: relay_parent_a,
-			storage_root: pvd_a.relay_parent_storage_root,
-		};
-
-		let max_depth = 4;
-		storage.add_candidate(candidate_a, pvd_a).unwrap();
-		storage.add_candidate(candidate_b, pvd_b).unwrap();
-		let scope = Scope::with_ancestors(
-			para_id,
-			relay_parent_a_info,
-			base_constraints,
-			pending_availability,
-			max_depth,
-			vec![],
-		)
-		.unwrap();
-		let tree = FragmentTree::populate(scope, &storage);
-
-		let candidates: Vec<_> = tree.candidates().collect();
-		assert_eq!(candidates.len(), 2);
-		assert_eq!(tree.nodes.len(), max_depth + 1);
-
-		assert_eq!(
-			tree.hypothetical_depths(
-				candidate_a_hash,
-				HypotheticalCandidate::Incomplete {
-					parent_head_data_hash: HeadData::from(vec![0x0a]).hash(),
-					relay_parent: relay_parent_a,
-				},
-				&storage,
-				false,
-			),
-			vec![0, 2, 4],
-		);
-
-		assert_eq!(
-			tree.hypothetical_depths(
-				candidate_b_hash,
-				HypotheticalCandidate::Incomplete {
-					parent_head_data_hash: HeadData::from(vec![0x0b]).hash(),
-					relay_parent: relay_parent_a,
-				},
-				&storage,
-				false,
-			),
-			vec![1, 3],
-		);
-
-		assert_eq!(
-			tree.hypothetical_depths(
-				CandidateHash(Hash::repeat_byte(21)),
-				HypotheticalCandidate::Incomplete {
-					parent_head_data_hash: HeadData::from(vec![0x0a]).hash(),
-					relay_parent: relay_parent_a,
-				},
-				&storage,
-				false,
-			),
-			vec![0, 2, 4],
-		);
-
-		assert_eq!(
-			tree.hypothetical_depths(
-				CandidateHash(Hash::repeat_byte(22)),
-				HypotheticalCandidate::Incomplete {
-					parent_head_data_hash: HeadData::from(vec![0x0b]).hash(),
-					relay_parent: relay_parent_a,
-				},
-				&storage,
-				false,
-			),
-			vec![1, 3]
-		);
-	}
-
-	#[test]
-	fn hypothetical_depths_stricter_on_complete() {
-		let storage = CandidateStorage::new();
-
-		let para_id = ParaId::from(5u32);
-		let relay_parent_a = Hash::repeat_byte(1);
-
-		let (pvd_a, candidate_a) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0a].into(),
-			vec![0x0b].into(),
-			1000, // watermark is illegal
-		);
-
-		let candidate_a_hash = candidate_a.hash();
-
-		let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
-		let pending_availability = Vec::new();
-
-		let relay_parent_a_info = RelayChainBlockInfo {
-			number: pvd_a.relay_parent_number,
-			hash: relay_parent_a,
-			storage_root: pvd_a.relay_parent_storage_root,
-		};
-
-		let max_depth = 4;
-		let scope = Scope::with_ancestors(
-			para_id,
-			relay_parent_a_info,
-			base_constraints,
-			pending_availability,
-			max_depth,
-			vec![],
-		)
-		.unwrap();
-		let tree = FragmentTree::populate(scope, &storage);
-
-		assert_eq!(
-			tree.hypothetical_depths(
-				candidate_a_hash,
-				HypotheticalCandidate::Incomplete {
-					parent_head_data_hash: HeadData::from(vec![0x0a]).hash(),
-					relay_parent: relay_parent_a,
-				},
-				&storage,
-				false,
-			),
-			vec![0],
-		);
-
-		assert!(tree
-			.hypothetical_depths(
-				candidate_a_hash,
-				HypotheticalCandidate::Complete {
-					receipt: Cow::Owned(candidate_a),
-					persisted_validation_data: Cow::Owned(pvd_a),
-				},
-				&storage,
-				false,
-			)
-			.is_empty());
-	}
-
-	#[test]
-	fn hypothetical_depths_backed_in_path() {
-		let mut storage = CandidateStorage::new();
-
-		let para_id = ParaId::from(5u32);
-		let relay_parent_a = Hash::repeat_byte(1);
-
-		let (pvd_a, candidate_a) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0a].into(),
-			vec![0x0b].into(),
-			0,
-		);
-		let candidate_a_hash = candidate_a.hash();
-
-		let (pvd_b, candidate_b) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0b].into(),
-			vec![0x0c].into(),
-			0,
-		);
-		let candidate_b_hash = candidate_b.hash();
-
-		let (pvd_c, candidate_c) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0b].into(),
-			vec![0x0d].into(),
-			0,
-		);
-
-		let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
-		let pending_availability = Vec::new();
-
-		let relay_parent_a_info = RelayChainBlockInfo {
-			number: pvd_a.relay_parent_number,
-			hash: relay_parent_a,
-			storage_root: pvd_a.relay_parent_storage_root,
-		};
-
-		let max_depth = 4;
-		storage.add_candidate(candidate_a, pvd_a).unwrap();
-		storage.add_candidate(candidate_b, pvd_b).unwrap();
-		storage.add_candidate(candidate_c, pvd_c).unwrap();
-
-		// `A` and `B` are backed, `C` is not.
-		storage.mark_backed(&candidate_a_hash);
-		storage.mark_backed(&candidate_b_hash);
-
-		let scope = Scope::with_ancestors(
-			para_id,
-			relay_parent_a_info,
-			base_constraints,
-			pending_availability,
-			max_depth,
-			vec![],
-		)
-		.unwrap();
-		let tree = FragmentTree::populate(scope, &storage);
-
-		let candidates: Vec<_> = tree.candidates().collect();
-		assert_eq!(candidates.len(), 3);
-		assert_eq!(tree.nodes.len(), 3);
-
-		let candidate_d_hash = CandidateHash(Hash::repeat_byte(0xAA));
-
-		assert_eq!(
-			tree.hypothetical_depths(
-				candidate_d_hash,
-				HypotheticalCandidate::Incomplete {
-					parent_head_data_hash: HeadData::from(vec![0x0a]).hash(),
-					relay_parent: relay_parent_a,
-				},
-				&storage,
-				true,
-			),
-			vec![0],
-		);
-
-		assert_eq!(
-			tree.hypothetical_depths(
-				candidate_d_hash,
-				HypotheticalCandidate::Incomplete {
-					parent_head_data_hash: HeadData::from(vec![0x0c]).hash(),
-					relay_parent: relay_parent_a,
-				},
-				&storage,
-				true,
-			),
-			vec![2],
-		);
-
-		assert_eq!(
-			tree.hypothetical_depths(
-				candidate_d_hash,
-				HypotheticalCandidate::Incomplete {
-					parent_head_data_hash: HeadData::from(vec![0x0d]).hash(),
-					relay_parent: relay_parent_a,
-				},
-				&storage,
-				true,
-			),
-			Vec::<usize>::new(),
-		);
-
-		assert_eq!(
-			tree.hypothetical_depths(
-				candidate_d_hash,
-				HypotheticalCandidate::Incomplete {
-					parent_head_data_hash: HeadData::from(vec![0x0d]).hash(),
-					relay_parent: relay_parent_a,
-				},
-				&storage,
-				false,
-			),
-			vec![2], // non-empty if `false`.
-		);
-	}
-
-	#[test]
-	fn pending_availability_in_scope() {
-		let mut storage = CandidateStorage::new();
-
-		let para_id = ParaId::from(5u32);
-		let relay_parent_a = Hash::repeat_byte(1);
-		let relay_parent_b = Hash::repeat_byte(2);
-		let relay_parent_c = Hash::repeat_byte(3);
-
-		let (pvd_a, candidate_a) = make_committed_candidate(
-			para_id,
-			relay_parent_a,
-			0,
-			vec![0x0a].into(),
-			vec![0x0b].into(),
-			0,
-		);
-		let candidate_a_hash = candidate_a.hash();
-
-		let (pvd_b, candidate_b) = make_committed_candidate(
-			para_id,
-			relay_parent_b,
-			1,
-			vec![0x0b].into(),
-			vec![0x0c].into(),
-			1,
-		);
-
-		// Note that relay parent `a` is not allowed.
-		let base_constraints = make_constraints(1, vec![], vec![0x0a].into());
-
-		let relay_parent_a_info = RelayChainBlockInfo {
-			number: pvd_a.relay_parent_number,
-			hash: relay_parent_a,
-			storage_root: pvd_a.relay_parent_storage_root,
-		};
-		let pending_availability = vec![PendingAvailability {
-			candidate_hash: candidate_a_hash,
-			relay_parent: relay_parent_a_info,
-		}];
-
-		let relay_parent_b_info = RelayChainBlockInfo {
-			number: pvd_b.relay_parent_number,
-			hash: relay_parent_b,
-			storage_root: pvd_b.relay_parent_storage_root,
-		};
-		let relay_parent_c_info = RelayChainBlockInfo {
-			number: pvd_b.relay_parent_number + 1,
-			hash: relay_parent_c,
-			storage_root: Hash::zero(),
-		};
-
-		let max_depth = 4;
-		storage.add_candidate(candidate_a, pvd_a).unwrap();
-		storage.add_candidate(candidate_b, pvd_b).unwrap();
-		storage.mark_backed(&candidate_a_hash);
-
-		let scope = Scope::with_ancestors(
-			para_id,
-			relay_parent_c_info,
-			base_constraints,
-			pending_availability,
-			max_depth,
-			vec![relay_parent_b_info],
-		)
-		.unwrap();
-		let tree = FragmentTree::populate(scope, &storage);
-
-		let candidates: Vec<_> = tree.candidates().collect();
-		assert_eq!(candidates.len(), 2);
-		assert_eq!(tree.nodes.len(), 2);
-
-		let candidate_d_hash = CandidateHash(Hash::repeat_byte(0xAA));
-
-		assert_eq!(
-			tree.hypothetical_depths(
-				candidate_d_hash,
-				HypotheticalCandidate::Incomplete {
-					parent_head_data_hash: HeadData::from(vec![0x0b]).hash(),
-					relay_parent: relay_parent_c,
-				},
-				&storage,
-				false,
-			),
-			vec![1],
-		);
-
-		assert_eq!(
-			tree.hypothetical_depths(
-				candidate_d_hash,
-				HypotheticalCandidate::Incomplete {
-					parent_head_data_hash: HeadData::from(vec![0x0c]).hash(),
-					relay_parent: relay_parent_b,
-				},
-				&storage,
-				false,
-			),
-			vec![2],
-		);
-	}
-}
diff --git a/polkadot/node/core/prospective-parachains/src/fragment_tree/tests.rs b/polkadot/node/core/prospective-parachains/src/fragment_tree/tests.rs
new file mode 100644
index 0000000000000000000000000000000000000000..fd41be55f7f960367ee0a57ccd4a4c2251b90d13
--- /dev/null
+++ b/polkadot/node/core/prospective-parachains/src/fragment_tree/tests.rs
@@ -0,0 +1,1451 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Polkadot is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
+
+use super::*;
+use assert_matches::assert_matches;
+use polkadot_node_subsystem_util::inclusion_emulator::InboundHrmpLimitations;
+use polkadot_primitives::{BlockNumber, CandidateCommitments, CandidateDescriptor, HeadData};
+use polkadot_primitives_test_helpers as test_helpers;
+use rstest::rstest;
+use std::iter;
+
+impl NodePointer {
+	fn unwrap_idx(self) -> usize {
+		match self {
+			NodePointer::Root => panic!("Unexpected root"),
+			NodePointer::Storage(index) => index,
+		}
+	}
+}
+
+fn make_constraints(
+	min_relay_parent_number: BlockNumber,
+	valid_watermarks: Vec<BlockNumber>,
+	required_parent: HeadData,
+) -> Constraints {
+	Constraints {
+		min_relay_parent_number,
+		max_pov_size: 1_000_000,
+		max_code_size: 1_000_000,
+		ump_remaining: 10,
+		ump_remaining_bytes: 1_000,
+		max_ump_num_per_candidate: 10,
+		dmp_remaining_messages: [0; 10].into(),
+		hrmp_inbound: InboundHrmpLimitations { valid_watermarks },
+		hrmp_channels_out: HashMap::new(),
+		max_hrmp_num_per_candidate: 0,
+		required_parent,
+		validation_code_hash: Hash::repeat_byte(42).into(),
+		upgrade_restriction: None,
+		future_validation_code: None,
+	}
+}
+
+fn make_committed_candidate(
+	para_id: ParaId,
+	relay_parent: Hash,
+	relay_parent_number: BlockNumber,
+	parent_head: HeadData,
+	para_head: HeadData,
+	hrmp_watermark: BlockNumber,
+) -> (PersistedValidationData, CommittedCandidateReceipt) {
+	let persisted_validation_data = PersistedValidationData {
+		parent_head,
+		relay_parent_number,
+		relay_parent_storage_root: Hash::repeat_byte(69),
+		max_pov_size: 1_000_000,
+	};
+
+	let candidate = CommittedCandidateReceipt {
+		descriptor: CandidateDescriptor {
+			para_id,
+			relay_parent,
+			collator: test_helpers::dummy_collator(),
+			persisted_validation_data_hash: persisted_validation_data.hash(),
+			pov_hash: Hash::repeat_byte(1),
+			erasure_root: Hash::repeat_byte(1),
+			signature: test_helpers::dummy_collator_signature(),
+			para_head: para_head.hash(),
+			validation_code_hash: Hash::repeat_byte(42).into(),
+		},
+		commitments: CandidateCommitments {
+			upward_messages: Default::default(),
+			horizontal_messages: Default::default(),
+			new_validation_code: None,
+			head_data: para_head,
+			processed_downward_messages: 1,
+			hrmp_watermark,
+		},
+	};
+
+	(persisted_validation_data, candidate)
+}
+
+#[test]
+fn scope_rejects_ancestors_that_skip_blocks() {
+	let para_id = ParaId::from(5u32);
+	let relay_parent = RelayChainBlockInfo {
+		number: 10,
+		hash: Hash::repeat_byte(10),
+		storage_root: Hash::repeat_byte(69),
+	};
+
+	let ancestors = vec![RelayChainBlockInfo {
+		number: 8,
+		hash: Hash::repeat_byte(8),
+		storage_root: Hash::repeat_byte(69),
+	}];
+
+	let max_depth = 2;
+	let base_constraints = make_constraints(8, vec![8, 9], vec![1, 2, 3].into());
+	let pending_availability = Vec::new();
+
+	assert_matches!(
+		Scope::with_ancestors(
+			para_id,
+			relay_parent,
+			base_constraints,
+			pending_availability,
+			max_depth,
+			ancestors
+		),
+		Err(UnexpectedAncestor { number: 8, prev: 10 })
+	);
+}
+
+#[test]
+fn scope_rejects_ancestor_for_0_block() {
+	let para_id = ParaId::from(5u32);
+	let relay_parent = RelayChainBlockInfo {
+		number: 0,
+		hash: Hash::repeat_byte(0),
+		storage_root: Hash::repeat_byte(69),
+	};
+
+	let ancestors = vec![RelayChainBlockInfo {
+		number: 99999,
+		hash: Hash::repeat_byte(99),
+		storage_root: Hash::repeat_byte(69),
+	}];
+
+	let max_depth = 2;
+	let base_constraints = make_constraints(0, vec![], vec![1, 2, 3].into());
+	let pending_availability = Vec::new();
+
+	assert_matches!(
+		Scope::with_ancestors(
+			para_id,
+			relay_parent,
+			base_constraints,
+			pending_availability,
+			max_depth,
+			ancestors,
+		),
+		Err(UnexpectedAncestor { number: 99999, prev: 0 })
+	);
+}
+
+#[test]
+fn scope_only_takes_ancestors_up_to_min() {
+	let para_id = ParaId::from(5u32);
+	let relay_parent = RelayChainBlockInfo {
+		number: 5,
+		hash: Hash::repeat_byte(0),
+		storage_root: Hash::repeat_byte(69),
+	};
+
+	let ancestors = vec![
+		RelayChainBlockInfo {
+			number: 4,
+			hash: Hash::repeat_byte(4),
+			storage_root: Hash::repeat_byte(69),
+		},
+		RelayChainBlockInfo {
+			number: 3,
+			hash: Hash::repeat_byte(3),
+			storage_root: Hash::repeat_byte(69),
+		},
+		RelayChainBlockInfo {
+			number: 2,
+			hash: Hash::repeat_byte(2),
+			storage_root: Hash::repeat_byte(69),
+		},
+	];
+
+	let max_depth = 2;
+	let base_constraints = make_constraints(3, vec![2], vec![1, 2, 3].into());
+	let pending_availability = Vec::new();
+
+	let scope = Scope::with_ancestors(
+		para_id,
+		relay_parent,
+		base_constraints,
+		pending_availability,
+		max_depth,
+		ancestors,
+	)
+	.unwrap();
+
+	assert_eq!(scope.ancestors.len(), 2);
+	assert_eq!(scope.ancestors_by_hash.len(), 2);
+}
+
+#[test]
+fn storage_add_candidate() {
+	let mut storage = CandidateStorage::new();
+	let relay_parent = Hash::repeat_byte(69);
+
+	let (pvd, candidate) = make_committed_candidate(
+		ParaId::from(5u32),
+		relay_parent,
+		8,
+		vec![4, 5, 6].into(),
+		vec![1, 2, 3].into(),
+		7,
+	);
+
+	let candidate_hash = candidate.hash();
+	let parent_head_hash = pvd.parent_head.hash();
+
+	storage.add_candidate(candidate, pvd).unwrap();
+	assert!(storage.contains(&candidate_hash));
+	assert_eq!(storage.iter_para_children(&parent_head_hash).count(), 1);
+
+	assert_eq!(storage.relay_parent_by_candidate_hash(&candidate_hash), Some(relay_parent));
+}
+
+#[test]
+fn storage_retain() {
+	let mut storage = CandidateStorage::new();
+
+	let (pvd, candidate) = make_committed_candidate(
+		ParaId::from(5u32),
+		Hash::repeat_byte(69),
+		8,
+		vec![4, 5, 6].into(),
+		vec![1, 2, 3].into(),
+		7,
+	);
+
+	let candidate_hash = candidate.hash();
+	let output_head_hash = candidate.commitments.head_data.hash();
+	let parent_head_hash = pvd.parent_head.hash();
+
+	storage.add_candidate(candidate, pvd).unwrap();
+	storage.retain(|_| true);
+	assert!(storage.contains(&candidate_hash));
+	assert_eq!(storage.iter_para_children(&parent_head_hash).count(), 1);
+	assert!(storage.head_data_by_hash(&output_head_hash).is_some());
+
+	storage.retain(|_| false);
+	assert!(!storage.contains(&candidate_hash));
+	assert_eq!(storage.iter_para_children(&parent_head_hash).count(), 0);
+	assert!(storage.head_data_by_hash(&output_head_hash).is_none());
+}
+
+// [`FragmentTree::populate`] should pick up candidates that build on other candidates.
+#[test]
+fn populate_works_recursively() {
+	let mut storage = CandidateStorage::new();
+
+	let para_id = ParaId::from(5u32);
+	let relay_parent_a = Hash::repeat_byte(1);
+	let relay_parent_b = Hash::repeat_byte(2);
+
+	let (pvd_a, candidate_a) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0a].into(),
+		vec![0x0b].into(),
+		0,
+	);
+	let candidate_a_hash = candidate_a.hash();
+
+	let (pvd_b, candidate_b) = make_committed_candidate(
+		para_id,
+		relay_parent_b,
+		1,
+		vec![0x0b].into(),
+		vec![0x0c].into(),
+		1,
+	);
+	let candidate_b_hash = candidate_b.hash();
+
+	let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
+	let pending_availability = Vec::new();
+
+	let ancestors = vec![RelayChainBlockInfo {
+		number: pvd_a.relay_parent_number,
+		hash: relay_parent_a,
+		storage_root: pvd_a.relay_parent_storage_root,
+	}];
+
+	let relay_parent_b_info = RelayChainBlockInfo {
+		number: pvd_b.relay_parent_number,
+		hash: relay_parent_b,
+		storage_root: pvd_b.relay_parent_storage_root,
+	};
+
+	storage.add_candidate(candidate_a, pvd_a).unwrap();
+	storage.add_candidate(candidate_b, pvd_b).unwrap();
+	let scope = Scope::with_ancestors(
+		para_id,
+		relay_parent_b_info,
+		base_constraints,
+		pending_availability,
+		4,
+		ancestors,
+	)
+	.unwrap();
+	let tree = FragmentTree::populate(scope, &storage);
+
+	let candidates: Vec<_> = tree.candidates().collect();
+	assert_eq!(candidates.len(), 2);
+	assert!(candidates.contains(&candidate_a_hash));
+	assert!(candidates.contains(&candidate_b_hash));
+
+	assert_eq!(tree.nodes.len(), 2);
+	assert_eq!(tree.nodes[0].parent, NodePointer::Root);
+	assert_eq!(tree.nodes[0].candidate_hash, candidate_a_hash);
+	assert_eq!(tree.nodes[0].depth, 0);
+
+	assert_eq!(tree.nodes[1].parent, NodePointer::Storage(0));
+	assert_eq!(tree.nodes[1].candidate_hash, candidate_b_hash);
+	assert_eq!(tree.nodes[1].depth, 1);
+}
+
+#[test]
+fn children_of_root_are_contiguous() {
+	let mut storage = CandidateStorage::new();
+
+	let para_id = ParaId::from(5u32);
+	let relay_parent_a = Hash::repeat_byte(1);
+	let relay_parent_b = Hash::repeat_byte(2);
+
+	let (pvd_a, candidate_a) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0a].into(),
+		vec![0x0b].into(),
+		0,
+	);
+
+	let (pvd_b, candidate_b) = make_committed_candidate(
+		para_id,
+		relay_parent_b,
+		1,
+		vec![0x0b].into(),
+		vec![0x0c].into(),
+		1,
+	);
+
+	let (pvd_a2, candidate_a2) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0a].into(),
+		vec![0x0b, 1].into(),
+		0,
+	);
+	let candidate_a2_hash = candidate_a2.hash();
+
+	let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
+	let pending_availability = Vec::new();
+
+	let ancestors = vec![RelayChainBlockInfo {
+		number: pvd_a.relay_parent_number,
+		hash: relay_parent_a,
+		storage_root: pvd_a.relay_parent_storage_root,
+	}];
+
+	let relay_parent_b_info = RelayChainBlockInfo {
+		number: pvd_b.relay_parent_number,
+		hash: relay_parent_b,
+		storage_root: pvd_b.relay_parent_storage_root,
+	};
+
+	storage.add_candidate(candidate_a, pvd_a).unwrap();
+	storage.add_candidate(candidate_b, pvd_b).unwrap();
+	let scope = Scope::with_ancestors(
+		para_id,
+		relay_parent_b_info,
+		base_constraints,
+		pending_availability,
+		4,
+		ancestors,
+	)
+	.unwrap();
+	let mut tree = FragmentTree::populate(scope, &storage);
+
+	storage.add_candidate(candidate_a2, pvd_a2).unwrap();
+	tree.add_and_populate(candidate_a2_hash, &storage);
+	let candidates: Vec<_> = tree.candidates().collect();
+	assert_eq!(candidates.len(), 3);
+
+	assert_eq!(tree.nodes[0].parent, NodePointer::Root);
+	assert_eq!(tree.nodes[1].parent, NodePointer::Root);
+	assert_eq!(tree.nodes[2].parent, NodePointer::Storage(0));
+}
+
+#[test]
+fn add_candidate_child_of_root() {
+	let mut storage = CandidateStorage::new();
+
+	let para_id = ParaId::from(5u32);
+	let relay_parent_a = Hash::repeat_byte(1);
+
+	let (pvd_a, candidate_a) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0a].into(),
+		vec![0x0b].into(),
+		0,
+	);
+
+	let (pvd_b, candidate_b) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0a].into(),
+		vec![0x0c].into(),
+		0,
+	);
+	let candidate_b_hash = candidate_b.hash();
+
+	let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
+	let pending_availability = Vec::new();
+
+	let relay_parent_a_info = RelayChainBlockInfo {
+		number: pvd_a.relay_parent_number,
+		hash: relay_parent_a,
+		storage_root: pvd_a.relay_parent_storage_root,
+	};
+
+	storage.add_candidate(candidate_a, pvd_a).unwrap();
+	let scope = Scope::with_ancestors(
+		para_id,
+		relay_parent_a_info,
+		base_constraints,
+		pending_availability,
+		4,
+		vec![],
+	)
+	.unwrap();
+	let mut tree = FragmentTree::populate(scope, &storage);
+
+	storage.add_candidate(candidate_b, pvd_b).unwrap();
+	tree.add_and_populate(candidate_b_hash, &storage);
+	let candidates: Vec<_> = tree.candidates().collect();
+	assert_eq!(candidates.len(), 2);
+
+	assert_eq!(tree.nodes[0].parent, NodePointer::Root);
+	assert_eq!(tree.nodes[1].parent, NodePointer::Root);
+}
+
+#[test]
+fn add_candidate_child_of_non_root() {
+	let mut storage = CandidateStorage::new();
+
+	let para_id = ParaId::from(5u32);
+	let relay_parent_a = Hash::repeat_byte(1);
+
+	let (pvd_a, candidate_a) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0a].into(),
+		vec![0x0b].into(),
+		0,
+	);
+
+	let (pvd_b, candidate_b) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0b].into(),
+		vec![0x0c].into(),
+		0,
+	);
+	let candidate_b_hash = candidate_b.hash();
+
+	let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
+	let pending_availability = Vec::new();
+
+	let relay_parent_a_info = RelayChainBlockInfo {
+		number: pvd_a.relay_parent_number,
+		hash: relay_parent_a,
+		storage_root: pvd_a.relay_parent_storage_root,
+	};
+
+	storage.add_candidate(candidate_a, pvd_a).unwrap();
+	let scope = Scope::with_ancestors(
+		para_id,
+		relay_parent_a_info,
+		base_constraints,
+		pending_availability,
+		4,
+		vec![],
+	)
+	.unwrap();
+	let mut tree = FragmentTree::populate(scope, &storage);
+
+	storage.add_candidate(candidate_b, pvd_b).unwrap();
+	tree.add_and_populate(candidate_b_hash, &storage);
+	let candidates: Vec<_> = tree.candidates().collect();
+	assert_eq!(candidates.len(), 2);
+
+	assert_eq!(tree.nodes[0].parent, NodePointer::Root);
+	assert_eq!(tree.nodes[1].parent, NodePointer::Storage(0));
+}
+
+#[test]
+fn test_find_ancestor_path_and_find_backable_chain_empty_tree() {
+	let para_id = ParaId::from(5u32);
+	let relay_parent = Hash::repeat_byte(1);
+	let required_parent: HeadData = vec![0xff].into();
+	let max_depth = 10;
+
+	// Empty tree
+	let storage = CandidateStorage::new();
+	let base_constraints = make_constraints(0, vec![0], required_parent.clone());
+
+	let relay_parent_info =
+		RelayChainBlockInfo { number: 0, hash: relay_parent, storage_root: Hash::zero() };
+
+	let scope = Scope::with_ancestors(
+		para_id,
+		relay_parent_info,
+		base_constraints,
+		vec![],
+		max_depth,
+		vec![],
+	)
+	.unwrap();
+	let tree = FragmentTree::populate(scope, &storage);
+	assert_eq!(tree.candidates().collect::<Vec<_>>().len(), 0);
+	assert_eq!(tree.nodes.len(), 0);
+
+	assert_eq!(tree.find_ancestor_path(Ancestors::new()).unwrap(), NodePointer::Root);
+	assert_eq!(tree.find_backable_chain(Ancestors::new(), 2, |_| true), vec![]);
+	// Invalid candidate.
+	let ancestors: Ancestors = [CandidateHash::default()].into_iter().collect();
+	assert_eq!(tree.find_ancestor_path(ancestors.clone()), Some(NodePointer::Root));
+	assert_eq!(tree.find_backable_chain(ancestors, 2, |_| true), vec![]);
+}
+
+#[rstest]
+#[case(true, 13)]
+#[case(false, 8)]
+// The tree with no cycles looks like:
+// Make a tree that looks like this (note that there's no cycle):
+//         +-(root)-+
+//         |        |
+//    +----0---+    7
+//    |        |
+//    1----+   5
+//    |    |
+//    |    |
+//    2    6
+//    |
+//    3
+//    |
+//    4
+//
+// The tree with cycles is the same as the first but has a cycle from 4 back to the state
+// produced by 0 (It's bounded by the max_depth + 1).
+//         +-(root)-+
+//         |        |
+//    +----0---+    7
+//    |        |
+//    1----+   5
+//    |    |
+//    |    |
+//    2    6
+//    |
+//    3
+//    |
+//    4---+
+//    |   |
+//    1   5
+//    |
+//    2
+//    |
+//    3
+fn test_find_ancestor_path_and_find_backable_chain(
+	#[case] has_cycle: bool,
+	#[case] expected_node_count: usize,
+) {
+	let para_id = ParaId::from(5u32);
+	let relay_parent = Hash::repeat_byte(1);
+	let required_parent: HeadData = vec![0xff].into();
+	let max_depth = 7;
+	let relay_parent_number = 0;
+	let relay_parent_storage_root = Hash::repeat_byte(69);
+
+	let mut candidates = vec![];
+
+	// Candidate 0
+	candidates.push(make_committed_candidate(
+		para_id,
+		relay_parent,
+		0,
+		required_parent.clone(),
+		vec![0].into(),
+		0,
+	));
+	// Candidate 1
+	candidates.push(make_committed_candidate(
+		para_id,
+		relay_parent,
+		0,
+		vec![0].into(),
+		vec![1].into(),
+		0,
+	));
+	// Candidate 2
+	candidates.push(make_committed_candidate(
+		para_id,
+		relay_parent,
+		0,
+		vec![1].into(),
+		vec![2].into(),
+		0,
+	));
+	// Candidate 3
+	candidates.push(make_committed_candidate(
+		para_id,
+		relay_parent,
+		0,
+		vec![2].into(),
+		vec![3].into(),
+		0,
+	));
+	// Candidate 4
+	candidates.push(make_committed_candidate(
+		para_id,
+		relay_parent,
+		0,
+		vec![3].into(),
+		vec![4].into(),
+		0,
+	));
+	// Candidate 5
+	candidates.push(make_committed_candidate(
+		para_id,
+		relay_parent,
+		0,
+		vec![0].into(),
+		vec![5].into(),
+		0,
+	));
+	// Candidate 6
+	candidates.push(make_committed_candidate(
+		para_id,
+		relay_parent,
+		0,
+		vec![1].into(),
+		vec![6].into(),
+		0,
+	));
+	// Candidate 7
+	candidates.push(make_committed_candidate(
+		para_id,
+		relay_parent,
+		0,
+		required_parent.clone(),
+		vec![7].into(),
+		0,
+	));
+
+	if has_cycle {
+		candidates[4] = make_committed_candidate(
+			para_id,
+			relay_parent,
+			0,
+			vec![3].into(),
+			vec![0].into(), // put the cycle here back to the output state of 0.
+			0,
+		);
+	}
+
+	let base_constraints = make_constraints(0, vec![0], required_parent.clone());
+	let mut storage = CandidateStorage::new();
+
+	let relay_parent_info = RelayChainBlockInfo {
+		number: relay_parent_number,
+		hash: relay_parent,
+		storage_root: relay_parent_storage_root,
+	};
+
+	for (pvd, candidate) in candidates.iter() {
+		storage.add_candidate(candidate.clone(), pvd.clone()).unwrap();
+	}
+	let candidates = candidates.into_iter().map(|(_pvd, candidate)| candidate).collect::<Vec<_>>();
+	let scope = Scope::with_ancestors(
+		para_id,
+		relay_parent_info,
+		base_constraints,
+		vec![],
+		max_depth,
+		vec![],
+	)
+	.unwrap();
+	let tree = FragmentTree::populate(scope, &storage);
+
+	assert_eq!(tree.candidates().collect::<Vec<_>>().len(), candidates.len());
+	assert_eq!(tree.nodes.len(), expected_node_count);
+
+	// Do some common tests on both trees.
+	{
+		// No ancestors supplied.
+		assert_eq!(tree.find_ancestor_path(Ancestors::new()).unwrap(), NodePointer::Root);
+		assert_eq!(
+			tree.find_backable_chain(Ancestors::new(), 4, |_| true),
+			[0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
+		);
+		// Ancestor which is not part of the tree. Will be ignored.
+		let ancestors: Ancestors = [CandidateHash::default()].into_iter().collect();
+		assert_eq!(tree.find_ancestor_path(ancestors.clone()).unwrap(), NodePointer::Root);
+		assert_eq!(
+			tree.find_backable_chain(ancestors, 4, |_| true),
+			[0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
+		);
+		// A chain fork.
+		let ancestors: Ancestors =
+			[(candidates[0].hash()), (candidates[7].hash())].into_iter().collect();
+		assert_eq!(tree.find_ancestor_path(ancestors.clone()), None);
+		assert_eq!(tree.find_backable_chain(ancestors, 1, |_| true), vec![]);
+
+		// Ancestors which are part of the tree but don't form a path. Will be ignored.
+		let ancestors: Ancestors =
+			[candidates[1].hash(), candidates[2].hash()].into_iter().collect();
+		assert_eq!(tree.find_ancestor_path(ancestors.clone()).unwrap(), NodePointer::Root);
+		assert_eq!(
+			tree.find_backable_chain(ancestors, 4, |_| true),
+			[0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
+		);
+
+		// Valid ancestors.
+		let ancestors: Ancestors = [candidates[7].hash()].into_iter().collect();
+		let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
+		let candidate = &tree.nodes[res.unwrap_idx()];
+		assert_eq!(candidate.candidate_hash, candidates[7].hash());
+		assert_eq!(tree.find_backable_chain(ancestors, 1, |_| true), vec![]);
+
+		let ancestors: Ancestors =
+			[candidates[2].hash(), candidates[0].hash(), candidates[1].hash()]
+				.into_iter()
+				.collect();
+		let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
+		let candidate = &tree.nodes[res.unwrap_idx()];
+		assert_eq!(candidate.candidate_hash, candidates[2].hash());
+		assert_eq!(
+			tree.find_backable_chain(ancestors.clone(), 2, |_| true),
+			[3, 4].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
+		);
+
+		// Valid ancestors with candidates which have been omitted due to timeouts
+		let ancestors: Ancestors =
+			[candidates[0].hash(), candidates[2].hash()].into_iter().collect();
+		let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
+		let candidate = &tree.nodes[res.unwrap_idx()];
+		assert_eq!(candidate.candidate_hash, candidates[0].hash());
+		assert_eq!(
+			tree.find_backable_chain(ancestors, 3, |_| true),
+			[1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
+		);
+
+		let ancestors: Ancestors =
+			[candidates[0].hash(), candidates[1].hash(), candidates[3].hash()]
+				.into_iter()
+				.collect();
+		let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
+		let candidate = &tree.nodes[res.unwrap_idx()];
+		assert_eq!(candidate.candidate_hash, candidates[1].hash());
+		if has_cycle {
+			assert_eq!(
+				tree.find_backable_chain(ancestors, 2, |_| true),
+				[2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
+			);
+		} else {
+			assert_eq!(
+				tree.find_backable_chain(ancestors, 4, |_| true),
+				[2, 3, 4].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
+			);
+		}
+
+		let ancestors: Ancestors =
+			[candidates[1].hash(), candidates[2].hash()].into_iter().collect();
+		let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
+		assert_eq!(res, NodePointer::Root);
+		assert_eq!(
+			tree.find_backable_chain(ancestors, 4, |_| true),
+			[0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
+		);
+
+		// Requested count is 0.
+		assert_eq!(tree.find_backable_chain(Ancestors::new(), 0, |_| true), vec![]);
+
+		let ancestors: Ancestors =
+			[candidates[2].hash(), candidates[0].hash(), candidates[1].hash()]
+				.into_iter()
+				.collect();
+		assert_eq!(tree.find_backable_chain(ancestors, 0, |_| true), vec![]);
+
+		let ancestors: Ancestors =
+			[candidates[2].hash(), candidates[0].hash()].into_iter().collect();
+		assert_eq!(tree.find_backable_chain(ancestors, 0, |_| true), vec![]);
+	}
+
+	// Now do some tests only on the tree with cycles
+	if has_cycle {
+		// Exceeds the maximum tree depth. 0-1-2-3-4-1-2-3-4, when the tree stops at
+		// 0-1-2-3-4-1-2-3.
+		let ancestors: Ancestors = [
+			candidates[0].hash(),
+			candidates[1].hash(),
+			candidates[2].hash(),
+			candidates[3].hash(),
+			candidates[4].hash(),
+		]
+		.into_iter()
+		.collect();
+		let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
+		let candidate = &tree.nodes[res.unwrap_idx()];
+		assert_eq!(candidate.candidate_hash, candidates[4].hash());
+		assert_eq!(
+			tree.find_backable_chain(ancestors, 4, |_| true),
+			[1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
+		);
+
+		// 0-1-2.
+		let ancestors: Ancestors =
+			[candidates[0].hash(), candidates[1].hash(), candidates[2].hash()]
+				.into_iter()
+				.collect();
+		let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
+		let candidate = &tree.nodes[res.unwrap_idx()];
+		assert_eq!(candidate.candidate_hash, candidates[2].hash());
+		assert_eq!(
+			tree.find_backable_chain(ancestors.clone(), 1, |_| true),
+			[3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
+		);
+		assert_eq!(
+			tree.find_backable_chain(ancestors, 5, |_| true),
+			[3, 4, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>()
+		);
+
+		// 0-1
+		let ancestors: Ancestors =
+			[candidates[0].hash(), candidates[1].hash()].into_iter().collect();
+		let res = tree.find_ancestor_path(ancestors.clone()).unwrap();
+		let candidate = &tree.nodes[res.unwrap_idx()];
+		assert_eq!(candidate.candidate_hash, candidates[1].hash());
+		assert_eq!(
+			tree.find_backable_chain(ancestors, 6, |_| true),
+			[2, 3, 4, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::<Vec<_>>(),
+		);
+
+		// For 0-1-2-3-4-5, there's more than 1 way of finding this path in
+		// the tree. `None` should be returned. The runtime should not have accepted this.
+		let ancestors: Ancestors = [
+			candidates[0].hash(),
+			candidates[1].hash(),
+			candidates[2].hash(),
+			candidates[3].hash(),
+			candidates[4].hash(),
+			candidates[5].hash(),
+		]
+		.into_iter()
+		.collect();
+		let res = tree.find_ancestor_path(ancestors.clone());
+		assert_eq!(res, None);
+		assert_eq!(tree.find_backable_chain(ancestors, 1, |_| true), vec![]);
+	}
+}
+
+#[test]
+fn graceful_cycle_of_0() {
+	let mut storage = CandidateStorage::new();
+
+	let para_id = ParaId::from(5u32);
+	let relay_parent_a = Hash::repeat_byte(1);
+
+	let (pvd_a, candidate_a) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0a].into(),
+		vec![0x0a].into(), // input same as output
+		0,
+	);
+	let candidate_a_hash = candidate_a.hash();
+	let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
+	let pending_availability = Vec::new();
+
+	let relay_parent_a_info = RelayChainBlockInfo {
+		number: pvd_a.relay_parent_number,
+		hash: relay_parent_a,
+		storage_root: pvd_a.relay_parent_storage_root,
+	};
+
+	let max_depth = 4;
+	storage.add_candidate(candidate_a, pvd_a).unwrap();
+	let scope = Scope::with_ancestors(
+		para_id,
+		relay_parent_a_info,
+		base_constraints,
+		pending_availability,
+		max_depth,
+		vec![],
+	)
+	.unwrap();
+	let tree = FragmentTree::populate(scope, &storage);
+
+	let candidates: Vec<_> = tree.candidates().collect();
+	assert_eq!(candidates.len(), 1);
+	assert_eq!(tree.nodes.len(), max_depth + 1);
+
+	assert_eq!(tree.nodes[0].parent, NodePointer::Root);
+	assert_eq!(tree.nodes[1].parent, NodePointer::Storage(0));
+	assert_eq!(tree.nodes[2].parent, NodePointer::Storage(1));
+	assert_eq!(tree.nodes[3].parent, NodePointer::Storage(2));
+	assert_eq!(tree.nodes[4].parent, NodePointer::Storage(3));
+
+	assert_eq!(tree.nodes[0].candidate_hash, candidate_a_hash);
+	assert_eq!(tree.nodes[1].candidate_hash, candidate_a_hash);
+	assert_eq!(tree.nodes[2].candidate_hash, candidate_a_hash);
+	assert_eq!(tree.nodes[3].candidate_hash, candidate_a_hash);
+	assert_eq!(tree.nodes[4].candidate_hash, candidate_a_hash);
+
+	for count in 1..10 {
+		assert_eq!(
+			tree.find_backable_chain(Ancestors::new(), count, |_| true),
+			iter::repeat(candidate_a_hash)
+				.take(std::cmp::min(count as usize, max_depth + 1))
+				.collect::<Vec<_>>()
+		);
+		assert_eq!(
+			tree.find_backable_chain([candidate_a_hash].into_iter().collect(), count - 1, |_| true),
+			iter::repeat(candidate_a_hash)
+				.take(std::cmp::min(count as usize - 1, max_depth))
+				.collect::<Vec<_>>()
+		);
+	}
+}
+
+#[test]
+fn graceful_cycle_of_1() {
+	let mut storage = CandidateStorage::new();
+
+	let para_id = ParaId::from(5u32);
+	let relay_parent_a = Hash::repeat_byte(1);
+
+	let (pvd_a, candidate_a) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0a].into(),
+		vec![0x0b].into(), // input same as output
+		0,
+	);
+	let candidate_a_hash = candidate_a.hash();
+
+	let (pvd_b, candidate_b) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0b].into(),
+		vec![0x0a].into(), // input same as output
+		0,
+	);
+	let candidate_b_hash = candidate_b.hash();
+
+	let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
+	let pending_availability = Vec::new();
+
+	let relay_parent_a_info = RelayChainBlockInfo {
+		number: pvd_a.relay_parent_number,
+		hash: relay_parent_a,
+		storage_root: pvd_a.relay_parent_storage_root,
+	};
+
+	let max_depth = 4;
+	storage.add_candidate(candidate_a, pvd_a).unwrap();
+	storage.add_candidate(candidate_b, pvd_b).unwrap();
+	let scope = Scope::with_ancestors(
+		para_id,
+		relay_parent_a_info,
+		base_constraints,
+		pending_availability,
+		max_depth,
+		vec![],
+	)
+	.unwrap();
+	let tree = FragmentTree::populate(scope, &storage);
+
+	let candidates: Vec<_> = tree.candidates().collect();
+	assert_eq!(candidates.len(), 2);
+	assert_eq!(tree.nodes.len(), max_depth + 1);
+
+	assert_eq!(tree.nodes[0].parent, NodePointer::Root);
+	assert_eq!(tree.nodes[1].parent, NodePointer::Storage(0));
+	assert_eq!(tree.nodes[2].parent, NodePointer::Storage(1));
+	assert_eq!(tree.nodes[3].parent, NodePointer::Storage(2));
+	assert_eq!(tree.nodes[4].parent, NodePointer::Storage(3));
+
+	assert_eq!(tree.nodes[0].candidate_hash, candidate_a_hash);
+	assert_eq!(tree.nodes[1].candidate_hash, candidate_b_hash);
+	assert_eq!(tree.nodes[2].candidate_hash, candidate_a_hash);
+	assert_eq!(tree.nodes[3].candidate_hash, candidate_b_hash);
+	assert_eq!(tree.nodes[4].candidate_hash, candidate_a_hash);
+
+	assert_eq!(tree.find_backable_chain(Ancestors::new(), 1, |_| true), vec![candidate_a_hash],);
+	assert_eq!(
+		tree.find_backable_chain(Ancestors::new(), 2, |_| true),
+		vec![candidate_a_hash, candidate_b_hash],
+	);
+	assert_eq!(
+		tree.find_backable_chain(Ancestors::new(), 3, |_| true),
+		vec![candidate_a_hash, candidate_b_hash, candidate_a_hash],
+	);
+	assert_eq!(
+		tree.find_backable_chain([candidate_a_hash].into_iter().collect(), 2, |_| true),
+		vec![candidate_b_hash, candidate_a_hash],
+	);
+
+	assert_eq!(
+		tree.find_backable_chain(Ancestors::new(), 6, |_| true),
+		vec![
+			candidate_a_hash,
+			candidate_b_hash,
+			candidate_a_hash,
+			candidate_b_hash,
+			candidate_a_hash
+		],
+	);
+
+	for count in 3..7 {
+		assert_eq!(
+			tree.find_backable_chain(
+				[candidate_a_hash, candidate_b_hash].into_iter().collect(),
+				count,
+				|_| true
+			),
+			vec![candidate_a_hash, candidate_b_hash, candidate_a_hash],
+		);
+	}
+}
+
+#[test]
+fn hypothetical_depths_known_and_unknown() {
+	let mut storage = CandidateStorage::new();
+
+	let para_id = ParaId::from(5u32);
+	let relay_parent_a = Hash::repeat_byte(1);
+
+	let (pvd_a, candidate_a) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0a].into(),
+		vec![0x0b].into(), // input same as output
+		0,
+	);
+	let candidate_a_hash = candidate_a.hash();
+
+	let (pvd_b, candidate_b) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0b].into(),
+		vec![0x0a].into(), // input same as output
+		0,
+	);
+	let candidate_b_hash = candidate_b.hash();
+
+	let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
+	let pending_availability = Vec::new();
+
+	let relay_parent_a_info = RelayChainBlockInfo {
+		number: pvd_a.relay_parent_number,
+		hash: relay_parent_a,
+		storage_root: pvd_a.relay_parent_storage_root,
+	};
+
+	let max_depth = 4;
+	storage.add_candidate(candidate_a, pvd_a).unwrap();
+	storage.add_candidate(candidate_b, pvd_b).unwrap();
+	let scope = Scope::with_ancestors(
+		para_id,
+		relay_parent_a_info,
+		base_constraints,
+		pending_availability,
+		max_depth,
+		vec![],
+	)
+	.unwrap();
+	let tree = FragmentTree::populate(scope, &storage);
+
+	let candidates: Vec<_> = tree.candidates().collect();
+	assert_eq!(candidates.len(), 2);
+	assert_eq!(tree.nodes.len(), max_depth + 1);
+
+	assert_eq!(
+		tree.hypothetical_depths(
+			candidate_a_hash,
+			HypotheticalCandidate::Incomplete {
+				parent_head_data_hash: HeadData::from(vec![0x0a]).hash(),
+				relay_parent: relay_parent_a,
+			},
+			&storage,
+			false,
+		),
+		vec![0, 2, 4],
+	);
+
+	assert_eq!(
+		tree.hypothetical_depths(
+			candidate_b_hash,
+			HypotheticalCandidate::Incomplete {
+				parent_head_data_hash: HeadData::from(vec![0x0b]).hash(),
+				relay_parent: relay_parent_a,
+			},
+			&storage,
+			false,
+		),
+		vec![1, 3],
+	);
+
+	assert_eq!(
+		tree.hypothetical_depths(
+			CandidateHash(Hash::repeat_byte(21)),
+			HypotheticalCandidate::Incomplete {
+				parent_head_data_hash: HeadData::from(vec![0x0a]).hash(),
+				relay_parent: relay_parent_a,
+			},
+			&storage,
+			false,
+		),
+		vec![0, 2, 4],
+	);
+
+	assert_eq!(
+		tree.hypothetical_depths(
+			CandidateHash(Hash::repeat_byte(22)),
+			HypotheticalCandidate::Incomplete {
+				parent_head_data_hash: HeadData::from(vec![0x0b]).hash(),
+				relay_parent: relay_parent_a,
+			},
+			&storage,
+			false,
+		),
+		vec![1, 3]
+	);
+}
+
+#[test]
+fn hypothetical_depths_stricter_on_complete() {
+	let storage = CandidateStorage::new();
+
+	let para_id = ParaId::from(5u32);
+	let relay_parent_a = Hash::repeat_byte(1);
+
+	let (pvd_a, candidate_a) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0a].into(),
+		vec![0x0b].into(),
+		1000, // watermark is illegal
+	);
+
+	let candidate_a_hash = candidate_a.hash();
+
+	let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
+	let pending_availability = Vec::new();
+
+	let relay_parent_a_info = RelayChainBlockInfo {
+		number: pvd_a.relay_parent_number,
+		hash: relay_parent_a,
+		storage_root: pvd_a.relay_parent_storage_root,
+	};
+
+	let max_depth = 4;
+	let scope = Scope::with_ancestors(
+		para_id,
+		relay_parent_a_info,
+		base_constraints,
+		pending_availability,
+		max_depth,
+		vec![],
+	)
+	.unwrap();
+	let tree = FragmentTree::populate(scope, &storage);
+
+	assert_eq!(
+		tree.hypothetical_depths(
+			candidate_a_hash,
+			HypotheticalCandidate::Incomplete {
+				parent_head_data_hash: HeadData::from(vec![0x0a]).hash(),
+				relay_parent: relay_parent_a,
+			},
+			&storage,
+			false,
+		),
+		vec![0],
+	);
+
+	assert!(tree
+		.hypothetical_depths(
+			candidate_a_hash,
+			HypotheticalCandidate::Complete {
+				receipt: Cow::Owned(candidate_a),
+				persisted_validation_data: Cow::Owned(pvd_a),
+			},
+			&storage,
+			false,
+		)
+		.is_empty());
+}
+
+#[test]
+fn hypothetical_depths_backed_in_path() {
+	let mut storage = CandidateStorage::new();
+
+	let para_id = ParaId::from(5u32);
+	let relay_parent_a = Hash::repeat_byte(1);
+
+	let (pvd_a, candidate_a) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0a].into(),
+		vec![0x0b].into(),
+		0,
+	);
+	let candidate_a_hash = candidate_a.hash();
+
+	let (pvd_b, candidate_b) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0b].into(),
+		vec![0x0c].into(),
+		0,
+	);
+	let candidate_b_hash = candidate_b.hash();
+
+	let (pvd_c, candidate_c) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0b].into(),
+		vec![0x0d].into(),
+		0,
+	);
+
+	let base_constraints = make_constraints(0, vec![0], vec![0x0a].into());
+	let pending_availability = Vec::new();
+
+	let relay_parent_a_info = RelayChainBlockInfo {
+		number: pvd_a.relay_parent_number,
+		hash: relay_parent_a,
+		storage_root: pvd_a.relay_parent_storage_root,
+	};
+
+	let max_depth = 4;
+	storage.add_candidate(candidate_a, pvd_a).unwrap();
+	storage.add_candidate(candidate_b, pvd_b).unwrap();
+	storage.add_candidate(candidate_c, pvd_c).unwrap();
+
+	// `A` and `B` are backed, `C` is not.
+	storage.mark_backed(&candidate_a_hash);
+	storage.mark_backed(&candidate_b_hash);
+
+	let scope = Scope::with_ancestors(
+		para_id,
+		relay_parent_a_info,
+		base_constraints,
+		pending_availability,
+		max_depth,
+		vec![],
+	)
+	.unwrap();
+	let tree = FragmentTree::populate(scope, &storage);
+
+	let candidates: Vec<_> = tree.candidates().collect();
+	assert_eq!(candidates.len(), 3);
+	assert_eq!(tree.nodes.len(), 3);
+
+	let candidate_d_hash = CandidateHash(Hash::repeat_byte(0xAA));
+
+	assert_eq!(
+		tree.hypothetical_depths(
+			candidate_d_hash,
+			HypotheticalCandidate::Incomplete {
+				parent_head_data_hash: HeadData::from(vec![0x0a]).hash(),
+				relay_parent: relay_parent_a,
+			},
+			&storage,
+			true,
+		),
+		vec![0],
+	);
+
+	assert_eq!(
+		tree.hypothetical_depths(
+			candidate_d_hash,
+			HypotheticalCandidate::Incomplete {
+				parent_head_data_hash: HeadData::from(vec![0x0c]).hash(),
+				relay_parent: relay_parent_a,
+			},
+			&storage,
+			true,
+		),
+		vec![2],
+	);
+
+	assert_eq!(
+		tree.hypothetical_depths(
+			candidate_d_hash,
+			HypotheticalCandidate::Incomplete {
+				parent_head_data_hash: HeadData::from(vec![0x0d]).hash(),
+				relay_parent: relay_parent_a,
+			},
+			&storage,
+			true,
+		),
+		Vec::<usize>::new(),
+	);
+
+	assert_eq!(
+		tree.hypothetical_depths(
+			candidate_d_hash,
+			HypotheticalCandidate::Incomplete {
+				parent_head_data_hash: HeadData::from(vec![0x0d]).hash(),
+				relay_parent: relay_parent_a,
+			},
+			&storage,
+			false,
+		),
+		vec![2], // non-empty if `false`.
+	);
+}
+
+#[test]
+fn pending_availability_in_scope() {
+	let mut storage = CandidateStorage::new();
+
+	let para_id = ParaId::from(5u32);
+	let relay_parent_a = Hash::repeat_byte(1);
+	let relay_parent_b = Hash::repeat_byte(2);
+	let relay_parent_c = Hash::repeat_byte(3);
+
+	let (pvd_a, candidate_a) = make_committed_candidate(
+		para_id,
+		relay_parent_a,
+		0,
+		vec![0x0a].into(),
+		vec![0x0b].into(),
+		0,
+	);
+	let candidate_a_hash = candidate_a.hash();
+
+	let (pvd_b, candidate_b) = make_committed_candidate(
+		para_id,
+		relay_parent_b,
+		1,
+		vec![0x0b].into(),
+		vec![0x0c].into(),
+		1,
+	);
+
+	// Note that relay parent `a` is not allowed.
+	let base_constraints = make_constraints(1, vec![], vec![0x0a].into());
+
+	let relay_parent_a_info = RelayChainBlockInfo {
+		number: pvd_a.relay_parent_number,
+		hash: relay_parent_a,
+		storage_root: pvd_a.relay_parent_storage_root,
+	};
+	let pending_availability = vec![PendingAvailability {
+		candidate_hash: candidate_a_hash,
+		relay_parent: relay_parent_a_info,
+	}];
+
+	let relay_parent_b_info = RelayChainBlockInfo {
+		number: pvd_b.relay_parent_number,
+		hash: relay_parent_b,
+		storage_root: pvd_b.relay_parent_storage_root,
+	};
+	let relay_parent_c_info = RelayChainBlockInfo {
+		number: pvd_b.relay_parent_number + 1,
+		hash: relay_parent_c,
+		storage_root: Hash::zero(),
+	};
+
+	let max_depth = 4;
+	storage.add_candidate(candidate_a, pvd_a).unwrap();
+	storage.add_candidate(candidate_b, pvd_b).unwrap();
+	storage.mark_backed(&candidate_a_hash);
+
+	let scope = Scope::with_ancestors(
+		para_id,
+		relay_parent_c_info,
+		base_constraints,
+		pending_availability,
+		max_depth,
+		vec![relay_parent_b_info],
+	)
+	.unwrap();
+	let tree = FragmentTree::populate(scope, &storage);
+
+	let candidates: Vec<_> = tree.candidates().collect();
+	assert_eq!(candidates.len(), 2);
+	assert_eq!(tree.nodes.len(), 2);
+
+	let candidate_d_hash = CandidateHash(Hash::repeat_byte(0xAA));
+
+	assert_eq!(
+		tree.hypothetical_depths(
+			candidate_d_hash,
+			HypotheticalCandidate::Incomplete {
+				parent_head_data_hash: HeadData::from(vec![0x0b]).hash(),
+				relay_parent: relay_parent_c,
+			},
+			&storage,
+			false,
+		),
+		vec![1],
+	);
+
+	assert_eq!(
+		tree.hypothetical_depths(
+			candidate_d_hash,
+			HypotheticalCandidate::Incomplete {
+				parent_head_data_hash: HeadData::from(vec![0x0c]).hash(),
+				relay_parent: relay_parent_b,
+			},
+			&storage,
+			false,
+		),
+		vec![2],
+	);
+}
diff --git a/polkadot/runtime/common/src/impls.rs b/polkadot/runtime/common/src/impls.rs
index cc1243790c2e58b23c169de918f28d75397420ba..85531e9c04fc47f83fb007802e30e87799c2150c 100644
--- a/polkadot/runtime/common/src/impls.rs
+++ b/polkadot/runtime/common/src/impls.rs
@@ -19,7 +19,7 @@
 use frame_support::traits::{
 	fungible::{Balanced, Credit},
 	tokens::imbalance::ResolveTo,
-	Imbalance, OnUnbalanced,
+	Contains, ContainsPair, Imbalance, OnUnbalanced,
 };
 use pallet_treasury::TreasuryAccountId;
 use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
@@ -156,6 +156,26 @@ impl TryConvert<&VersionedLocation, xcm::latest::Location> for VersionedLocation
 	}
 }
 
+/// Adapter for [`Contains`] trait to match [`VersionedLocatableAsset`] type converted to the latest
+/// version of itself where it's location matched by `L` and it's asset id by `A` parameter types.
+pub struct ContainsParts<C>(core::marker::PhantomData<C>);
+impl<C> Contains<VersionedLocatableAsset> for ContainsParts<C>
+where
+	C: ContainsPair<xcm::latest::Location, xcm::latest::Location>,
+{
+	fn contains(asset: &VersionedLocatableAsset) -> bool {
+		use VersionedLocatableAsset::*;
+		let (location, asset_id) = match asset.clone() {
+			V3 { location, asset_id } => match (location.try_into(), asset_id.try_into()) {
+				(Ok(l), Ok(a)) => (l, a),
+				_ => return false,
+			},
+			V4 { location, asset_id } => (location, asset_id),
+		};
+		C::contains(&location, &asset_id.0)
+	}
+}
+
 #[cfg(feature = "runtime-benchmarks")]
 pub mod benchmarks {
 	use super::VersionedLocatableAsset;
diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs
index 740a6240d39526cec795ba082848a480c8a7e3a3..ba80fa6942c7791e9166281f0bdf2199a41cf10f 100644
--- a/polkadot/runtime/rococo/src/lib.rs
+++ b/polkadot/runtime/rococo/src/lib.rs
@@ -25,7 +25,10 @@ use beefy_primitives::{
 	ecdsa_crypto::{AuthorityId as BeefyId, Signature as BeefySignature},
 	mmr::{BeefyDataProvider, MmrLeafVersion},
 };
-use frame_support::dynamic_params::{dynamic_pallet_params, dynamic_params};
+use frame_support::{
+	dynamic_params::{dynamic_pallet_params, dynamic_params},
+	traits::FromContains,
+};
 use pallet_nis::WithMaximumOf;
 use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
 use primitives::{
@@ -40,7 +43,8 @@ use rococo_runtime_constants::system_parachain::BROKER_ID;
 use runtime_common::{
 	assigned_slots, auctions, claims, crowdloan, identity_migrator, impl_runtime_weights,
 	impls::{
-		LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, VersionedLocationConverter,
+		ContainsParts, LocatableAssetConverter, ToAuthor, VersionedLocatableAsset,
+		VersionedLocationConverter,
 	},
 	paras_registrar, paras_sudo_wrapper, prod_or_fast, slots,
 	traits::{Leaser, OnSwap},
@@ -74,10 +78,10 @@ use frame_support::{
 	genesis_builder_helper::{build_state, get_preset},
 	parameter_types,
 	traits::{
-		fungible::HoldConsideration, Contains, EitherOf, EitherOfDiverse, EnsureOrigin,
-		EnsureOriginWithArg, EverythingBut, InstanceFilter, KeyOwnerProofSystem,
-		LinearStoragePrice, PrivilegeCmp, ProcessMessage, ProcessMessageError, StorageMapShim,
-		WithdrawReasons,
+		fungible::HoldConsideration, tokens::UnityOrOuterConversion, Contains, EitherOf,
+		EitherOfDiverse, EnsureOrigin, EnsureOriginWithArg, EverythingBut, InstanceFilter,
+		KeyOwnerProofSystem, LinearStoragePrice, PrivilegeCmp, ProcessMessage, ProcessMessageError,
+		StorageMapShim, WithdrawReasons,
 	},
 	weights::{ConstantMultiplier, WeightMeter, WeightToFee as _},
 	PalletId,
@@ -87,7 +91,7 @@ use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId};
 use pallet_identity::legacy::IdentityInfo;
 use pallet_session::historical as session_historical;
 use pallet_transaction_payment::{FeeDetails, FungibleAdapter, RuntimeDispatchInfo};
-use sp_core::{ConstU128, OpaqueMetadata, H256};
+use sp_core::{ConstU128, ConstU8, OpaqueMetadata, H256};
 use sp_runtime::{
 	create_runtime_str, generic, impl_opaque_keys,
 	traits::{
@@ -523,7 +527,15 @@ impl pallet_treasury::Config for Runtime {
 		LocatableAssetConverter,
 		VersionedLocationConverter,
 	>;
-	type BalanceConverter = AssetRate;
+	type BalanceConverter = UnityOrOuterConversion<
+		ContainsParts<
+			FromContains<
+				xcm_builder::IsChildSystemParachain<ParaId>,
+				xcm_builder::IsParentsOnly<ConstU8<1>>,
+			>,
+		>,
+		AssetRate,
+	>;
 	type PayoutPeriod = PayoutSpendPeriod;
 	#[cfg(feature = "runtime-benchmarks")]
 	type BenchmarkHelper = runtime_common::impls::benchmarks::TreasuryArguments;
diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs
index a119d78b83ab8a76642d0bc1cf407ec4935ab5dc..a06a1e1f7fc8dfbefee8aae69194265b80fbd8c5 100644
--- a/polkadot/runtime/westend/src/lib.rs
+++ b/polkadot/runtime/westend/src/lib.rs
@@ -31,9 +31,9 @@ use frame_support::{
 	genesis_builder_helper::{build_state, get_preset},
 	parameter_types,
 	traits::{
-		fungible::HoldConsideration, ConstU32, Contains, EitherOf, EitherOfDiverse, EverythingBut,
-		InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, ProcessMessage,
-		ProcessMessageError, WithdrawReasons,
+		fungible::HoldConsideration, tokens::UnityOrOuterConversion, ConstU32, Contains, EitherOf,
+		EitherOfDiverse, EverythingBut, FromContains, InstanceFilter, KeyOwnerProofSystem,
+		LinearStoragePrice, ProcessMessage, ProcessMessageError, WithdrawReasons,
 	},
 	weights::{ConstantMultiplier, WeightMeter, WeightToFee as _},
 	PalletId,
@@ -57,7 +57,8 @@ use runtime_common::{
 	elections::OnChainAccuracy,
 	identity_migrator, impl_runtime_weights,
 	impls::{
-		LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, VersionedLocationConverter,
+		ContainsParts, LocatableAssetConverter, ToAuthor, VersionedLocatableAsset,
+		VersionedLocationConverter,
 	},
 	paras_registrar, paras_sudo_wrapper, prod_or_fast, slots,
 	traits::{Leaser, OnSwap},
@@ -80,7 +81,7 @@ use runtime_parachains::{
 	shared as parachains_shared,
 };
 use scale_info::TypeInfo;
-use sp_core::{OpaqueMetadata, RuntimeDebug, H256};
+use sp_core::{ConstU8, OpaqueMetadata, RuntimeDebug, H256};
 use sp_runtime::{
 	create_runtime_str,
 	curve::PiecewiseLinear,
@@ -712,7 +713,15 @@ impl pallet_treasury::Config for Runtime {
 		LocatableAssetConverter,
 		VersionedLocationConverter,
 	>;
-	type BalanceConverter = AssetRate;
+	type BalanceConverter = UnityOrOuterConversion<
+		ContainsParts<
+			FromContains<
+				xcm_builder::IsChildSystemParachain<ParaId>,
+				xcm_builder::IsParentsOnly<ConstU8<1>>,
+			>,
+		>,
+		AssetRate,
+	>;
 	type PayoutPeriod = PayoutSpendPeriod;
 	#[cfg(feature = "runtime-benchmarks")]
 	type BenchmarkHelper = runtime_common::impls::benchmarks::TreasuryArguments;
diff --git a/polkadot/xcm/xcm-builder/src/barriers.rs b/polkadot/xcm/xcm-builder/src/barriers.rs
index b8923a4d5c6e88d9034536fa4dacf21c47e9108b..c0b328f38e96b23dbadcda4dd8fc1aacf9620d5d 100644
--- a/polkadot/xcm/xcm-builder/src/barriers.rs
+++ b/polkadot/xcm/xcm-builder/src/barriers.rs
@@ -322,6 +322,29 @@ impl<ParaId: IsSystem + From<u32>> Contains<Location> for IsChildSystemParachain
 	}
 }
 
+/// Matches if the given location is a system-level sibling parachain.
+pub struct IsSiblingSystemParachain<ParaId, SelfParaId>(PhantomData<(ParaId, SelfParaId)>);
+impl<ParaId: IsSystem + From<u32> + Eq, SelfParaId: Get<ParaId>> Contains<Location>
+	for IsSiblingSystemParachain<ParaId, SelfParaId>
+{
+	fn contains(l: &Location) -> bool {
+		matches!(
+			l.unpack(),
+			(1, [Junction::Parachain(id)])
+				if SelfParaId::get() != ParaId::from(*id) && ParaId::from(*id).is_system(),
+		)
+	}
+}
+
+/// Matches if the given location contains only the specified amount of parents and no interior
+/// junctions.
+pub struct IsParentsOnly<Count>(PhantomData<Count>);
+impl<Count: Get<u8>> Contains<Location> for IsParentsOnly<Count> {
+	fn contains(t: &Location) -> bool {
+		t.contains_parents_only(Count::get())
+	}
+}
+
 /// Allows only messages if the generic `ResponseHandler` expects them via `expecting_response`.
 pub struct AllowKnownQueryResponses<ResponseHandler>(PhantomData<ResponseHandler>);
 impl<ResponseHandler: OnResponse> ShouldExecute for AllowKnownQueryResponses<ResponseHandler> {
diff --git a/polkadot/xcm/xcm-builder/src/lib.rs b/polkadot/xcm/xcm-builder/src/lib.rs
index c3400cc72b48e97cb2cdfd85a028b21b7c032963..bd4a4c941c915c8da1f9c05d35444d86ac7668e8 100644
--- a/polkadot/xcm/xcm-builder/src/lib.rs
+++ b/polkadot/xcm/xcm-builder/src/lib.rs
@@ -37,8 +37,8 @@ mod barriers;
 pub use barriers::{
 	AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom,
 	AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, DenyReserveTransferToRelayChain,
-	DenyThenTry, IsChildSystemParachain, RespectSuspension, TakeWeightCredit, TrailingSetTopicAsId,
-	WithComputedOrigin,
+	DenyThenTry, IsChildSystemParachain, IsParentsOnly, IsSiblingSystemParachain,
+	RespectSuspension, TakeWeightCredit, TrailingSetTopicAsId, WithComputedOrigin,
 };
 
 mod controller;
diff --git a/prdoc/pr_3659.prdoc b/prdoc/pr_3659.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..393844d822d864bca595a0257f02989fb4a19ac7
--- /dev/null
+++ b/prdoc/pr_3659.prdoc
@@ -0,0 +1,12 @@
+# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
+# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
+
+title: Unity Balance Conversion for Different IDs of Native Asset 
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      Introduce types to define 1:1 balance conversion for different relative asset ids/locations 
+      of native asset for `ConversionToAssetBalance` trait bounds.
+
+crates: [ ]
\ No newline at end of file
diff --git a/prdoc/pr_4151.prdoc b/prdoc/pr_4151.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..70b9f5e60e14c5a0896b60651be89cc40fbe56a5
--- /dev/null
+++ b/prdoc/pr_4151.prdoc
@@ -0,0 +1,11 @@
+title: "[pallet-broker] Use saturating math in input validation"
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      Use saturating in the pallet-broker input validation of the `drop_history` extrinsic. This
+      fixes a safeguard that only expired historic instantaneous pool records get dropped.
+
+crates:
+  - name: pallet-broker
+    bump: patch
diff --git a/prdoc/schema_user.json b/prdoc/schema_user.json
index 6b44b1b28dfb859dde52e46974a6ef1d06aa3722..1fa4b8d1202c99c1fea077854b6f5efcf58f1ae5 100644
--- a/prdoc/schema_user.json
+++ b/prdoc/schema_user.json
@@ -200,6 +200,11 @@
             "const": "patch",
             "title": "Patch",
             "description": "A bump to the third leftmost non-zero digit of the version number."
+          },
+          {
+            "const": "none",
+            "title": "None",
+            "description": "This change requires no SemVer bump (e.g. change was a test)."
           }
         ]
       },
diff --git a/substrate/frame/broker/src/dispatchable_impls.rs b/substrate/frame/broker/src/dispatchable_impls.rs
index c2e731462ca58bb042ffe08c3b2c59af2cf3954c..b43911b6bc12d63a2806f3b708e842aee59c9ec0 100644
--- a/substrate/frame/broker/src/dispatchable_impls.rs
+++ b/substrate/frame/broker/src/dispatchable_impls.rs
@@ -419,7 +419,10 @@ impl<T: Config> Pallet<T> {
 	pub(crate) fn do_drop_history(when: Timeslice) -> DispatchResult {
 		let config = Configuration::<T>::get().ok_or(Error::<T>::Uninitialized)?;
 		let status = Status::<T>::get().ok_or(Error::<T>::Uninitialized)?;
-		ensure!(status.last_timeslice > when + config.contribution_timeout, Error::<T>::StillValid);
+		ensure!(
+			status.last_timeslice > when.saturating_add(config.contribution_timeout),
+			Error::<T>::StillValid
+		);
 		let record = InstaPoolHistory::<T>::take(when).ok_or(Error::<T>::NoHistory)?;
 		if let Some(payout) = record.maybe_payout {
 			let _ = Self::charge(&Self::account_id(), payout);
diff --git a/substrate/frame/broker/src/tests.rs b/substrate/frame/broker/src/tests.rs
index d738d34450336e8aa8c20eb2c7d232d2c69db592..8ec0c6d158b3bb03a5b1e7b1001f7ded8b7ef79d 100644
--- a/substrate/frame/broker/src/tests.rs
+++ b/substrate/frame/broker/src/tests.rs
@@ -146,6 +146,7 @@ fn drop_history_works() {
 			advance_to(16);
 			assert_eq!(InstaPoolHistory::<Test>::iter().count(), 6);
 			advance_to(17);
+			assert_noop!(Broker::do_drop_history(u32::MAX), Error::<Test>::StillValid);
 			assert_noop!(Broker::do_drop_history(region.begin), Error::<Test>::StillValid);
 			advance_to(18);
 			assert_eq!(InstaPoolHistory::<Test>::iter().count(), 6);
diff --git a/substrate/frame/contracts/src/benchmarking/mod.rs b/substrate/frame/contracts/src/benchmarking/mod.rs
index 676fd320a17299b2eb2471d485afcd2775168175..952ef180be21860b4a13a26fdf07bf03251f00a2 100644
--- a/substrate/frame/contracts/src/benchmarking/mod.rs
+++ b/substrate/frame/contracts/src/benchmarking/mod.rs
@@ -623,10 +623,13 @@ mod benchmarks {
 	#[benchmark(pov_mode = Measured)]
 	fn seal_caller(r: Linear<0, API_BENCHMARK_RUNS>) {
 		call_builder!(func, WasmModule::getter("seal0", "seal_caller", r));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
@@ -659,10 +662,13 @@ mod benchmarks {
 		for acc in accounts.iter() {
 			<ContractInfoOf<T>>::insert(acc, info.clone());
 		}
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
@@ -703,19 +709,25 @@ mod benchmarks {
 		for acc in accounts.iter() {
 			<ContractInfoOf<T>>::insert(acc, info.clone());
 		}
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
 	fn seal_own_code_hash(r: Linear<0, API_BENCHMARK_RUNS>) {
 		call_builder!(func, WasmModule::getter("seal0", "seal_own_code_hash", r));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
@@ -732,10 +744,13 @@ mod benchmarks {
 			..Default::default()
 		});
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
@@ -754,73 +769,97 @@ mod benchmarks {
 		let mut setup = CallSetup::<T>::new(code);
 		setup.set_origin(Origin::Root);
 		call_builder!(func, setup: setup);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
 	fn seal_address(r: Linear<0, API_BENCHMARK_RUNS>) {
 		call_builder!(func, WasmModule::getter("seal0", "seal_address", r));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
 	fn seal_gas_left(r: Linear<0, API_BENCHMARK_RUNS>) {
 		call_builder!(func, WasmModule::getter("seal1", "gas_left", r));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
 	fn seal_balance(r: Linear<0, API_BENCHMARK_RUNS>) {
 		call_builder!(func, WasmModule::getter("seal0", "seal_balance", r));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
 	fn seal_value_transferred(r: Linear<0, API_BENCHMARK_RUNS>) {
 		call_builder!(func, WasmModule::getter("seal0", "seal_value_transferred", r));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
 	fn seal_minimum_balance(r: Linear<0, API_BENCHMARK_RUNS>) {
 		call_builder!(func, WasmModule::getter("seal0", "seal_minimum_balance", r));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
 	fn seal_block_number(r: Linear<0, API_BENCHMARK_RUNS>) {
 		call_builder!(func, WasmModule::getter("seal0", "seal_block_number", r));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
 	fn seal_now(r: Linear<0, API_BENCHMARK_RUNS>) {
 		call_builder!(func, WasmModule::getter("seal0", "seal_now", r));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
@@ -851,10 +890,13 @@ mod benchmarks {
 			..Default::default()
 		});
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
@@ -880,10 +922,13 @@ mod benchmarks {
 		});
 
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
@@ -944,10 +989,13 @@ mod benchmarks {
 			..Default::default()
 		});
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	#[benchmark(pov_mode = Measured)]
@@ -970,10 +1018,13 @@ mod benchmarks {
 			..Default::default()
 		});
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	// The same argument as for `seal_return` is true here.
@@ -1108,10 +1159,13 @@ mod benchmarks {
 		});
 
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	// Overhead of calling the function without any topic.
@@ -1140,10 +1194,13 @@ mod benchmarks {
 		});
 
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	// Benchmark the overhead that topics generate.
@@ -1177,10 +1234,13 @@ mod benchmarks {
 		});
 
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	// Benchmark debug_message call with zero input data.
@@ -1210,10 +1270,13 @@ mod benchmarks {
 		let mut setup = CallSetup::<T>::new(code);
 		setup.enable_debug_message();
 		call_builder!(func, setup: setup);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -1260,10 +1323,13 @@ mod benchmarks {
 		let mut setup = CallSetup::<T>::new(code);
 		setup.enable_debug_message();
 		call_builder!(func, setup: setup);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		assert_eq!(setup.debug_message().unwrap().len() as u32, i);
 		Ok(())
 	}
@@ -1324,10 +1390,13 @@ mod benchmarks {
 			)
 			.map_err(|_| "Failed to write to storage during setup.")?;
 		}
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -1366,10 +1435,13 @@ mod benchmarks {
 			false,
 		)
 		.map_err(|_| "Failed to write to storage during setup.")?;
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -1409,10 +1481,13 @@ mod benchmarks {
 			false,
 		)
 		.map_err(|_| "Failed to write to storage during setup.")?;
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -1463,10 +1538,13 @@ mod benchmarks {
 			.map_err(|_| "Failed to write to storage during setup.")?;
 		}
 		<ContractInfoOf<T>>::insert(&instance.account_id, info);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -1504,10 +1582,12 @@ mod benchmarks {
 		)
 		.map_err(|_| "Failed to write to storage during setup.")?;
 
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -1564,10 +1644,13 @@ mod benchmarks {
 			.map_err(|_| "Failed to write to storage during setup.")?;
 		}
 		<ContractInfoOf<T>>::insert(&instance.account_id, info);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -1613,10 +1696,13 @@ mod benchmarks {
 		)
 		.map_err(|_| "Failed to write to storage during setup.")?;
 		<ContractInfoOf<T>>::insert(&instance.account_id, info);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 
 		Ok(())
 	}
@@ -1667,10 +1753,13 @@ mod benchmarks {
 			.map_err(|_| "Failed to write to storage during setup.")?;
 		}
 		<ContractInfoOf<T>>::insert(&instance.account_id, info);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -1708,10 +1797,13 @@ mod benchmarks {
 		)
 		.map_err(|_| "Failed to write to storage during setup.")?;
 		<ContractInfoOf<T>>::insert(&instance.account_id, info);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -1767,10 +1859,13 @@ mod benchmarks {
 			.map_err(|_| "Failed to write to storage during setup.")?;
 		}
 		<ContractInfoOf<T>>::insert(&instance.account_id, info);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -1816,10 +1911,13 @@ mod benchmarks {
 		)
 		.map_err(|_| "Failed to write to storage during setup.")?;
 		<ContractInfoOf<T>>::insert(&instance.account_id, info);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -1867,10 +1965,12 @@ mod benchmarks {
 			assert_eq!(T::Currency::total_balance(account), 0u32.into());
 		}
 
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 
 		for account in &accounts {
 			assert_eq!(T::Currency::total_balance(account), value);
@@ -1947,10 +2047,13 @@ mod benchmarks {
 		let mut setup = CallSetup::<T>::new(code);
 		setup.set_storage_deposit_limit(BalanceOf::<T>::from(u32::MAX.into()));
 		call_builder!(func, setup: setup);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -2002,10 +2105,13 @@ mod benchmarks {
 			..Default::default()
 		});
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -2057,10 +2163,13 @@ mod benchmarks {
 		let mut setup = CallSetup::<T>::new(code);
 		setup.set_data(vec![42; c as usize]);
 		call_builder!(func, setup: setup);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -2165,10 +2274,13 @@ mod benchmarks {
 				return Err("Expected that contract does not exist at this point.".into());
 			}
 		}
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		for addr in &addresses {
 			ContractInfoOf::<T>::get(&addr).ok_or("Contract should have been instantiated")?;
 		}
@@ -2240,10 +2352,13 @@ mod benchmarks {
 		let mut setup = CallSetup::<T>::new(code);
 		setup.set_balance(value + (Pallet::<T>::min_balance() * 2u32.into()));
 		call_builder!(func,  setup: setup);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -2251,80 +2366,104 @@ mod benchmarks {
 	#[benchmark(pov_mode = Measured)]
 	fn seal_hash_sha2_256(r: Linear<0, API_BENCHMARK_RUNS>) {
 		call_builder!(func, WasmModule::hasher("seal_hash_sha2_256", r, 0));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	// `n`: Input to hash in bytes
 	#[benchmark(pov_mode = Measured)]
 	fn seal_hash_sha2_256_per_byte(n: Linear<0, { code::max_pages::<T>() * 64 * 1024 }>) {
 		call_builder!(func, WasmModule::hasher("seal_hash_sha2_256", 1, n));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	// Only the overhead of calling the function itself with minimal arguments.
 	#[benchmark(pov_mode = Measured)]
 	fn seal_hash_keccak_256(r: Linear<0, API_BENCHMARK_RUNS>) {
 		call_builder!(func, WasmModule::hasher("seal_hash_keccak_256", r, 0));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	// `n`: Input to hash in bytes
 	#[benchmark(pov_mode = Measured)]
 	fn seal_hash_keccak_256_per_byte(n: Linear<0, { code::max_pages::<T>() * 64 * 1024 }>) {
 		call_builder!(func, WasmModule::hasher("seal_hash_keccak_256", 1, n));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	// Only the overhead of calling the function itself with minimal arguments.
 	#[benchmark(pov_mode = Measured)]
 	fn seal_hash_blake2_256(r: Linear<0, API_BENCHMARK_RUNS>) {
 		call_builder!(func, WasmModule::hasher("seal_hash_blake2_256", r, 0));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	// `n`: Input to hash in bytes
 	#[benchmark(pov_mode = Measured)]
 	fn seal_hash_blake2_256_per_byte(n: Linear<0, { code::max_pages::<T>() * 64 * 1024 }>) {
 		call_builder!(func, WasmModule::hasher("seal_hash_blake2_256", 1, n));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	// Only the overhead of calling the function itself with minimal arguments.
 	#[benchmark(pov_mode = Measured)]
 	fn seal_hash_blake2_128(r: Linear<0, API_BENCHMARK_RUNS>) {
 		call_builder!(func, WasmModule::hasher("seal_hash_blake2_128", r, 0));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	// `n`: Input to hash in bytes
 	#[benchmark(pov_mode = Measured)]
 	fn seal_hash_blake2_128_per_byte(n: Linear<0, { code::max_pages::<T>() * 64 * 1024 }>) {
 		call_builder!(func, WasmModule::hasher("seal_hash_blake2_128", 1, n));
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	// `n`: Message input length to verify in bytes.
@@ -2368,10 +2507,13 @@ mod benchmarks {
 		});
 
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -2425,10 +2567,13 @@ mod benchmarks {
 			..Default::default()
 		});
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -2475,10 +2620,13 @@ mod benchmarks {
 			..Default::default()
 		});
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -2515,10 +2663,13 @@ mod benchmarks {
 			..Default::default()
 		});
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -2556,10 +2707,13 @@ mod benchmarks {
 			..Default::default()
 		});
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -2598,10 +2752,13 @@ mod benchmarks {
 			..Default::default()
 		});
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -2656,10 +2813,13 @@ mod benchmarks {
 			..Default::default()
 		});
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -2713,10 +2873,13 @@ mod benchmarks {
 			..Default::default()
 		});
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 		Ok(())
 	}
 
@@ -2734,10 +2897,13 @@ mod benchmarks {
 			..Default::default()
 		});
 		call_builder!(func, code);
+
+		let res;
 		#[block]
 		{
-			func.call();
+			res = func.call();
 		}
+		assert_eq!(res.did_revert(), false);
 	}
 
 	// We load `i64` values from random linear memory locations and store the loaded
diff --git a/substrate/frame/contracts/src/weights.rs b/substrate/frame/contracts/src/weights.rs
index ca7f58cf5b0cada995a268cc241b36a0599cb709..b95b1d1a9a2e5ae47ca0d9fe1715031f47e43986 100644
--- a/substrate/frame/contracts/src/weights.rs
+++ b/substrate/frame/contracts/src/weights.rs
@@ -18,7 +18,7 @@
 //! Autogenerated weights for `pallet_contracts`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-04-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2024-04-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
 //! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
 //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024`
@@ -143,8 +143,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `142`
 		//  Estimated: `1627`
-		// Minimum execution time: 2_047_000 picoseconds.
-		Weight::from_parts(2_116_000, 1627)
+		// Minimum execution time: 2_149_000 picoseconds.
+		Weight::from_parts(2_274_000, 1627)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 	}
 	/// Storage: `Skipped::Metadata` (r:0 w:0)
@@ -154,10 +154,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `452 + k * (69 ±0)`
 		//  Estimated: `442 + k * (70 ±0)`
-		// Minimum execution time: 12_474_000 picoseconds.
-		Weight::from_parts(12_767_000, 442)
-			// Standard Error: 1_081
-			.saturating_add(Weight::from_parts(1_187_278, 0).saturating_mul(k.into()))
+		// Minimum execution time: 12_863_000 picoseconds.
+		Weight::from_parts(13_188_000, 442)
+			// Standard Error: 1_053
+			.saturating_add(Weight::from_parts(1_105_325, 0).saturating_mul(k.into()))
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into())))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
@@ -171,10 +171,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `211 + c * (1 ±0)`
 		//  Estimated: `6149 + c * (1 ±0)`
-		// Minimum execution time: 8_307_000 picoseconds.
-		Weight::from_parts(8_939_322, 6149)
+		// Minimum execution time: 8_432_000 picoseconds.
+		Weight::from_parts(9_203_290, 6149)
 			// Standard Error: 1
-			.saturating_add(Weight::from_parts(1_190, 0).saturating_mul(c.into()))
+			.saturating_add(Weight::from_parts(1_186, 0).saturating_mul(c.into()))
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into()))
@@ -187,8 +187,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `510`
 		//  Estimated: `6450`
-		// Minimum execution time: 16_915_000 picoseconds.
-		Weight::from_parts(17_638_000, 6450)
+		// Minimum execution time: 17_177_000 picoseconds.
+		Weight::from_parts(17_663_000, 6450)
 			.saturating_add(T::DbWeight::get().reads(3_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -201,10 +201,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `171 + k * (1 ±0)`
 		//  Estimated: `3635 + k * (1 ±0)`
-		// Minimum execution time: 3_607_000 picoseconds.
-		Weight::from_parts(1_979_323, 3635)
-			// Standard Error: 1_018
-			.saturating_add(Weight::from_parts(1_196_162, 0).saturating_mul(k.into()))
+		// Minimum execution time: 3_636_000 picoseconds.
+		Weight::from_parts(3_774_000, 3635)
+			// Standard Error: 542
+			.saturating_add(Weight::from_parts(1_260_058, 0).saturating_mul(k.into()))
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 			.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into())))
@@ -225,10 +225,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `328 + c * (1 ±0)`
 		//  Estimated: `6266 + c * (1 ±0)`
-		// Minimum execution time: 21_056_000 picoseconds.
-		Weight::from_parts(21_633_895, 6266)
+		// Minimum execution time: 21_585_000 picoseconds.
+		Weight::from_parts(22_069_944, 6266)
 			// Standard Error: 1
-			.saturating_add(Weight::from_parts(390, 0).saturating_mul(c.into()))
+			.saturating_add(Weight::from_parts(404, 0).saturating_mul(c.into()))
 			.saturating_add(T::DbWeight::get().reads(6_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into()))
@@ -239,8 +239,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `440`
 		//  Estimated: `6380`
-		// Minimum execution time: 12_860_000 picoseconds.
-		Weight::from_parts(13_525_000, 6380)
+		// Minimum execution time: 13_283_000 picoseconds.
+		Weight::from_parts(14_015_000, 6380)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -254,8 +254,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `352`
 		//  Estimated: `6292`
-		// Minimum execution time: 46_926_000 picoseconds.
-		Weight::from_parts(47_828_000, 6292)
+		// Minimum execution time: 48_022_000 picoseconds.
+		Weight::from_parts(49_627_000, 6292)
 			.saturating_add(T::DbWeight::get().reads(4_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -267,8 +267,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `594`
 		//  Estimated: `6534`
-		// Minimum execution time: 55_081_000 picoseconds.
-		Weight::from_parts(56_899_000, 6534)
+		// Minimum execution time: 58_374_000 picoseconds.
+		Weight::from_parts(59_615_000, 6534)
 			.saturating_add(T::DbWeight::get().reads(4_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 	}
@@ -278,8 +278,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `409`
 		//  Estimated: `6349`
-		// Minimum execution time: 12_595_000 picoseconds.
-		Weight::from_parts(13_059_000, 6349)
+		// Minimum execution time: 12_559_000 picoseconds.
+		Weight::from_parts(12_947_000, 6349)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -290,7 +290,7 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		//  Measured:  `142`
 		//  Estimated: `1627`
 		// Minimum execution time: 2_480_000 picoseconds.
-		Weight::from_parts(2_663_000, 1627)
+		Weight::from_parts(2_680_000, 1627)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -302,8 +302,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `166`
 		//  Estimated: `3631`
-		// Minimum execution time: 12_115_000 picoseconds.
-		Weight::from_parts(12_506_000, 3631)
+		// Minimum execution time: 12_625_000 picoseconds.
+		Weight::from_parts(13_094_000, 3631)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 	}
@@ -313,8 +313,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `142`
 		//  Estimated: `3607`
-		// Minimum execution time: 4_757_000 picoseconds.
-		Weight::from_parts(5_082_000, 3607)
+		// Minimum execution time: 4_836_000 picoseconds.
+		Weight::from_parts(5_182_000, 3607)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 	}
 	/// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0)
@@ -325,8 +325,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `167`
 		//  Estimated: `3632`
-		// Minimum execution time: 6_017_000 picoseconds.
-		Weight::from_parts(6_421_000, 3632)
+		// Minimum execution time: 6_319_000 picoseconds.
+		Weight::from_parts(6_582_000, 3632)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 	}
 	/// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0)
@@ -337,8 +337,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `142`
 		//  Estimated: `3607`
-		// Minimum execution time: 6_238_000 picoseconds.
-		Weight::from_parts(6_587_000, 3607)
+		// Minimum execution time: 6_532_000 picoseconds.
+		Weight::from_parts(6_909_000, 3607)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -363,10 +363,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `804 + c * (1 ±0)`
 		//  Estimated: `9217 + c * (1 ±0)`
-		// Minimum execution time: 288_968_000 picoseconds.
-		Weight::from_parts(267_291_922, 9217)
-			// Standard Error: 78
-			.saturating_add(Weight::from_parts(34_879, 0).saturating_mul(c.into()))
+		// Minimum execution time: 305_778_000 picoseconds.
+		Weight::from_parts(282_321_249, 9217)
+			// Standard Error: 72
+			.saturating_add(Weight::from_parts(33_456, 0).saturating_mul(c.into()))
 			.saturating_add(T::DbWeight::get().reads(11_u64))
 			.saturating_add(T::DbWeight::get().writes(4_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into()))
@@ -398,14 +398,14 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `326`
 		//  Estimated: `8740`
-		// Minimum execution time: 3_948_426_000 picoseconds.
-		Weight::from_parts(440_017_623, 8740)
-			// Standard Error: 555
-			.saturating_add(Weight::from_parts(71_483, 0).saturating_mul(c.into()))
-			// Standard Error: 66
-			.saturating_add(Weight::from_parts(1_831, 0).saturating_mul(i.into()))
-			// Standard Error: 66
-			.saturating_add(Weight::from_parts(1_694, 0).saturating_mul(s.into()))
+		// Minimum execution time: 3_810_809_000 picoseconds.
+		Weight::from_parts(739_511_598, 8740)
+			// Standard Error: 140
+			.saturating_add(Weight::from_parts(67_574, 0).saturating_mul(c.into()))
+			// Standard Error: 16
+			.saturating_add(Weight::from_parts(1_488, 0).saturating_mul(i.into()))
+			// Standard Error: 16
+			.saturating_add(Weight::from_parts(1_537, 0).saturating_mul(s.into()))
 			.saturating_add(T::DbWeight::get().reads(14_u64))
 			.saturating_add(T::DbWeight::get().writes(10_u64))
 	}
@@ -435,12 +435,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `563`
 		//  Estimated: `8982`
-		// Minimum execution time: 2_011_037_000 picoseconds.
-		Weight::from_parts(2_047_025_000, 8982)
-			// Standard Error: 28
-			.saturating_add(Weight::from_parts(968, 0).saturating_mul(i.into()))
-			// Standard Error: 28
-			.saturating_add(Weight::from_parts(780, 0).saturating_mul(s.into()))
+		// Minimum execution time: 1_986_789_000 picoseconds.
+		Weight::from_parts(2_017_466_000, 8982)
+			// Standard Error: 26
+			.saturating_add(Weight::from_parts(827, 0).saturating_mul(i.into()))
+			// Standard Error: 26
+			.saturating_add(Weight::from_parts(781, 0).saturating_mul(s.into()))
 			.saturating_add(T::DbWeight::get().reads(13_u64))
 			.saturating_add(T::DbWeight::get().writes(7_u64))
 	}
@@ -464,8 +464,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `829`
 		//  Estimated: `9244`
-		// Minimum execution time: 202_190_000 picoseconds.
-		Weight::from_parts(209_378_000, 9244)
+		// Minimum execution time: 210_724_000 picoseconds.
+		Weight::from_parts(218_608_000, 9244)
 			.saturating_add(T::DbWeight::get().reads(11_u64))
 			.saturating_add(T::DbWeight::get().writes(4_u64))
 	}
@@ -486,10 +486,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `145`
 		//  Estimated: `6085`
-		// Minimum execution time: 271_161_000 picoseconds.
-		Weight::from_parts(279_218_977, 6085)
-			// Standard Error: 80
-			.saturating_add(Weight::from_parts(33_973, 0).saturating_mul(c.into()))
+		// Minimum execution time: 271_259_000 picoseconds.
+		Weight::from_parts(298_852_854, 6085)
+			// Standard Error: 65
+			.saturating_add(Weight::from_parts(33_547, 0).saturating_mul(c.into()))
 			.saturating_add(T::DbWeight::get().reads(6_u64))
 			.saturating_add(T::DbWeight::get().writes(4_u64))
 	}
@@ -510,10 +510,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `145`
 		//  Estimated: `6085`
-		// Minimum execution time: 273_684_000 picoseconds.
-		Weight::from_parts(284_348_722, 6085)
-			// Standard Error: 79
-			.saturating_add(Weight::from_parts(34_205, 0).saturating_mul(c.into()))
+		// Minimum execution time: 278_167_000 picoseconds.
+		Weight::from_parts(311_888_941, 6085)
+			// Standard Error: 58
+			.saturating_add(Weight::from_parts(33_595, 0).saturating_mul(c.into()))
 			.saturating_add(T::DbWeight::get().reads(6_u64))
 			.saturating_add(T::DbWeight::get().writes(4_u64))
 	}
@@ -531,8 +531,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `315`
 		//  Estimated: `3780`
-		// Minimum execution time: 45_150_000 picoseconds.
-		Weight::from_parts(46_780_000, 3780)
+		// Minimum execution time: 47_403_000 picoseconds.
+		Weight::from_parts(48_707_000, 3780)
 			.saturating_add(T::DbWeight::get().reads(4_u64))
 			.saturating_add(T::DbWeight::get().writes(4_u64))
 	}
@@ -548,8 +548,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `552`
 		//  Estimated: `8967`
-		// Minimum execution time: 34_738_000 picoseconds.
-		Weight::from_parts(35_918_000, 8967)
+		// Minimum execution time: 35_361_000 picoseconds.
+		Weight::from_parts(36_714_000, 8967)
 			.saturating_add(T::DbWeight::get().reads(7_u64))
 			.saturating_add(T::DbWeight::get().writes(6_u64))
 	}
@@ -558,10 +558,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_094_000 picoseconds.
-		Weight::from_parts(10_253_702, 0)
-			// Standard Error: 223
-			.saturating_add(Weight::from_parts(250_757, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_340_000 picoseconds.
+		Weight::from_parts(9_360_237, 0)
+			// Standard Error: 269
+			.saturating_add(Weight::from_parts(249_611, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `Contracts::ContractInfoOf` (r:1600 w:0)
 	/// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`)
@@ -570,10 +570,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `509 + r * (77 ±0)`
 		//  Estimated: `1467 + r * (2552 ±0)`
-		// Minimum execution time: 9_102_000 picoseconds.
-		Weight::from_parts(9_238_000, 1467)
-			// Standard Error: 6_076
-			.saturating_add(Weight::from_parts(3_293_012, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_059_000 picoseconds.
+		Weight::from_parts(9_201_000, 1467)
+			// Standard Error: 5_643
+			.saturating_add(Weight::from_parts(3_343_859, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 2552).saturating_mul(r.into()))
 	}
@@ -584,10 +584,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `517 + r * (170 ±0)`
 		//  Estimated: `1468 + r * (2645 ±0)`
-		// Minimum execution time: 9_255_000 picoseconds.
-		Weight::from_parts(9_406_000, 1468)
-			// Standard Error: 6_826
-			.saturating_add(Weight::from_parts(4_205_039, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_220_000 picoseconds.
+		Weight::from_parts(9_399_000, 1468)
+			// Standard Error: 6_194
+			.saturating_add(Weight::from_parts(4_172_011, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 2645).saturating_mul(r.into()))
 	}
@@ -596,50 +596,50 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_388_000 picoseconds.
-		Weight::from_parts(9_322_209, 0)
-			// Standard Error: 269
-			.saturating_add(Weight::from_parts(358_189, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_707_000 picoseconds.
+		Weight::from_parts(10_100_456, 0)
+			// Standard Error: 234
+			.saturating_add(Weight::from_parts(338_464, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_caller_is_origin(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_300_000 picoseconds.
-		Weight::from_parts(10_268_326, 0)
-			// Standard Error: 72
-			.saturating_add(Weight::from_parts(104_650, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_524_000 picoseconds.
+		Weight::from_parts(10_813_389, 0)
+			// Standard Error: 76
+			.saturating_add(Weight::from_parts(102_535, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_caller_is_root(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_162_000 picoseconds.
-		Weight::from_parts(10_059_984, 0)
-			// Standard Error: 87
-			.saturating_add(Weight::from_parts(87_627, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_799_000 picoseconds.
+		Weight::from_parts(10_886_744, 0)
+			// Standard Error: 75
+			.saturating_add(Weight::from_parts(80_901, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_address(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_193_000 picoseconds.
-		Weight::from_parts(10_160_715, 0)
-			// Standard Error: 152
-			.saturating_add(Weight::from_parts(263_703, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_895_000 picoseconds.
+		Weight::from_parts(10_658_338, 0)
+			// Standard Error: 189
+			.saturating_add(Weight::from_parts(249_694, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_gas_left(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_109_000 picoseconds.
-		Weight::from_parts(9_766_924, 0)
-			// Standard Error: 212
-			.saturating_add(Weight::from_parts(291_694, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_643_000 picoseconds.
+		Weight::from_parts(10_932_126, 0)
+			// Standard Error: 153
+			.saturating_add(Weight::from_parts(280_924, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `System::Account` (r:1 w:0)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`)
@@ -648,10 +648,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `140`
 		//  Estimated: `3599`
-		// Minimum execution time: 9_463_000 picoseconds.
-		Weight::from_parts(9_541_000, 3599)
-			// Standard Error: 3_075
-			.saturating_add(Weight::from_parts(1_606_043, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_548_000 picoseconds.
+		Weight::from_parts(9_737_000, 3599)
+			// Standard Error: 971
+			.saturating_add(Weight::from_parts(1_704_134, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 	}
 	/// The range of component `r` is `[0, 1600]`.
@@ -659,40 +659,40 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_080_000 picoseconds.
-		Weight::from_parts(8_121_924, 0)
-			// Standard Error: 198
-			.saturating_add(Weight::from_parts(247_527, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_172_000 picoseconds.
+		Weight::from_parts(18_255_933, 0)
+			// Standard Error: 540
+			.saturating_add(Weight::from_parts(230_929, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_minimum_balance(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_393_000 picoseconds.
-		Weight::from_parts(9_999_247, 0)
-			// Standard Error: 169
-			.saturating_add(Weight::from_parts(244_563, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_232_000 picoseconds.
+		Weight::from_parts(9_796_584, 0)
+			// Standard Error: 208
+			.saturating_add(Weight::from_parts(239_962, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_block_number(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_236_000 picoseconds.
-		Weight::from_parts(9_561_435, 0)
-			// Standard Error: 195
-			.saturating_add(Weight::from_parts(239_812, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_747_000 picoseconds.
+		Weight::from_parts(8_733_230, 0)
+			// Standard Error: 377
+			.saturating_add(Weight::from_parts(253_801, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_now(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_259_000 picoseconds.
-		Weight::from_parts(10_353_960, 0)
-			// Standard Error: 216
-			.saturating_add(Weight::from_parts(243_754, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_214_000 picoseconds.
+		Weight::from_parts(10_194_153, 0)
+			// Standard Error: 516
+			.saturating_add(Weight::from_parts(247_621, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0)
 	/// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`)
@@ -701,10 +701,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `67`
 		//  Estimated: `1552`
-		// Minimum execution time: 9_145_000 picoseconds.
-		Weight::from_parts(16_524_937, 1552)
-			// Standard Error: 438
-			.saturating_add(Weight::from_parts(666_821, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_022_000 picoseconds.
+		Weight::from_parts(22_051_160, 1552)
+			// Standard Error: 697
+			.saturating_add(Weight::from_parts(709_612, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 	}
 	/// The range of component `r` is `[0, 1600]`.
@@ -712,10 +712,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_179_000 picoseconds.
-		Weight::from_parts(8_893_261, 0)
-			// Standard Error: 215
-			.saturating_add(Weight::from_parts(175_586, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_135_000 picoseconds.
+		Weight::from_parts(10_646_215, 0)
+			// Standard Error: 161
+			.saturating_add(Weight::from_parts(170_336, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `Contracts::MigrationInProgress` (r:1 w:0)
 	/// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`)
@@ -738,10 +738,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `872`
 		//  Estimated: `9287`
-		// Minimum execution time: 259_315_000 picoseconds.
-		Weight::from_parts(137_461_362, 9287)
-			// Standard Error: 18
-			.saturating_add(Weight::from_parts(1_388, 0).saturating_mul(n.into()))
+		// Minimum execution time: 273_896_000 picoseconds.
+		Weight::from_parts(148_309_654, 9287)
+			// Standard Error: 16
+			.saturating_add(Weight::from_parts(1_355, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(11_u64))
 			.saturating_add(T::DbWeight::get().writes(3_u64))
 	}
@@ -750,20 +750,20 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 8_919_000 picoseconds.
-		Weight::from_parts(9_465_187, 0)
-			// Standard Error: 32_481
-			.saturating_add(Weight::from_parts(992_912, 0).saturating_mul(r.into()))
+		// Minimum execution time: 8_906_000 picoseconds.
+		Weight::from_parts(9_264_446, 0)
+			// Standard Error: 19_760
+			.saturating_add(Weight::from_parts(1_256_053, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `n` is `[0, 1048576]`.
 	fn seal_return_per_byte(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_244_000 picoseconds.
-		Weight::from_parts(10_654_989, 0)
+		// Minimum execution time: 10_266_000 picoseconds.
+		Weight::from_parts(10_602_261, 0)
 			// Standard Error: 0
-			.saturating_add(Weight::from_parts(315, 0).saturating_mul(n.into()))
+			.saturating_add(Weight::from_parts(318, 0).saturating_mul(n.into()))
 	}
 	/// Storage: `Contracts::MigrationInProgress` (r:1 w:0)
 	/// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`)
@@ -792,10 +792,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `4805 + r * (2121 ±0)`
 		//  Estimated: `13220 + r * (81321 ±0)`
-		// Minimum execution time: 303_028_000 picoseconds.
-		Weight::from_parts(323_032_397, 13220)
-			// Standard Error: 848_406
-			.saturating_add(Weight::from_parts(242_988_002, 0).saturating_mul(r.into()))
+		// Minimum execution time: 295_922_000 picoseconds.
+		Weight::from_parts(322_472_877, 13220)
+			// Standard Error: 993_812
+			.saturating_add(Weight::from_parts(259_075_422, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads(11_u64))
 			.saturating_add(T::DbWeight::get().reads((36_u64).saturating_mul(r.into())))
 			.saturating_add(T::DbWeight::get().writes(3_u64))
@@ -809,10 +809,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `76`
 		//  Estimated: `1561`
-		// Minimum execution time: 9_227_000 picoseconds.
-		Weight::from_parts(14_055_283, 1561)
-			// Standard Error: 758
-			.saturating_add(Weight::from_parts(1_104_996, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_427_000 picoseconds.
+		Weight::from_parts(12_996_213, 1561)
+			// Standard Error: 845
+			.saturating_add(Weight::from_parts(1_182_642, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 	}
 	/// The range of component `r` is `[0, 1600]`.
@@ -820,10 +820,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_483_000 picoseconds.
-		Weight::from_parts(20_453_059, 0)
-			// Standard Error: 3_271
-			.saturating_add(Weight::from_parts(1_713_468, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_304_000 picoseconds.
+		Weight::from_parts(25_678_842, 0)
+			// Standard Error: 1_855
+			.saturating_add(Weight::from_parts(1_814_511, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `System::EventTopics` (r:4 w:4)
 	/// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`)
@@ -833,12 +833,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `990 + t * (2475 ±0)`
-		// Minimum execution time: 23_517_000 picoseconds.
-		Weight::from_parts(15_543_153, 990)
-			// Standard Error: 13_814
-			.saturating_add(Weight::from_parts(2_357_255, 0).saturating_mul(t.into()))
-			// Standard Error: 3
-			.saturating_add(Weight::from_parts(573, 0).saturating_mul(n.into()))
+		// Minimum execution time: 23_425_000 picoseconds.
+		Weight::from_parts(15_229_010, 990)
+			// Standard Error: 14_380
+			.saturating_add(Weight::from_parts(2_545_653, 0).saturating_mul(t.into()))
+			// Standard Error: 4
+			.saturating_add(Weight::from_parts(594, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into())))
 			.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(t.into())))
 			.saturating_add(Weight::from_parts(0, 2475).saturating_mul(t.into()))
@@ -848,20 +848,20 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 8_448_000 picoseconds.
-		Weight::from_parts(9_845_841, 0)
-			// Standard Error: 58
-			.saturating_add(Weight::from_parts(105_442, 0).saturating_mul(r.into()))
+		// Minimum execution time: 11_117_000 picoseconds.
+		Weight::from_parts(12_887_533, 0)
+			// Standard Error: 83
+			.saturating_add(Weight::from_parts(99_373, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `i` is `[0, 1048576]`.
 	fn seal_debug_message_per_byte(i: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_869_000 picoseconds.
-		Weight::from_parts(11_024_000, 0)
+		// Minimum execution time: 10_982_000 picoseconds.
+		Weight::from_parts(11_176_000, 0)
 			// Standard Error: 8
-			.saturating_add(Weight::from_parts(991, 0).saturating_mul(i.into()))
+			.saturating_add(Weight::from_parts(983, 0).saturating_mul(i.into()))
 	}
 	/// Storage: `Skipped::Metadata` (r:0 w:0)
 	/// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`)
@@ -870,10 +870,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `108 + r * (150 ±0)`
 		//  Estimated: `105 + r * (151 ±0)`
-		// Minimum execution time: 9_119_000 picoseconds.
-		Weight::from_parts(9_270_000, 105)
-			// Standard Error: 8_960
-			.saturating_add(Weight::from_parts(5_215_976, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_150_000 picoseconds.
+		Weight::from_parts(9_269_000, 105)
+			// Standard Error: 8_147
+			.saturating_add(Weight::from_parts(5_339_554, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into()))
@@ -885,10 +885,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `245`
 		//  Estimated: `245`
-		// Minimum execution time: 17_833_000 picoseconds.
-		Weight::from_parts(18_940_114, 245)
-			// Standard Error: 2
-			.saturating_add(Weight::from_parts(316, 0).saturating_mul(n.into()))
+		// Minimum execution time: 19_085_000 picoseconds.
+		Weight::from_parts(20_007_323, 245)
+			// Standard Error: 3
+			.saturating_add(Weight::from_parts(291, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -899,10 +899,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `248 + n * (1 ±0)`
 		//  Estimated: `248 + n * (1 ±0)`
-		// Minimum execution time: 18_428_000 picoseconds.
-		Weight::from_parts(19_372_726, 248)
-			// Standard Error: 2
-			.saturating_add(Weight::from_parts(85, 0).saturating_mul(n.into()))
+		// Minimum execution time: 19_127_000 picoseconds.
+		Weight::from_parts(21_152_987, 248)
+			// Standard Error: 3
+			.saturating_add(Weight::from_parts(42, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
@@ -914,10 +914,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `108 + r * (150 ±0)`
 		//  Estimated: `105 + r * (151 ±0)`
-		// Minimum execution time: 9_335_000 picoseconds.
-		Weight::from_parts(9_459_000, 105)
-			// Standard Error: 9_156
-			.saturating_add(Weight::from_parts(5_166_621, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_264_000 picoseconds.
+		Weight::from_parts(9_449_000, 105)
+			// Standard Error: 8_196
+			.saturating_add(Weight::from_parts(5_325_578, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into()))
@@ -929,10 +929,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `248 + n * (1 ±0)`
 		//  Estimated: `248 + n * (1 ±0)`
-		// Minimum execution time: 18_308_000 picoseconds.
-		Weight::from_parts(19_421_433, 248)
+		// Minimum execution time: 18_489_000 picoseconds.
+		Weight::from_parts(19_916_153, 248)
 			// Standard Error: 2
-			.saturating_add(Weight::from_parts(83, 0).saturating_mul(n.into()))
+			.saturating_add(Weight::from_parts(97, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
@@ -944,10 +944,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `108 + r * (150 ±0)`
 		//  Estimated: `105 + r * (151 ±0)`
-		// Minimum execution time: 9_184_000 picoseconds.
-		Weight::from_parts(9_245_000, 105)
-			// Standard Error: 8_442
-			.saturating_add(Weight::from_parts(4_543_991, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_299_000 picoseconds.
+		Weight::from_parts(9_464_000, 105)
+			// Standard Error: 6_827
+			.saturating_add(Weight::from_parts(4_720_699, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into()))
 	}
@@ -958,10 +958,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `248 + n * (1 ±0)`
 		//  Estimated: `248 + n * (1 ±0)`
-		// Minimum execution time: 17_194_000 picoseconds.
-		Weight::from_parts(19_032_094, 248)
+		// Minimum execution time: 17_981_000 picoseconds.
+		Weight::from_parts(19_802_353, 248)
 			// Standard Error: 3
-			.saturating_add(Weight::from_parts(590, 0).saturating_mul(n.into()))
+			.saturating_add(Weight::from_parts(617, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
 	}
@@ -972,10 +972,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `108 + r * (150 ±0)`
 		//  Estimated: `105 + r * (151 ±0)`
-		// Minimum execution time: 9_380_000 picoseconds.
-		Weight::from_parts(9_501_000, 105)
-			// Standard Error: 7_029
-			.saturating_add(Weight::from_parts(4_406_690, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_891_000 picoseconds.
+		Weight::from_parts(10_046_000, 105)
+			// Standard Error: 6_993
+			.saturating_add(Weight::from_parts(4_601_167, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into()))
 	}
@@ -986,10 +986,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `248 + n * (1 ±0)`
 		//  Estimated: `248 + n * (1 ±0)`
-		// Minimum execution time: 16_400_000 picoseconds.
-		Weight::from_parts(17_993_941, 248)
+		// Minimum execution time: 17_229_000 picoseconds.
+		Weight::from_parts(18_302_733, 248)
 			// Standard Error: 2
-			.saturating_add(Weight::from_parts(68, 0).saturating_mul(n.into()))
+			.saturating_add(Weight::from_parts(112, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
 	}
@@ -1000,10 +1000,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `108 + r * (150 ±0)`
 		//  Estimated: `105 + r * (151 ±0)`
-		// Minimum execution time: 9_109_000 picoseconds.
-		Weight::from_parts(9_265_000, 105)
-			// Standard Error: 8_733
-			.saturating_add(Weight::from_parts(5_218_811, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_323_000 picoseconds.
+		Weight::from_parts(9_462_000, 105)
+			// Standard Error: 8_031
+			.saturating_add(Weight::from_parts(5_433_981, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into()))
@@ -1015,10 +1015,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `248 + n * (1 ±0)`
 		//  Estimated: `248 + n * (1 ±0)`
-		// Minimum execution time: 18_423_000 picoseconds.
-		Weight::from_parts(20_025_132, 248)
+		// Minimum execution time: 18_711_000 picoseconds.
+		Weight::from_parts(20_495_670, 248)
 			// Standard Error: 3
-			.saturating_add(Weight::from_parts(628, 0).saturating_mul(n.into()))
+			.saturating_add(Weight::from_parts(640, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
@@ -1030,10 +1030,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `770`
 		//  Estimated: `4221 + r * (2475 ±0)`
-		// Minimum execution time: 9_043_000 picoseconds.
-		Weight::from_parts(9_176_000, 4221)
-			// Standard Error: 12_901
-			.saturating_add(Weight::from_parts(32_297_438, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_226_000 picoseconds.
+		Weight::from_parts(9_394_000, 4221)
+			// Standard Error: 14_741
+			.saturating_add(Weight::from_parts(34_179_316, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
@@ -1055,10 +1055,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `520 + r * (170 ±0)`
 		//  Estimated: `6463 + r * (2646 ±0)`
-		// Minimum execution time: 9_299_000 picoseconds.
-		Weight::from_parts(9_427_000, 6463)
-			// Standard Error: 101_949
-			.saturating_add(Weight::from_parts(244_143_691, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_455_000 picoseconds.
+		Weight::from_parts(9_671_000, 6463)
+			// Standard Error: 126_080
+			.saturating_add(Weight::from_parts(244_204_040, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads(5_u64))
 			.saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(r.into())))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
@@ -1079,11 +1079,11 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	fn seal_delegate_call(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0 + r * (527 ±0)`
-		//  Estimated: `6447 + r * (2583 ±3)`
-		// Minimum execution time: 9_359_000 picoseconds.
-		Weight::from_parts(9_425_000, 6447)
-			// Standard Error: 193_938
-			.saturating_add(Weight::from_parts(244_904_401, 0).saturating_mul(r.into()))
+		//  Estimated: `6447 + r * (2583 ±10)`
+		// Minimum execution time: 9_274_000 picoseconds.
+		Weight::from_parts(9_437_000, 6447)
+			// Standard Error: 150_832
+			.saturating_add(Weight::from_parts(244_196_269, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into())))
 			.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 2583).saturating_mul(r.into()))
@@ -1106,12 +1106,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `699 + t * (277 ±0)`
 		//  Estimated: `6639 + t * (3458 ±0)`
-		// Minimum execution time: 214_588_000 picoseconds.
-		Weight::from_parts(129_214_481, 6639)
-			// Standard Error: 2_468_090
-			.saturating_add(Weight::from_parts(32_514_739, 0).saturating_mul(t.into()))
+		// Minimum execution time: 214_483_000 picoseconds.
+		Weight::from_parts(122_634_366, 6639)
+			// Standard Error: 2_499_235
+			.saturating_add(Weight::from_parts(41_326_008, 0).saturating_mul(t.into()))
 			// Standard Error: 3
-			.saturating_add(Weight::from_parts(418, 0).saturating_mul(c.into()))
+			.saturating_add(Weight::from_parts(422, 0).saturating_mul(c.into()))
 			.saturating_add(T::DbWeight::get().reads(7_u64))
 			.saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(t.into())))
 			.saturating_add(T::DbWeight::get().writes(4_u64))
@@ -1126,10 +1126,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`)
 	/// Storage: `Contracts::ContractInfoOf` (r:800 w:801)
 	/// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`)
-	/// Storage: `Parameters::Parameters` (r:2 w:0)
-	/// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`)
 	/// Storage: `System::Account` (r:802 w:802)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`)
+	/// Storage: `Parameters::Parameters` (r:2 w:0)
+	/// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`)
 	/// Storage: `System::EventTopics` (r:801 w:801)
 	/// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`)
 	/// The range of component `r` is `[1, 800]`.
@@ -1137,10 +1137,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `1097 + r * (188 ±0)`
 		//  Estimated: `6990 + r * (2664 ±0)`
-		// Minimum execution time: 352_925_000 picoseconds.
-		Weight::from_parts(355_487_000, 6990)
-			// Standard Error: 261_528
-			.saturating_add(Weight::from_parts(337_897_187, 0).saturating_mul(r.into()))
+		// Minimum execution time: 341_569_000 picoseconds.
+		Weight::from_parts(360_574_000, 6990)
+			// Standard Error: 259_746
+			.saturating_add(Weight::from_parts(337_944_674, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads(6_u64))
 			.saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(r.into())))
 			.saturating_add(T::DbWeight::get().writes(4_u64))
@@ -1155,10 +1155,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`)
 	/// Storage: `Contracts::ContractInfoOf` (r:1 w:2)
 	/// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`)
-	/// Storage: `Parameters::Parameters` (r:2 w:0)
-	/// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`)
 	/// Storage: `System::Account` (r:3 w:3)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`)
+	/// Storage: `Parameters::Parameters` (r:2 w:0)
+	/// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`)
 	/// Storage: `System::EventTopics` (r:2 w:2)
 	/// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`)
 	/// The range of component `t` is `[0, 1]`.
@@ -1168,12 +1168,14 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `760 + t * (104 ±0)`
 		//  Estimated: `6719 + t * (2549 ±1)`
-		// Minimum execution time: 1_870_832_000 picoseconds.
-		Weight::from_parts(949_110_245, 6719)
-			// Standard Error: 24
-			.saturating_add(Weight::from_parts(1_084, 0).saturating_mul(i.into()))
-			// Standard Error: 24
-			.saturating_add(Weight::from_parts(1_206, 0).saturating_mul(s.into()))
+		// Minimum execution time: 1_863_119_000 picoseconds.
+		Weight::from_parts(900_189_174, 6719)
+			// Standard Error: 13_040_979
+			.saturating_add(Weight::from_parts(4_056_063, 0).saturating_mul(t.into()))
+			// Standard Error: 20
+			.saturating_add(Weight::from_parts(1_028, 0).saturating_mul(i.into()))
+			// Standard Error: 20
+			.saturating_add(Weight::from_parts(1_173, 0).saturating_mul(s.into()))
 			.saturating_add(T::DbWeight::get().reads(10_u64))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into())))
 			.saturating_add(T::DbWeight::get().writes(7_u64))
@@ -1185,58 +1187,58 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_142_000 picoseconds.
-		Weight::from_parts(9_787_220, 0)
-			// Standard Error: 236
-			.saturating_add(Weight::from_parts(267_264, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_211_000 picoseconds.
+		Weight::from_parts(11_696_412, 0)
+			// Standard Error: 388
+			.saturating_add(Weight::from_parts(265_538, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `n` is `[0, 1048576]`.
 	fn seal_hash_sha2_256_per_byte(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_485_000 picoseconds.
-		Weight::from_parts(1_870_250, 0)
+		// Minimum execution time: 10_296_000 picoseconds.
+		Weight::from_parts(572_494, 0)
 			// Standard Error: 1
-			.saturating_add(Weight::from_parts(1_073, 0).saturating_mul(n.into()))
+			.saturating_add(Weight::from_parts(1_067, 0).saturating_mul(n.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_hash_keccak_256(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_005_000 picoseconds.
-		Weight::from_parts(8_943_937, 0)
-			// Standard Error: 1_385
-			.saturating_add(Weight::from_parts(665_970, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_177_000 picoseconds.
+		Weight::from_parts(8_620_481, 0)
+			// Standard Error: 249
+			.saturating_add(Weight::from_parts(674_502, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `n` is `[0, 1048576]`.
 	fn seal_hash_keccak_256_per_byte(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_965_000 picoseconds.
-		Weight::from_parts(11_749_746, 0)
-			// Standard Error: 6
-			.saturating_add(Weight::from_parts(3_330, 0).saturating_mul(n.into()))
+		// Minimum execution time: 11_240_000 picoseconds.
+		Weight::from_parts(8_696_186, 0)
+			// Standard Error: 0
+			.saturating_add(Weight::from_parts(3_328, 0).saturating_mul(n.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_hash_blake2_256(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_400_000 picoseconds.
-		Weight::from_parts(13_857_546, 0)
-			// Standard Error: 246
-			.saturating_add(Weight::from_parts(326_483, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_889_000 picoseconds.
+		Weight::from_parts(16_103_170, 0)
+			// Standard Error: 343
+			.saturating_add(Weight::from_parts(328_939, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `n` is `[0, 1048576]`.
 	fn seal_hash_blake2_256_per_byte(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_064_000 picoseconds.
-		Weight::from_parts(1_885_873, 0)
+		// Minimum execution time: 10_405_000 picoseconds.
+		Weight::from_parts(2_264_024, 0)
 			// Standard Error: 0
 			.saturating_add(Weight::from_parts(1_196, 0).saturating_mul(n.into()))
 	}
@@ -1245,60 +1247,60 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_068_000 picoseconds.
-		Weight::from_parts(17_169_362, 0)
-			// Standard Error: 1_580
-			.saturating_add(Weight::from_parts(330_195, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_215_000 picoseconds.
+		Weight::from_parts(10_505_632, 0)
+			// Standard Error: 240
+			.saturating_add(Weight::from_parts(324_854, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `n` is `[0, 1048576]`.
 	fn seal_hash_blake2_128_per_byte(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_169_000 picoseconds.
-		Weight::from_parts(2_159_277, 0)
-			// Standard Error: 0
-			.saturating_add(Weight::from_parts(1_200, 0).saturating_mul(n.into()))
+		// Minimum execution time: 10_440_000 picoseconds.
+		Weight::from_parts(2_575_889, 0)
+			// Standard Error: 1
+			.saturating_add(Weight::from_parts(1_199, 0).saturating_mul(n.into()))
 	}
 	/// The range of component `n` is `[0, 125697]`.
 	fn seal_sr25519_verify_per_byte(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 53_863_000 picoseconds.
-		Weight::from_parts(54_902_157, 0)
-			// Standard Error: 9
-			.saturating_add(Weight::from_parts(4_588, 0).saturating_mul(n.into()))
+		// Minimum execution time: 55_119_000 picoseconds.
+		Weight::from_parts(56_732_248, 0)
+			// Standard Error: 8
+			.saturating_add(Weight::from_parts(4_639, 0).saturating_mul(n.into()))
 	}
 	/// The range of component `r` is `[0, 160]`.
 	fn seal_sr25519_verify(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_107_000 picoseconds.
-		Weight::from_parts(24_115_247, 0)
-			// Standard Error: 7_427
-			.saturating_add(Weight::from_parts(41_116_827, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_176_000 picoseconds.
+		Weight::from_parts(9_861_102, 0)
+			// Standard Error: 6_029
+			.saturating_add(Weight::from_parts(45_948_571, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 160]`.
 	fn seal_ecdsa_recover(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_404_000 picoseconds.
-		Weight::from_parts(31_763_334, 0)
-			// Standard Error: 9_833
-			.saturating_add(Weight::from_parts(45_529_880, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_293_000 picoseconds.
+		Weight::from_parts(28_785_765, 0)
+			// Standard Error: 9_160
+			.saturating_add(Weight::from_parts(45_566_150, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 160]`.
 	fn seal_ecdsa_to_eth_address(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 11_409_000 picoseconds.
-		Weight::from_parts(15_072_835, 0)
-			// Standard Error: 4_591
-			.saturating_add(Weight::from_parts(11_619_283, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_206_000 picoseconds.
+		Weight::from_parts(12_420_664, 0)
+			// Standard Error: 3_489
+			.saturating_add(Weight::from_parts(11_628_989, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `Contracts::CodeInfoOf` (r:1536 w:1536)
 	/// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`)
@@ -1312,11 +1314,11 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	fn seal_set_code_hash(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0 + r * (926 ±0)`
-		//  Estimated: `8969 + r * (3047 ±10)`
-		// Minimum execution time: 9_269_000 picoseconds.
-		Weight::from_parts(9_372_000, 8969)
-			// Standard Error: 61_354
-			.saturating_add(Weight::from_parts(26_280_409, 0).saturating_mul(r.into()))
+		//  Estimated: `8969 + r * (3047 ±7)`
+		// Minimum execution time: 9_219_000 picoseconds.
+		Weight::from_parts(9_385_000, 8969)
+			// Standard Error: 45_562
+			.saturating_add(Weight::from_parts(26_360_661, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into())))
 			.saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 3047).saturating_mul(r.into()))
@@ -1328,10 +1330,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `274 + r * (78 ±0)`
 		//  Estimated: `1265 + r * (2553 ±0)`
-		// Minimum execution time: 9_103_000 picoseconds.
-		Weight::from_parts(14_404_626, 1265)
-			// Standard Error: 9_343
-			.saturating_add(Weight::from_parts(5_154_949, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_355_000 picoseconds.
+		Weight::from_parts(15_071_309, 1265)
+			// Standard Error: 9_722
+			.saturating_add(Weight::from_parts(5_328_717, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 2553).saturating_mul(r.into()))
@@ -1343,10 +1345,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `275 + r * (78 ±0)`
 		//  Estimated: `990 + r * (2568 ±0)`
-		// Minimum execution time: 9_219_000 picoseconds.
-		Weight::from_parts(14_085_456, 990)
-			// Standard Error: 11_206
-			.saturating_add(Weight::from_parts(4_422_122, 0).saturating_mul(r.into()))
+		// Minimum execution time: 8_979_000 picoseconds.
+		Weight::from_parts(14_362_224, 990)
+			// Standard Error: 9_137
+			.saturating_add(Weight::from_parts(4_488_748, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 2568).saturating_mul(r.into()))
@@ -1372,10 +1374,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `861 + r * (3 ±0)`
 		//  Estimated: `9282 + r * (3 ±0)`
-		// Minimum execution time: 269_333_000 picoseconds.
-		Weight::from_parts(286_922_618, 9282)
-			// Standard Error: 443
-			.saturating_add(Weight::from_parts(168_869, 0).saturating_mul(r.into()))
+		// Minimum execution time: 269_704_000 picoseconds.
+		Weight::from_parts(289_916_035, 9282)
+			// Standard Error: 408
+			.saturating_add(Weight::from_parts(166_040, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads(11_u64))
 			.saturating_add(T::DbWeight::get().writes(3_u64))
 			.saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into()))
@@ -1385,10 +1387,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_328_000 picoseconds.
-		Weight::from_parts(14_019_583, 0)
-			// Standard Error: 171
-			.saturating_add(Weight::from_parts(88_751, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_361_000 picoseconds.
+		Weight::from_parts(11_633_836, 0)
+			// Standard Error: 86
+			.saturating_add(Weight::from_parts(83_083, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `Contracts::Nonce` (r:1 w:0)
 	/// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`)
@@ -1397,10 +1399,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `219`
 		//  Estimated: `1704`
-		// Minimum execution time: 9_267_000 picoseconds.
-		Weight::from_parts(15_304_284, 1704)
-			// Standard Error: 1_219
-			.saturating_add(Weight::from_parts(74_696, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_133_000 picoseconds.
+		Weight::from_parts(13_259_836, 1704)
+			// Standard Error: 121
+			.saturating_add(Weight::from_parts(76_878, 0).saturating_mul(r.into()))
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 	}
 	/// The range of component `r` is `[0, 5000]`.
@@ -1408,10 +1410,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 911_000 picoseconds.
-		Weight::from_parts(449_666, 0)
-			// Standard Error: 26
-			.saturating_add(Weight::from_parts(14_797, 0).saturating_mul(r.into()))
+		// Minimum execution time: 851_000 picoseconds.
+		Weight::from_parts(587_883, 0)
+			// Standard Error: 16
+			.saturating_add(Weight::from_parts(14_912, 0).saturating_mul(r.into()))
 	}
 }
 
@@ -1423,8 +1425,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `142`
 		//  Estimated: `1627`
-		// Minimum execution time: 2_047_000 picoseconds.
-		Weight::from_parts(2_116_000, 1627)
+		// Minimum execution time: 2_149_000 picoseconds.
+		Weight::from_parts(2_274_000, 1627)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 	}
 	/// Storage: `Skipped::Metadata` (r:0 w:0)
@@ -1434,10 +1436,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `452 + k * (69 ±0)`
 		//  Estimated: `442 + k * (70 ±0)`
-		// Minimum execution time: 12_474_000 picoseconds.
-		Weight::from_parts(12_767_000, 442)
-			// Standard Error: 1_081
-			.saturating_add(Weight::from_parts(1_187_278, 0).saturating_mul(k.into()))
+		// Minimum execution time: 12_863_000 picoseconds.
+		Weight::from_parts(13_188_000, 442)
+			// Standard Error: 1_053
+			.saturating_add(Weight::from_parts(1_105_325, 0).saturating_mul(k.into()))
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into())))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
@@ -1451,10 +1453,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `211 + c * (1 ±0)`
 		//  Estimated: `6149 + c * (1 ±0)`
-		// Minimum execution time: 8_307_000 picoseconds.
-		Weight::from_parts(8_939_322, 6149)
+		// Minimum execution time: 8_432_000 picoseconds.
+		Weight::from_parts(9_203_290, 6149)
 			// Standard Error: 1
-			.saturating_add(Weight::from_parts(1_190, 0).saturating_mul(c.into()))
+			.saturating_add(Weight::from_parts(1_186, 0).saturating_mul(c.into()))
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into()))
@@ -1467,8 +1469,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `510`
 		//  Estimated: `6450`
-		// Minimum execution time: 16_915_000 picoseconds.
-		Weight::from_parts(17_638_000, 6450)
+		// Minimum execution time: 17_177_000 picoseconds.
+		Weight::from_parts(17_663_000, 6450)
 			.saturating_add(RocksDbWeight::get().reads(3_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -1481,10 +1483,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `171 + k * (1 ±0)`
 		//  Estimated: `3635 + k * (1 ±0)`
-		// Minimum execution time: 3_607_000 picoseconds.
-		Weight::from_parts(1_979_323, 3635)
-			// Standard Error: 1_018
-			.saturating_add(Weight::from_parts(1_196_162, 0).saturating_mul(k.into()))
+		// Minimum execution time: 3_636_000 picoseconds.
+		Weight::from_parts(3_774_000, 3635)
+			// Standard Error: 542
+			.saturating_add(Weight::from_parts(1_260_058, 0).saturating_mul(k.into()))
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 			.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(k.into())))
@@ -1505,10 +1507,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `328 + c * (1 ±0)`
 		//  Estimated: `6266 + c * (1 ±0)`
-		// Minimum execution time: 21_056_000 picoseconds.
-		Weight::from_parts(21_633_895, 6266)
+		// Minimum execution time: 21_585_000 picoseconds.
+		Weight::from_parts(22_069_944, 6266)
 			// Standard Error: 1
-			.saturating_add(Weight::from_parts(390, 0).saturating_mul(c.into()))
+			.saturating_add(Weight::from_parts(404, 0).saturating_mul(c.into()))
 			.saturating_add(RocksDbWeight::get().reads(6_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into()))
@@ -1519,8 +1521,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `440`
 		//  Estimated: `6380`
-		// Minimum execution time: 12_860_000 picoseconds.
-		Weight::from_parts(13_525_000, 6380)
+		// Minimum execution time: 13_283_000 picoseconds.
+		Weight::from_parts(14_015_000, 6380)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -1534,8 +1536,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `352`
 		//  Estimated: `6292`
-		// Minimum execution time: 46_926_000 picoseconds.
-		Weight::from_parts(47_828_000, 6292)
+		// Minimum execution time: 48_022_000 picoseconds.
+		Weight::from_parts(49_627_000, 6292)
 			.saturating_add(RocksDbWeight::get().reads(4_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -1547,8 +1549,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `594`
 		//  Estimated: `6534`
-		// Minimum execution time: 55_081_000 picoseconds.
-		Weight::from_parts(56_899_000, 6534)
+		// Minimum execution time: 58_374_000 picoseconds.
+		Weight::from_parts(59_615_000, 6534)
 			.saturating_add(RocksDbWeight::get().reads(4_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
@@ -1558,8 +1560,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `409`
 		//  Estimated: `6349`
-		// Minimum execution time: 12_595_000 picoseconds.
-		Weight::from_parts(13_059_000, 6349)
+		// Minimum execution time: 12_559_000 picoseconds.
+		Weight::from_parts(12_947_000, 6349)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -1570,7 +1572,7 @@ impl WeightInfo for () {
 		//  Measured:  `142`
 		//  Estimated: `1627`
 		// Minimum execution time: 2_480_000 picoseconds.
-		Weight::from_parts(2_663_000, 1627)
+		Weight::from_parts(2_680_000, 1627)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -1582,8 +1584,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `166`
 		//  Estimated: `3631`
-		// Minimum execution time: 12_115_000 picoseconds.
-		Weight::from_parts(12_506_000, 3631)
+		// Minimum execution time: 12_625_000 picoseconds.
+		Weight::from_parts(13_094_000, 3631)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
@@ -1593,8 +1595,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `142`
 		//  Estimated: `3607`
-		// Minimum execution time: 4_757_000 picoseconds.
-		Weight::from_parts(5_082_000, 3607)
+		// Minimum execution time: 4_836_000 picoseconds.
+		Weight::from_parts(5_182_000, 3607)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 	}
 	/// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0)
@@ -1605,8 +1607,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `167`
 		//  Estimated: `3632`
-		// Minimum execution time: 6_017_000 picoseconds.
-		Weight::from_parts(6_421_000, 3632)
+		// Minimum execution time: 6_319_000 picoseconds.
+		Weight::from_parts(6_582_000, 3632)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 	}
 	/// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0)
@@ -1617,8 +1619,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `142`
 		//  Estimated: `3607`
-		// Minimum execution time: 6_238_000 picoseconds.
-		Weight::from_parts(6_587_000, 3607)
+		// Minimum execution time: 6_532_000 picoseconds.
+		Weight::from_parts(6_909_000, 3607)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -1643,10 +1645,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `804 + c * (1 ±0)`
 		//  Estimated: `9217 + c * (1 ±0)`
-		// Minimum execution time: 288_968_000 picoseconds.
-		Weight::from_parts(267_291_922, 9217)
-			// Standard Error: 78
-			.saturating_add(Weight::from_parts(34_879, 0).saturating_mul(c.into()))
+		// Minimum execution time: 305_778_000 picoseconds.
+		Weight::from_parts(282_321_249, 9217)
+			// Standard Error: 72
+			.saturating_add(Weight::from_parts(33_456, 0).saturating_mul(c.into()))
 			.saturating_add(RocksDbWeight::get().reads(11_u64))
 			.saturating_add(RocksDbWeight::get().writes(4_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into()))
@@ -1678,14 +1680,14 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `326`
 		//  Estimated: `8740`
-		// Minimum execution time: 3_948_426_000 picoseconds.
-		Weight::from_parts(440_017_623, 8740)
-			// Standard Error: 555
-			.saturating_add(Weight::from_parts(71_483, 0).saturating_mul(c.into()))
-			// Standard Error: 66
-			.saturating_add(Weight::from_parts(1_831, 0).saturating_mul(i.into()))
-			// Standard Error: 66
-			.saturating_add(Weight::from_parts(1_694, 0).saturating_mul(s.into()))
+		// Minimum execution time: 3_810_809_000 picoseconds.
+		Weight::from_parts(739_511_598, 8740)
+			// Standard Error: 140
+			.saturating_add(Weight::from_parts(67_574, 0).saturating_mul(c.into()))
+			// Standard Error: 16
+			.saturating_add(Weight::from_parts(1_488, 0).saturating_mul(i.into()))
+			// Standard Error: 16
+			.saturating_add(Weight::from_parts(1_537, 0).saturating_mul(s.into()))
 			.saturating_add(RocksDbWeight::get().reads(14_u64))
 			.saturating_add(RocksDbWeight::get().writes(10_u64))
 	}
@@ -1715,12 +1717,12 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `563`
 		//  Estimated: `8982`
-		// Minimum execution time: 2_011_037_000 picoseconds.
-		Weight::from_parts(2_047_025_000, 8982)
-			// Standard Error: 28
-			.saturating_add(Weight::from_parts(968, 0).saturating_mul(i.into()))
-			// Standard Error: 28
-			.saturating_add(Weight::from_parts(780, 0).saturating_mul(s.into()))
+		// Minimum execution time: 1_986_789_000 picoseconds.
+		Weight::from_parts(2_017_466_000, 8982)
+			// Standard Error: 26
+			.saturating_add(Weight::from_parts(827, 0).saturating_mul(i.into()))
+			// Standard Error: 26
+			.saturating_add(Weight::from_parts(781, 0).saturating_mul(s.into()))
 			.saturating_add(RocksDbWeight::get().reads(13_u64))
 			.saturating_add(RocksDbWeight::get().writes(7_u64))
 	}
@@ -1744,8 +1746,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `829`
 		//  Estimated: `9244`
-		// Minimum execution time: 202_190_000 picoseconds.
-		Weight::from_parts(209_378_000, 9244)
+		// Minimum execution time: 210_724_000 picoseconds.
+		Weight::from_parts(218_608_000, 9244)
 			.saturating_add(RocksDbWeight::get().reads(11_u64))
 			.saturating_add(RocksDbWeight::get().writes(4_u64))
 	}
@@ -1766,10 +1768,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `145`
 		//  Estimated: `6085`
-		// Minimum execution time: 271_161_000 picoseconds.
-		Weight::from_parts(279_218_977, 6085)
-			// Standard Error: 80
-			.saturating_add(Weight::from_parts(33_973, 0).saturating_mul(c.into()))
+		// Minimum execution time: 271_259_000 picoseconds.
+		Weight::from_parts(298_852_854, 6085)
+			// Standard Error: 65
+			.saturating_add(Weight::from_parts(33_547, 0).saturating_mul(c.into()))
 			.saturating_add(RocksDbWeight::get().reads(6_u64))
 			.saturating_add(RocksDbWeight::get().writes(4_u64))
 	}
@@ -1790,10 +1792,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `145`
 		//  Estimated: `6085`
-		// Minimum execution time: 273_684_000 picoseconds.
-		Weight::from_parts(284_348_722, 6085)
-			// Standard Error: 79
-			.saturating_add(Weight::from_parts(34_205, 0).saturating_mul(c.into()))
+		// Minimum execution time: 278_167_000 picoseconds.
+		Weight::from_parts(311_888_941, 6085)
+			// Standard Error: 58
+			.saturating_add(Weight::from_parts(33_595, 0).saturating_mul(c.into()))
 			.saturating_add(RocksDbWeight::get().reads(6_u64))
 			.saturating_add(RocksDbWeight::get().writes(4_u64))
 	}
@@ -1811,8 +1813,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `315`
 		//  Estimated: `3780`
-		// Minimum execution time: 45_150_000 picoseconds.
-		Weight::from_parts(46_780_000, 3780)
+		// Minimum execution time: 47_403_000 picoseconds.
+		Weight::from_parts(48_707_000, 3780)
 			.saturating_add(RocksDbWeight::get().reads(4_u64))
 			.saturating_add(RocksDbWeight::get().writes(4_u64))
 	}
@@ -1828,8 +1830,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `552`
 		//  Estimated: `8967`
-		// Minimum execution time: 34_738_000 picoseconds.
-		Weight::from_parts(35_918_000, 8967)
+		// Minimum execution time: 35_361_000 picoseconds.
+		Weight::from_parts(36_714_000, 8967)
 			.saturating_add(RocksDbWeight::get().reads(7_u64))
 			.saturating_add(RocksDbWeight::get().writes(6_u64))
 	}
@@ -1838,10 +1840,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_094_000 picoseconds.
-		Weight::from_parts(10_253_702, 0)
-			// Standard Error: 223
-			.saturating_add(Weight::from_parts(250_757, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_340_000 picoseconds.
+		Weight::from_parts(9_360_237, 0)
+			// Standard Error: 269
+			.saturating_add(Weight::from_parts(249_611, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `Contracts::ContractInfoOf` (r:1600 w:0)
 	/// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`)
@@ -1850,10 +1852,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `509 + r * (77 ±0)`
 		//  Estimated: `1467 + r * (2552 ±0)`
-		// Minimum execution time: 9_102_000 picoseconds.
-		Weight::from_parts(9_238_000, 1467)
-			// Standard Error: 6_076
-			.saturating_add(Weight::from_parts(3_293_012, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_059_000 picoseconds.
+		Weight::from_parts(9_201_000, 1467)
+			// Standard Error: 5_643
+			.saturating_add(Weight::from_parts(3_343_859, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 2552).saturating_mul(r.into()))
 	}
@@ -1864,10 +1866,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `517 + r * (170 ±0)`
 		//  Estimated: `1468 + r * (2645 ±0)`
-		// Minimum execution time: 9_255_000 picoseconds.
-		Weight::from_parts(9_406_000, 1468)
-			// Standard Error: 6_826
-			.saturating_add(Weight::from_parts(4_205_039, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_220_000 picoseconds.
+		Weight::from_parts(9_399_000, 1468)
+			// Standard Error: 6_194
+			.saturating_add(Weight::from_parts(4_172_011, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 2645).saturating_mul(r.into()))
 	}
@@ -1876,50 +1878,50 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_388_000 picoseconds.
-		Weight::from_parts(9_322_209, 0)
-			// Standard Error: 269
-			.saturating_add(Weight::from_parts(358_189, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_707_000 picoseconds.
+		Weight::from_parts(10_100_456, 0)
+			// Standard Error: 234
+			.saturating_add(Weight::from_parts(338_464, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_caller_is_origin(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_300_000 picoseconds.
-		Weight::from_parts(10_268_326, 0)
-			// Standard Error: 72
-			.saturating_add(Weight::from_parts(104_650, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_524_000 picoseconds.
+		Weight::from_parts(10_813_389, 0)
+			// Standard Error: 76
+			.saturating_add(Weight::from_parts(102_535, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_caller_is_root(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_162_000 picoseconds.
-		Weight::from_parts(10_059_984, 0)
-			// Standard Error: 87
-			.saturating_add(Weight::from_parts(87_627, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_799_000 picoseconds.
+		Weight::from_parts(10_886_744, 0)
+			// Standard Error: 75
+			.saturating_add(Weight::from_parts(80_901, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_address(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_193_000 picoseconds.
-		Weight::from_parts(10_160_715, 0)
-			// Standard Error: 152
-			.saturating_add(Weight::from_parts(263_703, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_895_000 picoseconds.
+		Weight::from_parts(10_658_338, 0)
+			// Standard Error: 189
+			.saturating_add(Weight::from_parts(249_694, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_gas_left(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_109_000 picoseconds.
-		Weight::from_parts(9_766_924, 0)
-			// Standard Error: 212
-			.saturating_add(Weight::from_parts(291_694, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_643_000 picoseconds.
+		Weight::from_parts(10_932_126, 0)
+			// Standard Error: 153
+			.saturating_add(Weight::from_parts(280_924, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `System::Account` (r:1 w:0)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`)
@@ -1928,10 +1930,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `140`
 		//  Estimated: `3599`
-		// Minimum execution time: 9_463_000 picoseconds.
-		Weight::from_parts(9_541_000, 3599)
-			// Standard Error: 3_075
-			.saturating_add(Weight::from_parts(1_606_043, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_548_000 picoseconds.
+		Weight::from_parts(9_737_000, 3599)
+			// Standard Error: 971
+			.saturating_add(Weight::from_parts(1_704_134, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 	}
 	/// The range of component `r` is `[0, 1600]`.
@@ -1939,40 +1941,40 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_080_000 picoseconds.
-		Weight::from_parts(8_121_924, 0)
-			// Standard Error: 198
-			.saturating_add(Weight::from_parts(247_527, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_172_000 picoseconds.
+		Weight::from_parts(18_255_933, 0)
+			// Standard Error: 540
+			.saturating_add(Weight::from_parts(230_929, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_minimum_balance(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_393_000 picoseconds.
-		Weight::from_parts(9_999_247, 0)
-			// Standard Error: 169
-			.saturating_add(Weight::from_parts(244_563, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_232_000 picoseconds.
+		Weight::from_parts(9_796_584, 0)
+			// Standard Error: 208
+			.saturating_add(Weight::from_parts(239_962, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_block_number(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_236_000 picoseconds.
-		Weight::from_parts(9_561_435, 0)
-			// Standard Error: 195
-			.saturating_add(Weight::from_parts(239_812, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_747_000 picoseconds.
+		Weight::from_parts(8_733_230, 0)
+			// Standard Error: 377
+			.saturating_add(Weight::from_parts(253_801, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_now(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_259_000 picoseconds.
-		Weight::from_parts(10_353_960, 0)
-			// Standard Error: 216
-			.saturating_add(Weight::from_parts(243_754, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_214_000 picoseconds.
+		Weight::from_parts(10_194_153, 0)
+			// Standard Error: 516
+			.saturating_add(Weight::from_parts(247_621, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0)
 	/// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`)
@@ -1981,10 +1983,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `67`
 		//  Estimated: `1552`
-		// Minimum execution time: 9_145_000 picoseconds.
-		Weight::from_parts(16_524_937, 1552)
-			// Standard Error: 438
-			.saturating_add(Weight::from_parts(666_821, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_022_000 picoseconds.
+		Weight::from_parts(22_051_160, 1552)
+			// Standard Error: 697
+			.saturating_add(Weight::from_parts(709_612, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 	}
 	/// The range of component `r` is `[0, 1600]`.
@@ -1992,10 +1994,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_179_000 picoseconds.
-		Weight::from_parts(8_893_261, 0)
-			// Standard Error: 215
-			.saturating_add(Weight::from_parts(175_586, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_135_000 picoseconds.
+		Weight::from_parts(10_646_215, 0)
+			// Standard Error: 161
+			.saturating_add(Weight::from_parts(170_336, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `Contracts::MigrationInProgress` (r:1 w:0)
 	/// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`)
@@ -2018,10 +2020,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `872`
 		//  Estimated: `9287`
-		// Minimum execution time: 259_315_000 picoseconds.
-		Weight::from_parts(137_461_362, 9287)
-			// Standard Error: 18
-			.saturating_add(Weight::from_parts(1_388, 0).saturating_mul(n.into()))
+		// Minimum execution time: 273_896_000 picoseconds.
+		Weight::from_parts(148_309_654, 9287)
+			// Standard Error: 16
+			.saturating_add(Weight::from_parts(1_355, 0).saturating_mul(n.into()))
 			.saturating_add(RocksDbWeight::get().reads(11_u64))
 			.saturating_add(RocksDbWeight::get().writes(3_u64))
 	}
@@ -2030,20 +2032,20 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 8_919_000 picoseconds.
-		Weight::from_parts(9_465_187, 0)
-			// Standard Error: 32_481
-			.saturating_add(Weight::from_parts(992_912, 0).saturating_mul(r.into()))
+		// Minimum execution time: 8_906_000 picoseconds.
+		Weight::from_parts(9_264_446, 0)
+			// Standard Error: 19_760
+			.saturating_add(Weight::from_parts(1_256_053, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `n` is `[0, 1048576]`.
 	fn seal_return_per_byte(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_244_000 picoseconds.
-		Weight::from_parts(10_654_989, 0)
+		// Minimum execution time: 10_266_000 picoseconds.
+		Weight::from_parts(10_602_261, 0)
 			// Standard Error: 0
-			.saturating_add(Weight::from_parts(315, 0).saturating_mul(n.into()))
+			.saturating_add(Weight::from_parts(318, 0).saturating_mul(n.into()))
 	}
 	/// Storage: `Contracts::MigrationInProgress` (r:1 w:0)
 	/// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`)
@@ -2072,10 +2074,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `4805 + r * (2121 ±0)`
 		//  Estimated: `13220 + r * (81321 ±0)`
-		// Minimum execution time: 303_028_000 picoseconds.
-		Weight::from_parts(323_032_397, 13220)
-			// Standard Error: 848_406
-			.saturating_add(Weight::from_parts(242_988_002, 0).saturating_mul(r.into()))
+		// Minimum execution time: 295_922_000 picoseconds.
+		Weight::from_parts(322_472_877, 13220)
+			// Standard Error: 993_812
+			.saturating_add(Weight::from_parts(259_075_422, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads(11_u64))
 			.saturating_add(RocksDbWeight::get().reads((36_u64).saturating_mul(r.into())))
 			.saturating_add(RocksDbWeight::get().writes(3_u64))
@@ -2089,10 +2091,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `76`
 		//  Estimated: `1561`
-		// Minimum execution time: 9_227_000 picoseconds.
-		Weight::from_parts(14_055_283, 1561)
-			// Standard Error: 758
-			.saturating_add(Weight::from_parts(1_104_996, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_427_000 picoseconds.
+		Weight::from_parts(12_996_213, 1561)
+			// Standard Error: 845
+			.saturating_add(Weight::from_parts(1_182_642, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 	}
 	/// The range of component `r` is `[0, 1600]`.
@@ -2100,10 +2102,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_483_000 picoseconds.
-		Weight::from_parts(20_453_059, 0)
-			// Standard Error: 3_271
-			.saturating_add(Weight::from_parts(1_713_468, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_304_000 picoseconds.
+		Weight::from_parts(25_678_842, 0)
+			// Standard Error: 1_855
+			.saturating_add(Weight::from_parts(1_814_511, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `System::EventTopics` (r:4 w:4)
 	/// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`)
@@ -2113,12 +2115,12 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `990 + t * (2475 ±0)`
-		// Minimum execution time: 23_517_000 picoseconds.
-		Weight::from_parts(15_543_153, 990)
-			// Standard Error: 13_814
-			.saturating_add(Weight::from_parts(2_357_255, 0).saturating_mul(t.into()))
-			// Standard Error: 3
-			.saturating_add(Weight::from_parts(573, 0).saturating_mul(n.into()))
+		// Minimum execution time: 23_425_000 picoseconds.
+		Weight::from_parts(15_229_010, 990)
+			// Standard Error: 14_380
+			.saturating_add(Weight::from_parts(2_545_653, 0).saturating_mul(t.into()))
+			// Standard Error: 4
+			.saturating_add(Weight::from_parts(594, 0).saturating_mul(n.into()))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into())))
 			.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(t.into())))
 			.saturating_add(Weight::from_parts(0, 2475).saturating_mul(t.into()))
@@ -2128,20 +2130,20 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 8_448_000 picoseconds.
-		Weight::from_parts(9_845_841, 0)
-			// Standard Error: 58
-			.saturating_add(Weight::from_parts(105_442, 0).saturating_mul(r.into()))
+		// Minimum execution time: 11_117_000 picoseconds.
+		Weight::from_parts(12_887_533, 0)
+			// Standard Error: 83
+			.saturating_add(Weight::from_parts(99_373, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `i` is `[0, 1048576]`.
 	fn seal_debug_message_per_byte(i: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_869_000 picoseconds.
-		Weight::from_parts(11_024_000, 0)
+		// Minimum execution time: 10_982_000 picoseconds.
+		Weight::from_parts(11_176_000, 0)
 			// Standard Error: 8
-			.saturating_add(Weight::from_parts(991, 0).saturating_mul(i.into()))
+			.saturating_add(Weight::from_parts(983, 0).saturating_mul(i.into()))
 	}
 	/// Storage: `Skipped::Metadata` (r:0 w:0)
 	/// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`)
@@ -2150,10 +2152,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `108 + r * (150 ±0)`
 		//  Estimated: `105 + r * (151 ±0)`
-		// Minimum execution time: 9_119_000 picoseconds.
-		Weight::from_parts(9_270_000, 105)
-			// Standard Error: 8_960
-			.saturating_add(Weight::from_parts(5_215_976, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_150_000 picoseconds.
+		Weight::from_parts(9_269_000, 105)
+			// Standard Error: 8_147
+			.saturating_add(Weight::from_parts(5_339_554, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into()))
@@ -2165,10 +2167,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `245`
 		//  Estimated: `245`
-		// Minimum execution time: 17_833_000 picoseconds.
-		Weight::from_parts(18_940_114, 245)
-			// Standard Error: 2
-			.saturating_add(Weight::from_parts(316, 0).saturating_mul(n.into()))
+		// Minimum execution time: 19_085_000 picoseconds.
+		Weight::from_parts(20_007_323, 245)
+			// Standard Error: 3
+			.saturating_add(Weight::from_parts(291, 0).saturating_mul(n.into()))
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -2179,10 +2181,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `248 + n * (1 ±0)`
 		//  Estimated: `248 + n * (1 ±0)`
-		// Minimum execution time: 18_428_000 picoseconds.
-		Weight::from_parts(19_372_726, 248)
-			// Standard Error: 2
-			.saturating_add(Weight::from_parts(85, 0).saturating_mul(n.into()))
+		// Minimum execution time: 19_127_000 picoseconds.
+		Weight::from_parts(21_152_987, 248)
+			// Standard Error: 3
+			.saturating_add(Weight::from_parts(42, 0).saturating_mul(n.into()))
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
@@ -2194,10 +2196,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `108 + r * (150 ±0)`
 		//  Estimated: `105 + r * (151 ±0)`
-		// Minimum execution time: 9_335_000 picoseconds.
-		Weight::from_parts(9_459_000, 105)
-			// Standard Error: 9_156
-			.saturating_add(Weight::from_parts(5_166_621, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_264_000 picoseconds.
+		Weight::from_parts(9_449_000, 105)
+			// Standard Error: 8_196
+			.saturating_add(Weight::from_parts(5_325_578, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into()))
@@ -2209,10 +2211,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `248 + n * (1 ±0)`
 		//  Estimated: `248 + n * (1 ±0)`
-		// Minimum execution time: 18_308_000 picoseconds.
-		Weight::from_parts(19_421_433, 248)
+		// Minimum execution time: 18_489_000 picoseconds.
+		Weight::from_parts(19_916_153, 248)
 			// Standard Error: 2
-			.saturating_add(Weight::from_parts(83, 0).saturating_mul(n.into()))
+			.saturating_add(Weight::from_parts(97, 0).saturating_mul(n.into()))
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
@@ -2224,10 +2226,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `108 + r * (150 ±0)`
 		//  Estimated: `105 + r * (151 ±0)`
-		// Minimum execution time: 9_184_000 picoseconds.
-		Weight::from_parts(9_245_000, 105)
-			// Standard Error: 8_442
-			.saturating_add(Weight::from_parts(4_543_991, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_299_000 picoseconds.
+		Weight::from_parts(9_464_000, 105)
+			// Standard Error: 6_827
+			.saturating_add(Weight::from_parts(4_720_699, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into()))
 	}
@@ -2238,10 +2240,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `248 + n * (1 ±0)`
 		//  Estimated: `248 + n * (1 ±0)`
-		// Minimum execution time: 17_194_000 picoseconds.
-		Weight::from_parts(19_032_094, 248)
+		// Minimum execution time: 17_981_000 picoseconds.
+		Weight::from_parts(19_802_353, 248)
 			// Standard Error: 3
-			.saturating_add(Weight::from_parts(590, 0).saturating_mul(n.into()))
+			.saturating_add(Weight::from_parts(617, 0).saturating_mul(n.into()))
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
 	}
@@ -2252,10 +2254,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `108 + r * (150 ±0)`
 		//  Estimated: `105 + r * (151 ±0)`
-		// Minimum execution time: 9_380_000 picoseconds.
-		Weight::from_parts(9_501_000, 105)
-			// Standard Error: 7_029
-			.saturating_add(Weight::from_parts(4_406_690, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_891_000 picoseconds.
+		Weight::from_parts(10_046_000, 105)
+			// Standard Error: 6_993
+			.saturating_add(Weight::from_parts(4_601_167, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into()))
 	}
@@ -2266,10 +2268,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `248 + n * (1 ±0)`
 		//  Estimated: `248 + n * (1 ±0)`
-		// Minimum execution time: 16_400_000 picoseconds.
-		Weight::from_parts(17_993_941, 248)
+		// Minimum execution time: 17_229_000 picoseconds.
+		Weight::from_parts(18_302_733, 248)
 			// Standard Error: 2
-			.saturating_add(Weight::from_parts(68, 0).saturating_mul(n.into()))
+			.saturating_add(Weight::from_parts(112, 0).saturating_mul(n.into()))
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
 	}
@@ -2280,10 +2282,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `108 + r * (150 ±0)`
 		//  Estimated: `105 + r * (151 ±0)`
-		// Minimum execution time: 9_109_000 picoseconds.
-		Weight::from_parts(9_265_000, 105)
-			// Standard Error: 8_733
-			.saturating_add(Weight::from_parts(5_218_811, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_323_000 picoseconds.
+		Weight::from_parts(9_462_000, 105)
+			// Standard Error: 8_031
+			.saturating_add(Weight::from_parts(5_433_981, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 151).saturating_mul(r.into()))
@@ -2295,10 +2297,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `248 + n * (1 ±0)`
 		//  Estimated: `248 + n * (1 ±0)`
-		// Minimum execution time: 18_423_000 picoseconds.
-		Weight::from_parts(20_025_132, 248)
+		// Minimum execution time: 18_711_000 picoseconds.
+		Weight::from_parts(20_495_670, 248)
 			// Standard Error: 3
-			.saturating_add(Weight::from_parts(628, 0).saturating_mul(n.into()))
+			.saturating_add(Weight::from_parts(640, 0).saturating_mul(n.into()))
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
@@ -2310,10 +2312,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `770`
 		//  Estimated: `4221 + r * (2475 ±0)`
-		// Minimum execution time: 9_043_000 picoseconds.
-		Weight::from_parts(9_176_000, 4221)
-			// Standard Error: 12_901
-			.saturating_add(Weight::from_parts(32_297_438, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_226_000 picoseconds.
+		Weight::from_parts(9_394_000, 4221)
+			// Standard Error: 14_741
+			.saturating_add(Weight::from_parts(34_179_316, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
@@ -2335,10 +2337,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `520 + r * (170 ±0)`
 		//  Estimated: `6463 + r * (2646 ±0)`
-		// Minimum execution time: 9_299_000 picoseconds.
-		Weight::from_parts(9_427_000, 6463)
-			// Standard Error: 101_949
-			.saturating_add(Weight::from_parts(244_143_691, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_455_000 picoseconds.
+		Weight::from_parts(9_671_000, 6463)
+			// Standard Error: 126_080
+			.saturating_add(Weight::from_parts(244_204_040, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads(5_u64))
 			.saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(r.into())))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
@@ -2359,11 +2361,11 @@ impl WeightInfo for () {
 	fn seal_delegate_call(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0 + r * (527 ±0)`
-		//  Estimated: `6447 + r * (2583 ±3)`
-		// Minimum execution time: 9_359_000 picoseconds.
-		Weight::from_parts(9_425_000, 6447)
-			// Standard Error: 193_938
-			.saturating_add(Weight::from_parts(244_904_401, 0).saturating_mul(r.into()))
+		//  Estimated: `6447 + r * (2583 ±10)`
+		// Minimum execution time: 9_274_000 picoseconds.
+		Weight::from_parts(9_437_000, 6447)
+			// Standard Error: 150_832
+			.saturating_add(Weight::from_parts(244_196_269, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into())))
 			.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 2583).saturating_mul(r.into()))
@@ -2386,12 +2388,12 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `699 + t * (277 ±0)`
 		//  Estimated: `6639 + t * (3458 ±0)`
-		// Minimum execution time: 214_588_000 picoseconds.
-		Weight::from_parts(129_214_481, 6639)
-			// Standard Error: 2_468_090
-			.saturating_add(Weight::from_parts(32_514_739, 0).saturating_mul(t.into()))
+		// Minimum execution time: 214_483_000 picoseconds.
+		Weight::from_parts(122_634_366, 6639)
+			// Standard Error: 2_499_235
+			.saturating_add(Weight::from_parts(41_326_008, 0).saturating_mul(t.into()))
 			// Standard Error: 3
-			.saturating_add(Weight::from_parts(418, 0).saturating_mul(c.into()))
+			.saturating_add(Weight::from_parts(422, 0).saturating_mul(c.into()))
 			.saturating_add(RocksDbWeight::get().reads(7_u64))
 			.saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(t.into())))
 			.saturating_add(RocksDbWeight::get().writes(4_u64))
@@ -2406,10 +2408,10 @@ impl WeightInfo for () {
 	/// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`)
 	/// Storage: `Contracts::ContractInfoOf` (r:800 w:801)
 	/// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`)
-	/// Storage: `Parameters::Parameters` (r:2 w:0)
-	/// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`)
 	/// Storage: `System::Account` (r:802 w:802)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`)
+	/// Storage: `Parameters::Parameters` (r:2 w:0)
+	/// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`)
 	/// Storage: `System::EventTopics` (r:801 w:801)
 	/// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`)
 	/// The range of component `r` is `[1, 800]`.
@@ -2417,10 +2419,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `1097 + r * (188 ±0)`
 		//  Estimated: `6990 + r * (2664 ±0)`
-		// Minimum execution time: 352_925_000 picoseconds.
-		Weight::from_parts(355_487_000, 6990)
-			// Standard Error: 261_528
-			.saturating_add(Weight::from_parts(337_897_187, 0).saturating_mul(r.into()))
+		// Minimum execution time: 341_569_000 picoseconds.
+		Weight::from_parts(360_574_000, 6990)
+			// Standard Error: 259_746
+			.saturating_add(Weight::from_parts(337_944_674, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads(6_u64))
 			.saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(r.into())))
 			.saturating_add(RocksDbWeight::get().writes(4_u64))
@@ -2435,10 +2437,10 @@ impl WeightInfo for () {
 	/// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`)
 	/// Storage: `Contracts::ContractInfoOf` (r:1 w:2)
 	/// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`)
-	/// Storage: `Parameters::Parameters` (r:2 w:0)
-	/// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`)
 	/// Storage: `System::Account` (r:3 w:3)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`)
+	/// Storage: `Parameters::Parameters` (r:2 w:0)
+	/// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`)
 	/// Storage: `System::EventTopics` (r:2 w:2)
 	/// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`)
 	/// The range of component `t` is `[0, 1]`.
@@ -2448,12 +2450,14 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `760 + t * (104 ±0)`
 		//  Estimated: `6719 + t * (2549 ±1)`
-		// Minimum execution time: 1_870_832_000 picoseconds.
-		Weight::from_parts(949_110_245, 6719)
-			// Standard Error: 24
-			.saturating_add(Weight::from_parts(1_084, 0).saturating_mul(i.into()))
-			// Standard Error: 24
-			.saturating_add(Weight::from_parts(1_206, 0).saturating_mul(s.into()))
+		// Minimum execution time: 1_863_119_000 picoseconds.
+		Weight::from_parts(900_189_174, 6719)
+			// Standard Error: 13_040_979
+			.saturating_add(Weight::from_parts(4_056_063, 0).saturating_mul(t.into()))
+			// Standard Error: 20
+			.saturating_add(Weight::from_parts(1_028, 0).saturating_mul(i.into()))
+			// Standard Error: 20
+			.saturating_add(Weight::from_parts(1_173, 0).saturating_mul(s.into()))
 			.saturating_add(RocksDbWeight::get().reads(10_u64))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into())))
 			.saturating_add(RocksDbWeight::get().writes(7_u64))
@@ -2465,58 +2469,58 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_142_000 picoseconds.
-		Weight::from_parts(9_787_220, 0)
-			// Standard Error: 236
-			.saturating_add(Weight::from_parts(267_264, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_211_000 picoseconds.
+		Weight::from_parts(11_696_412, 0)
+			// Standard Error: 388
+			.saturating_add(Weight::from_parts(265_538, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `n` is `[0, 1048576]`.
 	fn seal_hash_sha2_256_per_byte(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_485_000 picoseconds.
-		Weight::from_parts(1_870_250, 0)
+		// Minimum execution time: 10_296_000 picoseconds.
+		Weight::from_parts(572_494, 0)
 			// Standard Error: 1
-			.saturating_add(Weight::from_parts(1_073, 0).saturating_mul(n.into()))
+			.saturating_add(Weight::from_parts(1_067, 0).saturating_mul(n.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_hash_keccak_256(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_005_000 picoseconds.
-		Weight::from_parts(8_943_937, 0)
-			// Standard Error: 1_385
-			.saturating_add(Weight::from_parts(665_970, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_177_000 picoseconds.
+		Weight::from_parts(8_620_481, 0)
+			// Standard Error: 249
+			.saturating_add(Weight::from_parts(674_502, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `n` is `[0, 1048576]`.
 	fn seal_hash_keccak_256_per_byte(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_965_000 picoseconds.
-		Weight::from_parts(11_749_746, 0)
-			// Standard Error: 6
-			.saturating_add(Weight::from_parts(3_330, 0).saturating_mul(n.into()))
+		// Minimum execution time: 11_240_000 picoseconds.
+		Weight::from_parts(8_696_186, 0)
+			// Standard Error: 0
+			.saturating_add(Weight::from_parts(3_328, 0).saturating_mul(n.into()))
 	}
 	/// The range of component `r` is `[0, 1600]`.
 	fn seal_hash_blake2_256(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_400_000 picoseconds.
-		Weight::from_parts(13_857_546, 0)
-			// Standard Error: 246
-			.saturating_add(Weight::from_parts(326_483, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_889_000 picoseconds.
+		Weight::from_parts(16_103_170, 0)
+			// Standard Error: 343
+			.saturating_add(Weight::from_parts(328_939, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `n` is `[0, 1048576]`.
 	fn seal_hash_blake2_256_per_byte(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_064_000 picoseconds.
-		Weight::from_parts(1_885_873, 0)
+		// Minimum execution time: 10_405_000 picoseconds.
+		Weight::from_parts(2_264_024, 0)
 			// Standard Error: 0
 			.saturating_add(Weight::from_parts(1_196, 0).saturating_mul(n.into()))
 	}
@@ -2525,60 +2529,60 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_068_000 picoseconds.
-		Weight::from_parts(17_169_362, 0)
-			// Standard Error: 1_580
-			.saturating_add(Weight::from_parts(330_195, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_215_000 picoseconds.
+		Weight::from_parts(10_505_632, 0)
+			// Standard Error: 240
+			.saturating_add(Weight::from_parts(324_854, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `n` is `[0, 1048576]`.
 	fn seal_hash_blake2_128_per_byte(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 10_169_000 picoseconds.
-		Weight::from_parts(2_159_277, 0)
-			// Standard Error: 0
-			.saturating_add(Weight::from_parts(1_200, 0).saturating_mul(n.into()))
+		// Minimum execution time: 10_440_000 picoseconds.
+		Weight::from_parts(2_575_889, 0)
+			// Standard Error: 1
+			.saturating_add(Weight::from_parts(1_199, 0).saturating_mul(n.into()))
 	}
 	/// The range of component `n` is `[0, 125697]`.
 	fn seal_sr25519_verify_per_byte(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 53_863_000 picoseconds.
-		Weight::from_parts(54_902_157, 0)
-			// Standard Error: 9
-			.saturating_add(Weight::from_parts(4_588, 0).saturating_mul(n.into()))
+		// Minimum execution time: 55_119_000 picoseconds.
+		Weight::from_parts(56_732_248, 0)
+			// Standard Error: 8
+			.saturating_add(Weight::from_parts(4_639, 0).saturating_mul(n.into()))
 	}
 	/// The range of component `r` is `[0, 160]`.
 	fn seal_sr25519_verify(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_107_000 picoseconds.
-		Weight::from_parts(24_115_247, 0)
-			// Standard Error: 7_427
-			.saturating_add(Weight::from_parts(41_116_827, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_176_000 picoseconds.
+		Weight::from_parts(9_861_102, 0)
+			// Standard Error: 6_029
+			.saturating_add(Weight::from_parts(45_948_571, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 160]`.
 	fn seal_ecdsa_recover(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_404_000 picoseconds.
-		Weight::from_parts(31_763_334, 0)
-			// Standard Error: 9_833
-			.saturating_add(Weight::from_parts(45_529_880, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_293_000 picoseconds.
+		Weight::from_parts(28_785_765, 0)
+			// Standard Error: 9_160
+			.saturating_add(Weight::from_parts(45_566_150, 0).saturating_mul(r.into()))
 	}
 	/// The range of component `r` is `[0, 160]`.
 	fn seal_ecdsa_to_eth_address(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 11_409_000 picoseconds.
-		Weight::from_parts(15_072_835, 0)
-			// Standard Error: 4_591
-			.saturating_add(Weight::from_parts(11_619_283, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_206_000 picoseconds.
+		Weight::from_parts(12_420_664, 0)
+			// Standard Error: 3_489
+			.saturating_add(Weight::from_parts(11_628_989, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `Contracts::CodeInfoOf` (r:1536 w:1536)
 	/// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`)
@@ -2592,11 +2596,11 @@ impl WeightInfo for () {
 	fn seal_set_code_hash(r: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0 + r * (926 ±0)`
-		//  Estimated: `8969 + r * (3047 ±10)`
-		// Minimum execution time: 9_269_000 picoseconds.
-		Weight::from_parts(9_372_000, 8969)
-			// Standard Error: 61_354
-			.saturating_add(Weight::from_parts(26_280_409, 0).saturating_mul(r.into()))
+		//  Estimated: `8969 + r * (3047 ±7)`
+		// Minimum execution time: 9_219_000 picoseconds.
+		Weight::from_parts(9_385_000, 8969)
+			// Standard Error: 45_562
+			.saturating_add(Weight::from_parts(26_360_661, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into())))
 			.saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 3047).saturating_mul(r.into()))
@@ -2608,10 +2612,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `274 + r * (78 ±0)`
 		//  Estimated: `1265 + r * (2553 ±0)`
-		// Minimum execution time: 9_103_000 picoseconds.
-		Weight::from_parts(14_404_626, 1265)
-			// Standard Error: 9_343
-			.saturating_add(Weight::from_parts(5_154_949, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_355_000 picoseconds.
+		Weight::from_parts(15_071_309, 1265)
+			// Standard Error: 9_722
+			.saturating_add(Weight::from_parts(5_328_717, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 2553).saturating_mul(r.into()))
@@ -2623,10 +2627,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `275 + r * (78 ±0)`
 		//  Estimated: `990 + r * (2568 ±0)`
-		// Minimum execution time: 9_219_000 picoseconds.
-		Weight::from_parts(14_085_456, 990)
-			// Standard Error: 11_206
-			.saturating_add(Weight::from_parts(4_422_122, 0).saturating_mul(r.into()))
+		// Minimum execution time: 8_979_000 picoseconds.
+		Weight::from_parts(14_362_224, 990)
+			// Standard Error: 9_137
+			.saturating_add(Weight::from_parts(4_488_748, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into())))
 			.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into())))
 			.saturating_add(Weight::from_parts(0, 2568).saturating_mul(r.into()))
@@ -2652,10 +2656,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `861 + r * (3 ±0)`
 		//  Estimated: `9282 + r * (3 ±0)`
-		// Minimum execution time: 269_333_000 picoseconds.
-		Weight::from_parts(286_922_618, 9282)
-			// Standard Error: 443
-			.saturating_add(Weight::from_parts(168_869, 0).saturating_mul(r.into()))
+		// Minimum execution time: 269_704_000 picoseconds.
+		Weight::from_parts(289_916_035, 9282)
+			// Standard Error: 408
+			.saturating_add(Weight::from_parts(166_040, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads(11_u64))
 			.saturating_add(RocksDbWeight::get().writes(3_u64))
 			.saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into()))
@@ -2665,10 +2669,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 9_328_000 picoseconds.
-		Weight::from_parts(14_019_583, 0)
-			// Standard Error: 171
-			.saturating_add(Weight::from_parts(88_751, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_361_000 picoseconds.
+		Weight::from_parts(11_633_836, 0)
+			// Standard Error: 86
+			.saturating_add(Weight::from_parts(83_083, 0).saturating_mul(r.into()))
 	}
 	/// Storage: `Contracts::Nonce` (r:1 w:0)
 	/// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`)
@@ -2677,10 +2681,10 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `219`
 		//  Estimated: `1704`
-		// Minimum execution time: 9_267_000 picoseconds.
-		Weight::from_parts(15_304_284, 1704)
-			// Standard Error: 1_219
-			.saturating_add(Weight::from_parts(74_696, 0).saturating_mul(r.into()))
+		// Minimum execution time: 9_133_000 picoseconds.
+		Weight::from_parts(13_259_836, 1704)
+			// Standard Error: 121
+			.saturating_add(Weight::from_parts(76_878, 0).saturating_mul(r.into()))
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 	}
 	/// The range of component `r` is `[0, 5000]`.
@@ -2688,9 +2692,9 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 911_000 picoseconds.
-		Weight::from_parts(449_666, 0)
-			// Standard Error: 26
-			.saturating_add(Weight::from_parts(14_797, 0).saturating_mul(r.into()))
+		// Minimum execution time: 851_000 picoseconds.
+		Weight::from_parts(587_883, 0)
+			// Standard Error: 16
+			.saturating_add(Weight::from_parts(14_912, 0).saturating_mul(r.into()))
 	}
 }
diff --git a/substrate/frame/support/src/traits.rs b/substrate/frame/support/src/traits.rs
index 66777cef7b8e81960c1169c2fb1fd1033e58c4a2..a423656c394f28158da2aedd5d552814ccabb3c5 100644
--- a/substrate/frame/support/src/traits.rs
+++ b/substrate/frame/support/src/traits.rs
@@ -36,7 +36,7 @@ mod members;
 pub use members::{AllowAll, DenyAll, Filter};
 pub use members::{
 	AsContains, ChangeMembers, Contains, ContainsLengthBound, ContainsPair, Equals, Everything,
-	EverythingBut, FromContainsPair, InitializeMembers, InsideBoth, IsInVec, Nothing,
+	EverythingBut, FromContains, FromContainsPair, InitializeMembers, InsideBoth, IsInVec, Nothing,
 	RankedMembers, RankedMembersSwapHandler, SortedMembers, TheseExcept,
 };
 
diff --git a/substrate/frame/support/src/traits/members.rs b/substrate/frame/support/src/traits/members.rs
index 3a6e3719593a22c33ad24c24c56f858ea82779ee..53de84ab22455f2d778c1fd64ba94c348c685db0 100644
--- a/substrate/frame/support/src/traits/members.rs
+++ b/substrate/frame/support/src/traits/members.rs
@@ -66,6 +66,15 @@ impl<A, B, CP: ContainsPair<A, B>> Contains<(A, B)> for FromContainsPair<CP> {
 	}
 }
 
+/// A [`ContainsPair`] implementation that has a `Contains` implementation for each member of the
+/// pair.
+pub struct FromContains<CA, CB>(PhantomData<(CA, CB)>);
+impl<A, B, CA: Contains<A>, CB: Contains<B>> ContainsPair<A, B> for FromContains<CA, CB> {
+	fn contains(a: &A, b: &B) -> bool {
+		CA::contains(a) && CB::contains(b)
+	}
+}
+
 /// A [`Contains`] implementation that contains every value.
 pub enum Everything {}
 impl<T> Contains<T> for Everything {
diff --git a/substrate/frame/support/src/traits/tokens.rs b/substrate/frame/support/src/traits/tokens.rs
index 3635311e64357bbd2e7041d653a4268dfb65a182..8842b20580181f81e4377a0d9f6223e59a6fee6a 100644
--- a/substrate/frame/support/src/traits/tokens.rs
+++ b/substrate/frame/support/src/traits/tokens.rs
@@ -31,7 +31,7 @@ pub mod pay;
 pub use misc::{
 	AssetId, Balance, BalanceStatus, ConversionFromAssetBalance, ConversionToAssetBalance,
 	ConvertRank, DepositConsequence, ExistenceRequirement, Fortitude, GetSalary, Locker, Precision,
-	Preservation, Provenance, Restriction, UnityAssetBalanceConversion, WithdrawConsequence,
-	WithdrawReasons,
+	Preservation, Provenance, Restriction, UnityAssetBalanceConversion, UnityOrOuterConversion,
+	WithdrawConsequence, WithdrawReasons,
 };
 pub use pay::{Pay, PayFromAccount, PaymentStatus};
diff --git a/substrate/frame/support/src/traits/tokens/misc.rs b/substrate/frame/support/src/traits/tokens/misc.rs
index a4dd5e4914283e6da028aac038cecee501a2228f..424acb1d550b15b69582d004e2e466e65e6a9b3f 100644
--- a/substrate/frame/support/src/traits/tokens/misc.rs
+++ b/substrate/frame/support/src/traits/tokens/misc.rs
@@ -17,6 +17,7 @@
 
 //! Miscellaneous types.
 
+use crate::traits::Contains;
 use codec::{Decode, Encode, FullCodec, MaxEncodedLen};
 use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero};
 use sp_core::RuntimeDebug;
@@ -299,6 +300,33 @@ where
 	fn ensure_successful(_: AssetId) {}
 }
 
+/// Implements [`ConversionFromAssetBalance`], allowing for a 1:1 balance conversion of the asset
+/// when it meets the conditions specified by `C`. If the conditions are not met, the conversion is
+/// delegated to `O`.
+pub struct UnityOrOuterConversion<C, O>(core::marker::PhantomData<(C, O)>);
+impl<AssetBalance, AssetId, OutBalance, C, O>
+	ConversionFromAssetBalance<AssetBalance, AssetId, OutBalance> for UnityOrOuterConversion<C, O>
+where
+	C: Contains<AssetId>,
+	O: ConversionFromAssetBalance<AssetBalance, AssetId, OutBalance>,
+	AssetBalance: Into<OutBalance>,
+{
+	type Error = O::Error;
+	fn from_asset_balance(
+		balance: AssetBalance,
+		asset_id: AssetId,
+	) -> Result<OutBalance, Self::Error> {
+		if C::contains(&asset_id) {
+			return Ok(balance.into());
+		}
+		O::from_asset_balance(balance, asset_id)
+	}
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful(asset_id: AssetId) {
+		O::ensure_successful(asset_id)
+	}
+}
+
 /// Trait to handle NFT locking mechanism to ensure interactions with the asset can be implemented
 /// downstream to extend logic of Uniques/Nfts current functionality.
 pub trait Locker<CollectionId, ItemId> {