diff --git a/.config/lychee.toml b/.config/lychee.toml
index 58f8d068d9d13d270c19445fa6983c605b0febb4..55e368dacb50815e750b537ddb4e254590aeca5b 100644
--- a/.config/lychee.toml
+++ b/.config/lychee.toml
@@ -52,10 +52,15 @@ exclude = [
 	# Behind a captcha (code 403):
 	"https://chainlist.org/chain/*",
 	"https://iohk.io/en/blog/posts/2023/11/03/partner-chains-are-coming-to-cardano/",
+	"https://polymesh.network",
 	"https://www.reddit.com/r/rust/comments/3spfh1/does_collect_allocate_more_than_once_while/",
 
 	# 403 rate limited:
 	"https://etherscan.io/block/11090290",
 	"https://subscan.io/",
 	"https://substrate.stackexchange.com/.*",
+
+	# Exclude strings which contain templates like {} and {:?}
+	"%7B%7D",
+	"%7B:\\?}",
 ]
diff --git a/.forklift/config.toml b/.forklift/config.toml
index 6f8eed8882ea36f39d1f0a519180f92eb905f7be..0f7ba55578f47a55471730c181c3601d43da5685 100644
--- a/.forklift/config.toml
+++ b/.forklift/config.toml
@@ -26,4 +26,4 @@ project_name = "$CI_PROJECT_PATH"
 type = "gcs"
 
 [storage.gcs]
-bucketName = "parity-ci-forklift"
+bucketName = "parity-ci-forklift-regional"
diff --git a/.github/env b/.github/env
index 730c37f1db80beb0cf79f56140dd740c572a1353..6d3f8e994cbabbfffde163ce218fc79571ef99a2 100644
--- a/.github/env
+++ b/.github/env
@@ -1 +1 @@
-IMAGE="docker.io/paritytech/ci-unified:bullseye-1.81.0-2024-11-19-v202411281558"
+IMAGE="docker.io/paritytech/ci-unified:bullseye-1.84.1-2025-01-28-v202502131220"
diff --git a/.github/workflows/benchmarks-subsystem.yml b/.github/workflows/benchmarks-subsystem.yml
index 210714d847ff032dee89a4dfbd36e9a34b7f5940..82aff7e694f9b241f7d27c867559ae739ee7f1b8 100644
--- a/.github/workflows/benchmarks-subsystem.yml
+++ b/.github/workflows/benchmarks-subsystem.yml
@@ -16,9 +16,11 @@ permissions:
   contents: read
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
-
   build:
     timeout-minutes: 80
     needs: [preflight]
diff --git a/.github/workflows/build-misc.yml b/.github/workflows/build-misc.yml
index e1ef29f305d0f1e97866d84a83a960a04734b76c..fc29bfb7b34376612868c574901d8a86719ccc9a 100644
--- a/.github/workflows/build-misc.yml
+++ b/.github/workflows/build-misc.yml
@@ -16,7 +16,10 @@ permissions:
   contents: read
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
 
   build-runtimes-polkavm:
diff --git a/.github/workflows/build-publish-eth-rpc.yml b/.github/workflows/build-publish-eth-rpc.yml
index 621ac3cd44c3c49d474f420979f2d318720c18ca..e576f3b7938043f48c8f49843e7baa6032d35b27 100644
--- a/.github/workflows/build-publish-eth-rpc.yml
+++ b/.github/workflows/build-publish-eth-rpc.yml
@@ -5,7 +5,7 @@ on:
     branches:
       - master
   pull_request:
-    types: [opened, synchronize, reopened, ready_for_review, labeled]
+    types: [opened, synchronize, reopened, ready_for_review]
 
 concurrency:
   group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -15,10 +15,13 @@ env:
   ETH_RPC_IMAGE_NAME: "docker.io/paritypr/eth-rpc"
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   set-variables:
     # This workaround sets the container image for each job using 'set-variables' job output.
     # env variables don't work for PR from forks, so we need to use outputs.
     runs-on: ubuntu-latest
+    needs: isdraft
     outputs:
       VERSION: ${{ steps.version.outputs.VERSION }}
     steps:
@@ -77,4 +80,3 @@ jobs:
           push: true
           tags: |
             ${{ env.ETH_RPC_IMAGE_NAME }}:${{ env.VERSION }}
-
diff --git a/.github/workflows/build-publish-images.yml b/.github/workflows/build-publish-images.yml
index 0bf2bded0b0dfeaeb784c985d84ad0d4bef709c5..0ce33e2864a41fcf2d8a0a49b59a66932f0eba95 100644
--- a/.github/workflows/build-publish-images.yml
+++ b/.github/workflows/build-publish-images.yml
@@ -6,7 +6,7 @@ on:
     branches:
       - master
   pull_request:
-    types: [opened, synchronize, reopened, ready_for_review, labeled]
+    types: [opened, synchronize, reopened, ready_for_review]
   merge_group:
 concurrency:
   group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -18,7 +18,10 @@ jobs:
   #
   #
   #
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
 
   ### Build ########################
diff --git a/.github/workflows/check-cargo-check-runtimes.yml b/.github/workflows/check-cargo-check-runtimes.yml
index 376c34d1f25fd965f69f3c2874b38c39e6a76573..c4ad0f3d139de40908415c9d6c1202d22f38d339 100644
--- a/.github/workflows/check-cargo-check-runtimes.yml
+++ b/.github/workflows/check-cargo-check-runtimes.yml
@@ -13,7 +13,10 @@ on:
 # Jobs in this workflow depend on each other, only for limiting peak amount of spawned workers
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
 
   check-runtime-assets:
diff --git a/.github/workflows/check-frame-omni-bencher.yml b/.github/workflows/check-frame-omni-bencher.yml
index bc0ff82b677414d82b9e5724f3fa0b46612436dc..f4227cf5a6a662e1d1d36d487ca60c935c93b5c6 100644
--- a/.github/workflows/check-frame-omni-bencher.yml
+++ b/.github/workflows/check-frame-omni-bencher.yml
@@ -5,7 +5,7 @@ on:
     branches:
       - master
   pull_request:
-    types: [opened, synchronize, reopened, ready_for_review, labeled]
+    types: [opened, synchronize, reopened, ready_for_review]
   merge_group:
 
 concurrency:
@@ -16,7 +16,10 @@ env:
   ARTIFACTS_NAME: frame-omni-bencher-artifacts
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
 
   quick-benchmarks-omni:
diff --git a/.github/workflows/check-getting-started.yml b/.github/workflows/check-getting-started.yml
index 0661fa144348de687c0ddf1266be593664adc5e4..4178016bc25f8e0bf21ba89b3879d428a11ff8ac 100644
--- a/.github/workflows/check-getting-started.yml
+++ b/.github/workflows/check-getting-started.yml
@@ -26,16 +26,19 @@ on:
     paths:
       - ".github/workflows/check-getting-started.yml"
       - "scripts/getting-started.sh"
+    types: [opened, synchronize, reopened, ready_for_review]
   schedule:
     - cron: "0 5 * * *"
-  workflow_dispatch:
 
 concurrency:
   group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
   cancel-in-progress: true
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   check-getting-started:
+    needs: isdraft
     strategy:
       fail-fast: true
       matrix:
@@ -179,6 +182,7 @@ jobs:
         timeout-minutes: 5
 
   check-getting-started-macos:
+    needs: isdraft
     strategy:
       fail-fast: true
       matrix:
diff --git a/.github/workflows/check-licenses.yml b/.github/workflows/check-licenses.yml
index 9492d06c7fcf93dac1d4741bb2b4580d9e187dee..70f374142dc011202cbe80786f62869a3a419c1f 100644
--- a/.github/workflows/check-licenses.yml
+++ b/.github/workflows/check-licenses.yml
@@ -2,6 +2,7 @@ name: Check licenses
 
 on:
   pull_request:
+    types: [opened, synchronize, reopened, ready_for_review]
   merge_group:
 
 concurrency:
@@ -12,8 +13,11 @@ permissions:
   packages: read
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   check-licenses:
     runs-on: ubuntu-latest
+    needs: isdraft
     timeout-minutes: 10
     env:
       LICENSES: "'Apache-2.0' 'GPL-3.0-only' 'GPL-3.0-or-later WITH Classpath-exception-2.0' 'MIT-0' 'Unlicense'"
diff --git a/.github/workflows/check-links.yml b/.github/workflows/check-links.yml
index 81ce23492c721b6d87fb0ef712a8c71d49a18197..6d5a79ff34a3f0da9b12fc4da0d5e29b02971745 100644
--- a/.github/workflows/check-links.yml
+++ b/.github/workflows/check-links.yml
@@ -18,8 +18,11 @@ permissions:
   packages: read
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   link-checker:
     runs-on: ubuntu-latest
+    needs: isdraft
     timeout-minutes: 10
     steps:
       - name: Restore lychee cache
diff --git a/.github/workflows/check-runtime-migration.yml b/.github/workflows/check-runtime-migration.yml
index e935f1cb44981e07f06cfeb74811fec29e9f41a3..0596bab3ae82c16c3ddda95d021e1d5d9a6517e1 100644
--- a/.github/workflows/check-runtime-migration.yml
+++ b/.github/workflows/check-runtime-migration.yml
@@ -19,7 +19,10 @@ concurrency:
 permissions: {}
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
 
   # More info can be found here: https://github.com/paritytech/polkadot/pull/5865
diff --git a/.github/workflows/check-semver.yml b/.github/workflows/check-semver.yml
index a6e90cee53470810959941e4d86832c1b28bddd3..958a1590bd2488d796a22f3b32f49b3b028113e6 100644
--- a/.github/workflows/check-semver.yml
+++ b/.github/workflows/check-semver.yml
@@ -14,7 +14,10 @@ env:
   TOOLCHAIN: nightly-2024-11-19
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
   check-semver:
     runs-on: ubuntu-latest
diff --git a/.github/workflows/checks-quick.yml b/.github/workflows/checks-quick.yml
index 1a8813833deff8cccb412d832a38de470e0dc933..ff88fa6ff9f722f9b07f819088b631d7e608320f 100644
--- a/.github/workflows/checks-quick.yml
+++ b/.github/workflows/checks-quick.yml
@@ -15,7 +15,10 @@ concurrency:
 permissions: {}
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
 
   fmt:
@@ -37,6 +40,7 @@ jobs:
           app-key: ${{ secrets.WORKFLOW_STOPPER_RUNNER_APP_KEY }}
   check-dependency-rules:
     runs-on: ubuntu-latest
+    needs: isdraft
     timeout-minutes: 20
     steps:
       - uses: actions/checkout@6d193bf28034eafb982f37bd894289fe649468fc # v4.1.7
@@ -84,6 +88,7 @@ jobs:
           echo "Please run `taplo format --config .config/taplo.toml` to fix any toml formatting issues"
   check-workspace:
     runs-on: ubuntu-latest
+    needs: isdraft
     timeout-minutes: 20
     steps:
       - uses: actions/checkout@6d193bf28034eafb982f37bd894289fe649468fc # v4.1.0 (22. Sep 2023)
@@ -102,6 +107,7 @@ jobs:
         run: python3 .github/scripts/deny-git-deps.py .
   check-markdown:
     runs-on: ubuntu-latest
+    needs: isdraft
     timeout-minutes: 20
     steps:
       - name: Checkout sources
@@ -154,6 +160,7 @@ jobs:
           fi
   check-fail-ci:
     runs-on: ubuntu-latest
+    needs: isdraft
     container:
       # there's no "rg" in ci-unified, and tools is a smaller image anyway
       image: "paritytech/tools:latest"
@@ -179,6 +186,7 @@ jobs:
           GIT_DEPTH: 1
   check-readme:
     runs-on: ubuntu-latest
+    needs: isdraft
     timeout-minutes: 10
     steps:
       - uses: actions/checkout@v4
diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml
index 02428711811f957e35de0cf27af8ba51f9c40547..d1d97534d9e1803a00f05da01dc6fa5a5ff801cb 100644
--- a/.github/workflows/checks.yml
+++ b/.github/workflows/checks.yml
@@ -15,7 +15,10 @@ concurrency:
 permissions: {}
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
 
   cargo-clippy:
diff --git a/.github/workflows/cmd-tests.yml b/.github/workflows/cmd-tests.yml
index af73c6a5b2d32a19e7b64de4935f71988fbf8a1f..d2b46a98056a3a163d4095b4f025b45073af1b04 100644
--- a/.github/workflows/cmd-tests.yml
+++ b/.github/workflows/cmd-tests.yml
@@ -2,6 +2,7 @@ name: Command Bot Tests
 
 on:
   pull_request:
+    types: [opened, synchronize, reopened, ready_for_review]
 
 permissions:
   contents: read
@@ -11,8 +12,11 @@ concurrency:
   cancel-in-progress: true
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   test-cmd-bot:
     runs-on: ubuntu-latest
+    needs: [isdraft]
     steps:
       - uses: actions/checkout@v4
       - run: python3 .github/scripts/cmd/test_cmd.py
diff --git a/.github/workflows/command-backport.yml b/.github/workflows/command-backport.yml
index 8a017a434525a7289ca4a57879b0e11d39092807..d7b01000855ad7264a392bd5e074f9ee6328d00a 100644
--- a/.github/workflows/command-backport.yml
+++ b/.github/workflows/command-backport.yml
@@ -40,7 +40,7 @@ jobs:
         uses: korthout/backport-action@v3
         id: backport
         with:
-          target_branches: stable2407 stable2409 stable2412
+          target_branches: stable2407 stable2409 stable2412 stable2503
           merge_commits: skip
           github_token: ${{ steps.generate_token.outputs.token }}
           pull_description: |
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index b7c70c9e6d66f2dbef81c8f5aa2253b3b075820f..24fb284780be821bc4b947c9f62b6421ec205791 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -5,7 +5,7 @@ on:
     branches:
       - master
   pull_request:
-    types: [opened, synchronize, reopened, ready_for_review, labeled]
+    types: [opened, synchronize, reopened, ready_for_review]
   merge_group:
 
 concurrency:
@@ -13,7 +13,10 @@ concurrency:
   cancel-in-progress: true
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
 
   test-doc:
@@ -77,6 +80,7 @@ jobs:
 
   build-implementers-guide:
     runs-on: ubuntu-latest
+    needs: isdraft
     container:
       image: paritytech/mdbook-utils:e14aae4a-20221123
       options: --user root
diff --git a/.github/workflows/gitspiegel-trigger.yml b/.github/workflows/gitspiegel-trigger.yml
index 01058ad74d0b71385a8096964ea6c779fc6f4869..954e4ad6e70dbfb36c2b8c9deb272c2246be3f66 100644
--- a/.github/workflows/gitspiegel-trigger.yml
+++ b/.github/workflows/gitspiegel-trigger.yml
@@ -28,8 +28,11 @@ on:
 permissions: {}
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   sync:
     runs-on: ubuntu-latest
+    needs: isdraft
     steps:
       - name: Do nothing
         run: echo "let's go"
diff --git a/.github/workflows/publish-check-compile.yml b/.github/workflows/publish-check-compile.yml
index f20909106a82098d79ab8e47b03bf5b4076b9380..66d619a2426d394edace31c10e8abf4cc5ee6423 100644
--- a/.github/workflows/publish-check-compile.yml
+++ b/.github/workflows/publish-check-compile.yml
@@ -13,7 +13,10 @@ concurrency:
   cancel-in-progress: true
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
 
   check-publish-compile:
diff --git a/.github/workflows/publish-check-crates.yml b/.github/workflows/publish-check-crates.yml
index c1b13243ba193c7c141782dc263c577c5f0ec159..ac204b97dbdfe318dfeb021e6f3eb23c3c757b16 100644
--- a/.github/workflows/publish-check-crates.yml
+++ b/.github/workflows/publish-check-crates.yml
@@ -13,8 +13,11 @@ concurrency:
   cancel-in-progress: true
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   check-publish:
     runs-on: ubuntu-latest
+    needs: isdraft
     steps:
       - uses: actions/checkout@6d193bf28034eafb982f37bd894289fe649468fc # v4.1.7
 
diff --git a/.github/workflows/release-10_branchoff-stable.yml b/.github/workflows/release-10_branchoff-stable.yml
index cfe135ac7299e9e0bc53eda6f2c333d58f994bdd..ced08da5a0a0c6806bcc42536bc851431835f611 100644
--- a/.github/workflows/release-10_branchoff-stable.yml
+++ b/.github/workflows/release-10_branchoff-stable.yml
@@ -93,9 +93,9 @@ jobs:
 
           NODE_VERSION="${{ needs.prepare-tooling.outputs.node_version }}"
           NODE_VERSION_PATTERN="\(NODE_VERSION[^=]*= \)\".*\""
-          set_version $NODE_VERSION_PATTERN $NODE_VERSION "polkadot/node/primitives/src/lib.rs"
+          set_version "$NODE_VERSION_PATTERN" $NODE_VERSION "polkadot/node/primitives/src/lib.rs"
           commit_with_message "Bump node version to $NODE_VERSION in polkadot-cli"
-          set_version $NODE_VERSION_PATTERN $NODE_VERSION "cumulus/polkadot-omni-node/lib/src/nodes/mod.rs"
+          set_version "$NODE_VERSION_PATTERN" $NODE_VERSION "cumulus/polkadot-omni-node/lib/src/nodes/mod.rs"
           commit_with_message "Bump node version to $NODE_VERSION in polkadot-omni-node-lib"
 
           SPEC_VERSION=$(get_spec_version $NODE_VERSION)
diff --git a/.github/workflows/reusable-isdraft.yml b/.github/workflows/reusable-isdraft.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a0ee5c064fbe21e920d6f634f72ffa8dafd30c5c
--- /dev/null
+++ b/.github/workflows/reusable-isdraft.yml
@@ -0,0 +1,16 @@
+# The workflow is not part of reusable-preflight.yml to allow testing CI in draft.
+
+name: Preflight isdraft
+
+on:
+  workflow_call:
+    # Map the workflow outputs to job outputs
+
+jobs:
+  isdraft:
+    runs-on: ubuntu-latest
+    if: github.event.pull_request.draft == false || contains(github.event.pull_request.labels.*.name, 'A5-run-CI')
+    steps:
+      - name: echo test
+        shell: bash
+        run: echo "PR is not draft, starting CI"
diff --git a/.github/workflows/runtimes-matrix.json b/.github/workflows/runtimes-matrix.json
index 6578d2d347f554a81bee3275d47766a7890b0467..fbee38f71504edb64dab5aec0410cfcde7a1d978 100644
--- a/.github/workflows/runtimes-matrix.json
+++ b/.github/workflows/runtimes-matrix.json
@@ -67,7 +67,7 @@
   },
   {
     "name": "bridge-hub-westend",
-    "package": "bridge-hub-rococo-runtime",
+    "package": "bridge-hub-westend-runtime",
     "path": "cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend",
     "header": "cumulus/file_header.txt",
     "template": "cumulus/templates/xcm-bench-template.hbs",
@@ -105,7 +105,7 @@
     "header": "cumulus/file_header.txt",
     "template": "cumulus/templates/xcm-bench-template.hbs",
     "bench_features": "runtime-benchmarks",
-    "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic",
+    "bench_flags": "",
     "uri": "wss://rococo-coretime-rpc.polkadot.io:443",
     "is_relay": false
   },
@@ -116,7 +116,7 @@
     "header": "cumulus/file_header.txt",
     "template": "cumulus/templates/xcm-bench-template.hbs",
     "bench_features": "runtime-benchmarks",
-    "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic",
+    "bench_flags": "",
     "uri": "wss://westend-coretime-rpc.polkadot.io:443",
     "is_relay": false
   },
diff --git a/.github/workflows/tests-evm.yml b/.github/workflows/tests-evm.yml
index 2c98fa39d23a3021d4f0039d76f70d7729be9dce..3bf3b6f275ff0d0f583c7b030ff15f17aa0f72b3 100644
--- a/.github/workflows/tests-evm.yml
+++ b/.github/workflows/tests-evm.yml
@@ -12,7 +12,10 @@ concurrency:
   cancel-in-progress: true
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
 
   evm-test-suite:
diff --git a/.github/workflows/tests-linux-stable.yml b/.github/workflows/tests-linux-stable.yml
index 3f8dc4fe1240a078aef7ca498bc1e8667f13dda2..029d7bc7411326f90bbe9f2cf1f941a9cfc55136 100644
--- a/.github/workflows/tests-linux-stable.yml
+++ b/.github/workflows/tests-linux-stable.yml
@@ -13,7 +13,10 @@ concurrency:
   cancel-in-progress: true
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
 
   test-linux-stable-int:
diff --git a/.github/workflows/tests-misc.yml b/.github/workflows/tests-misc.yml
index decd88f2e84cfb5cf7519046f0018e6119c03315..77e39a99f9ed9f0241f95b1cc27ec523ecd2079b 100644
--- a/.github/workflows/tests-misc.yml
+++ b/.github/workflows/tests-misc.yml
@@ -14,7 +14,10 @@ concurrency:
 # Jobs in this workflow depend on each other, only for limiting peak amount of spawned workers
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
 
   # more information about this job can be found here:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index ba0574b51e686fa9c3ffa4e3b35e986c7f373e55..a178ea02f0c5f142376db1be12f747a027ec0647 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -12,7 +12,10 @@ concurrency:
   cancel-in-progress: true
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/reusable-preflight.yml
 
   # This job runs all benchmarks defined in the `/bin/node/runtime` once to check that there are no errors.
diff --git a/.github/workflows/zombienet_cumulus.yml b/.github/workflows/zombienet_cumulus.yml
index c2231060c9aa1fe336060ace9768c50bd9d3b0fd..492c63b302a10ebf2840041e40dbfc8099db3a81 100644
--- a/.github/workflows/zombienet_cumulus.yml
+++ b/.github/workflows/zombienet_cumulus.yml
@@ -19,7 +19,10 @@ env:
 
 # only run if we have changes in [subtrate, cumulus, polkadot] directories or this workflow.
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/zombienet-reusable-preflight.yml
 
   zombienet-cumulus-0001-sync_blocks_from_tip_without_connected_collator:
@@ -158,7 +161,6 @@ jobs:
           path: |
             /tmp/zombie*/logs/*
 
-
   zombienet-cumulus-0005-migrate_solo_to_para:
     needs: [preflight]
     if: ${{ needs.preflight.outputs.changes_substrate || needs.preflight.outputs.changes_cumulus || needs.preflight.outputs.changes_polkadot }}
diff --git a/.github/workflows/zombienet_substrate.yml b/.github/workflows/zombienet_substrate.yml
index 358438caa8afe7ddb65dff67cfc05c869c9742a1..7ddc2e613b238e83bdd2d701460bfdb22bc66039 100644
--- a/.github/workflows/zombienet_substrate.yml
+++ b/.github/workflows/zombienet_substrate.yml
@@ -24,7 +24,10 @@ env:
   DB_BLOCK_HEIGHT: 56687
 
 jobs:
+  isdraft:
+    uses: ./.github/workflows/reusable-isdraft.yml
   preflight:
+    needs: isdraft
     uses: ./.github/workflows/zombienet-reusable-preflight.yml
 
   zombienet-substrate-0000-block-building:
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 42a7e87bda433988a7d7dbad4e455dcd3cc80471..359aec73214e8dc9877338a1b61d7e115ae90c28 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -22,7 +22,7 @@ workflow:
 
 variables:
   # CI_IMAGE: !reference [ .ci-unified, variables, CI_IMAGE ]
-  CI_IMAGE: "docker.io/paritytech/ci-unified:bullseye-1.81.0-2024-11-19-v202411281558"
+  CI_IMAGE: "docker.io/paritytech/ci-unified:bullseye-1.84.1-2025-01-28-v202502131220"
   # BUILDAH_IMAGE is defined in group variables
   BUILDAH_COMMAND: "buildah --storage-driver overlay2"
   RELENG_SCRIPTS_BRANCH: "master"
@@ -125,18 +125,18 @@ default:
     - cat .forklift/config-gitlab.toml > .forklift/config.toml
     - >
       if [ "$FORKLIFT_BYPASS" != "true" ]; then
-        echo "FORKLIFT_BYPASS not set"; 
+        echo "FORKLIFT_BYPASS not set";
         if command -v forklift >/dev/null 2>&1; then
-          echo "forklift already exists"; 
+          echo "forklift already exists";
           forklift version
         else
           echo "forklift does not exist, downloading";
-          curl --header "PRIVATE-TOKEN: $FL_CI_GROUP_TOKEN" -o forklift  -L "${CI_API_V4_URL}/projects/676/packages/generic/forklift/${FL_FORKLIFT_VERSION}/forklift_${FL_FORKLIFT_VERSION}_linux_amd64"; 
+          curl --header "PRIVATE-TOKEN: $FL_CI_GROUP_TOKEN" -o forklift  -L "${CI_API_V4_URL}/projects/676/packages/generic/forklift/${FL_FORKLIFT_VERSION}/forklift_${FL_FORKLIFT_VERSION}_linux_amd64";
           chmod +x forklift;
           export PATH=$PATH:$(pwd);
           echo ${FL_FORKLIFT_VERSION};
         fi
-        echo "Creating alias cargo='forklift cargo'"; 
+        echo "Creating alias cargo='forklift cargo'";
         shopt -s expand_aliases;
         alias cargo="forklift cargo";
       fi
diff --git a/Cargo.lock b/Cargo.lock
index c6fefcfdfe186d9c1515d58a8bdfbb435c4937f4..bf41839ea646ae1cc6372fb958f53d90e9d5fe5a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -92,7 +92,7 @@ version = "0.7.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
 dependencies = [
- "getrandom",
+ "getrandom 0.2.10",
  "once_cell",
  "version_check",
 ]
@@ -104,10 +104,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
 dependencies = [
  "cfg-if",
- "getrandom",
+ "getrandom 0.2.10",
  "once_cell",
  "version_check",
- "zerocopy",
+ "zerocopy 0.7.32",
 ]
 
 [[package]]
@@ -181,7 +181,7 @@ dependencies = [
  "hex-literal",
  "itoa",
  "proptest",
- "rand",
+ "rand 0.8.5",
  "ruint",
  "serde",
  "tiny-keccak",
@@ -201,13 +201,13 @@ dependencies = [
  "foldhash",
  "hashbrown 0.15.2",
  "hex-literal",
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "itoa",
  "k256",
  "keccak-asm",
  "paste",
  "proptest",
- "rand",
+ "rand 0.8.5",
  "ruint",
  "rustc-hash 2.0.0",
  "serde",
@@ -266,7 +266,7 @@ dependencies = [
  "alloy-sol-macro-input",
  "const-hex",
  "heck 0.5.0",
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "proc-macro-error2",
  "proc-macro2 1.0.93",
  "quote 1.0.38",
@@ -781,7 +781,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c"
 dependencies = [
  "num-traits",
- "rand",
+ "rand 0.8.5",
 ]
 
 [[package]]
@@ -791,7 +791,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185"
 dependencies = [
  "num-traits",
- "rand",
+ "rand 0.8.5",
  "rayon",
 ]
 
@@ -847,13 +847,29 @@ version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "22ad1373757efa0f70ec53939aabc7152e1591cb485208052993070ac8d2429d"
 dependencies = [
- "asn1-rs-derive",
+ "asn1-rs-derive 0.5.0",
  "asn1-rs-impl",
  "displaydoc",
  "nom",
  "num-traits",
  "rusticata-macros",
- "thiserror",
+ "thiserror 1.0.65",
+ "time",
+]
+
+[[package]]
+name = "asn1-rs"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "607495ec7113b178fbba7a6166a27f99e774359ef4823adbefd756b5b81d7970"
+dependencies = [
+ "asn1-rs-derive 0.6.0",
+ "asn1-rs-impl",
+ "displaydoc",
+ "nom",
+ "num-traits",
+ "rusticata-macros",
+ "thiserror 2.0.11",
  "time",
 ]
 
@@ -869,6 +885,18 @@ dependencies = [
  "synstructure 0.13.1",
 ]
 
+[[package]]
+name = "asn1-rs-derive"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c"
+dependencies = [
+ "proc-macro2 1.0.93",
+ "quote 1.0.38",
+ "syn 2.0.98",
+ "synstructure 0.13.1",
+]
+
 [[package]]
 name = "asn1-rs-impl"
 version = "0.2.0"
@@ -1664,9 +1692,9 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1"
 dependencies = [
- "getrandom",
+ "getrandom 0.2.10",
  "instant",
- "rand",
+ "rand 0.8.5",
 ]
 
 [[package]]
@@ -1696,7 +1724,7 @@ dependencies = [
  "ark-serialize 0.4.2",
  "ark-std 0.4.0",
  "dleq_vrf",
- "rand_chacha",
+ "rand_chacha 0.3.1",
  "rand_core 0.6.4",
  "ring 0.1.0",
  "sha2 0.10.8",
@@ -1747,15 +1775,6 @@ version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
 
-[[package]]
-name = "basic-toml"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2db21524cad41c5591204d22d75e1970a2d1f71060214ca931dc7d5afe2c14e5"
-dependencies = [
- "serde",
-]
-
 [[package]]
 name = "binary-merkle-tree"
 version = "13.0.0"
@@ -2058,7 +2077,7 @@ version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "68534a48cbf63a4b1323c433cf21238c9ec23711e0df13b08c33e5c2082663ce"
 dependencies = [
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -3127,9 +3146,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "bytes"
-version = "1.7.2"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3"
+checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
 dependencies = [
  "serde",
 ]
@@ -3203,7 +3222,7 @@ dependencies = [
  "semver 1.0.18",
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -3598,7 +3617,7 @@ checksum = "a90d114103adbc625300f346d4d09dfb4ab1c4a8df6868435dd903392ecf4354"
 dependencies = [
  "libc",
  "once_cell",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
  "wasm-bindgen",
 ]
 
@@ -3819,7 +3838,7 @@ dependencies = [
  "fflonk",
  "getrandom_or_panic",
  "merlin",
- "rand_chacha",
+ "rand_chacha 0.3.1",
 ]
 
 [[package]]
@@ -3921,7 +3940,7 @@ version = "0.1.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9d7d6ab3c3a2282db210df5f02c4dab6e0a7057af0fb7ebd4070f30fe05c0ddb"
 dependencies = [
- "getrandom",
+ "getrandom 0.2.10",
  "once_cell",
  "proc-macro-hack",
  "tiny-keccak",
@@ -4161,12 +4180,14 @@ dependencies = [
  "rococo-runtime-constants 7.0.0",
  "scale-info",
  "serde",
+ "serde_json",
  "sp-api 26.0.0",
  "sp-block-builder 26.0.0",
  "sp-consensus-aura 0.32.0",
  "sp-core 28.0.0",
  "sp-genesis-builder 0.8.0",
  "sp-inherents 26.0.0",
+ "sp-keyring 31.0.0",
  "sp-offchain 26.0.0",
  "sp-runtime 31.0.1",
  "sp-session 27.0.0",
@@ -4247,6 +4268,7 @@ dependencies = [
  "pallet-multisig 28.0.0",
  "pallet-proxy 28.0.0",
  "pallet-session 28.0.0",
+ "pallet-sudo 28.0.0",
  "pallet-timestamp 27.0.0",
  "pallet-transaction-payment 28.0.0",
  "pallet-transaction-payment-rpc-runtime-api 28.0.0",
@@ -4260,12 +4282,14 @@ dependencies = [
  "polkadot-runtime-common 7.0.0",
  "scale-info",
  "serde",
+ "serde_json",
  "sp-api 26.0.0",
  "sp-block-builder 26.0.0",
  "sp-consensus-aura 0.32.0",
  "sp-core 28.0.0",
  "sp-genesis-builder 0.8.0",
  "sp-inherents 26.0.0",
+ "sp-keyring 31.0.0",
  "sp-offchain 26.0.0",
  "sp-runtime 31.0.1",
  "sp-session 27.0.0",
@@ -4730,7 +4754,7 @@ dependencies = [
  "sp-inherents 26.0.0",
  "sp-runtime 31.0.1",
  "sp-state-machine 0.35.0",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -4828,7 +4852,7 @@ dependencies = [
  "polkadot-node-subsystem",
  "polkadot-overseer",
  "polkadot-primitives 7.0.0",
- "rand",
+ "rand 0.8.5",
  "rstest",
  "sc-cli",
  "sc-client-api",
@@ -4982,7 +5006,7 @@ dependencies = [
  "parity-scale-codec",
  "polkadot-parachain-primitives 6.0.0",
  "polkadot-runtime-parachains 7.0.0",
- "rand",
+ "rand 0.8.5",
  "sc-client-api",
  "scale-info",
  "sp-consensus-slots 0.32.0",
@@ -5505,7 +5529,7 @@ dependencies = [
  "sp-blockchain",
  "sp-state-machine 0.35.0",
  "sp-version 29.0.0",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -5558,7 +5582,7 @@ dependencies = [
  "polkadot-overseer",
  "portpicker",
  "prometheus",
- "rand",
+ "rand 0.8.5",
  "sc-client-api",
  "sc-rpc-api",
  "sc-service",
@@ -5576,7 +5600,7 @@ dependencies = [
  "sp-storage 19.0.0",
  "sp-version 29.0.0",
  "substrate-prometheus-endpoint",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tokio-util",
  "tracing",
@@ -5726,7 +5750,7 @@ dependencies = [
  "polkadot-service",
  "polkadot-test-service",
  "prometheus",
- "rand",
+ "rand 0.8.5",
  "sc-basic-authorship",
  "sc-block-builder",
  "sc-chain-spec",
@@ -5777,7 +5801,7 @@ dependencies = [
  "openssl-probe",
  "openssl-sys",
  "schannel",
- "socket2 0.5.7",
+ "socket2 0.5.8",
  "windows-sys 0.52.0",
 ]
 
@@ -5994,7 +6018,21 @@ version = "9.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553"
 dependencies = [
- "asn1-rs",
+ "asn1-rs 0.6.1",
+ "displaydoc",
+ "nom",
+ "num-bigint",
+ "num-traits",
+ "rusticata-macros",
+]
+
+[[package]]
+name = "der-parser"
+version = "10.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6"
+dependencies = [
+ "asn1-rs 0.7.0",
  "displaydoc",
  "nom",
  "num-bigint",
@@ -6639,7 +6677,7 @@ dependencies = [
  "serde",
  "serde_json",
  "sha3 0.10.8",
- "thiserror",
+ "thiserror 1.0.65",
  "uint 0.9.5",
 ]
 
@@ -6842,7 +6880,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec6f82451ff7f0568c6181287189126d492b5654e30a788add08027b6363d019"
 dependencies = [
  "fatality-proc-macro",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -6852,7 +6890,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "eb42427514b063d97ce21d5199f36c0c307d981434a6be32582bc79fe5bd2303"
 dependencies = [
  "expander",
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "proc-macro-crate 3.1.0",
  "proc-macro2 1.0.93",
  "quote 1.0.38",
@@ -6866,7 +6904,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e182f7dbc2ef73d9ef67351c5fbbea084729c48362d3ce9dd44c28e32e277fe5"
 dependencies = [
  "libc",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -6959,7 +6997,7 @@ dependencies = [
  "num-traits",
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "scale-info",
 ]
 
@@ -7007,7 +7045,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534"
 dependencies = [
  "byteorder",
- "rand",
+ "rand 0.8.5",
  "rustc-hex",
  "static_assertions",
 ]
@@ -7098,7 +7136,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8835f84f38484cc86f110a805655697908257fb9a7af005234060891557198e9"
 dependencies = [
  "nonempty",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -7195,7 +7233,7 @@ dependencies = [
  "parity-scale-codec",
  "polkadot-parachain-primitives 6.0.0",
  "polkadot-primitives 7.0.0",
- "rand",
+ "rand 0.8.5",
  "rand_pcg",
  "sc-block-builder",
  "sc-chain-spec",
@@ -7231,7 +7269,7 @@ dependencies = [
  "substrate-test-runtime",
  "subxt",
  "subxt-signer",
- "thiserror",
+ "thiserror 1.0.65",
  "thousands",
  "westend-runtime",
 ]
@@ -7314,7 +7352,7 @@ dependencies = [
  "frame-support 28.0.0",
  "frame-system 28.0.0",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "sp-arithmetic 23.0.0",
  "sp-core 28.0.0",
@@ -7351,7 +7389,7 @@ dependencies = [
  "frame-support 28.0.0",
  "honggfuzz",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "sp-arithmetic 23.0.0",
  "sp-npos-elections 26.0.0",
@@ -8133,7 +8171,19 @@ checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
 dependencies = [
  "cfg-if",
  "libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.13.3+wasi-0.2.2",
+ "windows-targets 0.52.6",
 ]
 
 [[package]]
@@ -8142,7 +8192,7 @@ version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9"
 dependencies = [
- "rand",
+ "rand 0.8.5",
  "rand_core 0.6.4",
 ]
 
@@ -8227,7 +8277,7 @@ dependencies = [
  "pin-project",
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.65",
  "wasm-bindgen",
  "wasm-bindgen-futures",
  "web-sys",
@@ -8317,7 +8367,7 @@ dependencies = [
  "nonzero_ext",
  "parking_lot 0.12.3",
  "quanta",
- "rand",
+ "rand 0.8.5",
  "smallvec",
 ]
 
@@ -8344,7 +8394,7 @@ dependencies = [
  "futures-sink",
  "futures-util",
  "http 0.2.9",
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "slab",
  "tokio",
  "tokio-util",
@@ -8363,7 +8413,7 @@ dependencies = [
  "futures-core",
  "futures-sink",
  "http 1.1.0",
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "slab",
  "tokio",
  "tokio-util",
@@ -8387,7 +8437,7 @@ dependencies = [
  "pest_derive",
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -8544,9 +8594,9 @@ dependencies = [
  "idna 0.4.0",
  "ipnet",
  "once_cell",
- "rand",
- "socket2 0.5.7",
- "thiserror",
+ "rand 0.8.5",
+ "socket2 0.5.8",
+ "thiserror 1.0.65",
  "tinyvec",
  "tokio",
  "tracing",
@@ -8566,10 +8616,10 @@ dependencies = [
  "lru-cache",
  "once_cell",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "resolv-conf",
  "smallvec",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tracing",
 ]
@@ -8742,7 +8792,7 @@ dependencies = [
  "httpdate",
  "itoa",
  "pin-project-lite",
- "socket2 0.5.7",
+ "socket2 0.4.9",
  "tokio",
  "tower-service",
  "tracing",
@@ -8844,7 +8894,7 @@ dependencies = [
  "http-body 1.0.0",
  "hyper 1.6.0",
  "pin-project-lite",
- "socket2 0.5.7",
+ "socket2 0.5.8",
  "tokio",
  "tower-service",
  "tracing",
@@ -8873,6 +8923,124 @@ dependencies = [
  "cc",
 ]
 
+[[package]]
+name = "icu_collections"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_locid_transform_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
+
+[[package]]
+name = "icu_normalizer"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "utf16_iter",
+ "utf8_iter",
+ "write16",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
+
+[[package]]
+name = "icu_properties"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_locid_transform",
+ "icu_properties_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
+
+[[package]]
+name = "icu_provider"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_provider_macros",
+ "stable_deref_trait",
+ "tinystr",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_provider_macros"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
+dependencies = [
+ "proc-macro2 1.0.93",
+ "quote 1.0.38",
+ "syn 2.0.98",
+]
+
 [[package]]
 name = "ident_case"
 version = "1.0.1"
@@ -8891,12 +9059,23 @@ dependencies = [
 
 [[package]]
 name = "idna"
-version = "0.5.0"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
 dependencies = [
- "unicode-bidi",
- "unicode-normalization",
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
+dependencies = [
+ "icu_normalizer",
+ "icu_properties",
 ]
 
 [[package]]
@@ -8941,7 +9120,7 @@ dependencies = [
  "http 0.2.9",
  "hyper 0.14.29",
  "log",
- "rand",
+ "rand 0.8.5",
  "tokio",
  "url",
  "xmltree",
@@ -9072,9 +9251,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.7.0"
+version = "2.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
+checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
 dependencies = [
  "equivalent",
  "hashbrown 0.15.2",
@@ -9150,7 +9329,7 @@ version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f"
 dependencies = [
- "socket2 0.5.7",
+ "socket2 0.5.8",
  "widestring",
  "windows-sys 0.48.0",
  "winreg",
@@ -9162,7 +9341,7 @@ version = "0.21.3"
 source = "git+https://github.com/chevdor/subwasm?rev=v0.21.3#aa8acb6fdfb34144ac51ab95618a9b37fa251295"
 dependencies = [
  "ipfs-unixfs",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -9301,7 +9480,7 @@ dependencies = [
  "combine",
  "jni-sys",
  "log",
- "thiserror",
+ "thiserror 1.0.65",
  "walkdir",
 ]
 
@@ -9343,7 +9522,7 @@ checksum = "ec9ad60d674508f3ca8f380a928cfe7b096bc729c4e2dbfe3852bc45da3ab30b"
 dependencies = [
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -9356,7 +9535,7 @@ dependencies = [
  "pest_derive",
  "regex",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -9405,7 +9584,7 @@ dependencies = [
  "rustls-pki-types",
  "rustls-platform-verifier",
  "soketto 0.8.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tokio-rustls 0.26.0",
  "tokio-util",
@@ -9429,11 +9608,11 @@ dependencies = [
  "jsonrpsee-types",
  "parking_lot 0.12.3",
  "pin-project",
- "rand",
+ "rand 0.8.5",
  "rustc-hash 2.0.0",
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tokio-stream",
  "tracing",
@@ -9458,7 +9637,7 @@ dependencies = [
  "rustls-platform-verifier",
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tower",
  "tracing",
@@ -9497,7 +9676,7 @@ dependencies = [
  "serde",
  "serde_json",
  "soketto 0.8.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tokio-stream",
  "tokio-util",
@@ -9514,7 +9693,7 @@ dependencies = [
  "http 1.1.0",
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -9667,16 +9846,16 @@ dependencies = [
  "kube-core",
  "pem 3.0.4",
  "pin-project",
- "rand",
+ "rand 0.8.5",
  "rustls 0.21.7",
  "rustls-pemfile 1.0.3",
  "secrecy 0.8.0",
  "serde",
  "serde_json",
  "serde_yaml",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
- "tokio-tungstenite",
+ "tokio-tungstenite 0.20.1",
  "tokio-util",
  "tower",
  "tower-http 0.4.4",
@@ -9697,7 +9876,7 @@ dependencies = [
  "once_cell",
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -9720,7 +9899,7 @@ dependencies = [
  "serde",
  "serde_json",
  "smallvec",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tokio-util",
  "tracing",
@@ -9785,7 +9964,7 @@ checksum = "1530c5b973eeed4ac216af7e24baf5737645a6272e361f1fb95710678b67d9cc"
 dependencies = [
  "enumflags2",
  "libc",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -9894,7 +10073,7 @@ dependencies = [
  "either",
  "futures",
  "futures-timer",
- "getrandom",
+ "getrandom 0.2.10",
  "libp2p-allow-block-list",
  "libp2p-connection-limits",
  "libp2p-core",
@@ -9916,7 +10095,7 @@ dependencies = [
  "multiaddr 0.18.1",
  "pin-project",
  "rw-stream-sink",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -9961,10 +10140,10 @@ dependencies = [
  "parking_lot 0.12.3",
  "pin-project",
  "quick-protobuf 0.8.1",
- "rand",
+ "rand 0.8.5",
  "rw-stream-sink",
  "smallvec",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "unsigned-varint 0.8.0",
  "void",
@@ -10005,7 +10184,7 @@ dependencies = [
  "quick-protobuf 0.8.1",
  "quick-protobuf-codec",
  "smallvec",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "void",
 ]
@@ -10021,9 +10200,9 @@ dependencies = [
  "hkdf",
  "multihash 0.19.1",
  "quick-protobuf 0.8.1",
- "rand",
+ "rand 0.8.5",
  "sha2 0.10.8",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "zeroize",
 ]
@@ -10047,10 +10226,10 @@ dependencies = [
  "libp2p-swarm",
  "quick-protobuf 0.8.1",
  "quick-protobuf-codec",
- "rand",
+ "rand 0.8.5",
  "sha2 0.10.8",
  "smallvec",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "uint 0.9.5",
  "void",
@@ -10070,9 +10249,9 @@ dependencies = [
  "libp2p-core",
  "libp2p-identity",
  "libp2p-swarm",
- "rand",
+ "rand 0.8.5",
  "smallvec",
- "socket2 0.5.7",
+ "socket2 0.5.8",
  "tokio",
  "tracing",
  "void",
@@ -10112,11 +10291,11 @@ dependencies = [
  "multihash 0.19.1",
  "once_cell",
  "quick-protobuf 0.8.1",
- "rand",
+ "rand 0.8.5",
  "sha2 0.10.8",
  "snow",
  "static_assertions",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "x25519-dalek",
  "zeroize",
@@ -10134,7 +10313,7 @@ dependencies = [
  "libp2p-core",
  "libp2p-identity",
  "libp2p-swarm",
- "rand",
+ "rand 0.8.5",
  "tracing",
  "void",
  "web-time",
@@ -10155,11 +10334,11 @@ dependencies = [
  "libp2p-tls",
  "parking_lot 0.12.3",
  "quinn",
- "rand",
+ "rand 0.8.5",
  "ring 0.17.8",
  "rustls 0.23.18",
- "socket2 0.5.7",
- "thiserror",
+ "socket2 0.5.8",
+ "thiserror 1.0.65",
  "tokio",
  "tracing",
 ]
@@ -10177,7 +10356,7 @@ dependencies = [
  "libp2p-core",
  "libp2p-identity",
  "libp2p-swarm",
- "rand",
+ "rand 0.8.5",
  "smallvec",
  "tracing",
  "void",
@@ -10200,7 +10379,7 @@ dependencies = [
  "lru 0.12.3",
  "multistream-select",
  "once_cell",
- "rand",
+ "rand 0.8.5",
  "smallvec",
  "tokio",
  "tracing",
@@ -10232,7 +10411,7 @@ dependencies = [
  "libc",
  "libp2p-core",
  "libp2p-identity",
- "socket2 0.5.7",
+ "socket2 0.5.8",
  "tokio",
  "tracing",
 ]
@@ -10251,8 +10430,8 @@ dependencies = [
  "ring 0.17.8",
  "rustls 0.23.18",
  "rustls-webpki 0.101.4",
- "thiserror",
- "x509-parser",
+ "thiserror 1.0.65",
+ "x509-parser 0.16.0",
  "yasna",
 ]
 
@@ -10287,7 +10466,7 @@ dependencies = [
  "pin-project-lite",
  "rw-stream-sink",
  "soketto 0.8.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "url",
  "webpki-roots 0.25.2",
@@ -10302,10 +10481,10 @@ dependencies = [
  "either",
  "futures",
  "libp2p-core",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "yamux 0.12.1",
- "yamux 0.13.3",
+ "yamux 0.13.4",
 ]
 
 [[package]]
@@ -10336,7 +10515,7 @@ dependencies = [
  "libsecp256k1-core",
  "libsecp256k1-gen-ecmult",
  "libsecp256k1-gen-genmult",
- "rand",
+ "rand 0.8.5",
  "serde",
  "sha2 0.9.9",
  "typenum",
@@ -10475,11 +10654,17 @@ dependencies = [
  "paste",
 ]
 
+[[package]]
+name = "litemap"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
+
 [[package]]
 name = "litep2p"
-version = "0.9.0"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ca6ee50a125dc4fc4e9a3ae3640010796d1d07bc517a0ac715fdf0b24a0b6ac"
+checksum = "3e5a3d13ee6af6f01bb2093aa6d5f29b79ede7de6277e5d0394e8f5d8eaa5a86"
 dependencies = [
  "async-trait",
  "bs58",
@@ -10490,18 +10675,17 @@ dependencies = [
  "futures-timer",
  "hex-literal",
  "hickory-resolver",
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "libc",
- "mockall 0.13.0",
+ "mockall 0.13.1",
  "multiaddr 0.17.1",
  "multihash 0.17.0",
  "network-interface",
- "nohash-hasher",
  "parking_lot 0.12.3",
  "pin-project",
  "prost 0.12.6",
  "prost-build",
- "rand",
+ "rand 0.8.5",
  "rcgen 0.10.0",
  "ring 0.16.20",
  "rustls 0.20.9",
@@ -10510,19 +10694,19 @@ dependencies = [
  "simple-dns",
  "smallvec",
  "snow",
- "socket2 0.5.7",
- "static_assertions",
- "thiserror",
+ "socket2 0.5.8",
+ "thiserror 2.0.11",
  "tokio",
  "tokio-stream",
- "tokio-tungstenite",
+ "tokio-tungstenite 0.26.2",
  "tokio-util",
  "tracing",
- "uint 0.9.5",
+ "uint 0.10.0",
  "unsigned-varint 0.8.0",
  "url",
  "x25519-dalek",
- "x509-parser",
+ "x509-parser 0.17.0",
+ "yamux 0.13.4",
  "yasna",
  "zeroize",
 ]
@@ -10893,7 +11077,7 @@ checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
 dependencies = [
  "hermit-abi 0.3.9",
  "libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
  "windows-sys 0.52.0",
 ]
 
@@ -10914,11 +11098,11 @@ dependencies = [
  "lioness",
  "log",
  "parking_lot 0.12.3",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "rand_distr",
  "subtle 2.5.0",
- "thiserror",
+ "thiserror 1.0.65",
  "zeroize",
 ]
 
@@ -10977,14 +11161,14 @@ dependencies = [
 
 [[package]]
 name = "mockall"
-version = "0.13.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4c28b3fb6d753d28c20e826cd46ee611fda1cf3cde03a443a974043247c065a"
+checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2"
 dependencies = [
  "cfg-if",
  "downcast",
  "fragile",
- "mockall_derive 0.13.0",
+ "mockall_derive 0.13.1",
  "predicates 3.0.3",
  "predicates-tree",
 ]
@@ -11003,9 +11187,9 @@ dependencies = [
 
 [[package]]
 name = "mockall_derive"
-version = "0.13.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "341014e7f530314e9a1fdbc7400b244efea7122662c96bfa248c31da5bfb2020"
+checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898"
 dependencies = [
  "cfg-if",
  "proc-macro2 1.0.93",
@@ -11206,7 +11390,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7bddcd3bf5144b6392de80e04c347cd7fab2508f6df16a85fc496ecd5cec39bc"
 dependencies = [
  "clap 3.2.25",
- "rand",
+ "rand 0.8.5",
 ]
 
 [[package]]
@@ -11267,7 +11451,7 @@ dependencies = [
  "anyhow",
  "byteorder",
  "paste",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -11281,7 +11465,7 @@ dependencies = [
  "log",
  "netlink-packet-core",
  "netlink-sys",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -11306,7 +11490,7 @@ checksum = "ae72fd9dbd7f55dda80c00d66acc3b2130436fcba9ea89118fc508eaae48dfb0"
 dependencies = [
  "cc",
  "libc",
- "thiserror",
+ "thiserror 1.0.65",
  "winapi",
 ]
 
@@ -11374,7 +11558,7 @@ dependencies = [
  "node-primitives",
  "node-testing",
  "parity-db",
- "rand",
+ "rand 0.8.5",
  "sc-basic-authorship",
  "sc-client-api",
  "sc-transaction-pool",
@@ -11594,7 +11778,7 @@ dependencies = [
  "num-integer",
  "num-iter",
  "num-traits",
- "rand",
+ "rand 0.8.5",
  "smallvec",
  "zeroize",
 ]
@@ -11739,7 +11923,16 @@ version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1c958dd45046245b9c3c2547369bb634eb461670b2e7e0de552905801a648d1d"
 dependencies = [
- "asn1-rs",
+ "asn1-rs 0.6.1",
+]
+
+[[package]]
+name = "oid-registry"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7"
+dependencies = [
+ "asn1-rs 0.7.0",
 ]
 
 [[package]]
@@ -11829,7 +12022,7 @@ dependencies = [
  "orchestra-proc-macro",
  "pin-project",
  "prioritized-metered-channel",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
 ]
 
@@ -11840,7 +12033,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f7b1d40dd8f367db3c65bec8d3dd47d4a604ee8874480738f93191bddab4e0e0"
 dependencies = [
  "expander",
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "itertools 0.11.0",
  "petgraph",
  "proc-macro-crate 3.1.0",
@@ -12426,7 +12619,7 @@ dependencies = [
  "frame-election-provider-support 28.0.0",
  "honggfuzz",
  "pallet-bags-list 27.0.0",
- "rand",
+ "rand 0.8.5",
 ]
 
 [[package]]
@@ -12628,7 +12821,7 @@ dependencies = [
  "pallet-beefy-mmr 28.0.0",
  "pallet-mmr 27.0.0",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "serde",
  "sp-consensus-beefy 13.0.0",
@@ -12791,7 +12984,6 @@ dependencies = [
  "sp-core 28.0.0",
  "sp-io 30.0.0",
  "sp-runtime 31.0.1",
- "sp-std 14.0.0",
 ]
 
 [[package]]
@@ -12909,7 +13101,7 @@ dependencies = [
  "pallet-session 28.0.0",
  "pallet-timestamp 27.0.0",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "sp-consensus-aura 0.32.0",
  "sp-core 28.0.0",
@@ -12933,7 +13125,7 @@ dependencies = [
  "pallet-balances 39.0.0",
  "pallet-session 38.0.0",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "sp-runtime 39.0.2",
  "sp-staking 36.0.0",
@@ -13026,7 +13218,7 @@ dependencies = [
  "parity-scale-codec",
  "paste",
  "pretty_assertions",
- "rand",
+ "rand 0.8.5",
  "rand_pcg",
  "scale-info",
  "serde",
@@ -13062,7 +13254,7 @@ dependencies = [
  "pallet-contracts-uapi 12.0.0",
  "parity-scale-codec",
  "paste",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "serde",
  "smallvec",
@@ -13429,7 +13621,7 @@ dependencies = [
  "pallet-balances 28.0.0",
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "sp-arithmetic 23.0.0",
  "sp-core 28.0.0",
@@ -13453,7 +13645,7 @@ dependencies = [
  "pallet-election-provider-support-benchmarking 27.0.0",
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "sp-arithmetic 23.0.0",
  "sp-core 28.0.0",
@@ -13477,7 +13669,7 @@ dependencies = [
  "log",
  "pallet-election-provider-support-benchmarking 37.0.0",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "sp-arithmetic 26.0.0",
  "sp-core 34.0.0",
@@ -14057,7 +14249,7 @@ dependencies = [
  "frame-system 28.0.0",
  "log",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "rand_distr",
  "scale-info",
  "serde",
@@ -14471,7 +14663,7 @@ dependencies = [
  "honggfuzz",
  "log",
  "pallet-nomination-pools 25.0.0",
- "rand",
+ "rand 0.8.5",
  "sp-io 30.0.0",
  "sp-runtime 31.0.1",
  "sp-tracing 16.0.0",
@@ -15004,7 +15196,7 @@ dependencies = [
  "substrate-prometheus-endpoint",
  "subxt",
  "subxt-signer",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -15416,7 +15608,7 @@ dependencies = [
  "pallet-staking-reward-curve",
  "pallet-timestamp 27.0.0",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "sp-core 28.0.0",
  "sp-io 30.0.0",
@@ -15436,7 +15628,7 @@ dependencies = [
  "pallet-session 38.0.0",
  "pallet-staking 38.0.0",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "sp-runtime 39.0.2",
  "sp-session 36.0.0",
 ]
@@ -15476,7 +15668,7 @@ dependencies = [
  "log",
  "pallet-balances 28.0.0",
  "parity-scale-codec",
- "rand_chacha",
+ "rand_chacha 0.3.1",
  "scale-info",
  "sp-arithmetic 23.0.0",
  "sp-core 28.0.0",
@@ -15496,7 +15688,7 @@ dependencies = [
  "frame-system 38.0.0",
  "log",
  "parity-scale-codec",
- "rand_chacha",
+ "rand_chacha 0.3.1",
  "scale-info",
  "sp-arithmetic 26.0.0",
  "sp-io 38.0.0",
@@ -15519,8 +15711,8 @@ dependencies = [
  "pallet-staking-reward-curve",
  "pallet-timestamp 27.0.0",
  "parity-scale-codec",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "scale-info",
  "serde",
  "sp-application-crypto 30.0.0",
@@ -16536,7 +16728,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9"
 dependencies = [
  "bitcoin_hashes 0.13.0",
- "rand",
+ "rand 0.8.5",
  "rand_core 0.6.4",
  "serde",
  "unicode-normalization",
@@ -16563,7 +16755,7 @@ dependencies = [
  "lz4",
  "memmap2 0.5.10",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "siphasher 0.3.11",
  "snap",
 ]
@@ -17048,7 +17240,7 @@ version = "2.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1acb4a4365a13f749a93f1a094a7805e5cfa0955373a9de860d962eaa3a5fe5a"
 dependencies = [
- "thiserror",
+ "thiserror 1.0.65",
  "ucd-trie",
 ]
 
@@ -17093,7 +17285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
 dependencies = [
  "fixedbitset",
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
 ]
 
 [[package]]
@@ -17222,8 +17414,8 @@ dependencies = [
  "polkadot-node-subsystem-util",
  "polkadot-primitives 7.0.0",
  "polkadot-primitives-test-helpers",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "rand_core 0.6.4",
  "sc-keystore",
  "schnorrkel 0.11.4",
@@ -17249,8 +17441,8 @@ dependencies = [
  "polkadot-node-subsystem-test-helpers",
  "polkadot-node-subsystem-util",
  "polkadot-primitives 7.0.0",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "sp-application-crypto 30.0.0",
  "sp-authority-discovery 26.0.0",
  "sp-core 28.0.0",
@@ -17279,7 +17471,7 @@ dependencies = [
  "polkadot-primitives 7.0.0",
  "polkadot-primitives-test-helpers",
  "polkadot-subsystem-bench",
- "rand",
+ "rand 0.8.5",
  "rstest",
  "sc-network",
  "schnellru",
@@ -17287,7 +17479,7 @@ dependencies = [
  "sp-keyring 31.0.0",
  "sp-keystore 0.34.0",
  "sp-tracing 16.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17311,7 +17503,7 @@ dependencies = [
  "polkadot-primitives 7.0.0",
  "polkadot-primitives-test-helpers",
  "polkadot-subsystem-bench",
- "rand",
+ "rand 0.8.5",
  "rstest",
  "sc-network",
  "schnellru",
@@ -17319,7 +17511,7 @@ dependencies = [
  "sp-core 28.0.0",
  "sp-keyring 31.0.0",
  "sp-tracing 16.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tracing-gum",
 ]
@@ -17370,7 +17562,7 @@ dependencies = [
  "sp-maybe-compressed-blob 11.0.0",
  "sp-runtime 31.0.1",
  "substrate-build-script-utils",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -17399,7 +17591,7 @@ dependencies = [
  "sp-keystore 0.34.0",
  "sp-runtime 31.0.1",
  "sp-tracing 16.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio-util",
  "tracing-gum",
 ]
@@ -17437,7 +17629,7 @@ dependencies = [
  "fatality",
  "futures",
  "futures-timer",
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "parity-scale-codec",
  "polkadot-erasure-coding",
  "polkadot-node-network-protocol",
@@ -17454,7 +17646,7 @@ dependencies = [
  "sp-keyring 31.0.0",
  "sp-keystore 0.34.0",
  "sp-tracing 16.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17470,7 +17662,7 @@ dependencies = [
  "reed-solomon-novelpoly",
  "sp-core 28.0.0",
  "sp-trie 29.0.0",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -17488,8 +17680,8 @@ dependencies = [
  "polkadot-node-subsystem-util",
  "polkadot-primitives 7.0.0",
  "quickcheck",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "sc-network",
  "sc-network-common",
  "sp-application-crypto 30.0.0",
@@ -17528,7 +17720,7 @@ dependencies = [
  "sp-consensus",
  "sp-core 28.0.0",
  "sp-keyring 31.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17551,7 +17743,7 @@ dependencies = [
  "sp-core 28.0.0",
  "sp-keyring 31.0.0",
  "sp-maybe-compressed-blob 11.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17580,8 +17772,8 @@ dependencies = [
  "polkadot-primitives 7.0.0",
  "polkadot-primitives-test-helpers",
  "polkadot-subsystem-bench",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "rand_core 0.6.4",
  "sc-keystore",
  "schnellru",
@@ -17595,7 +17787,7 @@ dependencies = [
  "sp-keystore 0.34.0",
  "sp-runtime 31.0.1",
  "sp-tracing 16.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17623,8 +17815,8 @@ dependencies = [
  "polkadot-primitives 7.0.0",
  "polkadot-primitives-test-helpers",
  "polkadot-subsystem-bench",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "rand_core 0.6.4",
  "sc-keystore",
  "schnorrkel 0.11.4",
@@ -17637,7 +17829,7 @@ dependencies = [
  "sp-keystore 0.34.0",
  "sp-runtime 31.0.1",
  "sp-tracing 16.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17666,7 +17858,7 @@ dependencies = [
  "sp-core 28.0.0",
  "sp-keyring 31.0.0",
  "sp-tracing 16.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17695,7 +17887,7 @@ dependencies = [
  "sp-keyring 31.0.0",
  "sp-keystore 0.34.0",
  "sp-tracing 16.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17710,7 +17902,7 @@ dependencies = [
  "polkadot-primitives 7.0.0",
  "polkadot-primitives-test-helpers",
  "sp-keystore 0.34.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
  "wasm-timer",
 ]
@@ -17780,7 +17972,7 @@ dependencies = [
  "polkadot-node-subsystem-util",
  "polkadot-primitives 7.0.0",
  "sp-core 28.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17808,7 +18000,7 @@ dependencies = [
  "sp-keyring 31.0.0",
  "sp-keystore 0.34.0",
  "sp-tracing 16.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17824,7 +18016,7 @@ dependencies = [
  "polkadot-primitives 7.0.0",
  "sp-blockchain",
  "sp-inherents 26.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17840,11 +18032,11 @@ dependencies = [
  "polkadot-node-subsystem-util",
  "polkadot-primitives 7.0.0",
  "polkadot-primitives-test-helpers",
- "rand",
+ "rand 0.8.5",
  "rstest",
  "sp-core 28.0.0",
  "sp-tracing 16.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17866,7 +18058,7 @@ dependencies = [
  "schnellru",
  "sp-application-crypto 30.0.0",
  "sp-keystore 0.34.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17899,7 +18091,7 @@ dependencies = [
  "polkadot-parachain-primitives 6.0.0",
  "polkadot-primitives 7.0.0",
  "procfs",
- "rand",
+ "rand 0.8.5",
  "rococo-runtime",
  "rusty-fork",
  "sc-sysinfo",
@@ -17911,7 +18103,7 @@ dependencies = [
  "tempfile",
  "test-parachain-adder",
  "test-parachain-halt",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tracing-gum",
 ]
@@ -17935,7 +18127,7 @@ dependencies = [
  "sp-keyring 31.0.0",
  "sp-keystore 0.34.0",
  "sp-runtime 31.0.1",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -17962,7 +18154,7 @@ dependencies = [
  "sp-io 30.0.0",
  "sp-tracing 16.0.0",
  "tempfile",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -18068,14 +18260,14 @@ dependencies = [
  "parity-scale-codec",
  "polkadot-node-primitives",
  "polkadot-primitives 7.0.0",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "sc-authority-discovery",
  "sc-network",
  "sc-network-types",
  "sp-runtime 31.0.1",
  "strum 0.26.3",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -18101,7 +18293,7 @@ dependencies = [
  "sp-keystore 0.34.0",
  "sp-maybe-compressed-blob 11.0.0",
  "sp-runtime 31.0.1",
- "thiserror",
+ "thiserror 1.0.65",
  "zstd 0.12.4",
 ]
 
@@ -18159,7 +18351,7 @@ dependencies = [
  "sp-consensus-babe 0.32.0",
  "sp-runtime 31.0.1",
  "substrate-prometheus-endpoint",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -18192,14 +18384,14 @@ dependencies = [
  "polkadot-primitives 7.0.0",
  "polkadot-primitives-test-helpers",
  "prioritized-metered-channel",
- "rand",
+ "rand 0.8.5",
  "sc-client-api",
  "schnellru",
  "sp-application-crypto 30.0.0",
  "sp-core 28.0.0",
  "sp-keystore 0.34.0",
  "tempfile",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -18413,7 +18605,7 @@ dependencies = [
  "sp-runtime 31.0.1",
  "sp-staking 26.0.0",
  "sp-std 14.0.0",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -18475,7 +18667,7 @@ name = "polkadot-primitives-test-helpers"
 version = "1.0.0"
 dependencies = [
  "polkadot-primitives 7.0.0",
- "rand",
+ "rand 0.8.5",
  "sp-application-crypto 30.0.0",
  "sp-core 28.0.0",
  "sp-keyring 31.0.0",
@@ -18677,8 +18869,8 @@ dependencies = [
  "polkadot-primitives 7.0.0",
  "polkadot-primitives-test-helpers",
  "polkadot-runtime-metrics 7.0.0",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "rstest",
  "sc-keystore",
  "scale-info",
@@ -18734,8 +18926,8 @@ dependencies = [
  "polkadot-parachain-primitives 14.0.0",
  "polkadot-primitives 16.0.0",
  "polkadot-runtime-metrics 17.0.0",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "scale-info",
  "serde",
  "sp-api 34.0.0",
@@ -19430,7 +19622,7 @@ dependencies = [
  "polkadot-sdk-docs-first-pallet",
  "polkadot-sdk-docs-first-runtime",
  "polkadot-sdk-frame 0.1.0",
- "rand",
+ "rand 0.8.5",
  "sc-chain-spec",
  "sc-cli",
  "sc-client-db",
@@ -19680,7 +19872,7 @@ dependencies = [
  "staging-xcm 7.0.0",
  "substrate-prometheus-endpoint",
  "tempfile",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
  "westend-runtime",
  "westend-runtime-constants 7.0.0",
@@ -19698,7 +19890,7 @@ dependencies = [
  "fatality",
  "futures",
  "futures-timer",
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "parity-scale-codec",
  "polkadot-node-network-protocol",
  "polkadot-node-primitives",
@@ -19708,7 +19900,7 @@ dependencies = [
  "polkadot-primitives 7.0.0",
  "polkadot-primitives-test-helpers",
  "polkadot-subsystem-bench",
- "rand_chacha",
+ "rand_chacha 0.3.1",
  "rstest",
  "sc-keystore",
  "sc-network",
@@ -19719,7 +19911,7 @@ dependencies = [
  "sp-keystore 0.34.0",
  "sp-staking 26.0.0",
  "sp-tracing 16.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing-gum",
 ]
 
@@ -19779,8 +19971,8 @@ dependencies = [
  "prometheus",
  "pyroscope",
  "pyroscope_pprofrs",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "rand_core 0.6.4",
  "rand_distr",
  "sc-keystore",
@@ -19862,7 +20054,7 @@ dependencies = [
  "polkadot-node-subsystem-types",
  "polkadot-node-subsystem-util",
  "polkadot-primitives 7.0.0",
- "rand",
+ "rand 0.8.5",
  "sp-core 28.0.0",
  "sp-keystore 0.34.0",
  "substrate-build-script-utils",
@@ -19948,7 +20140,7 @@ dependencies = [
  "polkadot-runtime-parachains 7.0.0",
  "polkadot-service",
  "polkadot-test-runtime",
- "rand",
+ "rand 0.8.5",
  "sc-authority-discovery",
  "sc-chain-spec",
  "sc-cli",
@@ -20412,7 +20604,7 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "be97d76faf1bfab666e1375477b23fde79eccf0276e9b63b92a39d676a889ba9"
 dependencies = [
- "rand",
+ "rand 0.8.5",
 ]
 
 [[package]]
@@ -20438,7 +20630,7 @@ dependencies = [
  "smallvec",
  "symbolic-demangle",
  "tempfile",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -20564,7 +20756,7 @@ dependencies = [
  "futures",
  "futures-timer",
  "nanorand",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
 ]
 
@@ -20705,7 +20897,7 @@ dependencies = [
  "lazy_static",
  "memchr",
  "parking_lot 0.12.3",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -20754,8 +20946,8 @@ dependencies = [
  "bitflags 2.6.0",
  "lazy_static",
  "num-traits",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "rand_xorshift",
  "regex-syntax 0.8.5",
  "rusty-fork",
@@ -20884,7 +21076,7 @@ dependencies = [
  "names",
  "prost 0.11.9",
  "reqwest 0.11.27",
- "thiserror",
+ "thiserror 1.0.65",
  "url",
  "winapi",
 ]
@@ -20898,7 +21090,7 @@ dependencies = [
  "log",
  "pprof",
  "pyroscope",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -20912,7 +21104,7 @@ dependencies = [
  "mach2",
  "once_cell",
  "raw-cpuid",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
  "web-sys",
  "winapi",
 ]
@@ -20950,7 +21142,7 @@ dependencies = [
  "asynchronous-codec 0.7.0",
  "bytes",
  "quick-protobuf 0.8.1",
- "thiserror",
+ "thiserror 1.0.65",
  "unsigned-varint 0.8.0",
 ]
 
@@ -20973,7 +21165,7 @@ checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
 dependencies = [
  "env_logger 0.8.4",
  "log",
- "rand",
+ "rand 0.8.5",
 ]
 
 [[package]]
@@ -20989,8 +21181,8 @@ dependencies = [
  "quinn-udp",
  "rustc-hash 2.0.0",
  "rustls 0.23.18",
- "socket2 0.5.7",
- "thiserror",
+ "socket2 0.5.8",
+ "thiserror 1.0.65",
  "tokio",
  "tracing",
 ]
@@ -21002,12 +21194,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6"
 dependencies = [
  "bytes",
- "rand",
+ "rand 0.8.5",
  "ring 0.17.8",
  "rustc-hash 2.0.0",
  "rustls 0.23.18",
  "slab",
- "thiserror",
+ "thiserror 1.0.65",
  "tinyvec",
  "tracing",
 ]
@@ -21020,7 +21212,7 @@ checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285"
 dependencies = [
  "libc",
  "once_cell",
- "socket2 0.5.7",
+ "socket2 0.5.8",
  "tracing",
  "windows-sys 0.52.0",
 ]
@@ -21056,11 +21248,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
 dependencies = [
  "libc",
- "rand_chacha",
+ "rand_chacha 0.3.1",
  "rand_core 0.6.4",
  "serde",
 ]
 
+[[package]]
+name = "rand"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
+dependencies = [
+ "rand_chacha 0.9.0",
+ "rand_core 0.9.1",
+ "zerocopy 0.8.20",
+]
+
 [[package]]
 name = "rand_chacha"
 version = "0.3.1"
@@ -21071,6 +21274,16 @@ dependencies = [
  "rand_core 0.6.4",
 ]
 
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.9.1",
+]
+
 [[package]]
 name = "rand_core"
 version = "0.5.1"
@@ -21083,7 +21296,17 @@ version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
 dependencies = [
- "getrandom",
+ "getrandom 0.2.10",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a88e0da7a2c97baa202165137c158d0a2e824ac465d13d81046727b34cb247d3"
+dependencies = [
+ "getrandom 0.3.1",
+ "zerocopy 0.8.20",
 ]
 
 [[package]]
@@ -21093,7 +21316,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
 dependencies = [
  "num-traits",
- "rand",
+ "rand 0.8.5",
 ]
 
 [[package]]
@@ -21226,9 +21449,9 @@ version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
 dependencies = [
- "getrandom",
+ "getrandom 0.2.10",
  "redox_syscall 0.2.16",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -21240,7 +21463,7 @@ dependencies = [
  "derive_more 0.99.17",
  "fs-err",
  "static_init",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -21365,7 +21588,7 @@ dependencies = [
  "pallet-utility 28.0.0",
  "parity-scale-codec",
  "quick_cache",
- "rand",
+ "rand 0.8.5",
  "relay-utils",
  "sc-chain-spec",
  "sc-rpc-api",
@@ -21380,7 +21603,7 @@ dependencies = [
  "sp-trie 29.0.0",
  "sp-version 29.0.0",
  "staging-xcm 7.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -21404,7 +21627,7 @@ dependencies = [
  "sp-tracing 16.0.0",
  "substrate-prometheus-endpoint",
  "sysinfo",
- "thiserror",
+ "thiserror 1.0.65",
  "time",
  "tokio",
 ]
@@ -21571,7 +21794,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
 dependencies = [
  "cc",
  "cfg-if",
- "getrandom",
+ "getrandom 0.2.10",
  "libc",
  "spin 0.9.8",
  "untrusted 0.9.0",
@@ -21930,7 +22153,7 @@ dependencies = [
  "netlink-packet-route",
  "netlink-proto",
  "nix 0.24.3",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -21960,7 +22183,7 @@ dependencies = [
  "parity-scale-codec",
  "primitive-types 0.12.2",
  "proptest",
- "rand",
+ "rand 0.8.5",
  "rlp 0.5.2",
  "ruint-macro",
  "serde",
@@ -22337,7 +22560,7 @@ dependencies = [
  "log",
  "sp-core 28.0.0",
  "sp-wasm-interface 20.0.0",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -22349,7 +22572,7 @@ dependencies = [
  "log",
  "sp-core 33.0.1",
  "sp-wasm-interface 21.0.1",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -22361,7 +22584,7 @@ dependencies = [
  "log",
  "sp-core 34.0.0",
  "sp-wasm-interface 21.0.1",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -22379,7 +22602,7 @@ dependencies = [
  "prost 0.12.6",
  "prost-build",
  "quickcheck",
- "rand",
+ "rand 0.8.5",
  "sc-client-api",
  "sc-network",
  "sc-network-types",
@@ -22392,7 +22615,7 @@ dependencies = [
  "sp-tracing 16.0.0",
  "substrate-prometheus-endpoint",
  "substrate-test-runtime-client",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -22494,7 +22717,7 @@ dependencies = [
  "names",
  "parity-bip39",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "regex",
  "rpassword",
  "sc-client-api",
@@ -22518,7 +22741,7 @@ dependencies = [
  "sp-tracing 16.0.0",
  "sp-version 29.0.0",
  "tempfile",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -22547,7 +22770,7 @@ dependencies = [
  "sp-trie 29.0.0",
  "substrate-prometheus-endpoint",
  "substrate-test-runtime",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -22566,7 +22789,7 @@ dependencies = [
  "parity-db",
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "sc-client-api",
  "sc-state-db",
  "schnellru",
@@ -22603,7 +22826,7 @@ dependencies = [
  "sp-state-machine 0.35.0",
  "sp-test-primitives",
  "substrate-prometheus-endpoint",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -22640,7 +22863,7 @@ dependencies = [
  "substrate-prometheus-endpoint",
  "substrate-test-runtime-client",
  "tempfile",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -22682,7 +22905,7 @@ dependencies = [
  "sp-tracing 16.0.0",
  "substrate-prometheus-endpoint",
  "substrate-test-runtime-client",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -22710,7 +22933,7 @@ dependencies = [
  "sp-keystore 0.34.0",
  "sp-runtime 31.0.1",
  "substrate-test-runtime-client",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -22753,7 +22976,7 @@ dependencies = [
  "substrate-prometheus-endpoint",
  "substrate-test-runtime-client",
  "tempfile",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "wasm-timer",
 ]
@@ -22776,7 +22999,7 @@ dependencies = [
  "sp-core 28.0.0",
  "sp-runtime 31.0.1",
  "substrate-test-runtime-client",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -22808,7 +23031,7 @@ dependencies = [
  "log",
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "sc-block-builder",
  "sc-chain-spec",
  "sc-client-api",
@@ -22838,7 +23061,7 @@ dependencies = [
  "sp-tracing 16.0.0",
  "substrate-prometheus-endpoint",
  "substrate-test-runtime-client",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -22862,7 +23085,7 @@ dependencies = [
  "sp-keyring 31.0.0",
  "sp-runtime 31.0.1",
  "substrate-test-runtime-client",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -22900,7 +23123,7 @@ dependencies = [
  "substrate-prometheus-endpoint",
  "substrate-test-runtime-client",
  "substrate-test-runtime-transaction-pool",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -22925,7 +23148,7 @@ dependencies = [
  "sp-inherents 26.0.0",
  "sp-runtime 31.0.1",
  "substrate-prometheus-endpoint",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -23046,7 +23269,7 @@ dependencies = [
  "sc-allocator 23.0.0",
  "sp-maybe-compressed-blob 11.0.0",
  "sp-wasm-interface 20.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "wasm-instrument",
 ]
 
@@ -23060,7 +23283,7 @@ dependencies = [
  "sc-allocator 28.0.0",
  "sp-maybe-compressed-blob 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sp-wasm-interface 21.0.1",
- "thiserror",
+ "thiserror 1.0.65",
  "wasm-instrument",
 ]
 
@@ -23074,7 +23297,7 @@ dependencies = [
  "sc-allocator 29.0.0",
  "sp-maybe-compressed-blob 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sp-wasm-interface 21.0.1",
- "thiserror",
+ "thiserror 1.0.65",
  "wasm-instrument",
 ]
 
@@ -23201,7 +23424,7 @@ dependencies = [
  "sp-core 28.0.0",
  "sp-keystore 0.34.0",
  "tempfile",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -23229,7 +23452,7 @@ dependencies = [
  "sp-keystore 0.34.0",
  "sp-mixnet 0.4.0",
  "sp-runtime 31.0.1",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -23262,7 +23485,7 @@ dependencies = [
  "pin-project",
  "prost 0.12.6",
  "prost-build",
- "rand",
+ "rand 0.8.5",
  "sc-block-builder",
  "sc-client-api",
  "sc-consensus",
@@ -23287,7 +23510,7 @@ dependencies = [
  "substrate-test-runtime",
  "substrate-test-runtime-client",
  "tempfile",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tokio-stream",
  "tokio-test",
@@ -23350,7 +23573,7 @@ dependencies = [
  "sp-blockchain",
  "sp-core 28.0.0",
  "sp-runtime 31.0.1",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -23407,7 +23630,7 @@ dependencies = [
  "sp-tracing 16.0.0",
  "substrate-prometheus-endpoint",
  "substrate-test-runtime-client",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tokio-stream",
 ]
@@ -23423,7 +23646,7 @@ dependencies = [
  "libp2p",
  "log",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "sc-block-builder",
  "sc-client-api",
  "sc-consensus",
@@ -23476,8 +23699,8 @@ dependencies = [
  "multiaddr 0.18.1",
  "multihash 0.19.1",
  "quickcheck",
- "rand",
- "thiserror",
+ "rand 0.8.5",
+ "thiserror 1.0.65",
  "zeroize",
 ]
 
@@ -23500,7 +23723,7 @@ dependencies = [
  "once_cell",
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "rustls 0.23.18",
  "sc-block-builder",
  "sc-client-api",
@@ -23589,7 +23812,7 @@ dependencies = [
  "sp-rpc",
  "sp-runtime 31.0.1",
  "sp-version 29.0.0",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -23631,7 +23854,7 @@ dependencies = [
  "parity-scale-codec",
  "parking_lot 0.12.3",
  "pretty_assertions",
- "rand",
+ "rand 0.8.5",
  "sc-block-builder",
  "sc-chain-spec",
  "sc-client-api",
@@ -23655,7 +23878,7 @@ dependencies = [
  "substrate-test-runtime",
  "substrate-test-runtime-client",
  "substrate-test-runtime-transaction-pool",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tokio-stream",
 ]
@@ -23687,7 +23910,7 @@ dependencies = [
  "sp-version 29.0.0",
  "sp-wasm-interface 20.0.0",
  "subxt",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -23704,7 +23927,7 @@ dependencies = [
  "parity-scale-codec",
  "parking_lot 0.12.3",
  "pin-project",
- "rand",
+ "rand 0.8.5",
  "sc-chain-spec",
  "sc-client-api",
  "sc-client-db",
@@ -23749,7 +23972,7 @@ dependencies = [
  "substrate-test-runtime",
  "substrate-test-runtime-client",
  "tempfile",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tracing",
  "tracing-futures",
@@ -23829,7 +24052,7 @@ dependencies = [
  "fs4",
  "log",
  "sp-core 28.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -23848,7 +24071,7 @@ dependencies = [
  "serde_json",
  "sp-blockchain",
  "sp-runtime 31.0.1",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -23859,7 +24082,7 @@ dependencies = [
  "futures",
  "libc",
  "log",
- "rand",
+ "rand 0.8.5",
  "rand_pcg",
  "regex",
  "sc-telemetry",
@@ -23881,11 +24104,11 @@ dependencies = [
  "log",
  "parking_lot 0.12.3",
  "pin-project",
- "rand",
+ "rand 0.8.5",
  "sc-utils",
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.65",
  "wasm-timer",
 ]
 
@@ -23912,7 +24135,7 @@ dependencies = [
  "sp-rpc",
  "sp-runtime 31.0.1",
  "sp-tracing 16.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "tracing-log 0.2.0",
  "tracing-subscriber 0.3.18",
@@ -23938,7 +24161,7 @@ dependencies = [
  "criterion",
  "futures",
  "futures-timer",
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "itertools 0.11.0",
  "linked-hash-map",
  "log",
@@ -23961,7 +24184,7 @@ dependencies = [
  "substrate-test-runtime",
  "substrate-test-runtime-client",
  "substrate-test-runtime-transaction-pool",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tokio-stream",
  "tracing",
@@ -23973,7 +24196,7 @@ version = "28.0.0"
 dependencies = [
  "async-trait",
  "futures",
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "log",
  "parity-scale-codec",
  "serde",
@@ -23981,7 +24204,7 @@ dependencies = [
  "sp-blockchain",
  "sp-core 28.0.0",
  "sp-runtime 31.0.1",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -24124,7 +24347,7 @@ dependencies = [
  "quote 1.0.38",
  "scale-info",
  "syn 2.0.98",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -24300,7 +24523,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252"
 dependencies = [
  "bitcoin_hashes 0.14.0",
- "rand",
+ "rand 0.8.5",
  "secp256k1-sys 0.10.1",
 ]
 
@@ -24496,7 +24719,7 @@ version = "1.0.132"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
 dependencies = [
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "itoa",
  "memchr",
  "ryu",
@@ -24530,7 +24753,7 @@ version = "0.9.34+deprecated"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
 dependencies = [
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "itoa",
  "ryu",
  "serde",
@@ -24686,9 +24909,9 @@ dependencies = [
 
 [[package]]
 name = "simple-dns"
-version = "0.7.1"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c80e565e7dcc4f1ef247e2f395550d4cf7d777746d5988e7e4e3156b71077fc"
+checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a"
 dependencies = [
  "bitflags 2.6.0",
 ]
@@ -24861,8 +25084,8 @@ dependencies = [
  "pbkdf2",
  "pin-project",
  "poly1305",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "ruzstd 0.4.0",
  "schnorrkel 0.10.2",
  "serde",
@@ -24915,8 +25138,8 @@ dependencies = [
  "pbkdf2",
  "pin-project",
  "poly1305",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "ruzstd 0.6.0",
  "schnorrkel 0.11.4",
  "serde",
@@ -24958,8 +25181,8 @@ dependencies = [
  "no-std-net",
  "parking_lot 0.12.3",
  "pin-project",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "serde",
  "serde_json",
  "siphasher 0.3.11",
@@ -24994,8 +25217,8 @@ dependencies = [
  "lru 0.12.3",
  "parking_lot 0.12.3",
  "pin-project",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "serde",
  "serde_json",
  "siphasher 1.0.1",
@@ -25141,7 +25364,7 @@ dependencies = [
  "hex-literal",
  "parity-bytes",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "rlp 0.6.1",
  "scale-info",
  "serde",
@@ -25182,7 +25405,7 @@ dependencies = [
  "hex",
  "lazy_static",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "snowbridge-amcl",
  "zeroize",
@@ -25252,7 +25475,7 @@ dependencies = [
  "log",
  "pallet-timestamp 27.0.0",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "serde",
  "serde_json",
@@ -25655,9 +25878,9 @@ dependencies = [
 
 [[package]]
 name = "socket2"
-version = "0.5.7"
+version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
+checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
 dependencies = [
  "libc",
  "windows-sys 0.52.0",
@@ -25674,7 +25897,7 @@ dependencies = [
  "futures",
  "httparse",
  "log",
- "rand",
+ "rand 0.8.5",
  "sha-1",
 ]
 
@@ -25690,7 +25913,7 @@ dependencies = [
  "http 1.1.0",
  "httparse",
  "log",
- "rand",
+ "rand 0.8.5",
  "sha1",
 ]
 
@@ -25796,7 +26019,7 @@ dependencies = [
  "sp-test-primitives",
  "sp-trie 29.0.0",
  "sp-version 29.0.0",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -25819,7 +26042,7 @@ dependencies = [
  "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sp-trie 35.0.0",
  "sp-version 35.0.0",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -25842,7 +26065,7 @@ dependencies = [
  "sp-state-machine 0.43.0",
  "sp-trie 37.0.0",
  "sp-version 37.0.0",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -25986,7 +26209,7 @@ dependencies = [
  "num-traits",
  "parity-scale-codec",
  "primitive-types 0.13.1",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "serde",
  "sp-crypto-hashing 0.1.0",
@@ -26096,7 +26319,7 @@ dependencies = [
  "sp-database",
  "sp-runtime 31.0.1",
  "sp-state-machine 0.35.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
 ]
 
@@ -26112,7 +26335,7 @@ dependencies = [
  "sp-runtime 31.0.1",
  "sp-state-machine 0.35.0",
  "sp-test-primitives",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -26345,7 +26568,7 @@ dependencies = [
  "parking_lot 0.12.3",
  "paste",
  "primitive-types 0.13.1",
- "rand",
+ "rand 0.8.5",
  "regex",
  "scale-info",
  "schnorrkel 0.11.4",
@@ -26361,7 +26584,7 @@ dependencies = [
  "sp-storage 19.0.0",
  "ss58-registry",
  "substrate-bip39 0.4.7",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "w3f-bls",
  "zeroize",
@@ -26394,7 +26617,7 @@ dependencies = [
  "parking_lot 0.12.3",
  "paste",
  "primitive-types 0.12.2",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "schnorrkel 0.11.4",
  "secp256k1 0.28.2",
@@ -26408,7 +26631,7 @@ dependencies = [
  "sp-storage 21.0.0",
  "ss58-registry",
  "substrate-bip39 0.6.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "w3f-bls",
  "zeroize",
@@ -26441,7 +26664,7 @@ dependencies = [
  "parking_lot 0.12.3",
  "paste",
  "primitive-types 0.12.2",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "schnorrkel 0.11.4",
  "secp256k1 0.28.2",
@@ -26455,7 +26678,7 @@ dependencies = [
  "sp-storage 21.0.0",
  "ss58-registry",
  "substrate-bip39 0.6.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "w3f-bls",
  "zeroize",
@@ -26488,7 +26711,7 @@ dependencies = [
  "parking_lot 0.12.3",
  "paste",
  "primitive-types 0.12.2",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "schnorrkel 0.11.4",
  "secp256k1 0.28.2",
@@ -26502,7 +26725,7 @@ dependencies = [
  "sp-storage 21.0.0",
  "ss58-registry",
  "substrate-bip39 0.6.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "w3f-bls",
  "zeroize",
@@ -26535,7 +26758,7 @@ dependencies = [
  "parking_lot 0.12.3",
  "paste",
  "primitive-types 0.13.1",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "schnorrkel 0.11.4",
  "secp256k1 0.28.2",
@@ -26549,7 +26772,7 @@ dependencies = [
  "sp-storage 22.0.0",
  "ss58-registry",
  "substrate-bip39 0.6.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "w3f-bls",
  "zeroize",
@@ -26821,7 +27044,7 @@ dependencies = [
  "parity-scale-codec",
  "scale-info",
  "sp-runtime 31.0.1",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -26835,7 +27058,7 @@ dependencies = [
  "parity-scale-codec",
  "scale-info",
  "sp-runtime 39.0.2",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -26970,8 +27193,8 @@ version = "0.34.0"
 dependencies = [
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "sp-core 28.0.0",
  "sp-externalities 0.25.0",
 ]
@@ -27016,7 +27239,7 @@ dependencies = [
 name = "sp-maybe-compressed-blob"
 version = "11.0.0"
 dependencies = [
- "thiserror",
+ "thiserror 1.0.65",
  "zstd 0.12.4",
 ]
 
@@ -27026,7 +27249,7 @@ version = "11.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f0c768c11afbe698a090386876911da4236af199cd38a5866748df4d8628aeff"
 dependencies = [
- "thiserror",
+ "thiserror 1.0.65",
  "zstd 0.12.4",
 ]
 
@@ -27086,7 +27309,7 @@ dependencies = [
  "sp-core 28.0.0",
  "sp-debug-derive 14.0.0",
  "sp-runtime 31.0.1",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -27104,7 +27327,7 @@ dependencies = [
  "sp-core 34.0.0",
  "sp-debug-derive 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sp-runtime 39.0.2",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -27112,7 +27335,7 @@ name = "sp-npos-elections"
 version = "26.0.0"
 dependencies = [
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "serde",
  "sp-arithmetic 23.0.0",
@@ -27141,7 +27364,7 @@ version = "2.0.0-alpha.5"
 dependencies = [
  "clap 4.5.13",
  "honggfuzz",
- "rand",
+ "rand 0.8.5",
  "sp-npos-elections 26.0.0",
  "sp-runtime 31.0.1",
 ]
@@ -27208,7 +27431,7 @@ dependencies = [
  "num-traits",
  "parity-scale-codec",
  "paste",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "serde",
  "serde_json",
@@ -27242,7 +27465,7 @@ dependencies = [
  "log",
  "parity-scale-codec",
  "paste",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "serde",
  "simple-mermaid 0.1.1",
@@ -27268,7 +27491,7 @@ dependencies = [
  "num-traits",
  "parity-scale-codec",
  "paste",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "serde",
  "simple-mermaid 0.1.1",
@@ -27294,7 +27517,7 @@ dependencies = [
  "num-traits",
  "parity-scale-codec",
  "paste",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "serde",
  "simple-mermaid 0.1.1",
@@ -27564,14 +27787,14 @@ dependencies = [
  "parity-scale-codec",
  "parking_lot 0.12.3",
  "pretty_assertions",
- "rand",
+ "rand 0.8.5",
  "smallvec",
  "sp-core 28.0.0",
  "sp-externalities 0.25.0",
  "sp-panic-handler 13.0.0",
  "sp-runtime 31.0.1",
  "sp-trie 29.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "trie-db",
 ]
@@ -27586,13 +27809,13 @@ dependencies = [
  "log",
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "smallvec",
  "sp-core 32.0.0",
  "sp-externalities 0.28.0",
  "sp-panic-handler 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sp-trie 34.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "trie-db",
 ]
@@ -27607,13 +27830,13 @@ dependencies = [
  "log",
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "smallvec",
  "sp-core 33.0.1",
  "sp-externalities 0.28.0",
  "sp-panic-handler 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sp-trie 35.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "trie-db",
 ]
@@ -27628,13 +27851,13 @@ dependencies = [
  "log",
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "smallvec",
  "sp-core 34.0.0",
  "sp-externalities 0.29.0",
  "sp-panic-handler 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sp-trie 37.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "trie-db",
 ]
@@ -27648,7 +27871,7 @@ dependencies = [
  "ed25519-dalek",
  "hkdf",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "sha2 0.10.8",
  "sp-api 26.0.0",
@@ -27658,7 +27881,7 @@ dependencies = [
  "sp-externalities 0.25.0",
  "sp-runtime 31.0.1",
  "sp-runtime-interface 24.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "x25519-dalek",
 ]
 
@@ -27673,7 +27896,7 @@ dependencies = [
  "ed25519-dalek",
  "hkdf",
  "parity-scale-codec",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "sha2 0.10.8",
  "sp-api 34.0.0",
@@ -27683,7 +27906,7 @@ dependencies = [
  "sp-externalities 0.29.0",
  "sp-runtime 39.0.2",
  "sp-runtime-interface 28.0.0",
- "thiserror",
+ "thiserror 1.0.65",
  "x25519-dalek",
 ]
 
@@ -27772,7 +27995,7 @@ dependencies = [
  "parity-scale-codec",
  "sp-inherents 26.0.0",
  "sp-runtime 31.0.1",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -27785,7 +28008,7 @@ dependencies = [
  "parity-scale-codec",
  "sp-inherents 34.0.0",
  "sp-runtime 39.0.2",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -27880,13 +28103,13 @@ dependencies = [
  "nohash-hasher",
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "schnellru",
  "sp-core 28.0.0",
  "sp-externalities 0.25.0",
  "sp-runtime 31.0.1",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "trie-bench",
  "trie-db",
@@ -27907,12 +28130,12 @@ dependencies = [
  "nohash-hasher",
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "schnellru",
  "sp-core 32.0.0",
  "sp-externalities 0.28.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "trie-db",
  "trie-root",
@@ -27931,12 +28154,12 @@ dependencies = [
  "nohash-hasher",
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "schnellru",
  "sp-core 33.0.1",
  "sp-externalities 0.28.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "trie-db",
  "trie-root",
@@ -27955,12 +28178,12 @@ dependencies = [
  "nohash-hasher",
  "parity-scale-codec",
  "parking_lot 0.12.3",
- "rand",
+ "rand 0.8.5",
  "scale-info",
  "schnellru",
  "sp-core 34.0.0",
  "sp-externalities 0.29.0",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "trie-db",
  "trie-root",
@@ -27979,7 +28202,7 @@ dependencies = [
  "sp-runtime 31.0.1",
  "sp-std 14.0.0",
  "sp-version-proc-macro 13.0.0",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -27997,7 +28220,7 @@ dependencies = [
  "sp-runtime 37.0.0",
  "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sp-version-proc-macro 14.0.0",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -28015,7 +28238,7 @@ dependencies = [
  "sp-runtime 39.0.2",
  "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sp-version-proc-macro 14.0.0",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -28188,7 +28411,7 @@ dependencies = [
  "hashbrown 0.14.5",
  "hashlink 0.9.1",
  "hex",
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "log",
  "memchr",
  "once_cell",
@@ -28199,7 +28422,7 @@ dependencies = [
  "sha2 0.10.8",
  "smallvec",
  "sqlformat",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tokio-stream",
  "tracing",
@@ -28274,7 +28497,7 @@ dependencies = [
  "memchr",
  "once_cell",
  "percent-encoding",
- "rand",
+ "rand 0.8.5",
  "rsa",
  "serde",
  "sha1",
@@ -28282,7 +28505,7 @@ dependencies = [
  "smallvec",
  "sqlx-core",
  "stringprep",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "whoami",
 ]
@@ -28313,14 +28536,14 @@ dependencies = [
  "md-5",
  "memchr",
  "once_cell",
- "rand",
+ "rand 0.8.5",
  "serde",
  "serde_json",
  "sha2 0.10.8",
  "smallvec",
  "sqlx-core",
  "stringprep",
- "thiserror",
+ "thiserror 1.0.65",
  "tracing",
  "whoami",
 ]
@@ -28427,7 +28650,7 @@ dependencies = [
  "parity-scale-codec",
  "polkadot-sdk 0.1.0",
  "pretty_assertions",
- "rand",
+ "rand 0.8.5",
  "regex",
  "sc-service-test",
  "scale-info",
@@ -28459,7 +28682,7 @@ dependencies = [
  "sp-io 30.0.0",
  "sp-runtime 31.0.1",
  "sp-statement-store 10.0.0",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -28539,6 +28762,7 @@ dependencies = [
 name = "staging-xcm-builder"
 version = "7.0.0"
 dependencies = [
+ "environmental",
  "frame-support 28.0.0",
  "frame-system 28.0.0",
  "impl-trait-for-tuples",
@@ -28868,7 +29092,7 @@ dependencies = [
  "scale-info",
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.65",
  "wasm-testbed",
 ]
 
@@ -28922,7 +29146,7 @@ dependencies = [
  "hyper-util",
  "log",
  "prometheus",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
 ]
 
@@ -28966,7 +29190,7 @@ dependencies = [
  "sp-trie 29.0.0",
  "structopt",
  "strum 0.26.3",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -28996,7 +29220,7 @@ dependencies = [
  "sp-io 35.0.0",
  "sp-runtime 36.0.0",
  "sp-wasm-interface 21.0.1",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -29123,7 +29347,7 @@ dependencies = [
  "sp-blockchain",
  "sp-runtime 31.0.1",
  "substrate-test-runtime-client",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -29209,7 +29433,7 @@ dependencies = [
  "ipfs-hasher",
  "log",
  "num-format",
- "rand",
+ "rand 0.8.5",
  "reqwest 0.12.9",
  "scale-info",
  "semver 1.0.18",
@@ -29217,7 +29441,7 @@ dependencies = [
  "serde_json",
  "sp-version 35.0.0",
  "substrate-differ",
- "thiserror",
+ "thiserror 1.0.65",
  "url",
  "uuid",
  "wasm-loader",
@@ -29253,7 +29477,7 @@ dependencies = [
  "subxt-lightclient",
  "subxt-macro",
  "subxt-metadata",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tokio-util",
  "tracing",
@@ -29276,7 +29500,7 @@ dependencies = [
  "scale-typegen",
  "subxt-metadata",
  "syn 2.0.98",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -29319,7 +29543,7 @@ dependencies = [
  "serde",
  "serde_json",
  "smoldot-light 0.16.2",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tokio-stream",
  "tracing",
@@ -29392,7 +29616,7 @@ checksum = "3082b17a86e3c3fe45d858d94d68f6b5247caace193dad6201688f24db8ba9bb"
 dependencies = [
  "hex",
  "parity-scale-codec",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -29640,6 +29864,12 @@ version = "0.12.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a"
 
+[[package]]
+name = "target-triple"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42a4d50cdb458045afc8131fd91b64904da29548bcb63c7236e0844936c13078"
+
 [[package]]
 name = "tempfile"
 version = "3.14.0"
@@ -29869,7 +30099,16 @@ version = "1.0.65"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5"
 dependencies = [
- "thiserror-impl",
+ "thiserror-impl 1.0.65",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
+dependencies = [
+ "thiserror-impl 2.0.11",
 ]
 
 [[package]]
@@ -29903,6 +30142,17 @@ dependencies = [
  "syn 2.0.98",
 ]
 
+[[package]]
+name = "thiserror-impl"
+version = "2.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
+dependencies = [
+ "proc-macro2 1.0.93",
+ "quote 1.0.38",
+ "syn 2.0.98",
+]
+
 [[package]]
 name = "thousands"
 version = "0.2.0"
@@ -30001,6 +30251,16 @@ dependencies = [
  "crunchy",
 ]
 
+[[package]]
+name = "tinystr"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
 [[package]]
 name = "tinytemplate"
 version = "1.2.1"
@@ -30039,7 +30299,7 @@ dependencies = [
  "parking_lot 0.12.3",
  "pin-project-lite",
  "signal-hook-registry",
- "socket2 0.5.7",
+ "socket2 0.5.8",
  "tokio-macros",
  "windows-sys 0.52.0",
 ]
@@ -30082,7 +30342,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f"
 dependencies = [
  "pin-project",
- "rand",
+ "rand 0.8.5",
  "tokio",
 ]
 
@@ -30140,13 +30400,26 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c"
 dependencies = [
  "futures-util",
  "log",
- "rustls 0.21.7",
- "rustls-native-certs 0.6.3",
  "tokio",
- "tokio-rustls 0.24.1",
  "tungstenite 0.20.1",
 ]
 
+[[package]]
+name = "tokio-tungstenite"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084"
+dependencies = [
+ "futures-util",
+ "log",
+ "rustls 0.23.18",
+ "rustls-native-certs 0.8.0",
+ "rustls-pki-types",
+ "tokio",
+ "tokio-rustls 0.26.0",
+ "tungstenite 0.26.2",
+]
+
 [[package]]
 name = "tokio-util"
 version = "0.7.12"
@@ -30198,7 +30471,7 @@ version = "0.19.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
 dependencies = [
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "toml_datetime",
  "winnow 0.5.15",
 ]
@@ -30209,7 +30482,7 @@ version = "0.21.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
 dependencies = [
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "toml_datetime",
  "winnow 0.5.15",
 ]
@@ -30220,7 +30493,7 @@ version = "0.22.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
 dependencies = [
- "indexmap 2.7.0",
+ "indexmap 2.7.1",
  "serde",
  "serde_spanned",
  "toml_datetime",
@@ -30488,18 +30761,18 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
 
 [[package]]
 name = "trybuild"
-version = "1.0.89"
+version = "1.0.103"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a9d3ba662913483d6722303f619e75ea10b7855b0f8e0d72799cf8621bb488f"
+checksum = "b812699e0c4f813b872b373a4471717d9eb550da14b311058a4d9cf4173cbca6"
 dependencies = [
- "basic-toml",
  "dissimilar",
  "glob",
- "once_cell",
  "serde",
  "serde_derive",
  "serde_json",
+ "target-triple",
  "termcolor",
+ "toml 0.8.19",
 ]
 
 [[package]]
@@ -30520,10 +30793,9 @@ dependencies = [
  "http 0.2.9",
  "httparse",
  "log",
- "rand",
- "rustls 0.21.7",
+ "rand 0.8.5",
  "sha1",
- "thiserror",
+ "thiserror 1.0.65",
  "url",
  "utf-8",
 ]
@@ -30540,12 +30812,32 @@ dependencies = [
  "http 1.1.0",
  "httparse",
  "log",
- "rand",
+ "rand 0.8.5",
  "rustls 0.22.4",
  "rustls-native-certs 0.7.0",
  "rustls-pki-types",
  "sha1",
- "thiserror",
+ "thiserror 1.0.65",
+ "url",
+ "utf-8",
+]
+
+[[package]]
+name = "tungstenite"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13"
+dependencies = [
+ "bytes",
+ "data-encoding",
+ "http 1.1.0",
+ "httparse",
+ "log",
+ "rand 0.9.0",
+ "rustls 0.23.18",
+ "rustls-pki-types",
+ "sha1",
+ "thiserror 2.0.11",
  "url",
  "utf-8",
 ]
@@ -30564,7 +30856,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
 dependencies = [
  "cfg-if",
  "digest 0.10.7",
- "rand",
+ "rand 0.8.5",
  "static_assertions",
 ]
 
@@ -30749,12 +31041,12 @@ dependencies = [
 
 [[package]]
 name = "url"
-version = "2.5.2"
+version = "2.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
+checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
 dependencies = [
  "form_urlencoded",
- "idna 0.5.0",
+ "idna 1.0.3",
  "percent-encoding",
  "serde",
 ]
@@ -30765,6 +31057,18 @@ version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
 
+[[package]]
+name = "utf16_iter"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
 [[package]]
 name = "utf8parse"
 version = "0.2.1"
@@ -30777,7 +31081,7 @@ version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
 dependencies = [
- "getrandom",
+ "getrandom 0.2.10",
 ]
 
 [[package]]
@@ -30861,12 +31165,12 @@ dependencies = [
  "arrayref",
  "constcat",
  "digest 0.10.7",
- "rand",
- "rand_chacha",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "rand_core 0.6.4",
  "sha2 0.10.8",
  "sha3 0.10.8",
- "thiserror",
+ "thiserror 1.0.65",
  "zeroize",
 ]
 
@@ -30910,6 +31214,15 @@ version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
+[[package]]
+name = "wasi"
+version = "0.13.3+wasi-0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
+dependencies = [
+ "wit-bindgen-rt",
+]
+
 [[package]]
 name = "wasite"
 version = "0.1.0"
@@ -31016,7 +31329,7 @@ dependencies = [
  "serde_json",
  "sp-maybe-compressed-blob 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "subrpcer",
- "thiserror",
+ "thiserror 1.0.65",
  "tungstenite 0.21.0",
  "ureq",
  "url",
@@ -31033,7 +31346,7 @@ dependencies = [
  "strum 0.24.1",
  "strum_macros 0.24.3",
  "tempfile",
- "thiserror",
+ "thiserror 1.0.65",
  "wasm-opt-cxx-sys",
  "wasm-opt-sys",
 ]
@@ -31081,7 +31394,7 @@ dependencies = [
  "sp-version 35.0.0",
  "sp-wasm-interface 21.0.1",
  "substrate-runtime-proposal-hash",
- "thiserror",
+ "thiserror 1.0.65",
  "wasm-loader",
 ]
 
@@ -31263,7 +31576,7 @@ dependencies = [
  "log",
  "object 0.30.4",
  "target-lexicon",
- "thiserror",
+ "thiserror 1.0.65",
  "wasmparser",
  "wasmtime-cranelift-shared",
  "wasmtime-environ",
@@ -31298,7 +31611,7 @@ dependencies = [
  "object 0.30.4",
  "serde",
  "target-lexicon",
- "thiserror",
+ "thiserror 1.0.65",
  "wasmparser",
  "wasmtime-types",
 ]
@@ -31365,7 +31678,7 @@ dependencies = [
  "memfd",
  "memoffset 0.8.0",
  "paste",
- "rand",
+ "rand 0.8.5",
  "rustix 0.36.15",
  "wasmtime-asm-macros",
  "wasmtime-environ",
@@ -31381,7 +31694,7 @@ checksum = "a4f6fffd2a1011887d57f07654dd112791e872e3ff4a2e626aee8059ee17f06f"
 dependencies = [
  "cranelift-entity",
  "serde",
- "thiserror",
+ "thiserror 1.0.65",
  "wasmparser",
 ]
 
@@ -32005,6 +32318,27 @@ dependencies = [
  "windows-sys 0.48.0",
 ]
 
+[[package]]
+name = "wit-bindgen-rt"
+version = "0.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
+dependencies = [
+ "bitflags 2.6.0",
+]
+
+[[package]]
+name = "write16"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
+
+[[package]]
+name = "writeable"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
+
 [[package]]
 name = "wyz"
 version = "0.5.1"
@@ -32016,9 +32350,9 @@ dependencies = [
 
 [[package]]
 name = "x25519-dalek"
-version = "2.0.0"
+version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96"
+checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
 dependencies = [
  "curve25519-dalek 4.1.3",
  "rand_core 0.6.4",
@@ -32032,14 +32366,31 @@ version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69"
 dependencies = [
- "asn1-rs",
+ "asn1-rs 0.6.1",
  "data-encoding",
- "der-parser",
+ "der-parser 9.0.0",
  "lazy_static",
  "nom",
- "oid-registry",
+ "oid-registry 0.7.0",
  "rusticata-macros",
- "thiserror",
+ "thiserror 1.0.65",
+ "time",
+]
+
+[[package]]
+name = "x509-parser"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460"
+dependencies = [
+ "asn1-rs 0.7.0",
+ "data-encoding",
+ "der-parser 10.0.0",
+ "lazy_static",
+ "nom",
+ "oid-registry 0.8.1",
+ "rusticata-macros",
+ "thiserror 2.0.11",
  "time",
 ]
 
@@ -32322,22 +32673,22 @@ dependencies = [
  "nohash-hasher",
  "parking_lot 0.12.3",
  "pin-project",
- "rand",
+ "rand 0.8.5",
  "static_assertions",
 ]
 
 [[package]]
 name = "yamux"
-version = "0.13.3"
+version = "0.13.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a31b5e376a8b012bee9c423acdbb835fc34d45001cfa3106236a624e4b738028"
+checksum = "17610762a1207ee816c6fadc29220904753648aba0a9ed61c7b8336e80a559c4"
 dependencies = [
  "futures",
  "log",
  "nohash-hasher",
  "parking_lot 0.12.3",
  "pin-project",
- "rand",
+ "rand 0.8.5",
  "static_assertions",
  "web-time",
 ]
@@ -32363,13 +32714,46 @@ dependencies = [
  "time",
 ]
 
+[[package]]
+name = "yoke"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
+dependencies = [
+ "proc-macro2 1.0.93",
+ "quote 1.0.38",
+ "syn 2.0.98",
+ "synstructure 0.13.1",
+]
+
 [[package]]
 name = "zerocopy"
 version = "0.7.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
 dependencies = [
- "zerocopy-derive",
+ "zerocopy-derive 0.7.32",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.8.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dde3bb8c68a8f3f1ed4ac9221aad6b10cece3e60a8e2ea54a6a2dec806d0084c"
+dependencies = [
+ "zerocopy-derive 0.8.20",
 ]
 
 [[package]]
@@ -32383,6 +32767,38 @@ dependencies = [
  "syn 2.0.98",
 ]
 
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eea57037071898bf96a6da35fd626f4f27e9cee3ead2a6c703cf09d472b2e700"
+dependencies = [
+ "proc-macro2 1.0.93",
+ "quote 1.0.38",
+ "syn 2.0.98",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
+dependencies = [
+ "proc-macro2 1.0.93",
+ "quote 1.0.38",
+ "syn 2.0.98",
+ "synstructure 0.13.1",
+]
+
 [[package]]
 name = "zeroize"
 version = "1.8.1"
@@ -32403,6 +32819,28 @@ dependencies = [
  "syn 2.0.98",
 ]
 
+[[package]]
+name = "zerovec"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
+dependencies = [
+ "proc-macro2 1.0.93",
+ "quote 1.0.38",
+ "syn 2.0.98",
+]
+
 [[package]]
 name = "zombienet-backchannel"
 version = "1.0.0"
@@ -32412,9 +32850,9 @@ dependencies = [
  "reqwest 0.12.9",
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
- "tokio-tungstenite",
+ "tokio-tungstenite 0.20.1",
  "tracing-gum",
  "url",
 ]
@@ -32432,7 +32870,7 @@ dependencies = [
  "reqwest 0.11.27",
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "toml 0.8.19",
  "tracing",
@@ -32454,7 +32892,7 @@ dependencies = [
  "libp2p",
  "libsecp256k1",
  "multiaddr 0.18.1",
- "rand",
+ "rand 0.8.5",
  "regex",
  "reqwest 0.11.27",
  "serde",
@@ -32463,7 +32901,7 @@ dependencies = [
  "sp-core 35.0.0",
  "subxt",
  "subxt-signer",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tracing",
  "uuid",
@@ -32481,7 +32919,7 @@ checksum = "8a52a796a1521cf6420cc6384eac9ef25a146d453b568969774af643f3ecdc97"
 dependencies = [
  "pest",
  "pest_derive",
- "thiserror",
+ "thiserror 1.0.65",
 ]
 
 [[package]]
@@ -32505,7 +32943,7 @@ dependencies = [
  "serde_yaml",
  "sha2 0.10.8",
  "tar",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tokio-util",
  "tracing",
@@ -32543,10 +32981,10 @@ dependencies = [
  "async-trait",
  "futures",
  "nix 0.29.0",
- "rand",
+ "rand 0.8.5",
  "regex",
  "reqwest 0.11.27",
- "thiserror",
+ "thiserror 1.0.65",
  "tokio",
  "tracing",
  "uuid",
diff --git a/Cargo.toml b/Cargo.toml
index 0769a95932d443fa31772f376756edc51c0db98a..b73e87d9bac2662ea97bbf55ce3197b98420ac4a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -827,7 +827,7 @@ hyper-rustls = { version = "0.27.3", default-features = false, features = ["http
 hyper-util = { version = "0.1.5", default-features = false }
 impl-serde = { version = "0.5.0", default-features = false }
 impl-trait-for-tuples = { version = "0.2.2" }
-indexmap = { version = "2.0.0" }
+indexmap = { version = "2.7.1" }
 indicatif = { version = "0.17.7" }
 integer-sqrt = { version = "0.1.2" }
 ip_network = { version = "0.4.1" }
@@ -856,7 +856,7 @@ linked-hash-map = { version = "0.5.4" }
 linked_hash_set = { version = "0.1.4" }
 linregress = { version = "0.5.1" }
 lite-json = { version = "0.2.0", default-features = false }
-litep2p = { version = "0.9.0", features = ["websocket"] }
+litep2p = { version = "0.9.1", features = ["websocket"] }
 log = { version = "0.4.22", default-features = false }
 macro_magic = { version = "0.5.1" }
 maplit = { version = "1.0.2" }
@@ -1369,12 +1369,12 @@ trie-bench = { version = "0.39.0" }
 trie-db = { version = "0.29.1", default-features = false }
 trie-root = { version = "0.18.0", default-features = false }
 trie-standardmap = { version = "0.16.0" }
-trybuild = { version = "1.0.89" }
+trybuild = { version = "1.0.103" }
 tt-call = { version = "1.0.8" }
 tuplex = { version = "0.1", default-features = false }
 twox-hash = { version = "1.6.3", default-features = false }
 unsigned-varint = { version = "0.7.2" }
-url = { version = "2.4.0" }
+url = { version = "2.5.4" }
 void = { version = "1.0.2" }
 w3f-bls = { version = "0.1.3", default-features = false }
 wait-timeout = { version = "0.2" }
diff --git a/bridges/bin/runtime-common/src/extensions.rs b/bridges/bin/runtime-common/src/extensions.rs
index 44e6b40b7e0c76a805d485fb9cad28ff18d25e7a..a8ae17d23128e63d49502561d25d7b830fe89fcf 100644
--- a/bridges/bin/runtime-common/src/extensions.rs
+++ b/bridges/bin/runtime-common/src/extensions.rs
@@ -111,7 +111,7 @@ where
 		// let's slash registered relayer
 		RelayersPallet::<T>::slash_and_deregister(
 			relayer,
-			ExplicitOrAccountParams::Explicit(SlashAccount::get()),
+			ExplicitOrAccountParams::Explicit::<_, ()>(SlashAccount::get()),
 		);
 	}
 }
@@ -182,7 +182,7 @@ where
 		// let's slash registered relayer
 		RelayersPallet::<T>::slash_and_deregister(
 			relayer,
-			ExplicitOrAccountParams::Explicit(SlashAccount::get()),
+			ExplicitOrAccountParams::Explicit::<_, ()>(SlashAccount::get()),
 		);
 	}
 }
diff --git a/bridges/bin/runtime-common/src/mock.rs b/bridges/bin/runtime-common/src/mock.rs
index 88037d9deff52e468215eff10910d65e7e75388b..b081eafe94271c182a9cf29a5408108b36595b48 100644
--- a/bridges/bin/runtime-common/src/mock.rs
+++ b/bridges/bin/runtime-common/src/mock.rs
@@ -24,7 +24,7 @@ use bp_messages::{
 	ChainWithMessages, HashedLaneId, LaneIdType, MessageNonce,
 };
 use bp_parachains::SingleParaStoredHeaderDataBuilder;
-use bp_relayers::PayRewardFromAccount;
+use bp_relayers::{PayRewardFromAccount, RewardsAccountParams};
 use bp_runtime::{messages::MessageDispatchResult, Chain, ChainId, Parachain};
 use codec::Encode;
 use frame_support::{
@@ -70,7 +70,8 @@ pub type BridgedChainHeader =
 	sp_runtime::generic::Header<BridgedChainBlockNumber, BridgedChainHasher>;
 
 /// Rewards payment procedure.
-pub type TestPaymentProcedure = PayRewardFromAccount<Balances, ThisChainAccountId, TestLaneIdType>;
+pub type TestPaymentProcedure =
+	PayRewardFromAccount<Balances, ThisChainAccountId, TestLaneIdType, RewardBalance>;
 /// Stake that we are using in tests.
 pub type TestStake = ConstU64<5_000>;
 /// Stake and slash mechanism to use in tests.
@@ -89,6 +90,8 @@ pub type TestLaneIdType = HashedLaneId;
 pub fn test_lane_id() -> TestLaneIdType {
 	TestLaneIdType::try_new(1, 2).unwrap()
 }
+/// Reward measurement type.
+pub type RewardBalance = u32;
 
 /// Bridged chain id used in tests.
 pub const TEST_BRIDGED_CHAIN_ID: ChainId = *b"brdg";
@@ -197,7 +200,7 @@ impl pallet_bridge_messages::Config for TestRuntime {
 		TestRuntime,
 		(),
 		(),
-		ConstU64<100_000>,
+		ConstU32<100_000>,
 	>;
 	type OnMessagesDelivered = ();
 
@@ -210,11 +213,12 @@ impl pallet_bridge_messages::Config for TestRuntime {
 
 impl pallet_bridge_relayers::Config for TestRuntime {
 	type RuntimeEvent = RuntimeEvent;
-	type Reward = ThisChainBalance;
+	type RewardBalance = RewardBalance;
+	type Reward = RewardsAccountParams<pallet_bridge_messages::LaneIdOf<TestRuntime, ()>>;
 	type PaymentProcedure = TestPaymentProcedure;
 	type StakeAndSlash = TestStakeAndSlash;
+	type Balance = ThisChainBalance;
 	type WeightInfo = ();
-	type LaneId = TestLaneIdType;
 }
 
 /// Dummy message dispatcher.
diff --git a/bridges/modules/grandpa/src/lib.rs b/bridges/modules/grandpa/src/lib.rs
index 22a15ec4062f723223ce80cd9b18bd2a11914327..c2c1218418fb1f95c0b1c99fcfcba9d446fc7dd5 100644
--- a/bridges/modules/grandpa/src/lib.rs
+++ b/bridges/modules/grandpa/src/lib.rs
@@ -789,12 +789,9 @@ where
 	pub fn synced_headers_grandpa_info() -> Vec<StoredHeaderGrandpaInfo<BridgedHeader<T, I>>> {
 		frame_system::Pallet::<T>::read_events_no_consensus()
 			.filter_map(|event| {
-				if let Event::<T, I>::UpdatedBestFinalizedHeader { grandpa_info, .. } =
-					event.event.try_into().ok()?
-				{
-					return Some(grandpa_info)
-				}
-				None
+				let Event::<T, I>::UpdatedBestFinalizedHeader { grandpa_info, .. } =
+					event.event.try_into().ok()?;
+				Some(grandpa_info)
 			})
 			.collect()
 	}
diff --git a/bridges/modules/messages/src/lanes_manager.rs b/bridges/modules/messages/src/lanes_manager.rs
index 27cab48535d7bc354d31a7f11ac616edf7e879d1..c785ed4e01efa59d2c5d72283a1eddb432c04818 100644
--- a/bridges/modules/messages/src/lanes_manager.rs
+++ b/bridges/modules/messages/src/lanes_manager.rs
@@ -25,13 +25,15 @@ use bp_messages::{
 	MessageNonce, OutboundLaneData,
 };
 use bp_runtime::AccountIdOf;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_support::{ensure, sp_runtime::RuntimeDebug, PalletError};
 use scale_info::TypeInfo;
 use sp_std::marker::PhantomData;
 
 /// Lanes manager errors.
-#[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo)]
+#[derive(
+	Encode, Decode, DecodeWithMemTracking, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo,
+)]
 pub enum LanesManagerError {
 	/// Inbound lane already exists.
 	InboundLaneAlreadyExists,
diff --git a/bridges/modules/messages/src/outbound_lane.rs b/bridges/modules/messages/src/outbound_lane.rs
index c72713e7455a648622e9432a5c0c7bbd29b118b7..1e4411f7b4e29471926a955b01f907ef028d758c 100644
--- a/bridges/modules/messages/src/outbound_lane.rs
+++ b/bridges/modules/messages/src/outbound_lane.rs
@@ -22,7 +22,7 @@ use bp_messages::{
 	ChainWithMessages, DeliveredMessages, LaneState, MessageNonce, OutboundLaneData,
 	UnrewardedRelayer,
 };
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use frame_support::{traits::Get, BoundedVec, PalletError};
 use scale_info::TypeInfo;
 use sp_runtime::RuntimeDebug;
@@ -65,7 +65,9 @@ impl<T: Config<I>, I: 'static> Get<u32> for StoredMessagePayloadLimit<T, I> {
 pub type StoredMessagePayload<T, I> = BoundedVec<u8, StoredMessagePayloadLimit<T, I>>;
 
 /// Result of messages receival confirmation.
-#[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo)]
+#[derive(
+	Encode, Decode, DecodeWithMemTracking, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo,
+)]
 pub enum ReceptionConfirmationError {
 	/// Bridged chain is trying to confirm more messages than we have generated. May be a result
 	/// of invalid bridged chain storage.
diff --git a/bridges/modules/relayers/Cargo.toml b/bridges/modules/relayers/Cargo.toml
index 97ed61a9004e8be23334960fcebc8c8fc8a387a3..d0b19f612d2a6649d0dee3182b342b5d8ea04f2f 100644
--- a/bridges/modules/relayers/Cargo.toml
+++ b/bridges/modules/relayers/Cargo.toml
@@ -31,7 +31,6 @@ frame-system = { workspace = true }
 pallet-transaction-payment = { workspace = true }
 sp-arithmetic = { workspace = true }
 sp-runtime = { workspace = true }
-sp-std = { workspace = true }
 
 [dev-dependencies]
 bp-parachains = { workspace = true }
@@ -69,7 +68,6 @@ std = [
 	"sp-core/std",
 	"sp-io/std",
 	"sp-runtime/std",
-	"sp-std/std",
 ]
 runtime-benchmarks = [
 	"frame-benchmarking/runtime-benchmarks",
diff --git a/bridges/modules/relayers/src/benchmarking.rs b/bridges/modules/relayers/src/benchmarking.rs
index 8fe3fc11d6ae67c151119e585a3048149a81ea36..1d6ee56639e057beff62c4e647364c55cfb4ae9a 100644
--- a/bridges/modules/relayers/src/benchmarking.rs
+++ b/bridges/modules/relayers/src/benchmarking.rs
@@ -20,8 +20,10 @@
 
 use crate::*;
 
-use bp_relayers::RewardsAccountOwner;
-use frame_benchmarking::{benchmarks_instance_pallet, whitelisted_caller};
+use frame_benchmarking::{
+	benchmarks_instance_pallet, whitelisted_caller, BenchmarkError, BenchmarkResult,
+};
+use frame_support::{assert_ok, weights::Weight};
 use frame_system::RawOrigin;
 use sp_runtime::traits::One;
 
@@ -33,35 +35,70 @@ pub struct Pallet<T: Config<I>, I: 'static = ()>(crate::Pallet<T, I>);
 
 /// Trait that must be implemented by runtime.
 pub trait Config<I: 'static = ()>: crate::Config<I> {
-	/// Lane id to use in benchmarks.
-	fn bench_lane_id() -> Self::LaneId {
-		Self::LaneId::default()
-	}
+	/// `T::Reward` to use in benchmarks.
+	fn bench_reward() -> Self::Reward;
 	/// Prepare environment for paying given reward for serving given lane.
 	fn prepare_rewards_account(
-		account_params: RewardsAccountParams<Self::LaneId>,
-		reward: Self::Reward,
-	);
+		reward_kind: Self::Reward,
+		reward: Self::RewardBalance,
+	) -> Option<BeneficiaryOf<Self, I>>;
 	/// Give enough balance to given account.
-	fn deposit_account(account: Self::AccountId, balance: Self::Reward);
+	fn deposit_account(account: Self::AccountId, balance: Self::Balance);
+}
+
+fn assert_last_event<T: Config<I>, I: 'static>(
+	generic_event: <T as pallet::Config<I>>::RuntimeEvent,
+) {
+	frame_system::Pallet::<T>::assert_last_event(generic_event.into());
 }
 
 benchmarks_instance_pallet! {
+	where_clause { where
+		BeneficiaryOf<T, I>: From<<T as frame_system::Config>::AccountId>,
+	}
+
 	// Benchmark `claim_rewards` call.
 	claim_rewards {
-		let lane = T::bench_lane_id();
-		let account_params =
-			RewardsAccountParams::new(lane, *b"test", RewardsAccountOwner::ThisChain);
+		let reward_kind = T::bench_reward();
 		let relayer: T::AccountId = whitelisted_caller();
-		let reward = T::Reward::from(REWARD_AMOUNT);
+		let reward_balance = T::RewardBalance::from(REWARD_AMOUNT);
 
-		T::prepare_rewards_account(account_params, reward);
-		RelayerRewards::<T, I>::insert(&relayer, account_params, reward);
-	}: _(RawOrigin::Signed(relayer), account_params)
+		let _ = T::prepare_rewards_account(reward_kind, reward_balance);
+		RelayerRewards::<T, I>::insert(&relayer, reward_kind, reward_balance);
+	}: _(RawOrigin::Signed(relayer.clone()), reward_kind)
 	verify {
 		// we can't check anything here, because `PaymentProcedure` is responsible for
 		// payment logic, so we assume that if call has succeeded, the procedure has
 		// also completed successfully
+		assert_last_event::<T, I>(Event::RewardPaid {
+			relayer: relayer.clone(),
+			reward_kind,
+			reward_balance,
+			beneficiary: relayer.into(),
+		}.into());
+	}
+
+	// Benchmark `claim_rewards_to` call.
+	claim_rewards_to {
+		let reward_kind = T::bench_reward();
+		let relayer: T::AccountId = whitelisted_caller();
+		let reward_balance = T::RewardBalance::from(REWARD_AMOUNT);
+
+		let Some(alternative_beneficiary) = T::prepare_rewards_account(reward_kind, reward_balance) else {
+			return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)));
+		};
+		RelayerRewards::<T, I>::insert(&relayer, reward_kind, reward_balance);
+	}: _(RawOrigin::Signed(relayer.clone()), reward_kind, alternative_beneficiary.clone())
+	verify {
+		// we can't check anything here, because `PaymentProcedure` is responsible for
+		// payment logic, so we assume that if call has succeeded, the procedure has
+		// also completed successfully
+		assert_last_event::<T, I>(Event::RewardPaid {
+			relayer,
+			reward_kind,
+			reward_balance,
+			beneficiary: alternative_beneficiary,
+		}.into());
 	}
 
 	// Benchmark `register` call.
@@ -95,7 +132,7 @@ benchmarks_instance_pallet! {
 	}
 
 	// Benchmark `slash_and_deregister` method of the pallet. We are adding this weight to
-	// the weight of message delivery call if `RefundBridgedParachainMessages` signed extension
+	// the weight of message delivery call if `BridgeRelayersTransactionExtension` signed extension
 	// is deployed at runtime level.
 	slash_and_deregister {
 		// prepare and register relayer account
@@ -105,32 +142,30 @@ benchmarks_instance_pallet! {
 			.saturating_add(One::one())
 			.saturating_add(One::one());
 		T::deposit_account(relayer.clone(), crate::Pallet::<T, I>::required_stake());
-		crate::Pallet::<T, I>::register(RawOrigin::Signed(relayer.clone()).into(), valid_till).unwrap();
+		assert_ok!(crate::Pallet::<T, I>::register(RawOrigin::Signed(relayer.clone()).into(), valid_till));
 
 		// create slash destination account
-		let lane = T::bench_lane_id();
-		let slash_destination = RewardsAccountParams::new(lane, *b"test", RewardsAccountOwner::ThisChain);
-		T::prepare_rewards_account(slash_destination, Zero::zero());
+		let slash_destination: T::AccountId = whitelisted_caller();
+		T::deposit_account(slash_destination.clone(), Zero::zero());
 	}: {
-		crate::Pallet::<T, I>::slash_and_deregister(&relayer, slash_destination.into())
+		crate::Pallet::<T, I>::slash_and_deregister(&relayer, bp_relayers::ExplicitOrAccountParams::Explicit::<_, ()>(slash_destination))
 	}
 	verify {
 		assert!(!crate::Pallet::<T, I>::is_registration_active(&relayer));
 	}
 
 	// Benchmark `register_relayer_reward` method of the pallet. We are adding this weight to
-	// the weight of message delivery call if `RefundBridgedParachainMessages` signed extension
+	// the weight of message delivery call if `BridgeRelayersTransactionExtension` signed extension
 	// is deployed at runtime level.
 	register_relayer_reward {
-		let lane = T::bench_lane_id();
+		let reward_kind = T::bench_reward();
 		let relayer: T::AccountId = whitelisted_caller();
-		let account_params =
-			RewardsAccountParams::new(lane, *b"test", RewardsAccountOwner::ThisChain);
+
 	}: {
-		crate::Pallet::<T, I>::register_relayer_reward(account_params, &relayer, One::one());
+		crate::Pallet::<T, I>::register_relayer_reward(reward_kind, &relayer, One::one());
 	}
 	verify {
-		assert_eq!(RelayerRewards::<T, I>::get(relayer, &account_params), Some(One::one()));
+		assert_eq!(RelayerRewards::<T, I>::get(relayer, &reward_kind), Some(One::one()));
 	}
 
 	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::TestRuntime)
diff --git a/bridges/modules/relayers/src/extension/grandpa_adapter.rs b/bridges/modules/relayers/src/extension/grandpa_adapter.rs
index 2a8a6e78ef9c732b868f1293f313b35a044ad81a..9e98c73f8da049750c63a69b4cd38da12a1d5e0f 100644
--- a/bridges/modules/relayers/src/extension/grandpa_adapter.rs
+++ b/bridges/modules/relayers/src/extension/grandpa_adapter.rs
@@ -23,6 +23,7 @@ use crate::{
 
 use bp_relayers::{BatchCallUnpacker, ExtensionCallData, ExtensionCallInfo, ExtensionConfig};
 use bp_runtime::{Chain, StaticStrProvider};
+use core::marker::PhantomData;
 use frame_support::dispatch::{DispatchInfo, PostDispatchInfo};
 use frame_system::Config as SystemConfig;
 use pallet_bridge_grandpa::{
@@ -37,7 +38,6 @@ use sp_runtime::{
 	transaction_validity::{TransactionPriority, TransactionValidityError},
 	Saturating,
 };
-use sp_std::marker::PhantomData;
 
 /// Adapter to be used in signed extension configuration, when bridging with remote
 /// chains that are using GRANDPA finality.
diff --git a/bridges/modules/relayers/src/extension/messages_adapter.rs b/bridges/modules/relayers/src/extension/messages_adapter.rs
index e8c2088b7f2d3e6a08bfd45550bf0723132824d6..ffa8c5d8ab6d3016e50ab352513fd53884d6c48e 100644
--- a/bridges/modules/relayers/src/extension/messages_adapter.rs
+++ b/bridges/modules/relayers/src/extension/messages_adapter.rs
@@ -21,6 +21,7 @@ use crate::{extension::verify_messages_call_succeeded, Config as BridgeRelayersC
 
 use bp_relayers::{ExtensionCallData, ExtensionCallInfo, ExtensionConfig};
 use bp_runtime::StaticStrProvider;
+use core::marker::PhantomData;
 use frame_support::dispatch::{DispatchInfo, PostDispatchInfo};
 use pallet_bridge_messages::{
 	CallSubType as BridgeMessagesCallSubType, Config as BridgeMessagesConfig, LaneIdOf,
@@ -29,7 +30,6 @@ use sp_runtime::{
 	traits::{Dispatchable, Get},
 	transaction_validity::{TransactionPriority, TransactionValidityError},
 };
-use sp_std::marker::PhantomData;
 
 /// Transaction extension that refunds a relayer for standalone messages delivery and confirmation
 /// transactions. Finality transactions are not refunded.
diff --git a/bridges/modules/relayers/src/extension/mod.rs b/bridges/modules/relayers/src/extension/mod.rs
index d562ed9bcd0e87ed5bb910454ca57b0112fe25a9..0f74b501495544984e05333c1910405aa9c13137 100644
--- a/bridges/modules/relayers/src/extension/mod.rs
+++ b/bridges/modules/relayers/src/extension/mod.rs
@@ -31,6 +31,7 @@ use bp_relayers::{
 };
 use bp_runtime::{Chain, RangeInclusiveExt, StaticStrProvider};
 use codec::{Decode, Encode};
+use core::{fmt::Debug, marker::PhantomData};
 use frame_support::{
 	dispatch::{DispatchInfo, PostDispatchInfo},
 	pallet_prelude::TransactionSource,
@@ -53,7 +54,6 @@ use sp_runtime::{
 	transaction_validity::{InvalidTransaction, TransactionValidityError, ValidTransactionBuilder},
 	DispatchResult, RuntimeDebug,
 };
-use sp_std::{fmt::Debug, marker::PhantomData};
 
 pub use grandpa_adapter::WithGrandpaChainExtensionConfig;
 pub use messages_adapter::WithMessagesExtensionConfig;
@@ -97,11 +97,11 @@ impl<AccountId, RemoteGrandpaChainBlockNumber: Debug, LaneId: Clone + Copy + Deb
 
 /// The actions on relayer account that need to be performed because of his actions.
 #[derive(RuntimeDebug, PartialEq)]
-pub enum RelayerAccountAction<AccountId, Reward, LaneId> {
+pub enum RelayerAccountAction<AccountId, RewardBalance, LaneId> {
 	/// Do nothing with relayer account.
 	None,
 	/// Reward the relayer.
-	Reward(AccountId, RewardsAccountParams<LaneId>, Reward),
+	Reward(AccountId, RewardsAccountParams<LaneId>, RewardBalance),
 	/// Slash the relayer.
 	Slash(AccountId, RewardsAccountParams<LaneId>),
 }
@@ -111,6 +111,8 @@ pub enum RelayerAccountAction<AccountId, Reward, LaneId> {
 /// It may be incorporated into runtime to refund relayers for submitting correct
 /// message delivery and confirmation transactions, optionally batched with required
 /// finality proofs.
+///
+/// (Works only with `pallet-bridge-messages` and `RewardsAccountParams` as the `Reward`)
 #[derive(
 	DefaultNoBound,
 	CloneNoBound,
@@ -122,22 +124,24 @@ pub enum RelayerAccountAction<AccountId, Reward, LaneId> {
 	TypeInfo,
 )]
 #[scale_info(skip_type_params(Runtime, Config, LaneId))]
-pub struct BridgeRelayersTransactionExtension<Runtime, Config, LaneId>(
-	PhantomData<(Runtime, Config, LaneId)>,
-);
+pub struct BridgeRelayersTransactionExtension<Runtime, Config>(PhantomData<(Runtime, Config)>);
 
-impl<R, C, LaneId> BridgeRelayersTransactionExtension<R, C, LaneId>
+impl<R, C> BridgeRelayersTransactionExtension<R, C>
 where
 	Self: 'static + Send + Sync,
-	R: RelayersConfig<C::BridgeRelayersPalletInstance, LaneId = LaneId>
-		+ BridgeMessagesConfig<C::BridgeMessagesPalletInstance, LaneId = LaneId>
+	R: RelayersConfig<C::BridgeRelayersPalletInstance>
+		+ BridgeMessagesConfig<C::BridgeMessagesPalletInstance>
 		+ TransactionPaymentConfig,
-	C: ExtensionConfig<Runtime = R, LaneId = LaneId>,
+	C: ExtensionConfig<Runtime = R>,
 	R::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
 	<R::RuntimeCall as Dispatchable>::RuntimeOrigin: AsSystemOriginSigner<R::AccountId> + Clone,
-	<R as TransactionPaymentConfig>::OnChargeTransaction:
-		OnChargeTransaction<R, Balance = R::Reward>,
-	LaneId: Clone + Copy + Decode + Encode + Debug + TypeInfo,
+	<R as TransactionPaymentConfig>::OnChargeTransaction: OnChargeTransaction<R>,
+	<R as RelayersConfig<C::BridgeRelayersPalletInstance>>::Reward:
+		From<RewardsAccountParams<C::LaneId>>,
+	<R as RelayersConfig<C::BridgeRelayersPalletInstance>>::RewardBalance: From<
+		<<R as TransactionPaymentConfig>::OnChargeTransaction as OnChargeTransaction<R>>::Balance,
+	>,
+	C::LaneId: From<LaneIdOf<R, C::BridgeMessagesPalletInstance>>,
 {
 	/// Returns number of bundled messages `Some(_)`, if the given call info is a:
 	///
@@ -149,7 +153,7 @@ where
 	/// virtually boosted. The relayer registration (we only boost priority for registered
 	/// relayer transactions) must be checked outside.
 	fn bundled_messages_for_priority_boost(
-		parsed_call: &ExtensionCallInfo<C::RemoteGrandpaChainBlockNumber, LaneId>,
+		parsed_call: &ExtensionCallInfo<C::RemoteGrandpaChainBlockNumber, C::LaneId>,
 	) -> Option<MessageNonce> {
 		// we only boost priority of message delivery transactions
 		if !parsed_call.is_receive_messages_proof_call() {
@@ -172,12 +176,12 @@ where
 	/// Given post-dispatch information, analyze the outcome of relayer call and return
 	/// actions that need to be performed on relayer account.
 	fn analyze_call_result(
-		pre: Option<PreDispatchData<R::AccountId, C::RemoteGrandpaChainBlockNumber, LaneId>>,
+		pre: Option<PreDispatchData<R::AccountId, C::RemoteGrandpaChainBlockNumber, C::LaneId>>,
 		info: &DispatchInfo,
 		post_info: &PostDispatchInfo,
 		len: usize,
 		result: &DispatchResult,
-	) -> RelayerAccountAction<R::AccountId, R::Reward, LaneId> {
+	) -> RelayerAccountAction<R::AccountId, R::RewardBalance, C::LaneId> {
 		// We don't refund anything for transactions that we don't support.
 		let (relayer, call_info) = match pre {
 			Some(pre) => (pre.relayer, pre.call_info),
@@ -260,7 +264,7 @@ where
 		let refund = Self::compute_refund(info, &post_info, post_info_len, tip);
 
 		// we can finally reward relayer
-		RelayerAccountAction::Reward(relayer, reward_account_params, refund)
+		RelayerAccountAction::Reward(relayer, reward_account_params, refund.into())
 	}
 
 	/// Compute refund for the successful relayer transaction
@@ -268,29 +272,33 @@ where
 		info: &DispatchInfo,
 		post_info: &PostDispatchInfo,
 		len: usize,
-		tip: R::Reward,
-	) -> R::Reward {
+		tip: <<R as TransactionPaymentConfig>::OnChargeTransaction as OnChargeTransaction<R>>::Balance,
+	) -> <<R as TransactionPaymentConfig>::OnChargeTransaction as OnChargeTransaction<R>>::Balance
+	{
 		TransactionPaymentPallet::<R>::compute_actual_fee(len as _, info, post_info, tip)
 	}
 }
 
-impl<R, C, LaneId> TransactionExtension<R::RuntimeCall>
-	for BridgeRelayersTransactionExtension<R, C, LaneId>
+impl<R, C> TransactionExtension<R::RuntimeCall> for BridgeRelayersTransactionExtension<R, C>
 where
 	Self: 'static + Send + Sync,
-	R: RelayersConfig<C::BridgeRelayersPalletInstance, LaneId = LaneId>
-		+ BridgeMessagesConfig<C::BridgeMessagesPalletInstance, LaneId = LaneId>
+	R: RelayersConfig<C::BridgeRelayersPalletInstance>
+		+ BridgeMessagesConfig<C::BridgeMessagesPalletInstance>
 		+ TransactionPaymentConfig,
-	C: ExtensionConfig<Runtime = R, LaneId = LaneId>,
+	C: ExtensionConfig<Runtime = R>,
 	R::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
 	<R::RuntimeCall as Dispatchable>::RuntimeOrigin: AsSystemOriginSigner<R::AccountId> + Clone,
-	<R as TransactionPaymentConfig>::OnChargeTransaction:
-		OnChargeTransaction<R, Balance = R::Reward>,
-	LaneId: Clone + Copy + Decode + Encode + Debug + TypeInfo,
+	<R as TransactionPaymentConfig>::OnChargeTransaction: OnChargeTransaction<R>,
+	<R as RelayersConfig<C::BridgeRelayersPalletInstance>>::Reward:
+		From<RewardsAccountParams<C::LaneId>>,
+	<R as RelayersConfig<C::BridgeRelayersPalletInstance>>::RewardBalance: From<
+		<<R as TransactionPaymentConfig>::OnChargeTransaction as OnChargeTransaction<R>>::Balance,
+	>,
+	C::LaneId: From<LaneIdOf<R, C::BridgeMessagesPalletInstance>>,
 {
 	const IDENTIFIER: &'static str = C::IdProvider::STR;
 	type Implicit = ();
-	type Pre = Option<PreDispatchData<R::AccountId, C::RemoteGrandpaChainBlockNumber, LaneId>>;
+	type Pre = Option<PreDispatchData<R::AccountId, C::RemoteGrandpaChainBlockNumber, C::LaneId>>;
 	type Val = Self::Pre;
 
 	fn weight(&self, _call: &R::RuntimeCall) -> Weight {
@@ -385,7 +393,7 @@ where
 			RelayerAccountAction::None => (),
 			RelayerAccountAction::Reward(relayer, reward_account, reward) => {
 				RelayersPallet::<R, C::BridgeRelayersPalletInstance>::register_relayer_reward(
-					reward_account,
+					reward_account.into(),
 					&relayer,
 					reward,
 				);
@@ -505,7 +513,7 @@ mod tests {
 		ConstU64<1>,
 	>;
 	type TestGrandpaExtension =
-		BridgeRelayersTransactionExtension<TestRuntime, TestGrandpaExtensionConfig, TestLaneIdType>;
+		BridgeRelayersTransactionExtension<TestRuntime, TestGrandpaExtensionConfig>;
 	type TestExtensionConfig = parachain_adapter::WithParachainExtensionConfig<
 		StrTestExtension,
 		TestRuntime,
@@ -515,8 +523,7 @@ mod tests {
 		(),
 		ConstU64<1>,
 	>;
-	type TestExtension =
-		BridgeRelayersTransactionExtension<TestRuntime, TestExtensionConfig, TestLaneIdType>;
+	type TestExtension = BridgeRelayersTransactionExtension<TestRuntime, TestExtensionConfig>;
 	type TestMessagesExtensionConfig = messages_adapter::WithMessagesExtensionConfig<
 		StrTestMessagesExtension,
 		TestRuntime,
@@ -524,11 +531,8 @@ mod tests {
 		(),
 		ConstU64<1>,
 	>;
-	type TestMessagesExtension = BridgeRelayersTransactionExtension<
-		TestRuntime,
-		TestMessagesExtensionConfig,
-		TestLaneIdType,
-	>;
+	type TestMessagesExtension =
+		BridgeRelayersTransactionExtension<TestRuntime, TestMessagesExtensionConfig>;
 
 	fn initial_balance_of_relayer_account_at_this_chain() -> ThisChainBalance {
 		let test_stake: ThisChainBalance = Stake::get();
@@ -1214,7 +1218,7 @@ mod tests {
 		assert_eq!(post_dispatch_result, Ok(Weight::zero()));
 	}
 
-	fn expected_delivery_reward() -> ThisChainBalance {
+	fn expected_delivery_reward() -> RewardBalance {
 		let mut post_dispatch_info = post_dispatch_info();
 		let extra_weight = <TestRuntime as RelayersConfig>::WeightInfo::extra_weight_of_successful_receive_messages_proof_call();
 		post_dispatch_info.actual_weight =
@@ -1227,7 +1231,7 @@ mod tests {
 		)
 	}
 
-	fn expected_confirmation_reward() -> ThisChainBalance {
+	fn expected_confirmation_reward() -> RewardBalance {
 		pallet_transaction_payment::Pallet::<TestRuntime>::compute_actual_fee(
 			1024,
 			&dispatch_info(),
@@ -1980,7 +1984,7 @@ mod tests {
 			TestLaneIdType,
 		>,
 		dispatch_result: DispatchResult,
-	) -> RelayerAccountAction<ThisChainAccountId, ThisChainBalance, TestLaneIdType> {
+	) -> RelayerAccountAction<ThisChainAccountId, RewardBalance, TestLaneIdType> {
 		TestExtension::analyze_call_result(
 			Some(pre_dispatch_data),
 			&dispatch_info(),
diff --git a/bridges/modules/relayers/src/extension/parachain_adapter.rs b/bridges/modules/relayers/src/extension/parachain_adapter.rs
index 69cf766dd674de6d68d20531dec27f7b2424e419..122e7073632fac84f810ede23ed8a463c550284b 100644
--- a/bridges/modules/relayers/src/extension/parachain_adapter.rs
+++ b/bridges/modules/relayers/src/extension/parachain_adapter.rs
@@ -26,6 +26,7 @@ use crate::{
 
 use bp_relayers::{BatchCallUnpacker, ExtensionCallData, ExtensionCallInfo, ExtensionConfig};
 use bp_runtime::{Parachain, StaticStrProvider};
+use core::marker::PhantomData;
 use frame_support::dispatch::{DispatchInfo, PostDispatchInfo};
 use frame_system::Config as SystemConfig;
 use pallet_bridge_grandpa::{
@@ -42,7 +43,6 @@ use sp_runtime::{
 	traits::{Dispatchable, Get},
 	transaction_validity::{TransactionPriority, TransactionValidityError},
 };
-use sp_std::marker::PhantomData;
 
 /// Adapter to be used in signed extension configuration, when bridging with remote parachains.
 pub struct WithParachainExtensionConfig<
diff --git a/bridges/modules/relayers/src/lib.rs b/bridges/modules/relayers/src/lib.rs
index d1c71b6d30510f56f1cb134ebd1570b4ac8c0e0d..05d48982a938f191c53688cecd2d36ef3b5403e7 100644
--- a/bridges/modules/relayers/src/lib.rs
+++ b/bridges/modules/relayers/src/lib.rs
@@ -20,16 +20,18 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 #![warn(missing_docs)]
 
-use bp_relayers::{
-	ExplicitOrAccountParams, PaymentProcedure, Registration, RelayerRewardsKeyProvider,
-	StakeAndSlash,
-};
-pub use bp_relayers::{RewardsAccountOwner, RewardsAccountParams};
+extern crate alloc;
+
+pub use bp_relayers::RewardLedger;
+use bp_relayers::{PaymentProcedure, Registration, RelayerRewardsKeyProvider, StakeAndSlash};
 use bp_runtime::StorageDoubleMapKeyProvider;
-use frame_support::fail;
+use core::marker::PhantomData;
+use frame_support::{fail, traits::tokens::Balance};
 use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero};
-use sp_runtime::{traits::CheckedSub, Saturating};
-use sp_std::marker::PhantomData;
+use sp_runtime::{
+	traits::{CheckedSub, IdentifyAccount},
+	Saturating,
+};
 
 pub use pallet::*;
 pub use payment_adapter::{DeliveryConfirmationPaymentsAdapter, PayRewardFromAccount};
@@ -53,7 +55,6 @@ pub const LOG_TARGET: &str = "runtime::bridge-relayers";
 #[frame_support::pallet]
 pub mod pallet {
 	use super::*;
-	use bp_messages::LaneIdType;
 	use frame_support::pallet_prelude::*;
 	use frame_system::pallet_prelude::*;
 
@@ -61,28 +62,42 @@ pub mod pallet {
 	type RelayerRewardsKeyProviderOf<T, I> = RelayerRewardsKeyProvider<
 		<T as frame_system::Config>::AccountId,
 		<T as Config<I>>::Reward,
-		<T as Config<I>>::LaneId,
+		<T as Config<I>>::RewardBalance,
 	>;
 
+	/// Shortcut to alternative beneficiary type for `Config::PaymentProcedure`.
+	pub type BeneficiaryOf<T, I> = <<T as Config<I>>::PaymentProcedure as PaymentProcedure<
+		<T as frame_system::Config>::AccountId,
+		<T as Config<I>>::Reward,
+		<T as Config<I>>::RewardBalance,
+	>>::Beneficiary;
+
 	#[pallet::config]
 	pub trait Config<I: 'static = ()>: frame_system::Config {
 		/// The overarching event type.
 		type RuntimeEvent: From<Event<Self, I>>
 			+ IsType<<Self as frame_system::Config>::RuntimeEvent>;
-		/// Type of relayer reward.
-		type Reward: AtLeast32BitUnsigned + Copy + Member + Parameter + MaxEncodedLen;
+
+		/// Type of relayer reward balance.
+		type RewardBalance: AtLeast32BitUnsigned + Copy + Member + Parameter + MaxEncodedLen;
+		/// Reward discriminator type. The pallet can collect different types of rewards for a
+		/// single account, so `Reward` is used as the second key in the `RelayerRewards` double
+		/// map.
+		///
+		/// For example, rewards for different bridges can be stored, where `Reward` is
+		/// implemented as an enum representing each bridge.
+		type Reward: Parameter + MaxEncodedLen + Send + Sync + Copy + Clone;
+
 		/// Pay rewards scheme.
-		type PaymentProcedure: PaymentProcedure<
-			Self::AccountId,
-			Self::Reward,
-			LaneId = Self::LaneId,
-		>;
+		type PaymentProcedure: PaymentProcedure<Self::AccountId, Self::Reward, Self::RewardBalance>;
+
 		/// Stake and slash scheme.
-		type StakeAndSlash: StakeAndSlash<Self::AccountId, BlockNumberFor<Self>, Self::Reward>;
+		type StakeAndSlash: StakeAndSlash<Self::AccountId, BlockNumberFor<Self>, Self::Balance>;
+		/// Type for representing balance of an account used for `T::StakeAndSlash`.
+		type Balance: Balance;
+
 		/// Pallet call weights.
 		type WeightInfo: WeightInfoExt;
-		/// Lane identifier type.
-		type LaneId: LaneIdType + Send + Sync;
 	}
 
 	#[pallet::pallet]
@@ -90,41 +105,17 @@ pub mod pallet {
 	pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
 
 	#[pallet::call]
-	impl<T: Config<I>, I: 'static> Pallet<T, I> {
+	impl<T: Config<I>, I: 'static> Pallet<T, I>
+	where
+		BeneficiaryOf<T, I>: From<<T as frame_system::Config>::AccountId>,
+	{
 		/// Claim accumulated rewards.
 		#[pallet::call_index(0)]
 		#[pallet::weight(T::WeightInfo::claim_rewards())]
-		pub fn claim_rewards(
-			origin: OriginFor<T>,
-			rewards_account_params: RewardsAccountParams<T::LaneId>,
-		) -> DispatchResult {
+		pub fn claim_rewards(origin: OriginFor<T>, reward_kind: T::Reward) -> DispatchResult {
 			let relayer = ensure_signed(origin)?;
 
-			RelayerRewards::<T, I>::try_mutate_exists(
-				&relayer,
-				rewards_account_params,
-				|maybe_reward| -> DispatchResult {
-					let reward = maybe_reward.take().ok_or(Error::<T, I>::NoRewardForRelayer)?;
-					T::PaymentProcedure::pay_reward(&relayer, rewards_account_params, reward)
-						.map_err(|e| {
-							log::trace!(
-								target: LOG_TARGET,
-								"Failed to pay {:?} rewards to {:?}: {:?}",
-								rewards_account_params,
-								relayer,
-								e,
-							);
-							Error::<T, I>::FailedToPayReward
-						})?;
-
-					Self::deposit_event(Event::<T, I>::RewardPaid {
-						relayer: relayer.clone(),
-						rewards_account_params,
-						reward,
-					});
-					Ok(())
-				},
-			)
+			Self::do_claim_rewards(relayer.clone(), reward_kind, relayer.into())
 		}
 
 		/// Register relayer or update its registration.
@@ -229,9 +220,63 @@ pub mod pallet {
 				},
 			)
 		}
+
+		/// Claim accumulated rewards and send them to the alternative beneficiary.
+		#[pallet::call_index(3)]
+		#[pallet::weight(T::WeightInfo::claim_rewards_to())]
+		pub fn claim_rewards_to(
+			origin: OriginFor<T>,
+			reward_kind: T::Reward,
+			beneficiary: BeneficiaryOf<T, I>,
+		) -> DispatchResult {
+			let relayer = ensure_signed(origin)?;
+
+			Self::do_claim_rewards(relayer, reward_kind, beneficiary)
+		}
 	}
 
 	impl<T: Config<I>, I: 'static> Pallet<T, I> {
+		fn do_claim_rewards(
+			relayer: T::AccountId,
+			reward_kind: T::Reward,
+			beneficiary: BeneficiaryOf<T, I>,
+		) -> DispatchResult {
+			RelayerRewards::<T, I>::try_mutate_exists(
+				&relayer,
+				reward_kind,
+				|maybe_reward| -> DispatchResult {
+					let reward_balance =
+						maybe_reward.take().ok_or(Error::<T, I>::NoRewardForRelayer)?;
+					T::PaymentProcedure::pay_reward(
+						&relayer,
+						reward_kind,
+						reward_balance,
+						beneficiary.clone(),
+					)
+					.map_err(|e| {
+						log::error!(
+							target: LOG_TARGET,
+							"Failed to pay ({:?} / {:?}) rewards to {:?}(beneficiary: {:?}), error: {:?}",
+							reward_kind,
+							reward_balance,
+							relayer,
+							beneficiary,
+							e,
+						);
+						Error::<T, I>::FailedToPayReward
+					})?;
+
+					Self::deposit_event(Event::<T, I>::RewardPaid {
+						relayer: relayer.clone(),
+						reward_kind,
+						reward_balance,
+						beneficiary,
+					});
+					Ok(())
+				},
+			)
+		}
+
 		/// Returns true if given relayer registration is active at current block.
 		///
 		/// This call respects both `RequiredStake` and `RequiredRegistrationLease`, meaning that
@@ -264,7 +309,7 @@ pub mod pallet {
 		/// It may fail inside, but error is swallowed and we only log it.
 		pub fn slash_and_deregister(
 			relayer: &T::AccountId,
-			slash_destination: ExplicitOrAccountParams<T::AccountId, T::LaneId>,
+			slash_destination: impl IdentifyAccount<AccountId = T::AccountId>,
 		) {
 			let registration = match RegisteredRelayers::<T, I>::take(relayer) {
 				Some(registration) => registration,
@@ -278,10 +323,11 @@ pub mod pallet {
 					return
 				},
 			};
+			let slash_destination = slash_destination.into_account();
 
 			match T::StakeAndSlash::repatriate_reserved(
 				relayer,
-				slash_destination.clone(),
+				&slash_destination,
 				registration.stake,
 			) {
 				Ok(failed_to_slash) if failed_to_slash.is_zero() => {
@@ -307,8 +353,8 @@ pub mod pallet {
 				Err(e) => {
 					// TODO: document this. Where?
 
-					// it may fail if there's no beneficiary account. For us it means that this
-					// account must exists before we'll deploy the bridge
+					// it may fail if there's no beneficiary account. For us, it means that this
+					// account must exist before we'll deploy the bridge
 					log::debug!(
 						target: crate::LOG_TARGET,
 						"Failed to slash relayer account {:?}: {:?}. Maybe beneficiary account doesn't exist? \
@@ -324,34 +370,35 @@ pub mod pallet {
 		}
 
 		/// Register reward for given relayer.
-		pub fn register_relayer_reward(
-			rewards_account_params: RewardsAccountParams<T::LaneId>,
+		pub(crate) fn register_relayer_reward(
+			reward_kind: T::Reward,
 			relayer: &T::AccountId,
-			reward: T::Reward,
+			reward_balance: T::RewardBalance,
 		) {
-			if reward.is_zero() {
+			if reward_balance.is_zero() {
 				return
 			}
 
 			RelayerRewards::<T, I>::mutate(
 				relayer,
-				rewards_account_params,
-				|old_reward: &mut Option<T::Reward>| {
-					let new_reward = old_reward.unwrap_or_else(Zero::zero).saturating_add(reward);
+				reward_kind,
+				|old_reward: &mut Option<T::RewardBalance>| {
+					let new_reward =
+						old_reward.unwrap_or_else(Zero::zero).saturating_add(reward_balance);
 					*old_reward = Some(new_reward);
 
 					log::trace!(
 						target: crate::LOG_TARGET,
 						"Relayer {:?} can now claim reward for serving payer {:?}: {:?}",
 						relayer,
-						rewards_account_params,
+						reward_kind,
 						new_reward,
 					);
 
 					Self::deposit_event(Event::<T, I>::RewardRegistered {
 						relayer: relayer.clone(),
-						rewards_account_params,
-						reward,
+						reward_kind,
+						reward_balance,
 					});
 				},
 			);
@@ -362,21 +409,21 @@ pub mod pallet {
 			<T::StakeAndSlash as StakeAndSlash<
 				T::AccountId,
 				BlockNumberFor<T>,
-				T::Reward,
+				T::Balance,
 			>>::RequiredRegistrationLease::get()
 		}
 
 		/// Return required stake.
-		pub(crate) fn required_stake() -> T::Reward {
+		pub(crate) fn required_stake() -> T::Balance {
 			<T::StakeAndSlash as StakeAndSlash<
 				T::AccountId,
 				BlockNumberFor<T>,
-				T::Reward,
+				T::Balance,
 			>>::RequiredStake::get()
 		}
 
 		/// `Unreserve` given amount on relayer account.
-		fn do_unreserve(relayer: &T::AccountId, amount: T::Reward) -> DispatchResult {
+		fn do_unreserve(relayer: &T::AccountId, amount: T::Balance) -> DispatchResult {
 			let failed_to_unreserve = T::StakeAndSlash::unreserve(relayer, amount);
 			if !failed_to_unreserve.is_zero() {
 				log::trace!(
@@ -401,26 +448,28 @@ pub mod pallet {
 		RewardRegistered {
 			/// Relayer account that can claim reward.
 			relayer: T::AccountId,
-			/// Relayer can claim reward from this account.
-			rewards_account_params: RewardsAccountParams<T::LaneId>,
+			/// Relayer can claim this kind of reward.
+			reward_kind: T::Reward,
 			/// Reward amount.
-			reward: T::Reward,
+			reward_balance: T::RewardBalance,
 		},
 		/// Reward has been paid to the relayer.
 		RewardPaid {
 			/// Relayer account that has been rewarded.
 			relayer: T::AccountId,
-			/// Relayer has received reward from this account.
-			rewards_account_params: RewardsAccountParams<T::LaneId>,
+			/// Relayer has received reward of this kind.
+			reward_kind: T::Reward,
 			/// Reward amount.
-			reward: T::Reward,
+			reward_balance: T::RewardBalance,
+			/// Beneficiary.
+			beneficiary: BeneficiaryOf<T, I>,
 		},
 		/// Relayer registration has been added or updated.
 		RegistrationUpdated {
 			/// Relayer account that has been registered.
 			relayer: T::AccountId,
 			/// Relayer registration.
-			registration: Registration<BlockNumberFor<T>, T::Reward>,
+			registration: Registration<BlockNumberFor<T>, T::Balance>,
 		},
 		/// Relayer has been `deregistered`.
 		Deregistered {
@@ -432,7 +481,7 @@ pub mod pallet {
 			/// Relayer account that has been `deregistered`.
 			relayer: T::AccountId,
 			/// Registration that was removed.
-			registration: Registration<BlockNumberFor<T>, T::Reward>,
+			registration: Registration<BlockNumberFor<T>, T::Balance>,
 		},
 	}
 
@@ -482,23 +531,29 @@ pub mod pallet {
 		_,
 		Blake2_128Concat,
 		T::AccountId,
-		Registration<BlockNumberFor<T>, T::Reward>,
+		Registration<BlockNumberFor<T>, T::Balance>,
 		OptionQuery,
 	>;
 }
 
+/// Implementation of `RewardLedger` for the pallet.
+impl<T: Config<I>, I: 'static, Reward, RewardBalance>
+	RewardLedger<T::AccountId, Reward, RewardBalance> for Pallet<T, I>
+where
+	Reward: Into<T::Reward>,
+	RewardBalance: Into<T::RewardBalance>,
+{
+	fn register_reward(relayer: &T::AccountId, reward: Reward, reward_balance: RewardBalance) {
+		Self::register_relayer_reward(reward.into(), relayer, reward_balance.into());
+	}
+}
+
 #[cfg(test)]
 mod tests {
 	use super::*;
-	use bp_messages::LaneIdType;
 	use mock::{RuntimeEvent as TestEvent, *};
 
-	use crate::Event::{RewardPaid, RewardRegistered};
-	use bp_relayers::RewardsAccountOwner;
-	use frame_support::{
-		assert_noop, assert_ok,
-		traits::fungible::{Inspect, Mutate},
-	};
+	use frame_support::{assert_noop, assert_ok, traits::fungible::Mutate};
 	use frame_system::{EventRecord, Pallet as System, Phase};
 	use sp_runtime::DispatchError;
 
@@ -523,10 +578,10 @@ mod tests {
 				System::<TestRuntime>::events().last(),
 				Some(&EventRecord {
 					phase: Phase::Initialization,
-					event: TestEvent::BridgeRelayers(RewardRegistered {
+					event: TestEvent::BridgeRelayers(Event::RewardRegistered {
 						relayer: REGULAR_RELAYER,
-						rewards_account_params: test_reward_account_param(),
-						reward: 100
+						reward_kind: test_reward_account_param(),
+						reward_balance: 100
 					}),
 					topics: vec![],
 				}),
@@ -602,10 +657,11 @@ mod tests {
 				System::<TestRuntime>::events().last(),
 				Some(&EventRecord {
 					phase: Phase::Initialization,
-					event: TestEvent::BridgeRelayers(RewardPaid {
+					event: TestEvent::BridgeRelayers(Event::RewardPaid {
 						relayer: REGULAR_RELAYER,
-						rewards_account_params: test_reward_account_param(),
-						reward: 100
+						reward_kind: test_reward_account_param(),
+						reward_balance: 100,
+						beneficiary: REGULAR_RELAYER,
 					}),
 					topics: vec![],
 				}),
@@ -614,41 +670,39 @@ mod tests {
 	}
 
 	#[test]
-	fn pay_reward_from_account_actually_pays_reward() {
-		type Balances = pallet_balances::Pallet<TestRuntime>;
-		type PayLaneRewardFromAccount =
-			bp_relayers::PayRewardFromAccount<Balances, ThisChainAccountId, TestLaneIdType>;
-
+	fn relayer_can_claim_reward_to() {
 		run_test(|| {
-			let in_lane_0 = RewardsAccountParams::new(
-				TestLaneIdType::try_new(1, 2).unwrap(),
-				*b"test",
-				RewardsAccountOwner::ThisChain,
-			);
-			let out_lane_1 = RewardsAccountParams::new(
-				TestLaneIdType::try_new(1, 3).unwrap(),
-				*b"test",
-				RewardsAccountOwner::BridgedChain,
-			);
-
-			let in_lane0_rewards_account = PayLaneRewardFromAccount::rewards_account(in_lane_0);
-			let out_lane1_rewards_account = PayLaneRewardFromAccount::rewards_account(out_lane_1);
-
-			Balances::mint_into(&in_lane0_rewards_account, 100).unwrap();
-			Balances::mint_into(&out_lane1_rewards_account, 100).unwrap();
-			assert_eq!(Balances::balance(&in_lane0_rewards_account), 100);
-			assert_eq!(Balances::balance(&out_lane1_rewards_account), 100);
-			assert_eq!(Balances::balance(&1), 0);
-
-			PayLaneRewardFromAccount::pay_reward(&1, in_lane_0, 100).unwrap();
-			assert_eq!(Balances::balance(&in_lane0_rewards_account), 0);
-			assert_eq!(Balances::balance(&out_lane1_rewards_account), 100);
-			assert_eq!(Balances::balance(&1), 100);
-
-			PayLaneRewardFromAccount::pay_reward(&1, out_lane_1, 100).unwrap();
-			assert_eq!(Balances::balance(&in_lane0_rewards_account), 0);
-			assert_eq!(Balances::balance(&out_lane1_rewards_account), 0);
-			assert_eq!(Balances::balance(&1), 200);
+			get_ready_for_events();
+
+			RelayerRewards::<TestRuntime>::insert(
+				REGULAR_RELAYER,
+				test_reward_account_param(),
+				100,
+			);
+			assert_ok!(Pallet::<TestRuntime>::claim_rewards_to(
+				RuntimeOrigin::signed(REGULAR_RELAYER),
+				test_reward_account_param(),
+				REGULAR_RELAYER2,
+			));
+			assert_eq!(
+				RelayerRewards::<TestRuntime>::get(REGULAR_RELAYER, test_reward_account_param()),
+				None
+			);
+
+			// Check if the `RewardPaid` event was emitted.
+			assert_eq!(
+				System::<TestRuntime>::events().last(),
+				Some(&EventRecord {
+					phase: Phase::Initialization,
+					event: TestEvent::BridgeRelayers(Event::RewardPaid {
+						relayer: REGULAR_RELAYER,
+						reward_kind: test_reward_account_param(),
+						reward_balance: 100,
+						beneficiary: REGULAR_RELAYER2,
+					}),
+					topics: vec![],
+				}),
+			);
 		});
 	}
 
diff --git a/bridges/modules/relayers/src/migration.rs b/bridges/modules/relayers/src/migration.rs
index 8bf473b300c2a15eb983fb3e4c6f4c4c5dad0105..11a809e5d335e0810dbecbd85f792e94545c434c 100644
--- a/bridges/modules/relayers/src/migration.rs
+++ b/bridges/modules/relayers/src/migration.rs
@@ -16,13 +16,14 @@
 
 //! A module that is responsible for migration of storage.
 
+use alloc::vec::Vec;
 use frame_support::{
 	traits::{Get, StorageVersion},
 	weights::Weight,
 };
 
 /// The in-code storage version.
-pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
+pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);
 
 /// This module contains data structures that are valid for the initial state of `0`.
 /// (used with v1 migration).
@@ -31,10 +32,10 @@ pub mod v0 {
 	use bp_relayers::RewardsAccountOwner;
 	use bp_runtime::{ChainId, StorageDoubleMapKeyProvider};
 	use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen};
+	use core::marker::PhantomData;
 	use frame_support::{pallet_prelude::OptionQuery, Blake2_128Concat, Identity};
 	use scale_info::TypeInfo;
 	use sp_runtime::traits::AccountIdConversion;
-	use sp_std::marker::PhantomData;
 
 	/// Structure used to identify the account that pays a reward to the relayer.
 	#[derive(Copy, Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen)]
@@ -62,15 +63,15 @@ pub mod v0 {
 		const TYPE_ID: [u8; 4] = *b"brap";
 	}
 
-	pub(crate) struct RelayerRewardsKeyProvider<AccountId, Reward, LaneId>(
-		PhantomData<(AccountId, Reward, LaneId)>,
+	pub(crate) struct RelayerRewardsKeyProvider<AccountId, RewardBalance, LaneId>(
+		PhantomData<(AccountId, RewardBalance, LaneId)>,
 	);
 
-	impl<AccountId, Reward, LaneId> StorageDoubleMapKeyProvider
-		for RelayerRewardsKeyProvider<AccountId, Reward, LaneId>
+	impl<AccountId, RewardBalance, LaneId> StorageDoubleMapKeyProvider
+		for RelayerRewardsKeyProvider<AccountId, RewardBalance, LaneId>
 	where
 		AccountId: 'static + Codec + EncodeLike + Send + Sync,
-		Reward: 'static + Codec + EncodeLike + Send + Sync,
+		RewardBalance: 'static + Codec + EncodeLike + Send + Sync,
 		LaneId: Codec + EncodeLike + Send + Sync,
 	{
 		const MAP_NAME: &'static str = "RelayerRewards";
@@ -79,23 +80,23 @@ pub mod v0 {
 		type Key1 = AccountId;
 		type Hasher2 = Identity;
 		type Key2 = RewardsAccountParams<LaneId>;
-		type Value = Reward;
+		type Value = RewardBalance;
 	}
 
-	pub(crate) type RelayerRewardsKeyProviderOf<T, I> = RelayerRewardsKeyProvider<
+	pub(crate) type RelayerRewardsKeyProviderOf<T, I, LaneId> = RelayerRewardsKeyProvider<
 		<T as frame_system::Config>::AccountId,
-		<T as Config<I>>::Reward,
-		<T as Config<I>>::LaneId,
+		<T as Config<I>>::RewardBalance,
+		LaneId,
 	>;
 
 	#[frame_support::storage_alias]
-	pub(crate) type RelayerRewards<T: Config<I>, I: 'static> = StorageDoubleMap<
+	pub(crate) type RelayerRewards<T: Config<I>, I: 'static, LaneId> = StorageDoubleMap<
 		Pallet<T, I>,
-		<RelayerRewardsKeyProviderOf<T, I> as StorageDoubleMapKeyProvider>::Hasher1,
-		<RelayerRewardsKeyProviderOf<T, I> as StorageDoubleMapKeyProvider>::Key1,
-		<RelayerRewardsKeyProviderOf<T, I> as StorageDoubleMapKeyProvider>::Hasher2,
-		<RelayerRewardsKeyProviderOf<T, I> as StorageDoubleMapKeyProvider>::Key2,
-		<RelayerRewardsKeyProviderOf<T, I> as StorageDoubleMapKeyProvider>::Value,
+		<RelayerRewardsKeyProviderOf<T, I, LaneId> as StorageDoubleMapKeyProvider>::Hasher1,
+		<RelayerRewardsKeyProviderOf<T, I, LaneId> as StorageDoubleMapKeyProvider>::Key1,
+		<RelayerRewardsKeyProviderOf<T, I, LaneId> as StorageDoubleMapKeyProvider>::Hasher2,
+		<RelayerRewardsKeyProviderOf<T, I, LaneId> as StorageDoubleMapKeyProvider>::Key2,
+		<RelayerRewardsKeyProviderOf<T, I, LaneId> as StorageDoubleMapKeyProvider>::Value,
 		OptionQuery,
 	>;
 
@@ -119,27 +120,104 @@ pub mod v0 {
 pub mod v1 {
 	use super::*;
 	use crate::{Config, Pallet};
+	use bp_messages::LaneIdType;
 	use bp_relayers::RewardsAccountParams;
-	use frame_support::traits::UncheckedOnRuntimeUpgrade;
-	use sp_std::marker::PhantomData;
+	use bp_runtime::StorageDoubleMapKeyProvider;
+	use codec::{Codec, EncodeLike};
+	use core::marker::PhantomData;
+	use frame_support::{
+		pallet_prelude::OptionQuery, traits::UncheckedOnRuntimeUpgrade, Blake2_128Concat, Identity,
+	};
+	use sp_arithmetic::traits::Zero;
+
+	pub(crate) struct RelayerRewardsKeyProvider<AccountId, RewardBalance, LaneId>(
+		PhantomData<(AccountId, RewardBalance, LaneId)>,
+	);
 
-	#[cfg(feature = "try-runtime")]
-	use crate::RelayerRewards;
+	impl<AccountId, RewardBalance, LaneId> StorageDoubleMapKeyProvider
+		for RelayerRewardsKeyProvider<AccountId, RewardBalance, LaneId>
+	where
+		AccountId: 'static + Codec + EncodeLike + Send + Sync,
+		RewardBalance: 'static + Codec + EncodeLike + Send + Sync,
+		LaneId: Codec + EncodeLike + Send + Sync,
+	{
+		const MAP_NAME: &'static str = "RelayerRewards";
+
+		type Hasher1 = Blake2_128Concat;
+		type Key1 = AccountId;
+		type Hasher2 = Identity;
+		type Key2 = v1::RewardsAccountParams<LaneId>;
+		type Value = RewardBalance;
+	}
+
+	pub(crate) type RelayerRewardsKeyProviderOf<T, I, LaneId> = RelayerRewardsKeyProvider<
+		<T as frame_system::Config>::AccountId,
+		<T as Config<I>>::RewardBalance,
+		LaneId,
+	>;
+
+	#[frame_support::storage_alias]
+	pub(crate) type RelayerRewards<T: Config<I>, I: 'static, LaneId> = StorageDoubleMap<
+		Pallet<T, I>,
+		<RelayerRewardsKeyProviderOf<T, I, LaneId> as StorageDoubleMapKeyProvider>::Hasher1,
+		<RelayerRewardsKeyProviderOf<T, I, LaneId> as StorageDoubleMapKeyProvider>::Key1,
+		<RelayerRewardsKeyProviderOf<T, I, LaneId> as StorageDoubleMapKeyProvider>::Hasher2,
+		<RelayerRewardsKeyProviderOf<T, I, LaneId> as StorageDoubleMapKeyProvider>::Key2,
+		<RelayerRewardsKeyProviderOf<T, I, LaneId> as StorageDoubleMapKeyProvider>::Value,
+		OptionQuery,
+	>;
+
+	// Copy of `Pallet::<T, I>::register_relayer_reward` compatible with v1.
+	fn register_relayer_reward_for_v1<
+		T: Config<I>,
+		I: 'static,
+		LaneId: LaneIdType + Send + Sync,
+	>(
+		rewards_account_params: v1::RewardsAccountParams<LaneId>,
+		relayer: &T::AccountId,
+		reward_balance: T::RewardBalance,
+	) {
+		use sp_runtime::Saturating;
+
+		if reward_balance.is_zero() {
+			return
+		}
+
+		v1::RelayerRewards::<T, I, LaneId>::mutate(
+			relayer,
+			rewards_account_params,
+			|old_reward: &mut Option<T::RewardBalance>| {
+				let new_reward =
+					old_reward.unwrap_or_else(Zero::zero).saturating_add(reward_balance);
+				*old_reward = Some(new_reward);
+
+				log::trace!(
+					target: crate::LOG_TARGET,
+					"Relayer {:?} can now claim reward for serving payer {:?}: {:?}",
+					relayer,
+					rewards_account_params,
+					new_reward,
+				);
+			},
+		);
+	}
 
 	/// Migrates the pallet storage to v1.
-	pub struct UncheckedMigrationV0ToV1<T, I>(PhantomData<(T, I)>);
+	pub struct UncheckedMigrationV0ToV1<T, I, LaneId>(PhantomData<(T, I, LaneId)>);
 
 	#[cfg(feature = "try-runtime")]
 	const LOG_TARGET: &str = "runtime::bridge-relayers-migration";
 
-	impl<T: Config<I>, I: 'static> UncheckedOnRuntimeUpgrade for UncheckedMigrationV0ToV1<T, I> {
+	impl<T: Config<I>, I: 'static, LaneId: LaneIdType + Send + Sync> UncheckedOnRuntimeUpgrade
+		for UncheckedMigrationV0ToV1<T, I, LaneId>
+	{
 		fn on_runtime_upgrade() -> Weight {
 			let mut weight = T::DbWeight::get().reads(1);
 
 			// list all rewards (we cannot do this as one step because of `drain` limitation)
 			let mut rewards_to_migrate =
-				sp_std::vec::Vec::with_capacity(v0::RelayerRewards::<T, I>::iter().count());
-			for (key1, key2, reward) in v0::RelayerRewards::<T, I>::drain() {
+				Vec::with_capacity(v0::RelayerRewards::<T, I, LaneId>::iter().count());
+			for (key1, key2, reward) in v0::RelayerRewards::<T, I, LaneId>::drain() {
 				rewards_to_migrate.push((key1, key2, reward));
 				weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
 			}
@@ -150,7 +228,7 @@ pub mod v1 {
 				let v0::RewardsAccountParams { owner, lane_id, bridged_chain_id } = key2;
 
 				// re-register reward
-				Pallet::<T, I>::register_relayer_reward(
+				register_relayer_reward_for_v1::<T, I, LaneId>(
 					v1::RewardsAccountParams::new(lane_id, bridged_chain_id, owner),
 					&key1,
 					reward,
@@ -162,18 +240,18 @@ pub mod v1 {
 		}
 
 		#[cfg(feature = "try-runtime")]
-		fn pre_upgrade() -> Result<sp_std::vec::Vec<u8>, sp_runtime::DispatchError> {
+		fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::DispatchError> {
 			use codec::Encode;
 			use frame_support::BoundedBTreeMap;
 			use sp_runtime::traits::ConstU32;
 
 			// collect actual rewards
 			let mut rewards: BoundedBTreeMap<
-				(T::AccountId, T::LaneId),
-				T::Reward,
+				(T::AccountId, LaneId),
+				T::RewardBalance,
 				ConstU32<{ u32::MAX }>,
 			> = BoundedBTreeMap::new();
-			for (key1, key2, reward) in v0::RelayerRewards::<T, I>::iter() {
+			for (key1, key2, reward) in v0::RelayerRewards::<T, I, LaneId>::iter() {
 				log::info!(target: LOG_TARGET, "Reward to migrate: {key1:?}::{key2:?} - {reward:?}");
 				rewards = rewards
 					.try_mutate(|inner| {
@@ -190,24 +268,24 @@ pub mod v1 {
 		}
 
 		#[cfg(feature = "try-runtime")]
-		fn post_upgrade(state: sp_std::vec::Vec<u8>) -> Result<(), sp_runtime::DispatchError> {
+		fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::DispatchError> {
 			use codec::Decode;
 			use frame_support::BoundedBTreeMap;
 			use sp_runtime::traits::ConstU32;
 
 			let rewards_before: BoundedBTreeMap<
-				(T::AccountId, T::LaneId),
-				T::Reward,
+				(T::AccountId, LaneId),
+				T::RewardBalance,
 				ConstU32<{ u32::MAX }>,
 			> = Decode::decode(&mut &state[..]).unwrap();
 
 			// collect migrated rewards
 			let mut rewards_after: BoundedBTreeMap<
-				(T::AccountId, T::LaneId),
-				T::Reward,
+				(T::AccountId, LaneId),
+				T::RewardBalance,
 				ConstU32<{ u32::MAX }>,
 			> = BoundedBTreeMap::new();
-			for (key1, key2, reward) in v1::RelayerRewards::<T, I>::iter() {
+			for (key1, key2, reward) in v1::RelayerRewards::<T, I, LaneId>::iter() {
 				log::info!(target: LOG_TARGET, "Migrated rewards: {key1:?}::{key2:?} - {reward:?}");
 				rewards_after = rewards_after
 					.try_mutate(|inner| {
@@ -233,10 +311,140 @@ pub mod v1 {
 	/// [`UncheckedMigrationV0ToV1`] wrapped in a
 	/// [`VersionedMigration`](frame_support::migrations::VersionedMigration), ensuring the
 	/// migration is only performed when on-chain version is 0.
-	pub type MigrationToV1<T, I> = frame_support::migrations::VersionedMigration<
+	pub type MigrationToV1<T, I, LaneId> = frame_support::migrations::VersionedMigration<
 		0,
 		1,
-		UncheckedMigrationV0ToV1<T, I>,
+		UncheckedMigrationV0ToV1<T, I, LaneId>,
+		Pallet<T, I>,
+		<T as frame_system::Config>::DbWeight,
+	>;
+}
+
+/// The pallet in version 1 only supported rewards collected under the key of
+/// `RewardsAccountParams`. This migration essentially converts existing `RewardsAccountParams` keys
+/// to the generic type `T::Reward`.
+pub mod v2 {
+	use super::*;
+	#[cfg(feature = "try-runtime")]
+	use crate::RelayerRewards;
+	use crate::{Config, Pallet};
+	use bp_messages::LaneIdType;
+	use bp_relayers::RewardsAccountParams;
+	use core::marker::PhantomData;
+	use frame_support::traits::UncheckedOnRuntimeUpgrade;
+
+	/// Migrates the pallet storage to v2.
+	pub struct UncheckedMigrationV1ToV2<T, I, LaneId>(PhantomData<(T, I, LaneId)>);
+
+	#[cfg(feature = "try-runtime")]
+	const LOG_TARGET: &str = "runtime::bridge-relayers-migration";
+
+	impl<T: Config<I>, I: 'static, LaneId: LaneIdType + Send + Sync> UncheckedOnRuntimeUpgrade
+		for UncheckedMigrationV1ToV2<T, I, LaneId>
+	where
+		<T as Config<I>>::Reward: From<RewardsAccountParams<LaneId>>,
+	{
+		fn on_runtime_upgrade() -> Weight {
+			let mut weight = T::DbWeight::get().reads(1);
+
+			// list all rewards (we cannot do this as one step because of `drain` limitation)
+			let mut rewards_to_migrate =
+				Vec::with_capacity(v1::RelayerRewards::<T, I, LaneId>::iter().count());
+			for (key1, key2, reward) in v1::RelayerRewards::<T, I, LaneId>::drain() {
+				rewards_to_migrate.push((key1, key2, reward));
+				weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
+			}
+
+			// re-register rewards with new format.
+			for (key1, key2, reward) in rewards_to_migrate {
+				// convert old key to the new
+				let new_key2: T::Reward = key2.into();
+
+				// re-register reward (drained above)
+				Pallet::<T, I>::register_relayer_reward(new_key2, &key1, reward);
+				weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
+			}
+
+			weight
+		}
+
+		#[cfg(feature = "try-runtime")]
+		fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::DispatchError> {
+			use codec::Encode;
+			use frame_support::BoundedBTreeMap;
+			use sp_runtime::traits::ConstU32;
+
+			// collect actual rewards
+			let mut rewards: BoundedBTreeMap<
+				(T::AccountId, Vec<u8>),
+				T::RewardBalance,
+				ConstU32<{ u32::MAX }>,
+			> = BoundedBTreeMap::new();
+			for (key1, key2, reward) in v1::RelayerRewards::<T, I, LaneId>::iter() {
+				let new_key2: T::Reward = key2.into();
+				log::info!(target: LOG_TARGET, "Reward to migrate: {key1:?}::{key2:?}->{new_key2:?} - {reward:?}");
+				rewards = rewards
+					.try_mutate(|inner| {
+						inner
+							.entry((key1.clone(), new_key2.encode()))
+							.and_modify(|value| *value += reward)
+							.or_insert(reward);
+					})
+					.unwrap();
+			}
+			log::info!(target: LOG_TARGET, "Found total rewards to migrate: {rewards:?}");
+
+			Ok(rewards.encode())
+		}
+
+		#[cfg(feature = "try-runtime")]
+		fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::DispatchError> {
+			use codec::{Decode, Encode};
+			use frame_support::BoundedBTreeMap;
+			use sp_runtime::traits::ConstU32;
+
+			let rewards_before: BoundedBTreeMap<
+				(T::AccountId, Vec<u8>),
+				T::RewardBalance,
+				ConstU32<{ u32::MAX }>,
+			> = Decode::decode(&mut &state[..]).unwrap();
+
+			// collect migrated rewards
+			let mut rewards_after: BoundedBTreeMap<
+				(T::AccountId, Vec<u8>),
+				T::RewardBalance,
+				ConstU32<{ u32::MAX }>,
+			> = BoundedBTreeMap::new();
+			for (key1, key2, reward) in v2::RelayerRewards::<T, I>::iter() {
+				log::info!(target: LOG_TARGET, "Migrated rewards: {key1:?}::{key2:?} - {reward:?}");
+				rewards_after = rewards_after
+					.try_mutate(|inner| {
+						inner
+							.entry((key1.clone(), key2.encode()))
+							.and_modify(|value| *value += reward)
+							.or_insert(reward);
+					})
+					.unwrap();
+			}
+			log::info!(target: LOG_TARGET, "Found total migrated rewards: {rewards_after:?}");
+
+			frame_support::ensure!(
+				rewards_before == rewards_after,
+				"The rewards were not migrated correctly!."
+			);
+
+			log::info!(target: LOG_TARGET, "migrated all.");
+			Ok(())
+		}
+	}
+
+	/// [`UncheckedMigrationV1ToV2`] wrapped in a
+	/// [`VersionedMigration`](frame_support::migrations::VersionedMigration), ensuring the
+	/// migration is only performed when on-chain version is 1.
+	pub type MigrationToV2<T, I, LaneId> = frame_support::migrations::VersionedMigration<
+		1,
+		2,
+		UncheckedMigrationV1ToV2<T, I, LaneId>,
 		Pallet<T, I>,
 		<T as frame_system::Config>::DbWeight,
 	>;
diff --git a/bridges/modules/relayers/src/mock.rs b/bridges/modules/relayers/src/mock.rs
index 7dc213249379d794d23cc26f4efcb04f7c91b3e6..24067b9640be4a434cb46b9098715682c6b22688 100644
--- a/bridges/modules/relayers/src/mock.rs
+++ b/bridges/modules/relayers/src/mock.rs
@@ -35,9 +35,9 @@ use frame_support::{
 	weights::{ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight},
 };
 use pallet_transaction_payment::Multiplier;
-use sp_core::{ConstU64, ConstU8, H256};
+use sp_core::H256;
 use sp_runtime::{
-	traits::{BlakeTwo256, ConstU32},
+	traits::{BlakeTwo256, ConstU32, ConstU64, ConstU8},
 	BuildStorage, FixedPointNumber, Perquintill, StateVersion,
 };
 
@@ -81,6 +81,8 @@ pub type TestLaneIdType = HashedLaneId;
 pub fn test_lane_id() -> TestLaneIdType {
 	TestLaneIdType::try_new(1, 2).unwrap()
 }
+/// Reward measurement type.
+pub type RewardBalance = u64;
 
 /// Underlying chain of `ThisChain`.
 pub struct ThisUnderlyingChain;
@@ -280,34 +282,51 @@ impl pallet_bridge_messages::Config for TestRuntime {
 
 impl pallet_bridge_relayers::Config for TestRuntime {
 	type RuntimeEvent = RuntimeEvent;
-	type Reward = ThisChainBalance;
+	type RewardBalance = RewardBalance;
+	type Reward = RewardsAccountParams<pallet_bridge_messages::LaneIdOf<TestRuntime, ()>>;
 	type PaymentProcedure = TestPaymentProcedure;
 	type StakeAndSlash = TestStakeAndSlash;
+	type Balance = ThisChainBalance;
 	type WeightInfo = ();
-	type LaneId = TestLaneIdType;
 }
 
 #[cfg(feature = "runtime-benchmarks")]
 impl pallet_bridge_relayers::benchmarking::Config for TestRuntime {
+	fn bench_reward() -> Self::Reward {
+		RewardsAccountParams::new(
+			TestLaneIdType::default(),
+			*b"test",
+			RewardsAccountOwner::ThisChain,
+		)
+	}
+
 	fn prepare_rewards_account(
-		account_params: RewardsAccountParams<Self::LaneId>,
-		reward: Self::Reward,
-	) {
-		let rewards_account = bp_relayers::PayRewardFromAccount::<
+		account_params: RewardsAccountParams<TestLaneIdType>,
+		reward: Self::RewardBalance,
+	) -> Option<ThisChainAccountId> {
+		let rewards_account = PayRewardFromAccount::<
 			Balances,
 			ThisChainAccountId,
-			Self::LaneId,
+			TestLaneIdType,
+			RewardBalance,
 		>::rewards_account(account_params);
-		Self::deposit_account(rewards_account, reward);
+		Self::deposit_account(rewards_account, reward.into());
+
+		Some(REGULAR_RELAYER2)
 	}
 
-	fn deposit_account(account: Self::AccountId, balance: Self::Reward) {
-		Balances::mint_into(&account, balance.saturating_add(ExistentialDeposit::get())).unwrap();
+	fn deposit_account(account: Self::AccountId, balance: Self::Balance) {
+		frame_support::assert_ok!(Balances::mint_into(
+			&account,
+			balance.saturating_add(ExistentialDeposit::get())
+		));
 	}
 }
 
 /// Regular relayer that may receive rewards.
 pub const REGULAR_RELAYER: ThisChainAccountId = 1;
+/// Regular relayer that may receive rewards.
+pub const REGULAR_RELAYER2: ThisChainAccountId = 3;
 
 /// Relayer that can't receive rewards.
 pub const FAILING_RELAYER: ThisChainAccountId = 2;
@@ -320,18 +339,23 @@ pub struct TestPaymentProcedure;
 
 impl TestPaymentProcedure {
 	pub fn rewards_account(params: RewardsAccountParams<TestLaneIdType>) -> ThisChainAccountId {
-		PayRewardFromAccount::<(), ThisChainAccountId, TestLaneIdType>::rewards_account(params)
+		PayRewardFromAccount::<(), ThisChainAccountId, TestLaneIdType, RewardBalance>::rewards_account(
+			params,
+		)
 	}
 }
 
-impl PaymentProcedure<ThisChainAccountId, ThisChainBalance> for TestPaymentProcedure {
+impl PaymentProcedure<ThisChainAccountId, RewardsAccountParams<TestLaneIdType>, RewardBalance>
+	for TestPaymentProcedure
+{
 	type Error = ();
-	type LaneId = TestLaneIdType;
+	type Beneficiary = ThisChainAccountId;
 
 	fn pay_reward(
 		relayer: &ThisChainAccountId,
-		_lane_id: RewardsAccountParams<Self::LaneId>,
-		_reward: ThisChainBalance,
+		_reward_kind: RewardsAccountParams<TestLaneIdType>,
+		_reward: RewardBalance,
+		_beneficiary: Self::Beneficiary,
 	) -> Result<(), Self::Error> {
 		match *relayer {
 			FAILING_RELAYER => Err(()),
diff --git a/bridges/modules/relayers/src/payment_adapter.rs b/bridges/modules/relayers/src/payment_adapter.rs
index 5af0d8f9dfbf44788df61bce532cfce82285ba52..e375c6470de0a26caad014ffe469cbf9f5fda81c 100644
--- a/bridges/modules/relayers/src/payment_adapter.rs
+++ b/bridges/modules/relayers/src/payment_adapter.rs
@@ -14,10 +14,12 @@
 // You should have received a copy of the GNU General Public License
 // along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
 
-//! Code that allows relayers pallet to be used as a payment mechanism for the messages pallet.
+//! Code that allows relayers pallet to be used as a payment mechanism for
+//! the `pallet-bridge-messages` pallet using `RewardsAccountParams`.
 
 use crate::{Config, Pallet};
 
+use alloc::collections::vec_deque::VecDeque;
 use bp_messages::{
 	source_chain::{DeliveryConfirmationPayments, RelayersRewards},
 	MessageNonce,
@@ -25,13 +27,13 @@ use bp_messages::{
 pub use bp_relayers::PayRewardFromAccount;
 use bp_relayers::{RewardsAccountOwner, RewardsAccountParams};
 use bp_runtime::Chain;
+use core::{marker::PhantomData, ops::RangeInclusive};
 use frame_support::{sp_runtime::SaturatedConversion, traits::Get};
 use pallet_bridge_messages::LaneIdOf;
 use sp_arithmetic::traits::{Saturating, Zero};
-use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive};
 
 /// Adapter that allows relayers pallet to be used as a delivery+dispatch payment mechanism
-/// for the messages pallet.
+/// for the `pallet-bridge-messages` pallet and using `RewardsAccountParams`.
 pub struct DeliveryConfirmationPaymentsAdapter<T, MI, RI, DeliveryReward>(
 	PhantomData<(T, MI, RI, DeliveryReward)>,
 );
@@ -39,10 +41,11 @@ pub struct DeliveryConfirmationPaymentsAdapter<T, MI, RI, DeliveryReward>(
 impl<T, MI, RI, DeliveryReward> DeliveryConfirmationPayments<T::AccountId, LaneIdOf<T, MI>>
 	for DeliveryConfirmationPaymentsAdapter<T, MI, RI, DeliveryReward>
 where
-	T: Config<RI> + pallet_bridge_messages::Config<MI, LaneId = <T as Config<RI>>::LaneId>,
+	T: Config<RI> + pallet_bridge_messages::Config<MI>,
 	MI: 'static,
 	RI: 'static,
-	DeliveryReward: Get<T::Reward>,
+	DeliveryReward: Get<T::RewardBalance>,
+	<T as Config<RI>>::Reward: From<RewardsAccountParams<LaneIdOf<T, MI>>>,
 {
 	type Error = &'static str;
 
@@ -56,7 +59,7 @@ where
 			bp_messages::calc_relayers_rewards::<T::AccountId>(messages_relayers, received_range);
 		let rewarded_relayers = relayers_rewards.len();
 
-		register_relayers_rewards::<T, RI>(
+		register_relayers_rewards::<T, RI, MI>(
 			confirmation_relayer,
 			relayers_rewards,
 			RewardsAccountParams::new(
@@ -72,21 +75,28 @@ where
 }
 
 // Update rewards to given relayers, optionally rewarding confirmation relayer.
-fn register_relayers_rewards<T: Config<I>, I: 'static>(
+fn register_relayers_rewards<
+	T: Config<RI> + pallet_bridge_messages::Config<MI>,
+	RI: 'static,
+	MI: 'static,
+>(
 	confirmation_relayer: &T::AccountId,
 	relayers_rewards: RelayersRewards<T::AccountId>,
-	lane_id: RewardsAccountParams<T::LaneId>,
-	delivery_fee: T::Reward,
-) {
+	lane_id: RewardsAccountParams<LaneIdOf<T, MI>>,
+	delivery_fee: T::RewardBalance,
+) where
+	<T as Config<RI>>::Reward: From<RewardsAccountParams<LaneIdOf<T, MI>>>,
+{
 	// reward every relayer except `confirmation_relayer`
-	let mut confirmation_relayer_reward = T::Reward::zero();
+	let mut confirmation_relayer_reward = T::RewardBalance::zero();
 	for (relayer, messages) in relayers_rewards {
 		// sane runtime configurations guarantee that the number of messages will be below
 		// `u32::MAX`
-		let relayer_reward = T::Reward::saturated_from(messages).saturating_mul(delivery_fee);
+		let relayer_reward =
+			T::RewardBalance::saturated_from(messages).saturating_mul(delivery_fee);
 
 		if relayer != *confirmation_relayer {
-			Pallet::<T, I>::register_relayer_reward(lane_id, &relayer, relayer_reward);
+			Pallet::<T, RI>::register_relayer_reward(lane_id.into(), &relayer, relayer_reward);
 		} else {
 			confirmation_relayer_reward =
 				confirmation_relayer_reward.saturating_add(relayer_reward);
@@ -94,8 +104,8 @@ fn register_relayers_rewards<T: Config<I>, I: 'static>(
 	}
 
 	// finally - pay reward to confirmation relayer
-	Pallet::<T, I>::register_relayer_reward(
-		lane_id,
+	Pallet::<T, RI>::register_relayer_reward(
+		lane_id.into(),
 		confirmation_relayer,
 		confirmation_relayer_reward,
 	);
@@ -105,6 +115,12 @@ fn register_relayers_rewards<T: Config<I>, I: 'static>(
 mod tests {
 	use super::*;
 	use crate::{mock::*, RelayerRewards};
+	use bp_messages::LaneIdType;
+	use bp_relayers::PaymentProcedure;
+	use frame_support::{
+		assert_ok,
+		traits::fungible::{Inspect, Mutate},
+	};
 
 	const RELAYER_1: ThisChainAccountId = 1;
 	const RELAYER_2: ThisChainAccountId = 2;
@@ -117,7 +133,7 @@ mod tests {
 	#[test]
 	fn confirmation_relayer_is_rewarded_if_it_has_also_delivered_messages() {
 		run_test(|| {
-			register_relayers_rewards::<TestRuntime, ()>(
+			register_relayers_rewards::<TestRuntime, (), ()>(
 				&RELAYER_2,
 				relayers_rewards(),
 				test_reward_account_param(),
@@ -138,7 +154,7 @@ mod tests {
 	#[test]
 	fn confirmation_relayer_is_not_rewarded_if_it_has_not_delivered_any_messages() {
 		run_test(|| {
-			register_relayers_rewards::<TestRuntime, ()>(
+			register_relayers_rewards::<TestRuntime, (), ()>(
 				&RELAYER_3,
 				relayers_rewards(),
 				test_reward_account_param(),
@@ -159,4 +175,52 @@ mod tests {
 			);
 		});
 	}
+
+	#[test]
+	fn pay_reward_from_account_actually_pays_reward() {
+		type Balances = pallet_balances::Pallet<TestRuntime>;
+		type PayLaneRewardFromAccount =
+			PayRewardFromAccount<Balances, ThisChainAccountId, TestLaneIdType, RewardBalance>;
+
+		run_test(|| {
+			let in_lane_0 = RewardsAccountParams::new(
+				TestLaneIdType::try_new(1, 2).unwrap(),
+				*b"test",
+				RewardsAccountOwner::ThisChain,
+			);
+			let out_lane_1 = RewardsAccountParams::new(
+				TestLaneIdType::try_new(1, 3).unwrap(),
+				*b"test",
+				RewardsAccountOwner::BridgedChain,
+			);
+
+			let in_lane0_rewards_account = PayLaneRewardFromAccount::rewards_account(in_lane_0);
+			let out_lane1_rewards_account = PayLaneRewardFromAccount::rewards_account(out_lane_1);
+
+			assert_ok!(Balances::mint_into(&in_lane0_rewards_account, 200));
+			assert_ok!(Balances::mint_into(&out_lane1_rewards_account, 100));
+			assert_eq!(Balances::balance(&in_lane0_rewards_account), 200);
+			assert_eq!(Balances::balance(&out_lane1_rewards_account), 100);
+			assert_eq!(Balances::balance(&1), 0);
+			assert_eq!(Balances::balance(&2), 0);
+
+			assert_ok!(PayLaneRewardFromAccount::pay_reward(&1, in_lane_0, 100, 1_u64));
+			assert_eq!(Balances::balance(&in_lane0_rewards_account), 100);
+			assert_eq!(Balances::balance(&out_lane1_rewards_account), 100);
+			assert_eq!(Balances::balance(&1), 100);
+			assert_eq!(Balances::balance(&2), 0);
+
+			assert_ok!(PayLaneRewardFromAccount::pay_reward(&1, out_lane_1, 100, 1_u64));
+			assert_eq!(Balances::balance(&in_lane0_rewards_account), 100);
+			assert_eq!(Balances::balance(&out_lane1_rewards_account), 0);
+			assert_eq!(Balances::balance(&1), 200);
+			assert_eq!(Balances::balance(&2), 0);
+
+			assert_ok!(PayLaneRewardFromAccount::pay_reward(&1, in_lane_0, 100, 2_u64));
+			assert_eq!(Balances::balance(&in_lane0_rewards_account), 0);
+			assert_eq!(Balances::balance(&out_lane1_rewards_account), 0);
+			assert_eq!(Balances::balance(&1), 200);
+			assert_eq!(Balances::balance(&2), 100);
+		});
+	}
 }
diff --git a/bridges/modules/relayers/src/stake_adapter.rs b/bridges/modules/relayers/src/stake_adapter.rs
index 1792f0be8316acfc9b32508198654c035cc51289..9b5ae1739520c1cef94e50394c327f79e11203b1 100644
--- a/bridges/modules/relayers/src/stake_adapter.rs
+++ b/bridges/modules/relayers/src/stake_adapter.rs
@@ -17,11 +17,11 @@
 //! Code that allows `NamedReservableCurrency` to be used as a `StakeAndSlash`
 //! mechanism of the relayers pallet.
 
-use bp_relayers::{ExplicitOrAccountParams, PayRewardFromAccount, StakeAndSlash};
-use codec::{Codec, Decode, Encode};
+use bp_relayers::StakeAndSlash;
+use codec::Codec;
+use core::{fmt::Debug, marker::PhantomData};
 use frame_support::traits::{tokens::BalanceStatus, NamedReservableCurrency};
 use sp_runtime::{traits::Get, DispatchError, DispatchResult};
-use sp_std::{fmt::Debug, marker::PhantomData};
 
 /// `StakeAndSlash` that works with `NamedReservableCurrency` and uses named
 /// reservations.
@@ -53,20 +53,15 @@ where
 		Currency::unreserve_named(&ReserveId::get(), relayer, amount)
 	}
 
-	fn repatriate_reserved<LaneId: Decode + Encode>(
+	fn repatriate_reserved(
 		relayer: &AccountId,
-		beneficiary: ExplicitOrAccountParams<AccountId, LaneId>,
+		beneficiary: &AccountId,
 		amount: Currency::Balance,
 	) -> Result<Currency::Balance, DispatchError> {
-		let beneficiary_account = match beneficiary {
-			ExplicitOrAccountParams::Explicit(account) => account,
-			ExplicitOrAccountParams::Params(params) =>
-				PayRewardFromAccount::<(), AccountId, LaneId>::rewards_account(params),
-		};
 		Currency::repatriate_reserved_named(
 			&ReserveId::get(),
 			relayer,
-			&beneficiary_account,
+			&beneficiary,
 			amount,
 			BalanceStatus::Free,
 		)
@@ -77,8 +72,10 @@ where
 mod tests {
 	use super::*;
 	use crate::mock::*;
+	use bp_relayers::ExplicitOrAccountParams;
 
 	use frame_support::traits::fungible::Mutate;
+	use sp_runtime::traits::IdentifyAccount;
 
 	fn test_stake() -> ThisChainBalance {
 		Stake::get()
@@ -139,7 +136,7 @@ mod tests {
 			assert_eq!(
 				TestStakeAndSlash::repatriate_reserved(
 					&1,
-					ExplicitOrAccountParams::Params(beneficiary),
+					&(ExplicitOrAccountParams::Params(beneficiary).into_account()),
 					test_stake()
 				),
 				Ok(test_stake())
@@ -155,7 +152,7 @@ mod tests {
 			assert_eq!(
 				TestStakeAndSlash::repatriate_reserved(
 					&2,
-					ExplicitOrAccountParams::Params(beneficiary),
+					&(ExplicitOrAccountParams::Params(beneficiary).into_account()),
 					test_stake()
 				),
 				Ok(test_stake() - test_stake() / 3)
@@ -171,7 +168,7 @@ mod tests {
 			assert_eq!(
 				TestStakeAndSlash::repatriate_reserved(
 					&3,
-					ExplicitOrAccountParams::Params(beneficiary),
+					&(ExplicitOrAccountParams::Params(beneficiary).into_account()),
 					test_stake()
 				),
 				Ok(0)
@@ -193,7 +190,7 @@ mod tests {
 			TestStakeAndSlash::reserve(&3, test_stake()).unwrap();
 			assert!(TestStakeAndSlash::repatriate_reserved(
 				&3,
-				ExplicitOrAccountParams::Params(beneficiary),
+				&(ExplicitOrAccountParams::Params(beneficiary).into_account()),
 				test_stake()
 			)
 			.is_err());
diff --git a/bridges/modules/relayers/src/weights.rs b/bridges/modules/relayers/src/weights.rs
index c2c065b0c0a270a254a60dccb62465d6c2fa4aa6..6acaab7b78c3a4c0f3f1a5df9b567adad685886a 100644
--- a/bridges/modules/relayers/src/weights.rs
+++ b/bridges/modules/relayers/src/weights.rs
@@ -42,15 +42,16 @@
 #![allow(unused_imports)]
 #![allow(missing_docs)]
 
+use core::marker::PhantomData;
 use frame_support::{
 	traits::Get,
 	weights::{constants::RocksDbWeight, Weight},
 };
-use sp_std::marker::PhantomData;
 
 /// Weight functions needed for pallet_bridge_relayers.
 pub trait WeightInfo {
 	fn claim_rewards() -> Weight;
+	fn claim_rewards_to() -> Weight;
 	fn register() -> Weight;
 	fn deregister() -> Weight;
 	fn slash_and_deregister() -> Weight;
@@ -85,6 +86,29 @@ impl<T: frame_system::Config> WeightInfo for BridgeWeight<T> {
 			.saturating_add(T::DbWeight::get().reads(3_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 	}
+	/// Storage: BridgeRelayers RelayerRewards (r:1 w:1)
+	///
+	/// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540,
+	/// mode: MaxEncodedLen)
+	///
+	/// Storage: Balances TotalIssuance (r:1 w:0)
+	///
+	/// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode:
+	/// MaxEncodedLen)
+	///
+	/// Storage: System Account (r:1 w:1)
+	///
+	/// Proof: System Account (max_values: None, max_size: Some(104), added: 2579, mode:
+	/// MaxEncodedLen)
+	fn claim_rewards_to() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `294`
+		//  Estimated: `8592`
+		// Minimum execution time: 77_614 nanoseconds.
+		Weight::from_parts(79_987_000, 8592)
+			.saturating_add(T::DbWeight::get().reads(3_u64))
+			.saturating_add(T::DbWeight::get().writes(2_u64))
+	}
 	/// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1)
 	///
 	/// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(64), added: 2539,
@@ -184,6 +208,29 @@ impl WeightInfo for () {
 			.saturating_add(RocksDbWeight::get().reads(3_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
+	/// Storage: BridgeRelayers RelayerRewards (r:1 w:1)
+	///
+	/// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540,
+	/// mode: MaxEncodedLen)
+	///
+	/// Storage: Balances TotalIssuance (r:1 w:0)
+	///
+	/// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode:
+	/// MaxEncodedLen)
+	///
+	/// Storage: System Account (r:1 w:1)
+	///
+	/// Proof: System Account (max_values: None, max_size: Some(104), added: 2579, mode:
+	/// MaxEncodedLen)
+	fn claim_rewards_to() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `294`
+		//  Estimated: `8592`
+		// Minimum execution time: 77_614 nanoseconds.
+		Weight::from_parts(79_987_000, 8592)
+			.saturating_add(RocksDbWeight::get().reads(3_u64))
+			.saturating_add(RocksDbWeight::get().writes(2_u64))
+	}
 	/// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1)
 	///
 	/// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(64), added: 2539,
diff --git a/bridges/modules/relayers/src/weights_ext.rs b/bridges/modules/relayers/src/weights_ext.rs
index 9cd25c47c3782f709249dd9b1fd24e4c6ec8ab7f..e1d6dcc4a8ee5b87b2f6844e124b8e3a40d63c3a 100644
--- a/bridges/modules/relayers/src/weights_ext.rs
+++ b/bridges/modules/relayers/src/weights_ext.rs
@@ -23,13 +23,13 @@ use frame_support::pallet_prelude::Weight;
 /// Extended weight info.
 pub trait WeightInfoExt: WeightInfo {
 	/// Returns weight, that needs to be added to the pre-dispatch weight of message delivery call,
-	/// if `RefundBridgedParachainMessages` signed extension is deployed at runtime level.
+	/// if `BridgeRelayersTransactionExtension` signed extension is deployed at runtime level.
 	fn receive_messages_proof_overhead_from_runtime() -> Weight {
 		Self::slash_and_deregister().max(Self::register_relayer_reward())
 	}
 
 	/// Returns weight, that needs to be added to the pre-dispatch weight of message delivery
-	/// confirmation call, if `RefundBridgedParachainMessages` signed extension is deployed at
+	/// confirmation call, if `BridgeRelayersTransactionExtension` signed extension is deployed at
 	/// runtime level.
 	fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight {
 		Self::register_relayer_reward()
diff --git a/bridges/modules/xcm-bridge-hub/src/dispatcher.rs b/bridges/modules/xcm-bridge-hub/src/dispatcher.rs
index dd855c7069aadf1fc95840c462530cd7bb7bcb00..1a6be1f18e6b349fcfa1a457c6501cd266f33ddf 100644
--- a/bridges/modules/xcm-bridge-hub/src/dispatcher.rs
+++ b/bridges/modules/xcm-bridge-hub/src/dispatcher.rs
@@ -26,7 +26,7 @@ use crate::{Config, Pallet, LOG_TARGET};
 use bp_messages::target_chain::{DispatchMessage, MessageDispatch};
 use bp_runtime::messages::MessageDispatchResult;
 use bp_xcm_bridge_hub::{LocalXcmChannelManager, XcmAsPlainPayload};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use frame_support::{weights::Weight, CloneNoBound, EqNoBound, PartialEqNoBound};
 use pallet_bridge_messages::{Config as BridgeMessagesConfig, WeightInfoExt};
 use scale_info::TypeInfo;
@@ -35,7 +35,16 @@ use xcm::prelude::*;
 use xcm_builder::{DispatchBlob, DispatchBlobError};
 
 /// Message dispatch result type for single message.
-#[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)]
+#[derive(
+	CloneNoBound,
+	EqNoBound,
+	PartialEqNoBound,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Debug,
+	TypeInfo,
+)]
 pub enum XcmBlobMessageDispatchResult {
 	/// We've been unable to decode message payload.
 	InvalidPayload,
diff --git a/bridges/primitives/header-chain/src/justification/mod.rs b/bridges/primitives/header-chain/src/justification/mod.rs
index 87f53dac64638846f1a9c447aba4268e74cfa0f7..46c4656e33ac8fba9d53d7f349c52ae532c4e803 100644
--- a/bridges/primitives/header-chain/src/justification/mod.rs
+++ b/bridges/primitives/header-chain/src/justification/mod.rs
@@ -31,7 +31,7 @@ pub use verification::{
 };
 
 use bp_runtime::{BlockNumberOf, Chain, HashOf, HeaderId};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 use sp_consensus_grandpa::{AuthorityId, AuthoritySignature};
 use sp_runtime::{traits::Header as HeaderT, RuntimeDebug, SaturatedConversion};
@@ -42,7 +42,7 @@ use sp_std::prelude::*;
 ///
 /// This particular proof is used to prove that headers on a bridged chain
 /// (so not our chain) have been finalized correctly.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Debug))]
 pub struct GrandpaJustification<Header: HeaderT> {
 	/// The round (voting period) this justification is valid for.
diff --git a/bridges/primitives/header-chain/src/lib.rs b/bridges/primitives/header-chain/src/lib.rs
index 48326bf5c19d5a5cfcccab0c69ab2949978418e6..cf7fde2dd739d319995b0c309e4d69427e4871e8 100644
--- a/bridges/primitives/header-chain/src/lib.rs
+++ b/bridges/primitives/header-chain/src/lib.rs
@@ -27,7 +27,7 @@ use bp_runtime::{
 	BasicOperatingMode, BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, RawStorageProof,
 	StorageProofChecker, StorageProofError, UnderlyingChainProvider,
 };
-use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen};
+use codec::{Codec, Decode, DecodeWithMemTracking, Encode, EncodeLike, MaxEncodedLen};
 use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug};
 use frame_support::PalletError;
 use scale_info::TypeInfo;
@@ -46,7 +46,9 @@ pub mod justification;
 pub mod storage_keys;
 
 /// Header chain error.
-#[derive(Clone, Decode, Encode, Eq, PartialEq, PalletError, Debug, TypeInfo)]
+#[derive(
+	Clone, Decode, DecodeWithMemTracking, Encode, Eq, PartialEq, PalletError, Debug, TypeInfo,
+)]
 pub enum HeaderChainError {
 	/// Header with given hash is missing from the chain.
 	UnknownHeader,
@@ -101,7 +103,9 @@ pub trait Parameter: Codec + EncodeLike + Clone + Eq + Debug + TypeInfo {}
 impl<T> Parameter for T where T: Codec + EncodeLike + Clone + Eq + Debug + TypeInfo {}
 
 /// A GRANDPA Authority List and ID.
-#[derive(Default, Encode, Eq, Decode, RuntimeDebug, PartialEq, Clone, TypeInfo)]
+#[derive(
+	Default, Encode, Eq, Decode, DecodeWithMemTracking, RuntimeDebug, PartialEq, Clone, TypeInfo,
+)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub struct AuthoritySet {
 	/// List of GRANDPA authorities for the current round.
@@ -121,7 +125,17 @@ impl AuthoritySet {
 ///
 /// The bridge needs to know where to start its sync from, and this provides that initial context.
 #[derive(
-	Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, Clone, TypeInfo, Serialize, Deserialize,
+	Default,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	PartialEq,
+	Eq,
+	Clone,
+	TypeInfo,
+	Serialize,
+	Deserialize,
 )]
 pub struct InitializationData<H: HeaderT> {
 	/// The header from which we should start syncing.
@@ -189,7 +203,7 @@ impl<Number: Codec> ConsensusLogReader for GrandpaConsensusLogReader<Number> {
 }
 
 /// The finality-related info associated to a header.
-#[derive(Encode, Decode, Debug, PartialEq, Clone, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Debug, PartialEq, Clone, TypeInfo)]
 pub struct HeaderFinalityInfo<FinalityProof, FinalityVerificationContext> {
 	/// The header finality proof.
 	pub finality_proof: FinalityProof,
diff --git a/bridges/primitives/messages/src/lane.rs b/bridges/primitives/messages/src/lane.rs
index 75237a44d5385ace12db087a3258818f763496cd..adf06b64d31d913535124ec7535197a9c579f608 100644
--- a/bridges/primitives/messages/src/lane.rs
+++ b/bridges/primitives/messages/src/lane.rs
@@ -16,7 +16,7 @@
 
 //! Primitives of messages module, that represents lane id.
 
-use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen};
+use codec::{Codec, Decode, DecodeWithMemTracking, Encode, EncodeLike, MaxEncodedLen};
 use scale_info::TypeInfo;
 use serde::{de::DeserializeOwned, Deserialize, Serialize};
 use sp_core::{RuntimeDebug, TypeId, H256};
@@ -50,6 +50,7 @@ pub trait LaneIdType:
 	Clone,
 	Copy,
 	Decode,
+	DecodeWithMemTracking,
 	Default,
 	Encode,
 	Eq,
@@ -121,6 +122,7 @@ impl TypeId for LegacyLaneId {
 	Clone,
 	Copy,
 	Decode,
+	DecodeWithMemTracking,
 	Default,
 	Encode,
 	Eq,
diff --git a/bridges/primitives/messages/src/lib.rs b/bridges/primitives/messages/src/lib.rs
index 2776b806cc16bf30fb09c06d904c05f6bcea21d0..16f5cfa1bea660d4d894e5ca05f5505f2c01c031 100644
--- a/bridges/primitives/messages/src/lib.rs
+++ b/bridges/primitives/messages/src/lib.rs
@@ -24,7 +24,7 @@ use bp_runtime::{
 	messages::MessageDispatchResult, BasicOperatingMode, Chain, OperatingMode, RangeInclusiveExt,
 	StorageProofError, UnderlyingChainOf, UnderlyingChainProvider,
 };
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_support::PalletError;
 // Weight is reexported to avoid additional frame-support dependencies in related crates.
 pub use frame_support::weights::Weight;
@@ -135,6 +135,7 @@ where
 #[derive(
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Clone,
 	Copy,
 	PartialEq,
@@ -336,7 +337,7 @@ pub struct UnrewardedRelayer<RelayerId> {
 }
 
 /// Received messages with their dispatch result.
-#[derive(Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)]
+#[derive(Clone, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, PartialEq, Eq, TypeInfo)]
 pub struct ReceivedMessages<DispatchLevelResult, LaneId> {
 	/// Id of the lane which is receiving messages.
 	pub lane: LaneId,
@@ -360,7 +361,7 @@ impl<DispatchLevelResult, LaneId> ReceivedMessages<DispatchLevelResult, LaneId>
 }
 
 /// Result of single message receival.
-#[derive(RuntimeDebug, Encode, Decode, PartialEq, Eq, Clone, TypeInfo)]
+#[derive(RuntimeDebug, Encode, Decode, DecodeWithMemTracking, PartialEq, Eq, Clone, TypeInfo)]
 pub enum ReceptionResult<DispatchLevelResult> {
 	/// Message has been received and dispatched. Note that we don't care whether dispatch has
 	/// been successful or not - in both case message falls into this category.
@@ -376,7 +377,18 @@ pub enum ReceptionResult<DispatchLevelResult> {
 }
 
 /// Delivered messages with their dispatch result.
-#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone,
+	Default,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	PartialEq,
+	Eq,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct DeliveredMessages {
 	/// Nonce of the first message that has been delivered (inclusive).
 	pub begin: MessageNonce,
@@ -408,7 +420,9 @@ impl DeliveredMessages {
 }
 
 /// Gist of `InboundLaneData::relayers` field used by runtime APIs.
-#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)]
+#[derive(
+	Clone, Default, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, PartialEq, Eq, TypeInfo,
+)]
 pub struct UnrewardedRelayersState {
 	/// Number of entries in the `InboundLaneData::relayers` set.
 	pub unrewarded_relayer_entries: MessageNonce,
@@ -512,7 +526,9 @@ where
 }
 
 /// Error that happens during message verification.
-#[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo)]
+#[derive(
+	Encode, Decode, DecodeWithMemTracking, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo,
+)]
 pub enum VerificationError {
 	/// The message proof is empty.
 	EmptyMessageProof,
diff --git a/bridges/primitives/messages/src/source_chain.rs b/bridges/primitives/messages/src/source_chain.rs
index 1d4a513035c744bf4044156858bcdf9d756e94fa..afb70b3d0159817350d606ee260211bc46560b6d 100644
--- a/bridges/primitives/messages/src/source_chain.rs
+++ b/bridges/primitives/messages/src/source_chain.rs
@@ -19,7 +19,7 @@
 use crate::{MessageNonce, UnrewardedRelayer};
 
 use bp_runtime::{raw_storage_proof_size, RawStorageProof, Size};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use scale_info::TypeInfo;
 use sp_core::RuntimeDebug;
 use sp_std::{
@@ -38,7 +38,7 @@ use sp_std::{
 /// - storage proof of the inbound lane state;
 ///
 /// - lane id.
-#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Clone, Decode, DecodeWithMemTracking, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct FromBridgedChainMessagesDeliveryProof<BridgedHeaderHash, LaneId> {
 	/// Hash of the bridge header the proof is for.
 	pub bridged_header_hash: BridgedHeaderHash,
diff --git a/bridges/primitives/messages/src/target_chain.rs b/bridges/primitives/messages/src/target_chain.rs
index cf07a400933a965f5097d4654f6e405a1d11b33b..e5b860ce305ee4957ed6279f976ffd09a966c840 100644
--- a/bridges/primitives/messages/src/target_chain.rs
+++ b/bridges/primitives/messages/src/target_chain.rs
@@ -19,7 +19,7 @@
 use crate::{Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData};
 
 use bp_runtime::{messages::MessageDispatchResult, raw_storage_proof_size, RawStorageProof, Size};
-use codec::{Decode, Encode, Error as CodecError};
+use codec::{Decode, DecodeWithMemTracking, Encode, Error as CodecError};
 use frame_support::weights::Weight;
 use scale_info::TypeInfo;
 use sp_core::RuntimeDebug;
@@ -37,7 +37,7 @@ use sp_std::{fmt::Debug, marker::PhantomData, prelude::*};
 /// - lane id;
 ///
 /// - nonces (inclusive range) of messages which are included in this proof.
-#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Clone, Decode, DecodeWithMemTracking, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct FromBridgedChainMessagesProof<BridgedHeaderHash, Lane> {
 	/// Hash of the finalized bridged header the proof is for.
 	pub bridged_header_hash: BridgedHeaderHash,
diff --git a/bridges/primitives/polkadot-core/src/parachains.rs b/bridges/primitives/polkadot-core/src/parachains.rs
index a8b1cf6eebf49dedf40bcb94135d4e6717dc14d0..be13cba3dbeb21e30c87e63aced1b2369d3f2aec 100644
--- a/bridges/primitives/polkadot-core/src/parachains.rs
+++ b/bridges/primitives/polkadot-core/src/parachains.rs
@@ -23,7 +23,7 @@
 //! be two versions of polkadot crates included in the runtime. Which is bad.
 
 use bp_runtime::{raw_storage_proof_size, RawStorageProof, Size};
-use codec::{CompactAs, Decode, Encode, MaxEncodedLen};
+use codec::{CompactAs, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 use sp_core::Hasher;
 use sp_runtime::RuntimeDebug;
@@ -41,6 +41,7 @@ use serde::{Deserialize, Serialize};
 	CompactAs,
 	Copy,
 	Decode,
+	DecodeWithMemTracking,
 	Default,
 	Encode,
 	Eq,
@@ -85,7 +86,7 @@ pub type ParaHash = crate::Hash;
 pub type ParaHasher = crate::Hasher;
 
 /// Raw storage proof of parachain heads, stored in polkadot-like chain runtime.
-#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Clone, Decode, DecodeWithMemTracking, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct ParaHeadsProof {
 	/// Unverified storage proof of finalized parachain heads.
 	pub storage_proof: RawStorageProof,
diff --git a/bridges/primitives/relayers/src/lib.rs b/bridges/primitives/relayers/src/lib.rs
index faa4cb17762940ff0dc6d3fbf322dbf99bb92e49..1a58a0f32a6d22cc1327e9fb837eb5e56c9eea4e 100644
--- a/bridges/primitives/relayers/src/lib.rs
+++ b/bridges/primitives/relayers/src/lib.rs
@@ -29,7 +29,7 @@ use bp_runtime::{ChainId, StorageDoubleMapKeyProvider};
 use frame_support::{traits::tokens::Preservation, Blake2_128Concat, Identity};
 use scale_info::TypeInfo;
 use sp_runtime::{
-	codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen},
+	codec::{Codec, Decode, DecodeWithMemTracking, Encode, EncodeLike, MaxEncodedLen},
 	traits::AccountIdConversion,
 	TypeId,
 };
@@ -42,7 +42,18 @@ mod registration;
 ///
 /// Each of the 2 final points connected by a bridge owns a sovereign account at each end of the
 /// bridge. So here, at this end of the bridge there can be 2 sovereign accounts that pay rewards.
-#[derive(Copy, Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Copy,
+	Clone,
+	Debug,
+	Decode,
+	DecodeWithMemTracking,
+	Encode,
+	Eq,
+	PartialEq,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum RewardsAccountOwner {
 	/// The sovereign account of the final chain on this end of the bridge.
 	ThisChain,
@@ -59,7 +70,18 @@ pub enum RewardsAccountOwner {
 /// destinations of a bridge lane must have a sovereign account at each end of the bridge and each
 /// of the sovereign accounts will pay rewards for different operations. So we need multiple
 /// parameters to identify the account that pays a reward to the relayer.
-#[derive(Copy, Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Copy,
+	Clone,
+	Debug,
+	Decode,
+	DecodeWithMemTracking,
+	Encode,
+	Eq,
+	PartialEq,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct RewardsAccountParams<LaneId> {
 	// **IMPORTANT NOTE**: the order of fields here matters - we are using
 	// `into_account_truncating` and lane id is already `32` byte, so if other fields are encoded
@@ -90,38 +112,44 @@ impl<LaneId: Decode + Encode> TypeId for RewardsAccountParams<LaneId> {
 }
 
 /// Reward payment procedure.
-pub trait PaymentProcedure<Relayer, Reward> {
+pub trait PaymentProcedure<Relayer, Reward, RewardBalance> {
 	/// Error that may be returned by the procedure.
 	type Error: Debug;
-	/// Lane identifier type.
-	type LaneId: Decode + Encode;
 
-	/// Pay reward to the relayer from the account with provided params.
+	/// Type parameter used to identify the beneficiaries eligible to receive rewards.
+	type Beneficiary: Clone + Debug + Decode + Encode + Eq + TypeInfo;
+
+	/// Pay reward to the relayer (or alternative beneficiary if provided) from the account with
+	/// provided params.
 	fn pay_reward(
 		relayer: &Relayer,
-		rewards_account_params: RewardsAccountParams<Self::LaneId>,
 		reward: Reward,
+		reward_balance: RewardBalance,
+		beneficiary: Self::Beneficiary,
 	) -> Result<(), Self::Error>;
 }
 
-impl<Relayer, Reward> PaymentProcedure<Relayer, Reward> for () {
+impl<Relayer, Reward, RewardBalance> PaymentProcedure<Relayer, Reward, RewardBalance> for () {
 	type Error = &'static str;
-	type LaneId = ();
+	type Beneficiary = ();
 
 	fn pay_reward(
 		_: &Relayer,
-		_: RewardsAccountParams<Self::LaneId>,
 		_: Reward,
+		_: RewardBalance,
+		_: Self::Beneficiary,
 	) -> Result<(), Self::Error> {
 		Ok(())
 	}
 }
 
-/// Reward payment procedure that does `balances::transfer` call from the account, derived from
-/// given params.
-pub struct PayRewardFromAccount<T, Relayer, LaneId>(PhantomData<(T, Relayer, LaneId)>);
+/// Reward payment procedure that executes a `balances::transfer` call from the account
+/// derived from the given `RewardsAccountParams` to the relayer or an alternative beneficiary.
+pub struct PayRewardFromAccount<T, Relayer, LaneId, RewardBalance>(
+	PhantomData<(T, Relayer, LaneId, RewardBalance)>,
+);
 
-impl<T, Relayer, LaneId> PayRewardFromAccount<T, Relayer, LaneId>
+impl<T, Relayer, LaneId, RewardBalance> PayRewardFromAccount<T, Relayer, LaneId, RewardBalance>
 where
 	Relayer: Decode + Encode,
 	LaneId: Decode + Encode,
@@ -132,25 +160,28 @@ where
 	}
 }
 
-impl<T, Relayer, LaneId> PaymentProcedure<Relayer, T::Balance>
-	for PayRewardFromAccount<T, Relayer, LaneId>
+impl<T, Relayer, LaneId, RewardBalance>
+	PaymentProcedure<Relayer, RewardsAccountParams<LaneId>, RewardBalance>
+	for PayRewardFromAccount<T, Relayer, LaneId, RewardBalance>
 where
 	T: frame_support::traits::fungible::Mutate<Relayer>,
-	Relayer: Decode + Encode + Eq,
+	T::Balance: From<RewardBalance>,
+	Relayer: Clone + Debug + Decode + Encode + Eq + TypeInfo,
 	LaneId: Decode + Encode,
 {
 	type Error = sp_runtime::DispatchError;
-	type LaneId = LaneId;
+	type Beneficiary = Relayer;
 
 	fn pay_reward(
-		relayer: &Relayer,
-		rewards_account_params: RewardsAccountParams<Self::LaneId>,
-		reward: T::Balance,
+		_: &Relayer,
+		reward_kind: RewardsAccountParams<LaneId>,
+		reward: RewardBalance,
+		beneficiary: Self::Beneficiary,
 	) -> Result<(), Self::Error> {
 		T::transfer(
-			&Self::rewards_account(rewards_account_params),
-			relayer,
-			reward,
+			&Self::rewards_account(reward_kind),
+			&beneficiary.into(),
+			reward.into(),
 			Preservation::Expendable,
 		)
 		.map(drop)
@@ -159,24 +190,33 @@ where
 
 /// Can be used to access the runtime storage key within the `RelayerRewards` map of the relayers
 /// pallet.
-pub struct RelayerRewardsKeyProvider<AccountId, Reward, LaneId>(
-	PhantomData<(AccountId, Reward, LaneId)>,
+pub struct RelayerRewardsKeyProvider<AccountId, Reward, RewardBalance>(
+	PhantomData<(AccountId, Reward, RewardBalance)>,
 );
 
-impl<AccountId, Reward, LaneId> StorageDoubleMapKeyProvider
-	for RelayerRewardsKeyProvider<AccountId, Reward, LaneId>
+impl<AccountId, Reward, RewardBalance> StorageDoubleMapKeyProvider
+	for RelayerRewardsKeyProvider<AccountId, Reward, RewardBalance>
 where
 	AccountId: 'static + Codec + EncodeLike + Send + Sync,
-	Reward: 'static + Codec + EncodeLike + Send + Sync,
-	LaneId: Codec + EncodeLike + Send + Sync,
+	Reward: Codec + EncodeLike + Send + Sync,
+	RewardBalance: 'static + Codec + EncodeLike + Send + Sync,
 {
 	const MAP_NAME: &'static str = "RelayerRewards";
 
 	type Hasher1 = Blake2_128Concat;
 	type Key1 = AccountId;
 	type Hasher2 = Identity;
-	type Key2 = RewardsAccountParams<LaneId>;
-	type Value = Reward;
+	type Key2 = Reward;
+	type Value = RewardBalance;
+}
+
+/// A trait defining a reward ledger, which tracks rewards that can be later claimed.
+///
+/// This ledger allows registering rewards for a relayer, categorized by a specific `Reward`.
+/// The registered rewards can be claimed later through an appropriate payment procedure.
+pub trait RewardLedger<Relayer, Reward, RewardBalance> {
+	/// Registers a reward for a given relayer.
+	fn register_reward(relayer: &Relayer, reward: Reward, reward_balance: RewardBalance);
 }
 
 #[cfg(test)]
@@ -188,7 +228,7 @@ mod tests {
 	#[test]
 	fn different_lanes_are_using_different_accounts() {
 		assert_eq!(
-			PayRewardFromAccount::<(), H256, HashedLaneId>::rewards_account(
+			PayRewardFromAccount::<(), H256, HashedLaneId, ()>::rewards_account(
 				RewardsAccountParams::new(
 					HashedLaneId::try_new(1, 2).unwrap(),
 					*b"test",
@@ -200,7 +240,7 @@ mod tests {
 		);
 
 		assert_eq!(
-			PayRewardFromAccount::<(), H256, HashedLaneId>::rewards_account(
+			PayRewardFromAccount::<(), H256, HashedLaneId, ()>::rewards_account(
 				RewardsAccountParams::new(
 					HashedLaneId::try_new(1, 3).unwrap(),
 					*b"test",
@@ -215,7 +255,7 @@ mod tests {
 	#[test]
 	fn different_directions_are_using_different_accounts() {
 		assert_eq!(
-			PayRewardFromAccount::<(), H256, HashedLaneId>::rewards_account(
+			PayRewardFromAccount::<(), H256, HashedLaneId, ()>::rewards_account(
 				RewardsAccountParams::new(
 					HashedLaneId::try_new(1, 2).unwrap(),
 					*b"test",
@@ -227,7 +267,7 @@ mod tests {
 		);
 
 		assert_eq!(
-			PayRewardFromAccount::<(), H256, HashedLaneId>::rewards_account(
+			PayRewardFromAccount::<(), H256, HashedLaneId, ()>::rewards_account(
 				RewardsAccountParams::new(
 					HashedLaneId::try_new(1, 2).unwrap(),
 					*b"test",
@@ -303,6 +343,7 @@ mod tests {
 					[u8; 32],
 					[u8; 32],
 					LegacyLaneId,
+					(),
 				>::rewards_account(RewardsAccountParams::new(
 					lane_id,
 					*bridged_chain_id,
diff --git a/bridges/primitives/relayers/src/registration.rs b/bridges/primitives/relayers/src/registration.rs
index d74ef18cf706bdee134dc1157a150a3132b36a2e..1144eccd21a9ddb61f1ca3d9a05c4daee6c040dd 100644
--- a/bridges/primitives/relayers/src/registration.rs
+++ b/bridges/primitives/relayers/src/registration.rs
@@ -37,12 +37,12 @@
 //! that guarantees that their transactions are valid. Such relayers get priority
 //! for free, but they risk to lose their stake.
 
-use crate::RewardsAccountParams;
+use crate::{PayRewardFromAccount, RewardsAccountParams};
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 use sp_runtime::{
-	traits::{Get, Zero},
+	traits::{Get, IdentifyAccount, Zero},
 	DispatchError, DispatchResult,
 };
 
@@ -63,8 +63,33 @@ impl<AccountId, LaneId: Decode + Encode> From<RewardsAccountParams<LaneId>>
 	}
 }
 
+impl<AccountId: Decode + Encode, LaneId: Decode + Encode> IdentifyAccount
+	for ExplicitOrAccountParams<AccountId, LaneId>
+{
+	type AccountId = AccountId;
+
+	fn into_account(self) -> Self::AccountId {
+		match self {
+			ExplicitOrAccountParams::Explicit(account_id) => account_id,
+			ExplicitOrAccountParams::Params(params) =>
+				PayRewardFromAccount::<(), AccountId, LaneId, ()>::rewards_account(params),
+		}
+	}
+}
+
 /// Relayer registration.
-#[derive(Copy, Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Copy,
+	Clone,
+	Debug,
+	Decode,
+	DecodeWithMemTracking,
+	Encode,
+	Eq,
+	PartialEq,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct Registration<BlockNumber, Balance> {
 	/// The last block number, where this registration is considered active.
 	///
@@ -105,9 +130,9 @@ pub trait StakeAndSlash<AccountId, BlockNumber, Balance> {
 	/// `beneficiary`.
 	///
 	/// Returns `Ok(_)` with non-zero balance if we have failed to repatriate some portion of stake.
-	fn repatriate_reserved<LaneId: Decode + Encode>(
+	fn repatriate_reserved(
 		relayer: &AccountId,
-		beneficiary: ExplicitOrAccountParams<AccountId, LaneId>,
+		beneficiary: &AccountId,
 		amount: Balance,
 	) -> Result<Balance, DispatchError>;
 }
@@ -128,9 +153,9 @@ where
 		Zero::zero()
 	}
 
-	fn repatriate_reserved<LaneId: Decode + Encode>(
+	fn repatriate_reserved(
 		_relayer: &AccountId,
-		_beneficiary: ExplicitOrAccountParams<AccountId, LaneId>,
+		_beneficiary: &AccountId,
 		_amount: Balance,
 	) -> Result<Balance, DispatchError> {
 		Ok(Zero::zero())
diff --git a/bridges/primitives/runtime/src/lib.rs b/bridges/primitives/runtime/src/lib.rs
index 90eb72922beaa3bc490c879eacb43a7db521f9a0..85525f0eb1bd9db7c883a27a7008eb533662f034 100644
--- a/bridges/primitives/runtime/src/lib.rs
+++ b/bridges/primitives/runtime/src/lib.rs
@@ -19,7 +19,7 @@
 #![warn(missing_docs)]
 #![cfg_attr(not(feature = "std"), no_std)]
 
-use codec::{Decode, Encode, FullCodec, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, FullCodec, MaxEncodedLen};
 use frame_support::{
 	pallet_prelude::DispatchResult, weights::Weight, PalletError, StorageHasher, StorageValue,
 };
@@ -316,7 +316,7 @@ pub trait StorageDoubleMapKeyProvider {
 }
 
 /// Error generated by the `OwnedBridgeModule` trait.
-#[derive(Encode, Decode, PartialEq, Eq, TypeInfo, PalletError)]
+#[derive(Encode, Decode, DecodeWithMemTracking, PartialEq, Eq, TypeInfo, PalletError)]
 pub enum OwnedBridgeModuleError {
 	/// All pallet operations are halted.
 	Halted,
@@ -332,6 +332,7 @@ pub trait OperatingMode: Send + Copy + Debug + FullCodec {
 #[derive(
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Clone,
 	Copy,
 	PartialEq,
diff --git a/bridges/primitives/runtime/src/messages.rs b/bridges/primitives/runtime/src/messages.rs
index 0f219e984f7289b231c888c55e0e2acfb8829a88..4163fdc6fc15170b861997a060b009a04a7ee431 100644
--- a/bridges/primitives/runtime/src/messages.rs
+++ b/bridges/primitives/runtime/src/messages.rs
@@ -16,13 +16,13 @@
 
 //! Primitives that may be used by different message delivery and dispatch mechanisms.
 
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use frame_support::weights::Weight;
 use scale_info::TypeInfo;
 use sp_runtime::RuntimeDebug;
 
 /// Message dispatch result.
-#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)]
 pub struct MessageDispatchResult<DispatchLevelResult> {
 	/// Unspent dispatch weight. This weight that will be deducted from total delivery transaction
 	/// weight, thus reducing the transaction cost. This shall not be zero in (at least) two cases:
diff --git a/bridges/primitives/runtime/src/storage_proof.rs b/bridges/primitives/runtime/src/storage_proof.rs
index 8bd9001f2b6c137935f8757e125d8dd5ac4ff8d6..113e101e3703aad48b5084b52f55aa27bf706c1a 100644
--- a/bridges/primitives/runtime/src/storage_proof.rs
+++ b/bridges/primitives/runtime/src/storage_proof.rs
@@ -23,7 +23,7 @@ use sp_trie::{
 	accessed_nodes_tracker::AccessedNodesTracker, read_trie_value, LayoutV1, MemoryDB, StorageProof,
 };
 
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use hash_db::{HashDB, Hasher, EMPTY_PREFIX};
 use scale_info::TypeInfo;
 #[cfg(feature = "test-helpers")]
@@ -32,7 +32,9 @@ use sp_trie::{recorder_ext::RecorderExt, Recorder, TrieDBBuilder, TrieError, Tri
 use trie_db::{Trie, TrieConfiguration, TrieDBMut};
 
 /// Errors that can occur when interacting with `UnverifiedStorageProof` and `VerifiedStorageProof`.
-#[derive(Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo)]
+#[derive(
+	Clone, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo,
+)]
 pub enum StorageProofError {
 	/// Call to `generate_trie_proof()` failed.
 	UnableToGenerateTrieProof,
diff --git a/bridges/primitives/test-utils/src/lib.rs b/bridges/primitives/test-utils/src/lib.rs
index 9855c32a468954dd0f3011c029c793e5cd2cbc35..ae3d85ccdf51fab273405c2ed9780f812e61c2bb 100644
--- a/bridges/primitives/test-utils/src/lib.rs
+++ b/bridges/primitives/test-utils/src/lib.rs
@@ -110,7 +110,7 @@ pub fn make_justification_for_header<H: HeaderT>(
 	);
 
 	// Roughly, how many vote ancestries do we want per fork
-	let target_depth = (ancestors + forks - 1) / forks;
+	let target_depth = ancestors.div_ceil(forks);
 
 	let mut unsigned_precommits = vec![];
 	for i in 0..forks {
diff --git a/bridges/primitives/xcm-bridge-hub/src/lib.rs b/bridges/primitives/xcm-bridge-hub/src/lib.rs
index 471cf402c34fbdc6d2b47070ce19736d10669884..89bb888ab3faabd14df7db094c123faa8302fbc5 100644
--- a/bridges/primitives/xcm-bridge-hub/src/lib.rs
+++ b/bridges/primitives/xcm-bridge-hub/src/lib.rs
@@ -22,7 +22,7 @@
 use bp_messages::LaneIdType;
 use bp_runtime::{AccountIdOf, BalanceOf, Chain};
 pub use call_info::XcmBridgeHubCall;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_support::{
 	ensure, sp_runtime::RuntimeDebug, CloneNoBound, PalletError, PartialEqNoBound,
 	RuntimeDebugNoBound,
@@ -59,6 +59,7 @@ pub type XcmAsPlainPayload = sp_std::vec::Vec<u8>;
 	Copy,
 	Decode,
 	Encode,
+	DecodeWithMemTracking,
 	Eq,
 	Ord,
 	PartialOrd,
@@ -197,7 +198,9 @@ pub struct BridgeLocations {
 }
 
 /// Errors that may happen when we check bridge locations.
-#[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo)]
+#[derive(
+	Encode, Decode, DecodeWithMemTracking, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo,
+)]
 pub enum BridgeLocationsError {
 	/// Origin or destination locations are not universal.
 	NonUniversalLocation,
diff --git a/bridges/relays/client-substrate/src/chain.rs b/bridges/relays/client-substrate/src/chain.rs
index 9856f0d0237ea63997ffc24baf0f1f099df9ef6b..2e6241510d641fb857c3b33c4f6f5efee77abbc8 100644
--- a/bridges/relays/client-substrate/src/chain.rs
+++ b/bridges/relays/client-substrate/src/chain.rs
@@ -23,7 +23,8 @@ use bp_runtime::{
 	Chain as ChainBase, EncodedOrDecodedCall, HashOf, Parachain as ParachainBase, TransactionEra,
 	TransactionEraOf, UnderlyingChainProvider,
 };
-use codec::{Codec, Decode, Encode};
+use codec::{Codec, Decode, Encode, MaxEncodedLen};
+use frame_support::Parameter;
 use jsonrpsee::core::{DeserializeOwned, Serialize};
 use num_traits::Zero;
 use sc_transaction_pool_api::TransactionStatus;
@@ -31,7 +32,7 @@ use scale_info::TypeInfo;
 use sp_core::{storage::StorageKey, Pair};
 use sp_runtime::{
 	generic::SignedBlock,
-	traits::{Block as BlockT, Member},
+	traits::{AtLeast32BitUnsigned, Block as BlockT, Member},
 	ConsensusEngineId, EncodedJustification,
 };
 use std::{fmt::Debug, time::Duration};
@@ -113,13 +114,6 @@ impl<T> Parachain for T where T: UnderlyingChainProvider + Chain + ParachainBase
 
 /// Substrate-based chain with messaging support from minimal relay-client point of view.
 pub trait ChainWithMessages: Chain + ChainWithMessagesBase {
-	/// Name of the bridge relayers pallet (used in `construct_runtime` macro call) that is deployed
-	/// at some other chain to bridge with this `ChainWithMessages`.
-	///
-	/// We assume that all chains that are bridging with this `ChainWithMessages` are using
-	/// the same name.
-	const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str>;
-
 	/// Name of the `To<ChainWithMessages>OutboundLaneApi::message_details` runtime API method.
 	/// The method is provided by the runtime that is bridged with this `ChainWithMessages`.
 	const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str;
@@ -141,6 +135,22 @@ pub trait ChainWithBalances: Chain {
 	fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey;
 }
 
+/// Substrate-based chain with bridge relayers pallet as a reward ledger.
+pub trait ChainWithRewards: Chain {
+	/// Name of the bridge relayers pallet (used in `construct_runtime` macro call).
+	const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str>;
+	/// Type of relayer reward balance.
+	type RewardBalance: AtLeast32BitUnsigned + Copy + Member + Parameter + MaxEncodedLen;
+	/// Reward discriminator type.
+	type Reward: Parameter + MaxEncodedLen + Send + Sync + Copy + Clone;
+
+	/// Return runtime storage key for getting `reward_kind` of given account.
+	fn account_reward_storage_key(
+		account_id: &Self::AccountId,
+		reward: impl Into<Self::Reward>,
+	) -> StorageKey;
+}
+
 /// SCALE-encoded extrinsic.
 pub type EncodedExtrinsic = Vec<u8>;
 
diff --git a/bridges/relays/client-substrate/src/client/rpc.rs b/bridges/relays/client-substrate/src/client/rpc.rs
index 9c7f769462e5693bc944ed6a6525439f00311ee7..7147bad3c28ef9ab47c4feb2943ed81d11cd8c10 100644
--- a/bridges/relays/client-substrate/src/client/rpc.rs
+++ b/bridges/relays/client-substrate/src/client/rpc.rs
@@ -194,21 +194,7 @@ impl<C: Chain> RpcClient<C> {
 		params: &ConnectionParams,
 	) -> Result<(Arc<tokio::runtime::Runtime>, Arc<WsClient>)> {
 		let tokio = tokio::runtime::Runtime::new()?;
-		let uri = match params.uri {
-			Some(ref uri) => uri.clone(),
-			None => {
-				format!(
-					"{}://{}:{}{}",
-					if params.secure { "wss" } else { "ws" },
-					params.host,
-					params.port,
-					match params.path {
-						Some(ref path) => format!("/{}", path),
-						None => String::new(),
-					},
-				)
-			},
-		};
+		let uri = params.uri.clone();
 		log::info!(target: "bridge", "Connecting to {} node at {}", C::NAME, uri);
 
 		let client = tokio
diff --git a/bridges/relays/client-substrate/src/lib.rs b/bridges/relays/client-substrate/src/lib.rs
index 12a1c48c09c7ad59d05c0e40a578bc71f7575b35..76ba17bd2f37008c9fab1c971c82af24f86a241e 100644
--- a/bridges/relays/client-substrate/src/lib.rs
+++ b/bridges/relays/client-substrate/src/lib.rs
@@ -34,10 +34,10 @@ use std::time::Duration;
 pub use crate::{
 	chain::{
 		AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances,
-		ChainWithGrandpa, ChainWithMessages, ChainWithRuntimeVersion, ChainWithTransactions,
-		ChainWithUtilityPallet, FullRuntimeUtilityPallet, MockedRuntimeUtilityPallet, Parachain,
-		RelayChain, SignParam, SignedBlockOf, TransactionStatusOf, UnsignedTransaction,
-		UtilityPallet,
+		ChainWithGrandpa, ChainWithMessages, ChainWithRewards, ChainWithRuntimeVersion,
+		ChainWithTransactions, ChainWithUtilityPallet, FullRuntimeUtilityPallet,
+		MockedRuntimeUtilityPallet, Parachain, RelayChain, SignParam, SignedBlockOf,
+		TransactionStatusOf, UnsignedTransaction, UtilityPallet,
 	},
 	client::{
 		is_ancient_block, rpc_with_caching as new, ChainRuntimeVersion, Client,
@@ -57,17 +57,8 @@ pub use bp_runtime::{
 /// Substrate-over-websocket connection params.
 #[derive(Debug, Clone)]
 pub struct ConnectionParams {
-	/// Websocket endpoint URL. Overrides all other URL components (`host`, `port`, `path` and
-	/// `secure`).
-	pub uri: Option<String>,
-	/// Websocket server host name.
-	pub host: String,
-	/// Websocket server TCP port.
-	pub port: u16,
-	/// Websocket endpoint path at server.
-	pub path: Option<String>,
-	/// Use secure websocket connection.
-	pub secure: bool,
+	/// Websocket endpoint URL.
+	pub uri: String,
 	/// Defined chain runtime version
 	pub chain_runtime_version: ChainRuntimeVersion,
 }
@@ -75,11 +66,7 @@ pub struct ConnectionParams {
 impl Default for ConnectionParams {
 	fn default() -> Self {
 		ConnectionParams {
-			uri: None,
-			host: "localhost".into(),
-			port: 9944,
-			path: None,
-			secure: false,
+			uri: "ws://localhost:9944".into(),
 			chain_runtime_version: ChainRuntimeVersion::Auto,
 		}
 	}
diff --git a/bridges/relays/client-substrate/src/test_chain.rs b/bridges/relays/client-substrate/src/test_chain.rs
index 991202e9874c790e404b42b74102248cb5f6723f..8bdbea20e9a1ba8f21da33c2a9ccef57aaeeb740 100644
--- a/bridges/relays/client-substrate/src/test_chain.rs
+++ b/bridges/relays/client-substrate/src/test_chain.rs
@@ -80,7 +80,6 @@ impl ChainWithMessagesBase for TestChain {
 }
 
 impl ChainWithMessages for TestChain {
-	const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = None;
 	const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = "TestMessagesDetailsMethod";
 	const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = "TestFromMessagesDetailsMethod";
 }
diff --git a/bridges/relays/lib-substrate-relay/src/cli/chain_schema.rs b/bridges/relays/lib-substrate-relay/src/cli/chain_schema.rs
index d985d35c9e802e694e74264ed3f611f14e8bc0d2..ae00b243c0c4328e70245d638dda1a196257be7a 100644
--- a/bridges/relays/lib-substrate-relay/src/cli/chain_schema.rs
+++ b/bridges/relays/lib-substrate-relay/src/cli/chain_schema.rs
@@ -98,21 +98,9 @@ macro_rules! declare_chain_connection_params_cli_schema {
 			#[doc = $chain " connection params."]
 			#[derive(StructOpt, Debug, PartialEq, Eq, Clone)]
 			pub struct [<$chain ConnectionParams>] {
-				#[doc = "WS endpoint of " $chain ": full URI. Overrides all other connection string components (host, port, path, secure)."]
+				#[doc = "WS endpoint of " $chain ": full URI."]
 				#[structopt(long)]
-				pub [<$chain_prefix _uri>]: Option<String>,
-				#[doc = "WS endpoint of " $chain ": host component."]
-				#[structopt(long, default_value = "127.0.0.1")]
-				pub [<$chain_prefix _host>]: String,
-				#[doc = "WS endpoint of " $chain ": port component."]
-				#[structopt(long, default_value = "9944")]
-				pub [<$chain_prefix _port>]: u16,
-				#[doc = "WS endpoint of " $chain ": path component."]
-				#[structopt(long)]
-				pub [<$chain_prefix _path>]: Option<String>,
-				#[doc = "Use secure websocket connection."]
-				#[structopt(long)]
-				pub [<$chain_prefix _secure>]: bool,
+				pub [<$chain_prefix _uri>]: String,
 				#[doc = "Custom runtime version"]
 				#[structopt(flatten)]
 				pub [<$chain_prefix _runtime_version>]: [<$chain RuntimeVersionParams>],
@@ -129,10 +117,6 @@ macro_rules! declare_chain_connection_params_cli_schema {
 						.into_runtime_version(Chain::RUNTIME_VERSION)?;
 					Ok(relay_substrate_client::new(relay_substrate_client::ConnectionParams {
 						uri: self.[<$chain_prefix _uri>],
-						host: self.[<$chain_prefix _host>],
-						port: self.[<$chain_prefix _port>],
-						path: self.[<$chain_prefix _path>],
-						secure: self.[<$chain_prefix _secure>],
 						chain_runtime_version,
 					})
 					.await
diff --git a/bridges/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs b/bridges/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs
index bb6c689a76eb02bdbf6def9d3ac5d4742817ab06..227c9dc44919b4e4c8167d94f34d936630638546 100644
--- a/bridges/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs
+++ b/bridges/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs
@@ -316,23 +316,16 @@ where
 			})?;
 		{
 			let common = self.mut_base().mut_common();
-			crate::messages::metrics::add_relay_balances_metrics::<
-				_,
-				Self::Right,
-				MessagesLaneIdOf<Self::L2R>,
-			>(
-				common.left.client.clone(), &common.metrics_params, &common.left.accounts, &lanes_l2r
+			crate::messages::metrics::add_relay_balances_metrics::<_>(
+				common.left.client.clone(),
+				&common.metrics_params,
+				&common.left.accounts,
 			)
 			.await?;
-			crate::messages::metrics::add_relay_balances_metrics::<
-				_,
-				Self::Left,
-				MessagesLaneIdOf<Self::R2L>,
-			>(
+			crate::messages::metrics::add_relay_balances_metrics::<_>(
 				common.right.client.clone(),
 				&common.metrics_params,
 				&common.right.accounts,
-				&lanes_r2l,
 			)
 			.await?;
 		}
@@ -422,30 +415,22 @@ mod tests {
 
 		let res = BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages::from_iter(vec![
 			"bridge-hub-kusama-bridge-hub-polkadot-headers-and-messages",
-			"--bridge-hub-kusama-host",
-			"bridge-hub-kusama-node-collator1",
-			"--bridge-hub-kusama-port",
-			"9944",
+			"--bridge-hub-kusama-uri",
+			"ws://bridge-hub-kusama-node-collator1:9944",
 			"--bridge-hub-kusama-signer",
 			"//Iden",
 			"--bridge-hub-kusama-transactions-mortality",
 			"64",
-			"--kusama-host",
-			"kusama-alice",
-			"--kusama-port",
-			"9944",
-			"--bridge-hub-polkadot-host",
-			"bridge-hub-polkadot-collator1",
-			"--bridge-hub-polkadot-port",
-			"9944",
+			"--kusama-uri",
+			"ws://kusama-alice:9944",
+			"--bridge-hub-polkadot-uri",
+			"ws://bridge-hub-polkadot-collator1:9944",
 			"--bridge-hub-polkadot-signer",
 			"//George",
 			"--bridge-hub-polkadot-transactions-mortality",
 			"64",
-			"--polkadot-host",
-			"polkadot-alice",
-			"--polkadot-port",
-			"9944",
+			"--polkadot-uri",
+			"ws://polkadot-alice:9944",
 			"--lane",
 			"0000000000000000000000000000000000000000000000000000000000000000",
 			"--prometheus-host",
@@ -467,11 +452,7 @@ mod tests {
 					},
 				},
 				left: BridgeHubKusamaConnectionParams {
-					bridge_hub_kusama_uri: None,
-					bridge_hub_kusama_host: "bridge-hub-kusama-node-collator1".into(),
-					bridge_hub_kusama_port: 9944,
-					bridge_hub_kusama_path: None,
-					bridge_hub_kusama_secure: false,
+					bridge_hub_kusama_uri: "ws://bridge-hub-kusama-node-collator1:9944".into(),
 					bridge_hub_kusama_runtime_version: BridgeHubKusamaRuntimeVersionParams {
 						bridge_hub_kusama_version_mode: RuntimeVersionType::Bundle,
 						bridge_hub_kusama_spec_version: None,
@@ -486,11 +467,7 @@ mod tests {
 					bridge_hub_kusama_transactions_mortality: Some(64),
 				},
 				left_relay: KusamaConnectionParams {
-					kusama_uri: None,
-					kusama_host: "kusama-alice".into(),
-					kusama_port: 9944,
-					kusama_path: None,
-					kusama_secure: false,
+					kusama_uri: "ws://kusama-alice:9944".into(),
 					kusama_runtime_version: KusamaRuntimeVersionParams {
 						kusama_version_mode: RuntimeVersionType::Bundle,
 						kusama_spec_version: None,
@@ -498,11 +475,7 @@ mod tests {
 					},
 				},
 				right: BridgeHubPolkadotConnectionParams {
-					bridge_hub_polkadot_uri: None,
-					bridge_hub_polkadot_host: "bridge-hub-polkadot-collator1".into(),
-					bridge_hub_polkadot_port: 9944,
-					bridge_hub_polkadot_path: None,
-					bridge_hub_polkadot_secure: false,
+					bridge_hub_polkadot_uri: "ws://bridge-hub-polkadot-collator1:9944".into(),
 					bridge_hub_polkadot_runtime_version: BridgeHubPolkadotRuntimeVersionParams {
 						bridge_hub_polkadot_version_mode: RuntimeVersionType::Bundle,
 						bridge_hub_polkadot_spec_version: None,
@@ -517,11 +490,7 @@ mod tests {
 					bridge_hub_polkadot_transactions_mortality: Some(64),
 				},
 				right_relay: PolkadotConnectionParams {
-					polkadot_uri: None,
-					polkadot_host: "polkadot-alice".into(),
-					polkadot_port: 9944,
-					polkadot_path: None,
-					polkadot_secure: false,
+					polkadot_uri: "ws://polkadot-alice:9944".into(),
 					polkadot_runtime_version: PolkadotRuntimeVersionParams {
 						polkadot_version_mode: RuntimeVersionType::Bundle,
 						polkadot_spec_version: None,
diff --git a/bridges/relays/lib-substrate-relay/src/messages/metrics.rs b/bridges/relays/lib-substrate-relay/src/messages/metrics.rs
index efe429701c41b6796433db1f6f4cef5d42ebc331..88c91b52f22dc0c2519da670a095410511339ab0 100644
--- a/bridges/relays/lib-substrate-relay/src/messages/metrics.rs
+++ b/bridges/relays/lib-substrate-relay/src/messages/metrics.rs
@@ -19,14 +19,13 @@
 use crate::TaggedAccount;
 
 use bp_relayers::{RewardsAccountOwner, RewardsAccountParams};
-use bp_runtime::StorageDoubleMapKeyProvider;
 use codec::{Decode, EncodeLike};
 use frame_system::AccountInfo;
 use messages_relay::Labeled;
 use pallet_balances::AccountData;
 use relay_substrate_client::{
-	metrics::{FloatStorageValue, FloatStorageValueMetric},
-	AccountIdOf, BalanceOf, Chain, ChainWithBalances, ChainWithMessages, Client,
+	metrics::{FixedU128OrOne, FloatStorageValue, FloatStorageValueMetric},
+	AccountIdOf, BalanceOf, Chain, ChainWithBalances, ChainWithMessages, ChainWithRewards, Client,
 	Error as SubstrateError, NonceOf,
 };
 use relay_utils::metrics::{MetricsParams, StandaloneMetric};
@@ -35,15 +34,13 @@ use sp_runtime::{FixedPointNumber, FixedU128};
 use std::{fmt::Debug, marker::PhantomData};
 
 /// Add relay accounts balance metrics.
-pub async fn add_relay_balances_metrics<C: ChainWithBalances, BC: ChainWithMessages, LaneId>(
+pub async fn add_relay_balances_metrics<C: ChainWithBalances>(
 	client: impl Client<C>,
 	metrics: &MetricsParams,
 	relay_accounts: &Vec<TaggedAccount<AccountIdOf<C>>>,
-	lanes: &[LaneId],
 ) -> anyhow::Result<()>
 where
 	BalanceOf<C>: Into<u128> + std::fmt::Debug,
-	LaneId: Clone + Copy + Decode + EncodeLike + Send + Sync + Labeled,
 {
 	if relay_accounts.is_empty() {
 		return Ok(())
@@ -80,29 +77,42 @@ where
 			format!("Balance of the {} relay account at the {}", account.tag(), C::NAME),
 		)?;
 		relay_account_balance_metric.register_and_spawn(&metrics.registry)?;
+	}
+
+	Ok(())
+}
+
+/// Add relay accounts rewards metrics.
+pub async fn add_relay_rewards_metrics<C: ChainWithRewards, BC: ChainWithMessages, LaneId>(
+	client: impl Client<C>,
+	metrics: &MetricsParams,
+	relay_accounts: &Vec<TaggedAccount<AccountIdOf<C>>>,
+	lanes: &[LaneId],
+) -> anyhow::Result<()>
+where
+	C::RewardBalance: Into<u128> + std::fmt::Debug,
+	C::Reward: From<RewardsAccountParams<LaneId>>,
+	LaneId: Clone + Copy + Decode + EncodeLike + Send + Sync + Labeled,
+{
+	if relay_accounts.is_empty() {
+		return Ok(())
+	}
 
-		if let Some(relayers_pallet_name) = BC::WITH_CHAIN_RELAYERS_PALLET_NAME {
+	for account in relay_accounts {
+		if let Some(_) = C::WITH_CHAIN_RELAYERS_PALLET_NAME {
 			for lane in lanes {
 				FloatStorageValueMetric::new(
-					AccountBalance::<C> { token_decimals, _phantom: Default::default() },
+					FixedU128OrOne,
 					client.clone(),
-					bp_relayers::RelayerRewardsKeyProvider::<AccountIdOf<C>, BalanceOf<C>, LaneId>::final_key(
-						relayers_pallet_name,
-						account.id(),
-						&RewardsAccountParams::new(*lane, BC::ID, RewardsAccountOwner::ThisChain),
-					),
+					C::account_reward_storage_key(account.id(), RewardsAccountParams::new(*lane, BC::ID, RewardsAccountOwner::ThisChain)),
 					format!("at_{}_relay_{}_reward_for_msgs_from_{}_on_lane_{}", C::NAME, account.tag(), BC::NAME, lane.label()),
 					format!("Reward of the {} relay account at {} for delivering messages from {} on lane {:?}", account.tag(), C::NAME, BC::NAME, lane.label()),
 				)?.register_and_spawn(&metrics.registry)?;
 
 				FloatStorageValueMetric::new(
-					AccountBalance::<C> { token_decimals, _phantom: Default::default() },
+					FixedU128OrOne,
 					client.clone(),
-					bp_relayers::RelayerRewardsKeyProvider::<AccountIdOf<C>, BalanceOf<C>, LaneId>::final_key(
-						relayers_pallet_name,
-						account.id(),
-						&RewardsAccountParams::new(*lane, BC::ID, RewardsAccountOwner::BridgedChain),
-					),
+					C::account_reward_storage_key(account.id(), RewardsAccountParams::new(*lane, BC::ID, RewardsAccountOwner::BridgedChain)),
 					format!("at_{}_relay_{}_reward_for_msgs_to_{}_on_lane_{}", C::NAME, account.tag(), BC::NAME, lane.label()),
 					format!("Reward of the {} relay account at {} for delivering messages confirmations from {} on lane {:?}", account.tag(), C::NAME, BC::NAME, lane.label()),
 				)?.register_and_spawn(&metrics.registry)?;
@@ -143,34 +153,6 @@ where
 	}
 }
 
-/// Adapter for `FloatStorageValueMetric` to decode account free balance.
-#[derive(Clone, Debug)]
-struct AccountBalance<C> {
-	token_decimals: u32,
-	_phantom: PhantomData<C>,
-}
-
-impl<C> FloatStorageValue for AccountBalance<C>
-where
-	C: Chain,
-	BalanceOf<C>: Into<u128>,
-{
-	type Value = FixedU128;
-
-	fn decode(
-		&self,
-		maybe_raw_value: Option<StorageData>,
-	) -> Result<Option<Self::Value>, SubstrateError> {
-		maybe_raw_value
-			.map(|raw_value| {
-				BalanceOf::<C>::decode(&mut &raw_value.0[..])
-					.map_err(SubstrateError::ResponseParseFailed)
-					.map(|balance| convert_to_token_balance(balance.into(), self.token_decimals))
-			})
-			.transpose()
-	}
-}
-
 /// Convert from raw `u128` balance (nominated in smallest chain token units) to the float regular
 /// tokens value.
 fn convert_to_token_balance(balance: u128, token_decimals: u32) -> FixedU128 {
diff --git a/bridges/relays/lib-substrate-relay/src/messages/mod.rs b/bridges/relays/lib-substrate-relay/src/messages/mod.rs
index b4ee57ed7742e684a3c04d133d28940d21d81e84..8c1ffc2a8480eadf98b272216fb07d6cecac5f64 100644
--- a/bridges/relays/lib-substrate-relay/src/messages/mod.rs
+++ b/bridges/relays/lib-substrate-relay/src/messages/mod.rs
@@ -820,6 +820,7 @@ mod tests {
 	}
 
 	// mock runtime with `pallet_bridge_messages`
+	#[allow(unexpected_cfgs)]
 	mod mock {
 		use super::super::*;
 		use bp_messages::{target_chain::ForbidInboundMessages, HashedLaneId};
@@ -974,7 +975,6 @@ mod tests {
 			}
 		}
 		impl relay_substrate_client::ChainWithMessages for ThisChain {
-			const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = None;
 			const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = "";
 			const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = "";
 		}
@@ -1010,7 +1010,6 @@ mod tests {
 			}
 		}
 		impl relay_substrate_client::ChainWithMessages for BridgedChain {
-			const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = None;
 			const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = "";
 			const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = "";
 		}
diff --git a/bridges/snowbridge/pallets/inbound-queue/src/lib.rs b/bridges/snowbridge/pallets/inbound-queue/src/lib.rs
index 423b92b9fae04dceca93820f0a2f11a866498576..85b98c643b6c81af2cac3e3f3ac1be52bc9b88b2 100644
--- a/bridges/snowbridge/pallets/inbound-queue/src/lib.rs
+++ b/bridges/snowbridge/pallets/inbound-queue/src/lib.rs
@@ -188,7 +188,9 @@ pub mod pallet {
 		ConvertMessage(ConvertMessageError),
 	}
 
-	#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo, PalletError)]
+	#[derive(
+		Clone, Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, Debug, TypeInfo, PalletError,
+	)]
 	pub enum SendError {
 		NotApplicable,
 		NotRoutable,
diff --git a/bridges/snowbridge/pallets/system/src/mock.rs b/bridges/snowbridge/pallets/system/src/mock.rs
index 47b089866a53fda4a689efb5e37b8e66f5df433d..523034c9c7350b612a15b4203b8eb6fb0009cdfc 100644
--- a/bridges/snowbridge/pallets/system/src/mock.rs
+++ b/bridges/snowbridge/pallets/system/src/mock.rs
@@ -48,7 +48,17 @@ mod pallet_xcm_origin {
 
 	// Insert this custom Origin into the aggregate RuntimeOrigin
 	#[pallet::origin]
-	#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+	#[derive(
+		PartialEq,
+		Eq,
+		Clone,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		RuntimeDebug,
+		TypeInfo,
+		MaxEncodedLen,
+	)]
 	pub struct Origin(pub Location);
 
 	impl From<Location> for Origin {
diff --git a/bridges/snowbridge/primitives/beacon/src/bls.rs b/bridges/snowbridge/primitives/beacon/src/bls.rs
index 589b72e67348f70122ad2362b8bc51474cb577ac..5834b9986564c98306b528294fd540c294f53838 100644
--- a/bridges/snowbridge/primitives/beacon/src/bls.rs
+++ b/bridges/snowbridge/primitives/beacon/src/bls.rs
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: Apache-2.0
 // SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
 use crate::{PublicKey, Signature};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use frame_support::{ensure, PalletError};
 pub use milagro_bls::{
 	AggregatePublicKey, AggregateSignature, PublicKey as PublicKeyPrepared,
@@ -12,7 +12,18 @@ use sp_core::H256;
 use sp_runtime::RuntimeDebug;
 use sp_std::prelude::*;
 
-#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, TypeInfo, RuntimeDebug, PalletError)]
+#[derive(
+	Copy,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	TypeInfo,
+	RuntimeDebug,
+	PalletError,
+)]
 pub enum BlsError {
 	InvalidSignature,
 	InvalidPublicKey,
diff --git a/bridges/snowbridge/primitives/beacon/src/types.rs b/bridges/snowbridge/primitives/beacon/src/types.rs
index e12350510c9b83c85e27ecfa1534b984ff23fb05..44fa7c4450ae9943dde51143d581d4dc290ac52d 100644
--- a/bridges/snowbridge/primitives/beacon/src/types.rs
+++ b/bridges/snowbridge/primitives/beacon/src/types.rs
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: Apache-2.0
 // SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_support::{CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound};
 use scale_info::TypeInfo;
 use sp_core::{H160, H256, U256};
@@ -44,7 +44,7 @@ pub struct Fork {
 	pub epoch: u64,
 }
 
-#[derive(Copy, Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Copy, Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct PublicKey(pub [u8; PUBKEY_SIZE]);
 
 impl Default for PublicKey {
@@ -85,7 +85,7 @@ impl Serialize for PublicKey {
 	}
 }
 
-#[derive(Copy, Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Copy, Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct Signature(pub [u8; SIGNATURE_SIZE]);
 
 impl Default for Signature {
@@ -143,7 +143,14 @@ impl SigningData {
 
 /// Sync committee as it is stored in the runtime storage.
 #[derive(
-	Encode, Decode, PartialEqNoBound, CloneNoBound, RuntimeDebugNoBound, TypeInfo, MaxEncodedLen,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	PartialEqNoBound,
+	CloneNoBound,
+	RuntimeDebugNoBound,
+	TypeInfo,
+	MaxEncodedLen,
 )]
 #[cfg_attr(
 	feature = "std",
@@ -215,7 +222,16 @@ impl<const COMMITTEE_SIZE: usize> TryFrom<&SyncCommittee<COMMITTEE_SIZE>>
 /// Beacon block header as it is stored in the runtime storage. The block root is the
 /// Merkleization of a BeaconHeader.
 #[derive(
-	Copy, Clone, Default, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen,
+	Copy,
+	Clone,
+	Default,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
 )]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub struct BeaconHeader {
@@ -238,7 +254,15 @@ impl BeaconHeader {
 	}
 }
 
-#[derive(Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	CloneNoBound,
+	PartialEqNoBound,
+	RuntimeDebugNoBound,
+	TypeInfo,
+)]
 #[cfg_attr(
 	feature = "std",
 	derive(Deserialize),
@@ -303,7 +327,14 @@ impl<const COMMITTEE_SIZE: usize, const COMMITTEE_BITS_SIZE: usize>
 /// ExecutionPayloadHeader
 /// <https://github.com/ethereum/annotated-spec/blob/master/capella/beacon-chain.md#executionpayloadheader>
 #[derive(
-	Default, Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo,
+	Default,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	CloneNoBound,
+	PartialEqNoBound,
+	RuntimeDebugNoBound,
+	TypeInfo,
 )]
 #[cfg_attr(
 	feature = "std",
@@ -356,7 +387,15 @@ pub struct CompactBeaconState {
 }
 
 /// VersionedExecutionPayloadHeader
-#[derive(Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	CloneNoBound,
+	PartialEqNoBound,
+	RuntimeDebugNoBound,
+	TypeInfo,
+)]
 #[cfg_attr(
 	feature = "std",
 	derive(Serialize, Deserialize),
@@ -410,7 +449,15 @@ impl VersionedExecutionPayloadHeader {
 	}
 }
 
-#[derive(Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	CloneNoBound,
+	PartialEqNoBound,
+	RuntimeDebugNoBound,
+	TypeInfo,
+)]
 #[cfg_attr(
 	feature = "std",
 	derive(serde::Deserialize),
@@ -427,7 +474,15 @@ pub struct ExecutionProof {
 	pub execution_branch: Vec<H256>,
 }
 
-#[derive(Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	CloneNoBound,
+	PartialEqNoBound,
+	RuntimeDebugNoBound,
+	TypeInfo,
+)]
 #[cfg_attr(
 	feature = "std",
 	derive(serde::Deserialize),
@@ -566,7 +621,7 @@ pub enum Mode {
 }
 
 pub mod deneb {
-	use codec::{Decode, Encode};
+	use codec::{Decode, DecodeWithMemTracking, Encode};
 	use frame_support::{CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound};
 	use scale_info::TypeInfo;
 	#[cfg(feature = "std")]
@@ -577,7 +632,14 @@ pub mod deneb {
 	/// ExecutionPayloadHeader
 	/// <https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/beacon-chain.md#executionpayloadheader>
 	#[derive(
-		Default, Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo,
+		Default,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		CloneNoBound,
+		PartialEqNoBound,
+		RuntimeDebugNoBound,
+		TypeInfo,
 	)]
 	#[cfg_attr(
 		feature = "std",
diff --git a/bridges/snowbridge/primitives/beacon/src/updates.rs b/bridges/snowbridge/primitives/beacon/src/updates.rs
index ca651b5806f270f85d830c218c53cb6a509cc6f4..bcd371b6c77a0d5266f290bc3a3665b6c989bd21 100644
--- a/bridges/snowbridge/primitives/beacon/src/updates.rs
+++ b/bridges/snowbridge/primitives/beacon/src/updates.rs
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: Apache-2.0
 // SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use frame_support::{CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound};
 use scale_info::TypeInfo;
 use sp_core::H256;
@@ -8,7 +8,15 @@ use sp_std::prelude::*;
 
 use crate::types::{BeaconHeader, SyncAggregate, SyncCommittee};
 
-#[derive(Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	CloneNoBound,
+	PartialEqNoBound,
+	RuntimeDebugNoBound,
+	TypeInfo,
+)]
 #[cfg_attr(
 	feature = "std",
 	derive(serde::Serialize, serde::Deserialize),
@@ -24,7 +32,14 @@ pub struct CheckpointUpdate<const COMMITTEE_SIZE: usize> {
 }
 
 #[derive(
-	Default, Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo,
+	Default,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	CloneNoBound,
+	PartialEqNoBound,
+	RuntimeDebugNoBound,
+	TypeInfo,
 )]
 #[cfg_attr(
 	feature = "std",
@@ -54,7 +69,14 @@ pub struct Update<const COMMITTEE_SIZE: usize, const COMMITTEE_BITS_SIZE: usize>
 }
 
 #[derive(
-	Default, Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo,
+	Default,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	CloneNoBound,
+	PartialEqNoBound,
+	RuntimeDebugNoBound,
+	TypeInfo,
 )]
 #[cfg_attr(
 	feature = "std",
diff --git a/bridges/snowbridge/primitives/core/src/inbound.rs b/bridges/snowbridge/primitives/core/src/inbound.rs
index 9e8ed789ab500917eb520176fdf39343a65838da..5e5ae673359b58db435e858406526030fe79ee5e 100644
--- a/bridges/snowbridge/primitives/core/src/inbound.rs
+++ b/bridges/snowbridge/primitives/core/src/inbound.rs
@@ -2,7 +2,7 @@
 // SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
 //! Types for representing inbound messages
 
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use frame_support::PalletError;
 use scale_info::TypeInfo;
 use snowbridge_beacon_primitives::{BeaconHeader, ExecutionProof};
@@ -15,7 +15,7 @@ pub trait Verifier {
 	fn verify(event: &Log, proof: &Proof) -> Result<(), VerificationError>;
 }
 
-#[derive(Clone, Encode, Decode, RuntimeDebug, PalletError, TypeInfo)]
+#[derive(Clone, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, PalletError, TypeInfo)]
 #[cfg_attr(feature = "std", derive(PartialEq))]
 pub enum VerificationError {
 	/// Execution header is missing
@@ -33,7 +33,7 @@ pub enum VerificationError {
 pub type MessageNonce = u64;
 
 /// A bridge message from the Gateway contract on Ethereum
-#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct Message {
 	/// Event log emitted by Gateway contract
 	pub event_log: Log,
@@ -49,7 +49,7 @@ pub enum LogValidationError {
 }
 
 /// Event log
-#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct Log {
 	pub address: H160,
 	pub topics: Vec<H256>,
@@ -66,7 +66,7 @@ impl Log {
 }
 
 /// Inclusion proof for a transaction receipt
-#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct Proof {
 	// Proof keys and values (receipts tree)
 	pub receipt_proof: (Vec<Vec<u8>>, Vec<Vec<u8>>),
diff --git a/bridges/snowbridge/primitives/core/src/lib.rs b/bridges/snowbridge/primitives/core/src/lib.rs
index 7ad129a52542ed32f96e4533e7cf962039d7224d..9d18932c8faab92d1e2f52c315a59683c3b854a6 100644
--- a/bridges/snowbridge/primitives/core/src/lib.rs
+++ b/bridges/snowbridge/primitives/core/src/lib.rs
@@ -22,7 +22,7 @@ pub use polkadot_parachain_primitives::primitives::{
 pub use ringbuffer::{RingBufferMap, RingBufferMapImpl};
 pub use sp_core::U256;
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_support::{traits::Contains, BoundedVec};
 use hex_literal::hex;
 use scale_info::TypeInfo;
@@ -67,7 +67,17 @@ pub const ROC: u128 = 1_000_000_000_000;
 
 /// Identifier for a message channel
 #[derive(
-	Clone, Copy, Encode, Decode, PartialEq, Eq, Default, RuntimeDebug, MaxEncodedLen, TypeInfo,
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	PartialEq,
+	Eq,
+	Default,
+	RuntimeDebug,
+	MaxEncodedLen,
+	TypeInfo,
 )]
 pub struct ChannelId([u8; 32]);
 
@@ -152,7 +162,7 @@ pub const SECONDARY_GOVERNANCE_CHANNEL: ChannelId =
 	ChannelId::new(hex!("0000000000000000000000000000000000000000000000000000000000000002"));
 
 /// Metadata to include in the instantiated ERC20 token contract
-#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct AssetMetadata {
 	pub name: BoundedVec<u8, ConstU32<METADATA_FIELD_MAX_LEN>>,
 	pub symbol: BoundedVec<u8, ConstU32<METADATA_FIELD_MAX_LEN>>,
diff --git a/bridges/snowbridge/primitives/core/src/operating_mode.rs b/bridges/snowbridge/primitives/core/src/operating_mode.rs
index 9894e587ef5e7ff31d19a0b5593c3c78cb7c1f99..e450a78d9fd0768d810ad920648625f4ef5557ce 100644
--- a/bridges/snowbridge/primitives/core/src/operating_mode.rs
+++ b/bridges/snowbridge/primitives/core/src/operating_mode.rs
@@ -1,9 +1,20 @@
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 use sp_runtime::RuntimeDebug;
 
 /// Basic operating modes for a bridges module (Normal/Halted).
-#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Clone,
+	Copy,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
 pub enum BasicOperatingMode {
 	/// Normal mode, when all operations are allowed.
diff --git a/bridges/snowbridge/primitives/core/src/outbound.rs b/bridges/snowbridge/primitives/core/src/outbound.rs
index 77770761822a8fe1a88d39f304dac9124ba9be1a..4119dbd7f925160327dacb94a89bfd895a64392f 100644
--- a/bridges/snowbridge/primitives/core/src/outbound.rs
+++ b/bridges/snowbridge/primitives/core/src/outbound.rs
@@ -1,4 +1,4 @@
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use frame_support::PalletError;
 use scale_info::TypeInfo;
 use sp_arithmetic::traits::{BaseArithmetic, Unsigned};
@@ -31,7 +31,7 @@ impl<T: Into<QueuedMessage>> From<T> for VersionedQueuedMessage {
 
 mod v1 {
 	use crate::{pricing::UD60x18, ChannelId};
-	use codec::{Decode, Encode};
+	use codec::{Decode, DecodeWithMemTracking, Encode};
 	use ethabi::Token;
 	use scale_info::TypeInfo;
 	use sp_core::{RuntimeDebug, H160, H256, U256};
@@ -55,7 +55,9 @@ mod v1 {
 	}
 
 	/// The operating mode of Channels and Gateway contract on Ethereum.
-	#[derive(Copy, Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)]
+	#[derive(
+		Copy, Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, Eq, RuntimeDebug, TypeInfo,
+	)]
 	pub enum OperatingMode {
 		/// Normal operations. Allow sending and receiving messages.
 		Normal,
@@ -271,7 +273,7 @@ mod v1 {
 
 	/// Representation of a call to the initializer of an implementation contract.
 	/// The initializer has the following ABI signature: `initialize(bytes)`.
-	#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
+	#[derive(Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, RuntimeDebug, TypeInfo)]
 	pub struct Initializer {
 		/// ABI-encoded params of type `bytes` to pass to the initializer
 		pub params: Vec<u8>,
@@ -389,7 +391,18 @@ pub trait SendMessageFeeProvider {
 }
 
 /// Reasons why sending to Ethereum could not be initiated
-#[derive(Copy, Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, PalletError, TypeInfo)]
+#[derive(
+	Copy,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	PalletError,
+	TypeInfo,
+)]
 pub enum SendError {
 	/// Message is too large to be safely executed on Ethereum
 	MessageTooLarge,
diff --git a/bridges/snowbridge/primitives/core/src/pricing.rs b/bridges/snowbridge/primitives/core/src/pricing.rs
index 0f392c7ad4bdde9c4bed812b995b039816c8977c..460c59e1f2cdf9f4587c4dc9120e617b1de3b3e4 100644
--- a/bridges/snowbridge/primitives/core/src/pricing.rs
+++ b/bridges/snowbridge/primitives/core/src/pricing.rs
@@ -1,11 +1,13 @@
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 use sp_arithmetic::traits::{BaseArithmetic, Unsigned, Zero};
 use sp_core::U256;
 use sp_runtime::{FixedU128, RuntimeDebug};
 use sp_std::prelude::*;
 
-#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
+#[derive(
+	Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo,
+)]
 pub struct PricingParameters<Balance> {
 	/// ETH/DOT exchange rate
 	pub exchange_rate: FixedU128,
@@ -17,7 +19,9 @@ pub struct PricingParameters<Balance> {
 	pub multiplier: FixedU128,
 }
 
-#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
+#[derive(
+	Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo,
+)]
 pub struct Rewards<Balance> {
 	/// Local reward in DOT
 	pub local: Balance,
diff --git a/bridges/snowbridge/primitives/router/src/inbound/mod.rs b/bridges/snowbridge/primitives/router/src/inbound/mod.rs
index 1c210afb1f7403d84dd8fc2f0acf35cb3063a171..f2d5b02e8bbdfbeb2a7feb443b0411862169fd0f 100644
--- a/bridges/snowbridge/primitives/router/src/inbound/mod.rs
+++ b/bridges/snowbridge/primitives/router/src/inbound/mod.rs
@@ -7,7 +7,7 @@ mod mock;
 #[cfg(test)]
 mod tests;
 
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use core::marker::PhantomData;
 use frame_support::{traits::tokens::Balance as BalanceT, PalletError};
 use scale_info::TypeInfo;
@@ -127,7 +127,9 @@ pub struct MessageToXcm<
 }
 
 /// Reason why a message conversion failed.
-#[derive(Copy, Clone, TypeInfo, PalletError, Encode, Decode, RuntimeDebug)]
+#[derive(
+	Copy, Clone, TypeInfo, PalletError, Encode, Decode, DecodeWithMemTracking, RuntimeDebug,
+)]
 pub enum ConvertMessageError {
 	/// The message version is not supported for conversion.
 	UnsupportedVersion,
diff --git a/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh b/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh
index 321f4d9f26d0bc3c2f3008ac3aee4f75a45b053e..b146c28ff5585d6889e7252ef9cb5c9d19e92ea1 100755
--- a/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh
+++ b/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh
@@ -131,13 +131,11 @@ function init_ro_wnd() {
 
     RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
         $relayer_path init-bridge rococo-to-bridge-hub-westend \
-	--source-host localhost \
-	--source-port 9942 \
-	--source-version-mode Auto \
-	--target-host localhost \
-	--target-port 8945 \
-	--target-version-mode Auto \
-	--target-signer //Bob
+        --source-uri ws://localhost:9942 \
+        --source-version-mode Auto \
+        --target-uri ws://localhost:8945  \
+        --target-version-mode Auto \
+        --target-signer //Bob
 }
 
 function init_wnd_ro() {
@@ -145,39 +143,13 @@ function init_wnd_ro() {
 
     RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
         $relayer_path init-bridge westend-to-bridge-hub-rococo \
-        --source-host localhost \
-        --source-port 9945 \
+        --source-uri ws://localhost:9945  \
         --source-version-mode Auto \
-        --target-host localhost \
-        --target-port 8943 \
+        --target-uri ws://localhost:8943 \
         --target-version-mode Auto \
         --target-signer //Bob
 }
 
-function run_relay() {
-    local relayer_path=$(ensure_relayer)
-
-    RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
-        $relayer_path relay-headers-and-messages bridge-hub-rococo-bridge-hub-westend \
-        --rococo-host localhost \
-        --rococo-port 9942 \
-        --rococo-version-mode Auto \
-        --bridge-hub-rococo-host localhost \
-        --bridge-hub-rococo-port 8943 \
-        --bridge-hub-rococo-version-mode Auto \
-        --bridge-hub-rococo-signer //Charlie \
-        --bridge-hub-rococo-transactions-mortality 4 \
-        --westend-host localhost \
-        --westend-port 9945 \
-        --westend-version-mode Auto \
-        --bridge-hub-westend-host localhost \
-        --bridge-hub-westend-port 8945 \
-        --bridge-hub-westend-version-mode Auto \
-        --bridge-hub-westend-signer //Charlie \
-        --bridge-hub-westend-transactions-mortality 4 \
-        --lane "${LANE_ID}"
-}
-
 function run_finality_relay() {
     local relayer_path=$(ensure_relayer)
 
diff --git a/bridges/testing/framework/js-helpers/relayer-rewards.js b/bridges/testing/framework/js-helpers/relayer-rewards.js
index 5347c649604fc209042725c9cf269c9d3ca0290f..59c7c389a5ba7bea1bafc83c136f956b8b8f5296 100644
--- a/bridges/testing/framework/js-helpers/relayer-rewards.js
+++ b/bridges/testing/framework/js-helpers/relayer-rewards.js
@@ -3,16 +3,12 @@ async function run(nodeName, networkInfo, args) {
     const api = await zombie.connect(wsUri, userDefinedTypes);
 
     // TODO: could be replaced with https://github.com/polkadot-js/api/issues/4930 (depends on metadata v15) later
-    const relayerAccountAddress = args[0];
-    const laneId = args[1];
-    const bridgedChainId = args[2];
-    const relayerFundOwner = args[3];
-    const expectedRelayerReward = BigInt(args[4]);
+    const relayerAccountAddress = args.relayerAccountAddress;
+    const reward = args.reward;
+    const expectedRelayerReward = BigInt(args.expectedRelayerReward);
+    console.log("Waiting rewards for relayerAccountAddress: " + relayerAccountAddress + " expecting minimal rewards at least: " + expectedRelayerReward + " for " + JSON.stringify(reward));
     while (true) {
-        const relayerReward = await api.query.bridgeRelayers.relayerRewards(
-            relayerAccountAddress,
-            { laneId: laneId, bridgedChainId: bridgedChainId, owner: relayerFundOwner }
-        );
+        const relayerReward = await api.query.bridgeRelayers.relayerRewards(relayerAccountAddress, reward);
         if (relayerReward.isSome) {
             const relayerRewardBalance = relayerReward.unwrap().toBigInt();
             if (relayerRewardBalance > expectedRelayerReward) {
diff --git a/bridges/testing/scripts/start-relayer.sh b/bridges/testing/scripts/start-relayer.sh
deleted file mode 100755
index 38ea62fad524486c40cf88943c48a2e4df4b86e8..0000000000000000000000000000000000000000
--- a/bridges/testing/scripts/start-relayer.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-RELAY_LOG=`mktemp -p $TEST_FOLDER relay.XXXXX`
-
-pushd $POLKADOT_SDK_PATH/bridges/testing/environments/rococo-westend
-./bridges_rococo_westend.sh run-relay >$RELAY_LOG 2>&1&
-popd
diff --git a/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl b/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl
index b3cafc993e543639efbd0c897ac5f4652922b986..d799593386d6d1e8eda790885e6e873741bf8918 100644
--- a/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl
+++ b/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl
@@ -9,4 +9,4 @@ asset-hub-westend-collator1: run {{ENV_PATH}}/helper.sh with "auto-log reserve-t
 asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with '{ "accountAddress": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", "expectedAssetBalance": 4800000000000, "expectedAssetId": { "parents": 2, "interior": { "X1": [{ "GlobalConsensus": { "ByGenesis": [100,8,222,119,55,197,156,35,136,144,83,58,242,88,150,162,194,6,8,216,179,128,187,1,2,154,203,57,39,129,6,62] } }] }}}' within 600 seconds
 
 # relayer //Ferdie is rewarded for delivering messages from Rococo BH
-bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw,0x00000002,0x6268726F,ThisChain,0" within 300 seconds
+bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with '{ "relayerAccountAddress": "5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw", "reward": { "RococoWestend": { "laneId": "0x00000002", "bridgedChainId": "0x6268726F", "owner": "ThisChain" }}, "expectedRelayerReward": 1}' within 300 seconds
diff --git a/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl b/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl
index eacac98982ab90ebc49da163563be0df05686c43..d1d293262d423405afab84bb679e18087843e30e 100644
--- a/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl
+++ b/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl
@@ -9,4 +9,4 @@ asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "auto-log reserve-tr
 asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with '{ "accountAddress": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", "expectedAssetBalance": 4800000000000, "expectedAssetId": { "parents": 2, "interior": { "X1": [{ "GlobalConsensus": { "ByGenesis": [225,67,242,56,3,172,80,232,246,248,230,38,149,209,206,158,78,29,104,170,54,193,205,44,253,21,52,2,19,243,66,62] } }] }}}' within 600 seconds
 
 # relayer //Eve is rewarded for delivering messages from Westend BH
-bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL,0x00000002,0x62687764,ThisChain,0" within 300 seconds
+bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with '{ "relayerAccountAddress": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", "reward": { "laneId": "0x00000002", "bridgedChainId": "0x62687764", "owner": "ThisChain" }, "expectedRelayerReward": 1}' within 300 seconds
diff --git a/cumulus/pallets/xcm/src/lib.rs b/cumulus/pallets/xcm/src/lib.rs
index e60ff78a8032854c052bda3ed8bf76c235f21b12..db98b781304c1e459581c3ca0865cfdebedebff9 100644
--- a/cumulus/pallets/xcm/src/lib.rs
+++ b/cumulus/pallets/xcm/src/lib.rs
@@ -58,7 +58,17 @@ pub mod pallet {
 	}
 
 	/// Origin for the parachains module.
-	#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug, MaxEncodedLen)]
+	#[derive(
+		PartialEq,
+		Eq,
+		Clone,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		TypeInfo,
+		RuntimeDebug,
+		MaxEncodedLen,
+	)]
 	#[pallet::origin]
 	pub enum Origin {
 		/// It comes from the (parent) relay chain.
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs
index 15c1a822b756c211508cc961bed835d73366dce8..0a2357dbd3c17f45d48ad7452e135c1d8780cc32 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs
@@ -53,7 +53,7 @@ use testnet_parachains_constants::rococo::snowbridge::EthereumNetwork;
 use sp_version::NativeVersion;
 use sp_version::RuntimeVersion;
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use cumulus_primitives_core::ParaId;
 use frame_support::{
 	construct_runtime, derive_impl,
@@ -562,6 +562,7 @@ parameter_types! {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	MaxEncodedLen,
 	scale_info::TypeInfo,
@@ -1687,6 +1688,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_utility.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_utility.rs
index 80afbde1b1e0788948ef69bfb0f1238bdde7904b..d70c1947c4e34f3400377cbd452136dd888b2c8c 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_utility.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_utility.rs
@@ -99,6 +99,11 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
 			// Standard Error: 1_745
 			.saturating_add(Weight::from_parts(6_562_902, 0).saturating_mul(c.into()))
 	}
+
+	fn dispatch_as_fallible() -> Weight {
+		Default::default()
+	}
+
 	fn if_else() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs
index 0c6ff5e4bfddc6c236fe1ec4a5a5f425027f41f5..84526b2e4f2ee0df214b53737b5d4676b1080ee4 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs
@@ -51,7 +51,7 @@ use xcm::latest::{prelude::*, ROCOCO_GENESIS_HASH, WESTEND_GENESIS_HASH};
 use xcm_builder::{
 	AccountId32Aliases, AliasChildLocation, AllowExplicitUnpaidExecutionFrom,
 	AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom,
-	AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, DenyThenTry,
+	AllowTopLevelPaidExecutionFrom, DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry,
 	DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor,
 	FungibleAdapter, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription,
 	IsConcrete, LocalMint, MatchedConvertedConcreteId, NetworkExportTableItem, NoChecking,
@@ -269,7 +269,7 @@ impl Contains<Location> for ParentOrParentsPlurality {
 
 pub type Barrier = TrailingSetTopicAsId<
 	DenyThenTry<
-		DenyReserveTransferToRelayChain,
+		DenyRecursively<DenyReserveTransferToRelayChain>,
 		(
 			TakeWeightCredit,
 			// Expected responses are OK.
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
index 016f46d3c556a6a2dd1a545e10bf3092af3a039a..66486a42c347459f87518dcbf084f9e366d0cc9b 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
@@ -35,7 +35,7 @@ use assets_common::{
 	local_and_foreign_assets::{LocalFromLeft, TargetFromLeft},
 	AssetIdForPoolAssets, AssetIdForPoolAssetsConvert, AssetIdForTrustBackedAssetsConvert,
 };
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
 use cumulus_primitives_core::{AggregateMessageOrigin, ClaimQueueOffset, CoreSelector, ParaId};
 use frame_support::{
@@ -614,6 +614,7 @@ parameter_types! {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	MaxEncodedLen,
 	scale_info::TypeInfo,
@@ -1883,6 +1884,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
@@ -2370,11 +2372,15 @@ impl_runtime_apis! {
 		{
 			use pallet_revive::tracing::trace;
 			let mut tracer = config.build(Revive::evm_gas_from_weight);
-			trace(&mut tracer, || {
-				Self::eth_transact(tx)
-			})?;
-
-			Ok(tracer.collect_traces().pop().expect("eth_transact succeeded, trace must exist, qed"))
+			let result = trace(&mut tracer, || Self::eth_transact(tx));
+
+			if let Some(trace) = tracer.collect_traces().pop() {
+				Ok(trace)
+			} else if let Err(err) = result {
+				Err(err)
+			} else {
+				Ok(Default::default())
+			}
 		}
 	}
 }
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_utility.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_utility.rs
index ef6d9fb4ba945f46689722d363d4b5ec42dad3bc..240779520a0b28b669feaaf1d83936a54afe71e4 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_utility.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_utility.rs
@@ -98,6 +98,11 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
 			// Standard Error: 3_765
 			.saturating_add(Weight::from_parts(6_028_416, 0).saturating_mul(c.into()))
 	}
+
+	fn dispatch_as_fallible() -> Weight {
+		Default::default()
+	}
+
 	fn if_else() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs
index 1ea2ce5136abd09348e8843b48b7a356b00c57f0..e144f36dd6b88ae9794fc29a10db9a86bfdc2f58 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs
@@ -48,7 +48,7 @@ use xcm::latest::{prelude::*, ROCOCO_GENESIS_HASH, WESTEND_GENESIS_HASH};
 use xcm_builder::{
 	AccountId32Aliases, AliasChildLocation, AllowExplicitUnpaidExecutionFrom,
 	AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom,
-	AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, DenyThenTry,
+	AllowTopLevelPaidExecutionFrom, DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry,
 	DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor,
 	FungibleAdapter, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription,
 	IsConcrete, LocalMint, MatchedConvertedConcreteId, NetworkExportTableItem, NoChecking,
@@ -281,7 +281,7 @@ impl Contains<Location> for AmbassadorEntities {
 
 pub type Barrier = TrailingSetTopicAsId<
 	DenyThenTry<
-		DenyReserveTransferToRelayChain,
+		DenyRecursively<DenyReserveTransferToRelayChain>,
 		(
 			TakeWeightCredit,
 			// Expected responses are OK.
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_common_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_common_config.rs
index 3995f520caf04d59129ce4f9e5cbb90f57ff65f9..bec529404d54059db0b6bc76a6f89d41fd099e02 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_common_config.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_common_config.rs
@@ -23,6 +23,7 @@
 
 use super::{weights, AccountId, Balance, Balances, BlockNumber, Runtime, RuntimeEvent};
 use bp_parachains::SingleParaStoredHeaderDataBuilder;
+use bp_relayers::RewardsAccountParams;
 use frame_support::{parameter_types, traits::ConstU32};
 
 parameter_types! {
@@ -67,11 +68,13 @@ impl pallet_bridge_parachains::Config<BridgeParachainWestendInstance> for Runtim
 pub type RelayersForLegacyLaneIdsMessagesInstance = ();
 impl pallet_bridge_relayers::Config<RelayersForLegacyLaneIdsMessagesInstance> for Runtime {
 	type RuntimeEvent = RuntimeEvent;
-	type Reward = Balance;
+	type RewardBalance = Balance;
+	type Reward = RewardsAccountParams<bp_messages::LegacyLaneId>;
 	type PaymentProcedure = bp_relayers::PayRewardFromAccount<
 		pallet_balances::Pallet<Runtime>,
 		AccountId,
-		Self::LaneId,
+		bp_messages::LegacyLaneId,
+		Self::RewardBalance,
 	>;
 	type StakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed<
 		AccountId,
@@ -81,19 +84,21 @@ impl pallet_bridge_relayers::Config<RelayersForLegacyLaneIdsMessagesInstance> fo
 		RequiredStakeForStakeAndSlash,
 		RelayerStakeLease,
 	>;
-	type WeightInfo = weights::pallet_bridge_relayers::WeightInfo<Runtime>;
-	type LaneId = bp_messages::LegacyLaneId;
+	type Balance = Balance;
+	type WeightInfo = weights::pallet_bridge_relayers_legacy::WeightInfo<Runtime>;
 }
 
 /// Allows collect and claim rewards for relayers
 pub type RelayersForPermissionlessLanesInstance = pallet_bridge_relayers::Instance2;
 impl pallet_bridge_relayers::Config<RelayersForPermissionlessLanesInstance> for Runtime {
 	type RuntimeEvent = RuntimeEvent;
-	type Reward = Balance;
+	type RewardBalance = Balance;
+	type Reward = RewardsAccountParams<bp_messages::HashedLaneId>;
 	type PaymentProcedure = bp_relayers::PayRewardFromAccount<
 		pallet_balances::Pallet<Runtime>,
 		AccountId,
-		Self::LaneId,
+		bp_messages::HashedLaneId,
+		Self::RewardBalance,
 	>;
 	type StakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed<
 		AccountId,
@@ -103,8 +108,8 @@ impl pallet_bridge_relayers::Config<RelayersForPermissionlessLanesInstance> for
 		RequiredStakeForStakeAndSlash,
 		RelayerStakeLease,
 	>;
-	type WeightInfo = weights::pallet_bridge_relayers::WeightInfo<Runtime>;
-	type LaneId = bp_messages::HashedLaneId;
+	type Balance = Balance;
+	type WeightInfo = weights::pallet_bridge_relayers_permissionless_lanes::WeightInfo<Runtime>;
 }
 
 /// Add GRANDPA bridge pallet to track Rococo Bulletin chain.
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_bulletin_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_bulletin_config.rs
index 78e83451835f7190487e789d152870baff0e5889..1a973193b9625778e912e1aeb327d453e68b46c2 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_bulletin_config.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_bulletin_config.rs
@@ -103,7 +103,6 @@ pub type OnBridgeHubRococoRefundRococoBulletinMessages = BridgeRelayersTransacti
 		RelayersForPermissionlessLanesInstance,
 		PriorityBoostPerMessage,
 	>,
-	LaneIdOf<Runtime, WithRococoBulletinMessagesInstance>,
 >;
 bp_runtime::generate_static_str_provider!(OnBridgeHubRococoRefundRococoBulletinMessages);
 
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_westend_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_westend_config.rs
index b70f8e076057ce972da9a9c7cc6aefd4a9df32ab..8eb7e6719bad395ac0319be9413e9a3398744e4e 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_westend_config.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_westend_config.rs
@@ -95,7 +95,6 @@ pub type OnBridgeHubRococoRefundBridgeHubWestendMessages = BridgeRelayersTransac
 		RelayersForLegacyLaneIdsMessagesInstance,
 		PriorityBoostPerMessage,
 	>,
-	LaneIdOf<Runtime, WithBridgeHubWestendMessagesInstance>,
 >;
 bp_runtime::generate_static_str_provider!(OnBridgeHubRococoRefundBridgeHubWestendMessages);
 
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs
index 140056e724a79836c3a20594735bcc356fdd2698..5cdfc7fe35a2cf5a53f49c40d711f02eca873d1b 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs
@@ -181,7 +181,11 @@ pub type Migrations = (
 		OutboundLanesCongestedSignalsKey,
 		RocksDbWeight,
 	>,
-	pallet_bridge_relayers::migration::v1::MigrationToV1<Runtime, ()>,
+	pallet_bridge_relayers::migration::v1::MigrationToV1<
+		Runtime,
+		bridge_common_config::RelayersForLegacyLaneIdsMessagesInstance,
+		bp_messages::LegacyLaneId,
+	>,
 	pallet_session::migrations::v1::MigrateV0ToV1<
 		Runtime,
 		pallet_session::migrations::v1::InitOffenceSeverity<Runtime>,
@@ -1086,6 +1090,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
@@ -1349,7 +1354,7 @@ impl_runtime_apis! {
 					let bench_lane_id = <Self as BridgeMessagesConfig<bridge_to_westend_config::WithBridgeHubWestendMessagesInstance>>::bench_lane_id();
 					use bp_runtime::Chain;
 					let bridged_chain_id =<Self as pallet_bridge_messages::Config<bridge_to_westend_config::WithBridgeHubWestendMessagesInstance>>::BridgedChain::ID;
-					pallet_bridge_relayers::Pallet::<Runtime>::relayer_reward(
+					pallet_bridge_relayers::Pallet::<Runtime, bridge_common_config::RelayersForLegacyLaneIdsMessagesInstance>::relayer_reward(
 						relayer,
 						bp_relayers::RewardsAccountParams::new(
 							bench_lane_id,
@@ -1475,16 +1480,27 @@ impl_runtime_apis! {
 			}
 
 			impl BridgeRelayersConfig<bridge_common_config::RelayersForLegacyLaneIdsMessagesInstance> for Runtime {
+				fn bench_reward() -> Self::Reward {
+					bp_relayers::RewardsAccountParams::new(
+						bp_messages::LegacyLaneId::default(),
+						*b"test",
+						bp_relayers::RewardsAccountOwner::ThisChain
+					)
+				}
+
 				fn prepare_rewards_account(
-					account_params: bp_relayers::RewardsAccountParams<<Self as pallet_bridge_relayers::Config<bridge_common_config::RelayersForLegacyLaneIdsMessagesInstance>>::LaneId>,
+					reward_kind: Self::Reward,
 					reward: Balance,
-				) {
+				) -> Option<AccountId> {
 					let rewards_account = bp_relayers::PayRewardFromAccount::<
 						Balances,
 						AccountId,
-						<Self as pallet_bridge_relayers::Config<bridge_common_config::RelayersForLegacyLaneIdsMessagesInstance>>::LaneId,
-					>::rewards_account(account_params);
+						bp_messages::LegacyLaneId,
+						Balance,
+					>::rewards_account(reward_kind);
 					<Runtime as BridgeRelayersConfig<bridge_common_config::RelayersForLegacyLaneIdsMessagesInstance>>::deposit_account(rewards_account, reward);
+
+					None
 				}
 
 				fn deposit_account(account: AccountId, balance: Balance) {
@@ -1494,16 +1510,27 @@ impl_runtime_apis! {
 			}
 
 			impl BridgeRelayersConfig<bridge_common_config::RelayersForPermissionlessLanesInstance> for Runtime {
+				fn bench_reward() -> Self::Reward {
+					bp_relayers::RewardsAccountParams::new(
+						bp_messages::HashedLaneId::default(),
+						*b"test",
+						bp_relayers::RewardsAccountOwner::ThisChain
+					)
+				}
+
 				fn prepare_rewards_account(
-					account_params: bp_relayers::RewardsAccountParams<<Self as pallet_bridge_relayers::Config<bridge_common_config::RelayersForPermissionlessLanesInstance>>::LaneId>,
+					reward_kind: Self::Reward,
 					reward: Balance,
-				) {
+				) -> Option<AccountId> {
 					let rewards_account = bp_relayers::PayRewardFromAccount::<
 						Balances,
 						AccountId,
-						<Self as pallet_bridge_relayers::Config<bridge_common_config::RelayersForPermissionlessLanesInstance>>::LaneId,
-					>::rewards_account(account_params);
+						bp_messages::HashedLaneId,
+						Balance,
+					>::rewards_account(reward_kind);
 					<Runtime as BridgeRelayersConfig<bridge_common_config::RelayersForPermissionlessLanesInstance>>::deposit_account(rewards_account, reward);
+
+					None
 				}
 
 				fn deposit_account(account: AccountId, balance: Balance) {
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs
index 7a0accf2e7a4530c291e02fcdb742e834bd2e7c9..ebd7f5640e03b963ab823c37a7d6689f566dc2f5 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs
@@ -34,7 +34,8 @@ pub mod pallet_bridge_grandpa;
 pub mod pallet_bridge_messages_rococo_to_rococo_bulletin;
 pub mod pallet_bridge_messages_rococo_to_westend;
 pub mod pallet_bridge_parachains;
-pub mod pallet_bridge_relayers;
+pub mod pallet_bridge_relayers_legacy;
+pub mod pallet_bridge_relayers_permissionless_lanes;
 pub mod pallet_collator_selection;
 pub mod pallet_message_queue;
 pub mod pallet_multisig;
@@ -67,7 +68,7 @@ impl GrandpaWeightInfoExt for pallet_bridge_grandpa::WeightInfo<crate::Runtime>
 		// 1) checks whether relayer registration is active from validate/pre_dispatch;
 		// 2) may slash and deregister relayer from post_dispatch
 		// (2) includes (1), so (2) is the worst case
-		pallet_bridge_relayers::WeightInfo::<Runtime>::slash_and_deregister()
+		pallet_bridge_relayers_legacy::WeightInfo::<Runtime>::slash_and_deregister()
 	}
 }
 
@@ -79,12 +80,12 @@ impl MessagesWeightInfoExt
 	}
 
 	fn receive_messages_proof_overhead_from_runtime() -> Weight {
-		pallet_bridge_relayers::WeightInfo::<Runtime>::receive_messages_proof_overhead_from_runtime(
+		pallet_bridge_relayers_permissionless_lanes::WeightInfo::<Runtime>::receive_messages_proof_overhead_from_runtime(
 		)
 	}
 
 	fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight {
-		pallet_bridge_relayers::WeightInfo::<Runtime>::receive_messages_delivery_proof_overhead_from_runtime()
+		pallet_bridge_relayers_permissionless_lanes::WeightInfo::<Runtime>::receive_messages_delivery_proof_overhead_from_runtime()
 	}
 }
 
@@ -96,12 +97,12 @@ impl MessagesWeightInfoExt
 	}
 
 	fn receive_messages_proof_overhead_from_runtime() -> Weight {
-		pallet_bridge_relayers::WeightInfo::<Runtime>::receive_messages_proof_overhead_from_runtime(
+		pallet_bridge_relayers_legacy::WeightInfo::<Runtime>::receive_messages_proof_overhead_from_runtime(
 		)
 	}
 
 	fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight {
-		pallet_bridge_relayers::WeightInfo::<Runtime>::receive_messages_delivery_proof_overhead_from_runtime()
+		pallet_bridge_relayers_legacy::WeightInfo::<Runtime>::receive_messages_delivery_proof_overhead_from_runtime()
 	}
 }
 
@@ -115,6 +116,6 @@ impl ParachainsWeightInfoExt for pallet_bridge_parachains::WeightInfo<crate::Run
 		// 1) checks whether relayer registration is active from validate/pre_dispatch;
 		// 2) may slash and deregister relayer from post_dispatch
 		// (2) includes (1), so (2) is the worst case
-		pallet_bridge_relayers::WeightInfo::<Runtime>::slash_and_deregister()
+		pallet_bridge_relayers_legacy::WeightInfo::<Runtime>::slash_and_deregister()
 	}
 }
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_relayers.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_relayers_legacy.rs
similarity index 71%
rename from cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_relayers.rs
rename to cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_relayers_legacy.rs
index c30abd093d14bf23f70db551e45cef61641a48ed..25a920fa21f77727559ddea5d3d97c89c32ed9c0 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_relayers.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_relayers_legacy.rs
@@ -1,5 +1,4 @@
 // Copyright (C) Parity Technologies (UK) Ltd.
-// This file is part of Cumulus.
 // SPDX-License-Identifier: Apache-2.0
 
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,25 +16,28 @@
 //! Autogenerated weights for `pallet_bridge_relayers`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-08-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2025-02-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-696hpswk-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
-//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024
+//! HOSTNAME: `a763a8995546`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024
 
 // Executed Command:
-// target/production/polkadot-parachain
+// frame-omni-bencher
+// v1
 // benchmark
 // pallet
-// --steps=50
-// --repeat=20
 // --extrinsic=*
+// --runtime=target/production/wbuild/bridge-hub-rococo-runtime/bridge_hub_rococo_runtime.wasm
+// --pallet=pallet_bridge_relayers
+// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights
 // --wasm-execution=compiled
+// --steps=50
+// --repeat=20
 // --heap-pages=4096
-// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
-// --pallet=pallet_bridge_relayers
-// --chain=bridge-hub-rococo-dev
-// --header=./cumulus/file_header.txt
-// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/
+// --no-storage-info
+// --no-min-squares
+// --no-median-slopes
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
@@ -49,19 +51,29 @@ use core::marker::PhantomData;
 pub struct WeightInfo<T>(PhantomData<T>);
 impl<T: frame_system::Config> pallet_bridge_relayers::WeightInfo for WeightInfo<T> {
 	/// Storage: `BridgeRelayers::RelayerRewards` (r:1 w:1)
-	/// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(102), added: 2577, mode: `MaxEncodedLen`)
+	/// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`)
 	/// Storage: `System::Account` (r:1 w:1)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn claim_rewards() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `306`
+		//  Measured:  `278`
 		//  Estimated: `3593`
-		// Minimum execution time: 53_924_000 picoseconds.
-		Weight::from_parts(54_736_000, 0)
+		// Minimum execution time: 50_375_000 picoseconds.
+		Weight::from_parts(51_947_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
+	/// Storage: `Benchmark::Override` (r:0 w:0)
+	/// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	fn claim_rewards_to() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 18_446_744_073_709_551_000 picoseconds.
+		Weight::from_parts(18_446_744_073_709_551_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
+	}
 	/// Storage: `BridgeRelayers::RegisteredRelayers` (r:1 w:1)
 	/// Proof: `BridgeRelayers::RegisteredRelayers` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	/// Storage: UNKNOWN KEY `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0)
@@ -72,8 +84,8 @@ impl<T: frame_system::Config> pallet_bridge_relayers::WeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `131`
 		//  Estimated: `4714`
-		// Minimum execution time: 28_608_000 picoseconds.
-		Weight::from_parts(29_081_000, 0)
+		// Minimum execution time: 27_761_000 picoseconds.
+		Weight::from_parts(29_163_000, 0)
 			.saturating_add(Weight::from_parts(0, 4714))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -86,8 +98,8 @@ impl<T: frame_system::Config> pallet_bridge_relayers::WeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `231`
 		//  Estimated: `4714`
-		// Minimum execution time: 29_738_000 picoseconds.
-		Weight::from_parts(30_242_000, 0)
+		// Minimum execution time: 32_981_000 picoseconds.
+		Weight::from_parts(34_143_000, 0)
 			.saturating_add(Weight::from_parts(0, 4714))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -96,27 +108,25 @@ impl<T: frame_system::Config> pallet_bridge_relayers::WeightInfo for WeightInfo<
 	/// Proof: `BridgeRelayers::RegisteredRelayers` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	/// Storage: `Balances::Reserves` (r:1 w:1)
 	/// Proof: `Balances::Reserves` (`max_values`: None, `max_size`: Some(1249), added: 3724, mode: `MaxEncodedLen`)
-	/// Storage: `System::Account` (r:1 w:1)
-	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn slash_and_deregister() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `334`
+		//  Measured:  `231`
 		//  Estimated: `4714`
-		// Minimum execution time: 33_174_000 picoseconds.
-		Weight::from_parts(33_992_000, 0)
+		// Minimum execution time: 27_188_000 picoseconds.
+		Weight::from_parts(28_098_000, 0)
 			.saturating_add(Weight::from_parts(0, 4714))
-			.saturating_add(T::DbWeight::get().reads(3))
-			.saturating_add(T::DbWeight::get().writes(3))
+			.saturating_add(T::DbWeight::get().reads(2))
+			.saturating_add(T::DbWeight::get().writes(2))
 	}
 	/// Storage: `BridgeRelayers::RelayerRewards` (r:1 w:1)
-	/// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(102), added: 2577, mode: `MaxEncodedLen`)
+	/// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`)
 	fn register_relayer_reward() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `76`
-		//  Estimated: `3567`
-		// Minimum execution time: 7_950_000 picoseconds.
-		Weight::from_parts(8_123_000, 0)
-			.saturating_add(Weight::from_parts(0, 3567))
+		//  Estimated: `3538`
+		// Minimum execution time: 7_269_000 picoseconds.
+		Weight::from_parts(7_639_000, 0)
+			.saturating_add(Weight::from_parts(0, 3538))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_relayers_permissionless_lanes.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_relayers_permissionless_lanes.rs
new file mode 100644
index 0000000000000000000000000000000000000000..79918088f33c5000873f36e977f70037a822bbdf
--- /dev/null
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_relayers_permissionless_lanes.rs
@@ -0,0 +1,133 @@
+// 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.
+
+//! Autogenerated weights for `pallet_bridge_relayers`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2025-02-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! HOSTNAME: `a763a8995546`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024
+
+// Executed Command:
+// frame-omni-bencher
+// v1
+// benchmark
+// pallet
+// --extrinsic=*
+// --runtime=target/production/wbuild/bridge-hub-rococo-runtime/bridge_hub_rococo_runtime.wasm
+// --pallet=pallet_bridge_relayers
+// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights
+// --wasm-execution=compiled
+// --steps=50
+// --repeat=20
+// --heap-pages=4096
+// --no-storage-info
+// --no-min-squares
+// --no-median-slopes
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::Weight};
+use core::marker::PhantomData;
+
+/// Weight functions for `pallet_bridge_relayers`.
+pub struct WeightInfo<T>(PhantomData<T>);
+impl<T: frame_system::Config> pallet_bridge_relayers::WeightInfo for WeightInfo<T> {
+	/// Storage: `BridgeRelayersForPermissionlessLanes::RelayerRewards` (r:1 w:1)
+	/// Proof: `BridgeRelayersForPermissionlessLanes::RelayerRewards` (`max_values`: None, `max_size`: Some(101), added: 2576, mode: `MaxEncodedLen`)
+	/// Storage: `System::Account` (r:1 w:1)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
+	fn claim_rewards() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `270`
+		//  Estimated: `3593`
+		// Minimum execution time: 51_845_000 picoseconds.
+		Weight::from_parts(53_071_000, 0)
+			.saturating_add(Weight::from_parts(0, 3593))
+			.saturating_add(T::DbWeight::get().reads(2))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
+	/// Storage: `Benchmark::Override` (r:0 w:0)
+	/// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	fn claim_rewards_to() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 18_446_744_073_709_551_000 picoseconds.
+		Weight::from_parts(18_446_744_073_709_551_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
+	}
+	/// Storage: `BridgeRelayersForPermissionlessLanes::RegisteredRelayers` (r:1 w:1)
+	/// Proof: `BridgeRelayersForPermissionlessLanes::RegisteredRelayers` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
+	/// Storage: UNKNOWN KEY `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0)
+	/// Proof: UNKNOWN KEY `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0)
+	/// Storage: `Balances::Reserves` (r:1 w:1)
+	/// Proof: `Balances::Reserves` (`max_values`: None, `max_size`: Some(1249), added: 3724, mode: `MaxEncodedLen`)
+	fn register() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `58`
+		//  Estimated: `4714`
+		// Minimum execution time: 26_683_000 picoseconds.
+		Weight::from_parts(27_836_000, 0)
+			.saturating_add(Weight::from_parts(0, 4714))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
+	/// Storage: `BridgeRelayersForPermissionlessLanes::RegisteredRelayers` (r:1 w:1)
+	/// Proof: `BridgeRelayersForPermissionlessLanes::RegisteredRelayers` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
+	/// Storage: `Balances::Reserves` (r:1 w:1)
+	/// Proof: `Balances::Reserves` (`max_values`: None, `max_size`: Some(1249), added: 3724, mode: `MaxEncodedLen`)
+	fn deregister() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `158`
+		//  Estimated: `4714`
+		// Minimum execution time: 28_456_000 picoseconds.
+		Weight::from_parts(28_997_000, 0)
+			.saturating_add(Weight::from_parts(0, 4714))
+			.saturating_add(T::DbWeight::get().reads(2))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
+	/// Storage: `BridgeRelayersForPermissionlessLanes::RegisteredRelayers` (r:1 w:1)
+	/// Proof: `BridgeRelayersForPermissionlessLanes::RegisteredRelayers` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
+	/// Storage: `Balances::Reserves` (r:1 w:1)
+	/// Proof: `Balances::Reserves` (`max_values`: None, `max_size`: Some(1249), added: 3724, mode: `MaxEncodedLen`)
+	fn slash_and_deregister() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `158`
+		//  Estimated: `4714`
+		// Minimum execution time: 22_474_000 picoseconds.
+		Weight::from_parts(23_057_000, 0)
+			.saturating_add(Weight::from_parts(0, 4714))
+			.saturating_add(T::DbWeight::get().reads(2))
+			.saturating_add(T::DbWeight::get().writes(2))
+	}
+	/// Storage: `BridgeRelayersForPermissionlessLanes::RelayerRewards` (r:1 w:1)
+	/// Proof: `BridgeRelayersForPermissionlessLanes::RelayerRewards` (`max_values`: None, `max_size`: Some(101), added: 2576, mode: `MaxEncodedLen`)
+	fn register_relayer_reward() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `3`
+		//  Estimated: `3566`
+		// Minimum execution time: 7_245_000 picoseconds.
+		Weight::from_parts(7_816_000, 0)
+			.saturating_add(Weight::from_parts(0, 3566))
+			.saturating_add(T::DbWeight::get().reads(1))
+			.saturating_add(T::DbWeight::get().writes(1))
+	}
+}
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_utility.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_utility.rs
index 4e531593f4d532fa8b60076e5cce4f7b0c5deb90..0c5a7cf0aeb34a9dba013daadd1ddb00e312af9e 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_utility.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_utility.rs
@@ -98,6 +98,11 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
 			// Standard Error: 1_601
 			.saturating_add(Weight::from_parts(5_138_293, 0).saturating_mul(c.into()))
 	}
+
+	fn dispatch_as_fallible() -> Weight {
+		Default::default()
+	}
+
 	fn if_else() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs
index 12dc7e5dd7332873418905407be250286b18484b..13145a723baa67f23ff3105c79408a42d943c884 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs
@@ -44,12 +44,12 @@ use xcm::latest::{prelude::*, ROCOCO_GENESIS_HASH};
 use xcm_builder::{
 	AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
 	AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
-	DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily,
-	EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter, HandleFee, HashedDescription,
-	IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SendXcmFeeToAccount,
-	SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
-	SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId,
-	UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
+	DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal,
+	DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter, HandleFee,
+	HashedDescription, IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
+	SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
+	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
+	TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
 };
 use xcm_executor::{
 	traits::{FeeManager, FeeReason, FeeReason::Export},
@@ -131,7 +131,7 @@ impl Contains<Location> for ParentOrParentsPlurality {
 
 pub type Barrier = TrailingSetTopicAsId<
 	DenyThenTry<
-		DenyReserveTransferToRelayChain,
+		DenyRecursively<DenyReserveTransferToRelayChain>,
 		(
 			// Allow local users to buy weight credit.
 			TakeWeightCredit,
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_common_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_common_config.rs
index a5ab4e5137853d3b437af9387bc47d4c8ea403d3..4ff417a47517cb5f9427b4100ed69b067c11255c 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_common_config.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_common_config.rs
@@ -23,26 +23,104 @@
 
 use super::{weights, AccountId, Balance, Balances, BlockNumber, Runtime, RuntimeEvent};
 use bp_messages::LegacyLaneId;
+use bp_relayers::RewardsAccountParams;
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_support::parameter_types;
+use scale_info::TypeInfo;
+use xcm::VersionedLocation;
 
 parameter_types! {
 	pub storage RequiredStakeForStakeAndSlash: Balance = 1_000_000;
 	pub const RelayerStakeLease: u32 = 8;
 	pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs";
+}
+
+/// Showcasing that we can handle multiple different rewards with the same pallet.
+#[derive(
+	Clone,
+	Copy,
+	Debug,
+	Decode,
+	DecodeWithMemTracking,
+	Encode,
+	Eq,
+	MaxEncodedLen,
+	PartialEq,
+	TypeInfo,
+)]
+pub enum BridgeReward {
+	/// Rewards for the R/W bridge—distinguished by the `RewardsAccountParams` key.
+	RococoWestend(RewardsAccountParams<LegacyLaneId>),
+	/// Rewards for Snowbridge.
+	Snowbridge,
+}
+
+impl From<RewardsAccountParams<LegacyLaneId>> for BridgeReward {
+	fn from(value: RewardsAccountParams<LegacyLaneId>) -> Self {
+		Self::RococoWestend(value)
+	}
+}
+
+/// An enum representing the different types of supported beneficiaries.
+#[derive(
+	Clone, Debug, Decode, DecodeWithMemTracking, Encode, Eq, MaxEncodedLen, PartialEq, TypeInfo,
+)]
+pub enum BridgeRewardBeneficiaries {
+	/// A local chain account.
+	LocalAccount(AccountId),
+	/// A beneficiary specified by a VersionedLocation.
+	AssetHubLocation(VersionedLocation),
+}
 
-	pub storage DeliveryRewardInBalance: u64 = 1_000_000;
+impl From<sp_runtime::AccountId32> for BridgeRewardBeneficiaries {
+	fn from(value: sp_runtime::AccountId32) -> Self {
+		BridgeRewardBeneficiaries::LocalAccount(value)
+	}
+}
+
+/// Implementation of `bp_relayers::PaymentProcedure` as a pay/claim rewards scheme.
+pub struct BridgeRewardPayer;
+impl bp_relayers::PaymentProcedure<AccountId, BridgeReward, u128> for BridgeRewardPayer {
+	type Error = sp_runtime::DispatchError;
+	type Beneficiary = BridgeRewardBeneficiaries;
+
+	fn pay_reward(
+		relayer: &AccountId,
+		reward_kind: BridgeReward,
+		reward: u128,
+		beneficiary: BridgeRewardBeneficiaries,
+	) -> Result<(), Self::Error> {
+		match reward_kind {
+			BridgeReward::RococoWestend(lane_params) => {
+				match beneficiary {
+					BridgeRewardBeneficiaries::LocalAccount(account) => {
+						bp_relayers::PayRewardFromAccount::<
+							Balances,
+							AccountId,
+							LegacyLaneId,
+							u128,
+						>::pay_reward(
+							&relayer, lane_params, reward, account,
+						)
+					},
+					BridgeRewardBeneficiaries::AssetHubLocation(_) => Err(Self::Error::Other("`AssetHubLocation` beneficiary is not supported for `RococoWestend` rewards!")),
+				}
+			},
+			BridgeReward::Snowbridge =>
+				Err(sp_runtime::DispatchError::Other("Not implemented yet, check also `fn prepare_rewards_account` to return `alternative_beneficiary`!")),
+		}
+	}
 }
 
 /// Allows collect and claim rewards for relayers
-pub type RelayersForLegacyLaneIdsMessagesInstance = ();
-impl pallet_bridge_relayers::Config<RelayersForLegacyLaneIdsMessagesInstance> for Runtime {
+pub type BridgeRelayersInstance = ();
+impl pallet_bridge_relayers::Config<BridgeRelayersInstance> for Runtime {
 	type RuntimeEvent = RuntimeEvent;
-	type Reward = Balance;
-	type PaymentProcedure = bp_relayers::PayRewardFromAccount<
-		pallet_balances::Pallet<Runtime>,
-		AccountId,
-		Self::LaneId,
-	>;
+
+	type RewardBalance = u128;
+	type Reward = BridgeReward;
+	type PaymentProcedure = BridgeRewardPayer;
+
 	type StakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed<
 		AccountId,
 		BlockNumber,
@@ -51,6 +129,6 @@ impl pallet_bridge_relayers::Config<RelayersForLegacyLaneIdsMessagesInstance> fo
 		RequiredStakeForStakeAndSlash,
 		RelayerStakeLease,
 	>;
+	type Balance = Balance;
 	type WeightInfo = weights::pallet_bridge_relayers::WeightInfo<Runtime>;
-	type LaneId = LegacyLaneId;
 }
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs
index cdad13212676a8a0788faebe62b2897968215e52..de5b11d78bcce86f82d9e7873733c1acc40b504d 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs
@@ -17,9 +17,7 @@
 //! Bridge definitions used on BridgeHub with the Westend flavor.
 
 use crate::{
-	bridge_common_config::{DeliveryRewardInBalance, RelayersForLegacyLaneIdsMessagesInstance},
-	weights,
-	xcm_config::UniversalLocation,
+	bridge_common_config::BridgeRelayersInstance, weights, xcm_config::UniversalLocation,
 	AccountId, Balance, Balances, BridgeRococoMessages, PolkadotXcm, Runtime, RuntimeEvent,
 	RuntimeHoldReason, XcmOverBridgeHubRococo, XcmRouter, XcmpQueue,
 };
@@ -78,6 +76,7 @@ parameter_types! {
 	);
 
 	pub storage BridgeDeposit: Balance = 10 * WND;
+	pub storage DeliveryRewardInBalance: u64 = 1_000_000;
 }
 
 /// Proof of messages, coming from Rococo.
@@ -99,10 +98,9 @@ pub type OnBridgeHubWestendRefundBridgeHubRococoMessages = BridgeRelayersTransac
 		StrOnBridgeHubWestendRefundBridgeHubRococoMessages,
 		Runtime,
 		WithBridgeHubRococoMessagesInstance,
-		RelayersForLegacyLaneIdsMessagesInstance,
+		BridgeRelayersInstance,
 		PriorityBoostPerMessage,
 	>,
-	LaneIdOf<Runtime, WithBridgeHubRococoMessagesInstance>,
 >;
 bp_runtime::generate_static_str_provider!(OnBridgeHubWestendRefundBridgeHubRococoMessages);
 
@@ -152,7 +150,7 @@ impl pallet_bridge_messages::Config<WithBridgeHubRococoMessagesInstance> for Run
 	type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
 		Runtime,
 		WithBridgeHubRococoMessagesInstance,
-		RelayersForLegacyLaneIdsMessagesInstance,
+		BridgeRelayersInstance,
 		DeliveryRewardInBalance,
 	>;
 
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs
index 83712df8295b78c1c3f9de628c50c8ddc33be698..69d2ed06e32be85a25df0ca0e4c780528e0afcba 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs
@@ -162,7 +162,16 @@ pub type Migrations = (
 		OutboundLanesCongestedSignalsKey,
 		RocksDbWeight,
 	>,
-	pallet_bridge_relayers::migration::v1::MigrationToV1<Runtime, ()>,
+	pallet_bridge_relayers::migration::v1::MigrationToV1<
+		Runtime,
+		bridge_common_config::BridgeRelayersInstance,
+		bp_messages::LegacyLaneId,
+	>,
+	pallet_bridge_relayers::migration::v2::MigrationToV2<
+		Runtime,
+		bridge_common_config::BridgeRelayersInstance,
+		bp_messages::LegacyLaneId,
+	>,
 	snowbridge_pallet_system::migration::v0::InitializeOnUpgrade<
 		Runtime,
 		ConstU32<BRIDGE_HUB_ID>,
@@ -976,6 +985,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
@@ -1234,12 +1244,14 @@ impl_runtime_apis! {
 					let bench_lane_id = <Self as BridgeMessagesConfig<bridge_to_rococo_config::WithBridgeHubRococoMessagesInstance>>::bench_lane_id();
 					use bp_runtime::Chain;
 					let bridged_chain_id =<Self as pallet_bridge_messages::Config<bridge_to_rococo_config::WithBridgeHubRococoMessagesInstance>>::BridgedChain::ID;
-					pallet_bridge_relayers::Pallet::<Runtime>::relayer_reward(
+					pallet_bridge_relayers::Pallet::<Runtime, bridge_common_config::BridgeRelayersInstance>::relayer_reward(
 						relayer,
-						bp_relayers::RewardsAccountParams::new(
-							bench_lane_id,
-							bridged_chain_id,
-							bp_relayers::RewardsAccountOwner::BridgedChain
+						bridge_common_config::BridgeReward::RococoWestend(
+							bp_relayers::RewardsAccountParams::new(
+								bench_lane_id,
+								bridged_chain_id,
+								bp_relayers::RewardsAccountOwner::BridgedChain
+							)
 						)
 					).is_some()
 				}
@@ -1314,17 +1326,31 @@ impl_runtime_apis! {
 				}
 			}
 
-			impl BridgeRelayersConfig<bridge_common_config::RelayersForLegacyLaneIdsMessagesInstance> for Runtime {
+			impl BridgeRelayersConfig<bridge_common_config::BridgeRelayersInstance> for Runtime {
+				fn bench_reward() -> Self::Reward {
+					bp_relayers::RewardsAccountParams::new(
+						bp_messages::LegacyLaneId::default(),
+						*b"test",
+						bp_relayers::RewardsAccountOwner::ThisChain
+					).into()
+				}
+
 				fn prepare_rewards_account(
-					account_params: bp_relayers::RewardsAccountParams<<Self as pallet_bridge_relayers::Config<bridge_common_config::RelayersForLegacyLaneIdsMessagesInstance>>::LaneId>,
+					reward_kind: Self::Reward,
 					reward: Balance,
-				) {
+				) -> Option<pallet_bridge_relayers::BeneficiaryOf<Runtime, bridge_common_config::BridgeRelayersInstance>> {
+					let bridge_common_config::BridgeReward::RococoWestend(reward_kind) = reward_kind else {
+						panic!("Unexpected reward_kind: {:?} - not compatible with `bench_reward`!", reward_kind);
+					};
 					let rewards_account = bp_relayers::PayRewardFromAccount::<
 						Balances,
 						AccountId,
-						<Self as pallet_bridge_relayers::Config<bridge_common_config::RelayersForLegacyLaneIdsMessagesInstance>>::LaneId,
-					>::rewards_account(account_params);
+						bp_messages::LegacyLaneId,
+						u128,
+					>::rewards_account(reward_kind);
 					Self::deposit_account(rewards_account, reward);
+
+					None
 				}
 
 				fn deposit_account(account: AccountId, balance: Balance) {
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_bridge_relayers.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_bridge_relayers.rs
index 4127624f1b87c48fb95420334f5b9ff0a46d74b8..4d8381bb84e2dfb4d3ec03bbbc75168bbd501a37 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_bridge_relayers.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_bridge_relayers.rs
@@ -1,5 +1,4 @@
 // Copyright (C) Parity Technologies (UK) Ltd.
-// This file is part of Cumulus.
 // SPDX-License-Identifier: Apache-2.0
 
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,25 +16,28 @@
 //! Autogenerated weights for `pallet_bridge_relayers`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-08-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2025-02-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-696hpswk-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
-//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-dev")`, DB CACHE: 1024
+//! HOSTNAME: `b50e56a3e1c7`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024
 
 // Executed Command:
-// target/production/polkadot-parachain
+// frame-omni-bencher
+// v1
 // benchmark
 // pallet
-// --steps=50
-// --repeat=20
 // --extrinsic=*
+// --runtime=target/production/wbuild/bridge-hub-westend-runtime/bridge_hub_westend_runtime.wasm
+// --pallet=pallet_bridge_relayers
+// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights
 // --wasm-execution=compiled
+// --steps=50
+// --repeat=20
 // --heap-pages=4096
-// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
-// --pallet=pallet_bridge_relayers
-// --chain=bridge-hub-westend-dev
-// --header=./cumulus/file_header.txt
-// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/
+// --no-storage-info
+// --no-min-squares
+// --no-median-slopes
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
@@ -49,19 +51,29 @@ use core::marker::PhantomData;
 pub struct WeightInfo<T>(PhantomData<T>);
 impl<T: frame_system::Config> pallet_bridge_relayers::WeightInfo for WeightInfo<T> {
 	/// Storage: `BridgeRelayers::RelayerRewards` (r:1 w:1)
-	/// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(102), added: 2577, mode: `MaxEncodedLen`)
+	/// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(74), added: 2549, mode: `MaxEncodedLen`)
 	/// Storage: `System::Account` (r:1 w:1)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn claim_rewards() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `272`
+		//  Measured:  `245`
 		//  Estimated: `3593`
-		// Minimum execution time: 52_499_000 picoseconds.
-		Weight::from_parts(53_659_000, 0)
+		// Minimum execution time: 51_920_000 picoseconds.
+		Weight::from_parts(53_320_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
+	/// Storage: `Benchmark::Override` (r:0 w:0)
+	/// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	fn claim_rewards_to() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 18_446_744_073_709_551_000 picoseconds.
+		Weight::from_parts(18_446_744_073_709_551_000, 0)
+			.saturating_add(Weight::from_parts(0, 0))
+	}
 	/// Storage: `BridgeRelayers::RegisteredRelayers` (r:1 w:1)
 	/// Proof: `BridgeRelayers::RegisteredRelayers` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	/// Storage: UNKNOWN KEY `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0)
@@ -72,8 +84,8 @@ impl<T: frame_system::Config> pallet_bridge_relayers::WeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `97`
 		//  Estimated: `4714`
-		// Minimum execution time: 28_706_000 picoseconds.
-		Weight::from_parts(29_434_000, 0)
+		// Minimum execution time: 28_380_000 picoseconds.
+		Weight::from_parts(29_192_000, 0)
 			.saturating_add(Weight::from_parts(0, 4714))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -86,8 +98,8 @@ impl<T: frame_system::Config> pallet_bridge_relayers::WeightInfo for WeightInfo<
 		// Proof Size summary in bytes:
 		//  Measured:  `197`
 		//  Estimated: `4714`
-		// Minimum execution time: 29_563_000 picoseconds.
-		Weight::from_parts(30_222_000, 0)
+		// Minimum execution time: 29_084_000 picoseconds.
+		Weight::from_parts(30_297_000, 0)
 			.saturating_add(Weight::from_parts(0, 4714))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -96,27 +108,25 @@ impl<T: frame_system::Config> pallet_bridge_relayers::WeightInfo for WeightInfo<
 	/// Proof: `BridgeRelayers::RegisteredRelayers` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	/// Storage: `Balances::Reserves` (r:1 w:1)
 	/// Proof: `Balances::Reserves` (`max_values`: None, `max_size`: Some(1249), added: 3724, mode: `MaxEncodedLen`)
-	/// Storage: `System::Account` (r:1 w:1)
-	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn slash_and_deregister() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `300`
+		//  Measured:  `197`
 		//  Estimated: `4714`
-		// Minimum execution time: 32_618_000 picoseconds.
-		Weight::from_parts(33_528_000, 0)
+		// Minimum execution time: 23_805_000 picoseconds.
+		Weight::from_parts(24_552_000, 0)
 			.saturating_add(Weight::from_parts(0, 4714))
-			.saturating_add(T::DbWeight::get().reads(3))
-			.saturating_add(T::DbWeight::get().writes(3))
+			.saturating_add(T::DbWeight::get().reads(2))
+			.saturating_add(T::DbWeight::get().writes(2))
 	}
 	/// Storage: `BridgeRelayers::RelayerRewards` (r:1 w:1)
-	/// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(102), added: 2577, mode: `MaxEncodedLen`)
+	/// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(74), added: 2549, mode: `MaxEncodedLen`)
 	fn register_relayer_reward() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `42`
-		//  Estimated: `3567`
-		// Minimum execution time: 7_521_000 picoseconds.
-		Weight::from_parts(7_844_000, 0)
-			.saturating_add(Weight::from_parts(0, 3567))
+		//  Estimated: `3539`
+		// Minimum execution time: 7_220_000 picoseconds.
+		Weight::from_parts(7_497_000, 0)
+			.saturating_add(Weight::from_parts(0, 3539))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_utility.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_utility.rs
index 5d05e89e45932b3e1044d9afe287bf35e6d64632..b81d217f5b0103aa71ba888c6b94dfc6b8ebb522 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_utility.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_utility.rs
@@ -99,6 +99,11 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
 			// Standard Error: 1_601
 			.saturating_add(Weight::from_parts(5_138_293, 0).saturating_mul(c.into()))
 	}
+
+	fn dispatch_as_fallible() -> Weight {
+		Default::default()
+	}
+	
 	fn if_else() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs
index 1585ef692fd52306a0beb186454eda6278a5ca65..3e844f9841654e62acaecb7e317b3962df90c9f6 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs
@@ -43,12 +43,12 @@ use xcm::latest::{prelude::*, WESTEND_GENESIS_HASH};
 use xcm_builder::{
 	AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
 	AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
-	DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily,
-	EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter, HandleFee, HashedDescription,
-	IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SendXcmFeeToAccount,
-	SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
-	SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId,
-	UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
+	DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal,
+	DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter, HandleFee,
+	HashedDescription, IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
+	SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
+	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
+	TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
 };
 use xcm_executor::{
 	traits::{FeeManager, FeeReason, FeeReason::Export},
@@ -129,7 +129,7 @@ impl Contains<Location> for ParentOrParentsPlurality {
 
 pub type Barrier = TrailingSetTopicAsId<
 	DenyThenTry<
-		DenyReserveTransferToRelayChain,
+		DenyRecursively<DenyReserveTransferToRelayChain>,
 		(
 			// Allow local users to buy weight credit.
 			TakeWeightCredit,
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs
index c9a97af63461513af201a2357abdb89100d02b18..b414338aab2d146a8d432130d61ef135166c9167 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs
@@ -18,29 +18,39 @@
 
 use bp_messages::LegacyLaneId;
 use bp_polkadot_core::Signature;
-use bridge_common_config::{
-	DeliveryRewardInBalance, RelayersForLegacyLaneIdsMessagesInstance,
-	RequiredStakeForStakeAndSlash,
+use bp_relayers::{PayRewardFromAccount, RewardsAccountOwner, RewardsAccountParams};
+use bridge_common_config::{BridgeRelayersInstance, BridgeReward, RequiredStakeForStakeAndSlash};
+use bridge_hub_test_utils::{
+	test_cases::{from_parachain, run_test},
+	SlotDurations,
 };
-use bridge_hub_test_utils::{test_cases::from_parachain, SlotDurations};
 use bridge_hub_westend_runtime::{
 	bridge_common_config, bridge_to_rococo_config,
 	bridge_to_rococo_config::RococoGlobalConsensusNetwork,
 	xcm_config::{LocationToAccountId, RelayNetwork, WestendLocation, XcmConfig},
-	AllPalletsWithoutSystem, Block, BridgeRejectObsoleteHeadersAndMessages, Executive,
-	ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent,
-	RuntimeOrigin, SessionKeys, TransactionPayment, TxExtension, UncheckedExtrinsic,
+	AllPalletsWithoutSystem, Balances, Block, BridgeRejectObsoleteHeadersAndMessages,
+	BridgeRelayers, Executive, ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime,
+	RuntimeCall, RuntimeEvent, RuntimeOrigin, SessionKeys, TransactionPayment, TxExtension,
+	UncheckedExtrinsic,
 };
 use bridge_to_rococo_config::{
 	BridgeGrandpaRococoInstance, BridgeHubRococoLocation, BridgeParachainRococoInstance,
-	WithBridgeHubRococoMessagesInstance, XcmOverBridgeHubRococoInstance,
+	DeliveryRewardInBalance, WithBridgeHubRococoMessagesInstance, XcmOverBridgeHubRococoInstance,
 };
 use codec::{Decode, Encode};
-use frame_support::{dispatch::GetDispatchInfo, parameter_types, traits::ConstU8};
+use frame_support::{
+	assert_err, assert_ok,
+	dispatch::GetDispatchInfo,
+	parameter_types,
+	traits::{
+		fungible::{Inspect, Mutate},
+		ConstU8,
+	},
+};
 use parachains_common::{AccountId, AuraId, Balance};
 use sp_consensus_aura::SlotDuration;
 use sp_core::crypto::Ss58Codec;
-use sp_keyring::Sr25519Keyring::Alice;
+use sp_keyring::Sr25519Keyring::{Alice, Bob};
 use sp_runtime::{
 	generic::{Era, SignedPayload},
 	AccountId32, Perbill,
@@ -69,7 +79,7 @@ type RuntimeTestsAdapter = from_parachain::WithRemoteParachainHelperAdapter<
 	BridgeGrandpaRococoInstance,
 	BridgeParachainRococoInstance,
 	WithBridgeHubRococoMessagesInstance,
-	RelayersForLegacyLaneIdsMessagesInstance,
+	BridgeRelayersInstance,
 >;
 
 parameter_types! {
@@ -534,3 +544,83 @@ fn xcm_payment_api_works() {
 		Block,
 	>();
 }
+
+#[test]
+pub fn bridge_rewards_works() {
+	run_test::<Runtime, _>(
+		collator_session_keys(),
+		bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID,
+		vec![],
+		|| {
+			// reward in WNDs
+			let reward1: u128 = 2_000_000_000;
+			// reward in WETH
+			let reward2: u128 = 3_000_000_000;
+
+			// prepare accounts
+			let account1 = AccountId32::from(Alice);
+			let account2 = AccountId32::from(Bob);
+			let reward1_for = RewardsAccountParams::new(
+				LegacyLaneId([1; 4]),
+				*b"test",
+				RewardsAccountOwner::ThisChain,
+			);
+			let expected_reward1_account =
+				PayRewardFromAccount::<(), AccountId, LegacyLaneId, ()>::rewards_account(
+					reward1_for,
+				);
+			assert_ok!(Balances::mint_into(&expected_reward1_account, ExistentialDeposit::get()));
+			assert_ok!(Balances::mint_into(&expected_reward1_account, reward1.into()));
+			assert_ok!(Balances::mint_into(&account1, ExistentialDeposit::get()));
+
+			// register rewards
+			use bp_relayers::RewardLedger;
+			BridgeRelayers::register_reward(&account1, BridgeReward::from(reward1_for), reward1);
+			BridgeRelayers::register_reward(&account2, BridgeReward::Snowbridge, reward2);
+
+			// check stored rewards
+			assert_eq!(
+				BridgeRelayers::relayer_reward(&account1, BridgeReward::from(reward1_for)),
+				Some(reward1)
+			);
+			assert_eq!(BridgeRelayers::relayer_reward(&account1, BridgeReward::Snowbridge), None,);
+			assert_eq!(
+				BridgeRelayers::relayer_reward(&account2, BridgeReward::Snowbridge),
+				Some(reward2),
+			);
+			assert_eq!(
+				BridgeRelayers::relayer_reward(&account2, BridgeReward::from(reward1_for)),
+				None,
+			);
+
+			// claim rewards
+			assert_ok!(BridgeRelayers::claim_rewards(
+				RuntimeOrigin::signed(account1.clone()),
+				reward1_for.into()
+			));
+			assert_eq!(Balances::total_balance(&account1), ExistentialDeposit::get() + reward1);
+			assert_eq!(
+				BridgeRelayers::relayer_reward(&account1, BridgeReward::from(reward1_for)),
+				None,
+			);
+
+			// already claimed
+			assert_err!(
+				BridgeRelayers::claim_rewards(
+					RuntimeOrigin::signed(account1.clone()),
+					reward1_for.into()
+				),
+				pallet_bridge_relayers::Error::<Runtime, BridgeRelayersInstance>::NoRewardForRelayer
+			);
+
+			// not yet implemented for Snowbridge
+			assert_err!(
+				BridgeRelayers::claim_rewards(
+					RuntimeOrigin::signed(account2.clone()),
+					BridgeReward::Snowbridge
+				),
+				pallet_bridge_relayers::Error::<Runtime, BridgeRelayersInstance>::FailedToPayReward
+			);
+		},
+	);
+}
diff --git a/cumulus/parachains/runtimes/bridge-hubs/common/src/message_queue.rs b/cumulus/parachains/runtimes/bridge-hubs/common/src/message_queue.rs
index 2f5aa76fbdd7717177c32d0529c7ca1de661723a..ccf61f0440bcc84ec8e6d3e2e8327c3a75958973 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/common/src/message_queue.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/common/src/message_queue.rs
@@ -13,7 +13,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //! Runtime configuration for MessageQueue pallet
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::marker::PhantomData;
 use cumulus_primitives_core::{AggregateMessageOrigin as CumulusAggregateMessageOrigin, ParaId};
 use frame_support::{
@@ -28,7 +28,18 @@ use xcm::latest::prelude::{Junction, Location};
 /// The aggregate origin of an inbound message.
 /// This is specialized for BridgeHub, as the snowbridge-outbound-queue-pallet is also using
 /// the shared MessageQueue pallet.
-#[derive(Encode, Decode, Copy, MaxEncodedLen, Clone, Eq, PartialEq, TypeInfo, Debug)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Copy,
+	MaxEncodedLen,
+	Clone,
+	Eq,
+	PartialEq,
+	TypeInfo,
+	Debug,
+)]
 pub enum AggregateMessageOrigin {
 	/// The message came from the para-chain itself.
 	Here,
diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs
index 036223759e6550853cc824a58e849d99698fd587..4f1c073c35ffc1393a2209de6fab5c6446d2e22b 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs
@@ -50,7 +50,7 @@ pub trait WithRemoteGrandpaChainHelper {
 			Self::MPI,
 			InboundPayload = XcmAsPlainPayload,
 			OutboundPayload = XcmAsPlainPayload,
-		> + pallet_bridge_relayers::Config<Self::RPI, LaneId = LaneIdOf<Self::Runtime, Self::MPI>>;
+		> + pallet_bridge_relayers::Config<Self::RPI, Reward = Self::RelayerReward>;
 	/// All pallets of this chain, excluding system pallet.
 	type AllPalletsWithoutSystem: OnInitialize<BlockNumberFor<Self::Runtime>>
 		+ OnFinalize<BlockNumberFor<Self::Runtime>>;
@@ -61,6 +61,8 @@ pub trait WithRemoteGrandpaChainHelper {
 	/// Instance of the `pallet-bridge-relayers`, used to collect rewards from messages `MPI`
 	/// instance.
 	type RPI: 'static;
+	/// Relayer reward type.
+	type RelayerReward: From<RewardsAccountParams<LaneIdOf<Self::Runtime, Self::MPI>>>;
 }
 
 /// Adapter struct that implements [`WithRemoteGrandpaChainHelper`].
@@ -78,9 +80,11 @@ where
 			MPI,
 			InboundPayload = XcmAsPlainPayload,
 			OutboundPayload = XcmAsPlainPayload,
-		> + pallet_bridge_relayers::Config<RPI, LaneId = LaneIdOf<Runtime, MPI>>,
+		> + pallet_bridge_relayers::Config<RPI>,
 	AllPalletsWithoutSystem:
 		OnInitialize<BlockNumberFor<Runtime>> + OnFinalize<BlockNumberFor<Runtime>>,
+	<Runtime as pallet_bridge_relayers::Config<RPI>>::Reward:
+		From<RewardsAccountParams<LaneIdOf<Runtime, MPI>>>,
 	GPI: 'static,
 	MPI: 'static,
 	RPI: 'static,
@@ -90,6 +94,7 @@ where
 	type GPI = GPI;
 	type MPI = MPI;
 	type RPI = RPI;
+	type RelayerReward = Runtime::Reward;
 }
 
 /// Test-case makes sure that Runtime can dispatch XCM messages submitted by relayer,
diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs
index 4fbfe18b9953f5308427f71388cbb0f0b679a4c8..523ea5dc0db4ab9e98ab64df85efeec820fb6d95 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs
@@ -53,7 +53,7 @@ pub trait WithRemoteParachainHelper {
 			Self::MPI,
 			InboundPayload = XcmAsPlainPayload,
 			OutboundPayload = XcmAsPlainPayload,
-		> + pallet_bridge_relayers::Config<Self::RPI, LaneId = LaneIdOf<Self::Runtime, Self::MPI>>;
+		> + pallet_bridge_relayers::Config<Self::RPI, Reward = Self::RelayerReward>;
 	/// All pallets of this chain, excluding system pallet.
 	type AllPalletsWithoutSystem: OnInitialize<BlockNumberFor<Self::Runtime>>
 		+ OnFinalize<BlockNumberFor<Self::Runtime>>;
@@ -66,6 +66,8 @@ pub trait WithRemoteParachainHelper {
 	/// Instance of the `pallet-bridge-relayers`, used to collect rewards from messages `MPI`
 	/// instance.
 	type RPI: 'static;
+	/// Relayer reward type.
+	type RelayerReward: From<RewardsAccountParams<LaneIdOf<Self::Runtime, Self::MPI>>>;
 }
 
 /// Adapter struct that implements `WithRemoteParachainHelper`.
@@ -84,9 +86,11 @@ where
 			MPI,
 			InboundPayload = XcmAsPlainPayload,
 			OutboundPayload = XcmAsPlainPayload,
-		> + pallet_bridge_relayers::Config<RPI, LaneId = LaneIdOf<Runtime, MPI>>,
+		> + pallet_bridge_relayers::Config<RPI>,
 	AllPalletsWithoutSystem:
 		OnInitialize<BlockNumberFor<Runtime>> + OnFinalize<BlockNumberFor<Runtime>>,
+	<Runtime as pallet_bridge_relayers::Config<RPI>>::Reward:
+		From<RewardsAccountParams<LaneIdOf<Runtime, MPI>>>,
 	GPI: 'static,
 	PPI: 'static,
 	MPI: 'static,
@@ -98,6 +102,7 @@ where
 	type PPI = PPI;
 	type MPI = MPI;
 	type RPI = RPI;
+	type RelayerReward = Runtime::Reward;
 }
 
 /// Test-case makes sure that Runtime can dispatch XCM messages submitted by relayer,
diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs
index 1d6935b843b74dff3b471152bdfa4629253b7284..5460a9286b2f6db1fd7ed0950c7a1bdd4c7a136f 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs
@@ -21,7 +21,6 @@ use crate::test_cases::{bridges_prelude::*, run_test, RuntimeHelper};
 use asset_test_utils::BasicParachainRuntime;
 use bp_messages::MessageNonce;
 use bp_polkadot_core::parachains::{ParaHash, ParaId};
-use bp_relayers::RewardsAccountParams;
 use bp_runtime::Chain;
 use codec::Decode;
 use core::marker::PhantomData;
@@ -168,7 +167,7 @@ where
 /// Verifies that relayer is rewarded at this chain.
 pub struct VerifyRelayerRewarded<Runtime: pallet_bridge_relayers::Config<RPI>, RPI: 'static> {
 	relayer: Runtime::AccountId,
-	reward_params: RewardsAccountParams<Runtime::LaneId>,
+	reward_params: Runtime::Reward,
 }
 
 impl<Runtime, RPI> VerifyRelayerRewarded<Runtime, RPI>
@@ -179,9 +178,9 @@ where
 	/// Expect given delivered nonce to be the latest after transaction.
 	pub fn expect_relayer_reward(
 		relayer: Runtime::AccountId,
-		reward_params: RewardsAccountParams<Runtime::LaneId>,
+		reward_params: impl Into<Runtime::Reward>,
 	) -> Box<dyn VerifyTransactionOutcome> {
-		Box::new(Self { relayer, reward_params })
+		Box::new(Self { relayer, reward_params: reward_params.into() })
 	}
 }
 
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/ambassador/origins.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/ambassador/origins.rs
index 3ce8a6b9e5d1bf7f70dda395f1998fd66d20cbeb..db386dbfafea7873bf1e8a0b1e4604e87c76bf35 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/ambassador/origins.rs
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/ambassador/origins.rs
@@ -28,7 +28,17 @@ pub mod pallet_origins {
 	#[pallet::config]
 	pub trait Config: frame_system::Config {}
 
-	#[derive(PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug)]
+	#[derive(
+		PartialEq,
+		Eq,
+		Clone,
+		MaxEncodedLen,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		TypeInfo,
+		RuntimeDebug,
+	)]
 	#[pallet::origin]
 	pub enum Origin {
 		/// Plurality voice of the [ranks::AMBASSADOR_TIER_1] members or above given via
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/origins.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/origins.rs
index 20476a968e405f208cdb4113053fd1423d2f8772..5c88dfbf72fa372486030dd69a273bfe071b47cb 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/origins.rs
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/origins.rs
@@ -31,7 +31,17 @@ pub mod pallet_origins {
 	#[pallet::pallet]
 	pub struct Pallet<T>(_);
 
-	#[derive(PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug)]
+	#[derive(
+		PartialEq,
+		Eq,
+		Clone,
+		MaxEncodedLen,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		TypeInfo,
+		RuntimeDebug,
+	)]
 	#[pallet::origin]
 	pub enum Origin {
 		/// Origin aggregated through weighted votes of those with rank 1 or above; `Success` is 1.
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs
index 65f3e27ae9a711ce8f39f7a9b5adad9b802d12b4..d09fa83eca9b36148377dce4e4e6d8d086d74de4 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs
@@ -66,7 +66,7 @@ use sp_runtime::{
 use sp_version::NativeVersion;
 use sp_version::RuntimeVersion;
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use cumulus_primitives_core::{AggregateMessageOrigin, ClaimQueueOffset, CoreSelector, ParaId};
 use frame_support::{
 	construct_runtime, derive_impl,
@@ -292,6 +292,7 @@ parameter_types! {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	MaxEncodedLen,
 	scale_info::TypeInfo,
@@ -1088,6 +1089,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_utility.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_utility.rs
index 6887e41099e350b07f941a42cd93705eb2abf732..d959b11649bbbdf0e06dd51c01e63c1f5a688bb8 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_utility.rs
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_utility.rs
@@ -98,6 +98,11 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
 			// Standard Error: 1_395
 			.saturating_add(Weight::from_parts(5_000_971, 0).saturating_mul(c.into()))
 	}
+
+	fn dispatch_as_fallible() -> Weight {
+		Default::default()
+	}
+
 	fn if_else() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs
index c5ab21fe8f904372fc4d12b20961006fd01df612..71208b7ce875fd708ae038518c8f43800c5ae6f5 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs
@@ -37,13 +37,13 @@ use xcm_builder::{
 	AccountId32Aliases, AliasChildLocation, AliasOriginRootUsingFilter,
 	AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
 	AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
-	DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily,
-	EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter, HashedDescription, IsConcrete,
-	LocatableAssetId, OriginToPluralityVoice, ParentAsSuperuser, ParentIsPreset,
-	RelayChainAsNative, SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
-	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
-	TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
-	XcmFeeManagerFromComponents,
+	DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal,
+	DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter,
+	HashedDescription, IsConcrete, LocatableAssetId, OriginToPluralityVoice, ParentAsSuperuser,
+	ParentIsPreset, RelayChainAsNative, SendXcmFeeToAccount, SiblingParachainAsNative,
+	SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
+	SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
+	WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents,
 };
 use xcm_executor::XcmExecutor;
 
@@ -146,7 +146,7 @@ impl Contains<Location> for LocalPlurality {
 
 pub type Barrier = TrailingSetTopicAsId<
 	DenyThenTry<
-		DenyReserveTransferToRelayChain,
+		DenyRecursively<DenyReserveTransferToRelayChain>,
 		(
 			// Allow local users to buy weight credit.
 			TakeWeightCredit,
diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs
index 165e60361cd187f36f144b37ca71f2e4e3397762..7dee5443271387361d5425330f4b115dcfbf64da 100644
--- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs
@@ -785,6 +785,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs
index 532ad4ff4ce008ca9cabe5660ea1f6bdbce7dda8..e1da08ae80670a7aa46658e366bef07380c62671 100644
--- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs
+++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs
@@ -40,9 +40,9 @@ use xcm::latest::{prelude::*, ROCOCO_GENESIS_HASH};
 use xcm_builder::{
 	AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
 	AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
-	DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily,
-	EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, FungibleAdapter,
-	HashedDescription, IsConcrete, NativeAsset, ParentAsSuperuser, ParentIsPreset,
+	DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal,
+	DescribeFamily, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor,
+	FungibleAdapter, HashedDescription, IsConcrete, NativeAsset, ParentAsSuperuser, ParentIsPreset,
 	RelayChainAsNative, SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
 	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
 	TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic,
@@ -134,7 +134,7 @@ impl Contains<Location> for ParentOrParentsPlurality {
 
 pub type Barrier = TrailingSetTopicAsId<
 	DenyThenTry<
-		DenyReserveTransferToRelayChain,
+		DenyRecursively<DenyReserveTransferToRelayChain>,
 		(
 			TakeWeightCredit,
 			// Expected responses are OK.
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
index 668b4cc6c7b9bd6a358254f1c86b639dbc487cf5..844166c17c25c5d3f14bbf6bc6c6521257e05121 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
@@ -20,6 +20,7 @@ hex-literal = { workspace = true, default-features = true }
 log = { workspace = true }
 scale-info = { features = ["derive"], workspace = true }
 serde = { optional = true, features = ["derive"], workspace = true, default-features = true }
+serde_json = { features = ["alloc"], workspace = true }
 
 # Substrate
 frame-benchmarking = { optional = true, workspace = true }
@@ -49,6 +50,7 @@ sp-consensus-aura = { workspace = true }
 sp-core = { workspace = true }
 sp-genesis-builder = { workspace = true }
 sp-inherents = { workspace = true }
+sp-keyring = { workspace = true }
 sp-offchain = { workspace = true }
 sp-runtime = { workspace = true }
 sp-session = { workspace = true }
@@ -131,12 +133,14 @@ std = [
 	"rococo-runtime-constants/std",
 	"scale-info/std",
 	"serde",
+	"serde_json/std",
 	"sp-api/std",
 	"sp-block-builder/std",
 	"sp-consensus-aura/std",
 	"sp-core/std",
 	"sp-genesis-builder/std",
 	"sp-inherents/std",
+	"sp-keyring/std",
 	"sp-offchain/std",
 	"sp-runtime/std",
 	"sp-session/std",
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/genesis_config_presets.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/genesis_config_presets.rs
new file mode 100644
index 0000000000000000000000000000000000000000..296def2ce2769eba2b9691d6e102753c582b94f0
--- /dev/null
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/genesis_config_presets.rs
@@ -0,0 +1,103 @@
+// 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.
+
+//! # Coretime Rococo Runtime genesis config presets
+
+use crate::*;
+use alloc::{vec, vec::Vec};
+use cumulus_primitives_core::ParaId;
+use frame_support::build_struct_json_patch;
+use parachains_common::{AccountId, AuraId};
+use sp_genesis_builder::PresetId;
+use sp_keyring::Sr25519Keyring;
+use testnet_parachains_constants::rococo::{currency::UNITS as ROC, xcm_version::SAFE_XCM_VERSION};
+
+const CORETIME_ROCOCO_ED: Balance = ExistentialDeposit::get();
+pub const CORETIME_PARA_ID: ParaId = ParaId::new(1005);
+
+fn coretime_rococo_genesis(
+	invulnerables: Vec<(AccountId, AuraId)>,
+	endowed_accounts: Vec<AccountId>,
+	endowment: Balance,
+	id: ParaId,
+) -> serde_json::Value {
+	build_struct_json_patch!(RuntimeGenesisConfig {
+		balances: BalancesConfig {
+			balances: endowed_accounts.iter().cloned().map(|k| (k, endowment)).collect(),
+		},
+		parachain_info: ParachainInfoConfig { parachain_id: id },
+		collator_selection: CollatorSelectionConfig {
+			invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(),
+			candidacy_bond: CORETIME_ROCOCO_ED * 16,
+		},
+		session: SessionConfig {
+			keys: invulnerables
+				.into_iter()
+				.map(|(acc, aura)| {
+					(
+						acc.clone(),          // account id
+						acc,                  // validator id
+						SessionKeys { aura }, // session keys
+					)
+				})
+				.collect(),
+		},
+		polkadot_xcm: PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION) },
+		sudo: SudoConfig { key: Some(Sr25519Keyring::Alice.to_account_id()) }
+	})
+}
+
+/// Provides the JSON representation of predefined genesis config for given `id`.
+pub fn get_preset(id: &PresetId) -> Option<Vec<u8>> {
+	let patch = match id.as_ref() {
+		sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET => coretime_rococo_genesis(
+			// initial collators.
+			vec![
+				(Sr25519Keyring::Alice.to_account_id(), Sr25519Keyring::Alice.public().into()),
+				(Sr25519Keyring::Bob.to_account_id(), Sr25519Keyring::Bob.public().into()),
+			],
+			Sr25519Keyring::well_known().map(|x| x.to_account_id()).collect(),
+			ROC * 1_000_000,
+			CORETIME_PARA_ID,
+		),
+		sp_genesis_builder::DEV_RUNTIME_PRESET => coretime_rococo_genesis(
+			// initial collators.
+			vec![(Sr25519Keyring::Alice.to_account_id(), Sr25519Keyring::Alice.public().into())],
+			vec![
+				Sr25519Keyring::Alice.to_account_id(),
+				Sr25519Keyring::Bob.to_account_id(),
+				Sr25519Keyring::AliceStash.to_account_id(),
+				Sr25519Keyring::BobStash.to_account_id(),
+			],
+			ROC * 1_000_000,
+			CORETIME_PARA_ID,
+		),
+		_ => return None,
+	};
+
+	Some(
+		serde_json::to_string(&patch)
+			.expect("serialization to json is expected to work. qed.")
+			.into_bytes(),
+	)
+}
+
+/// List of supported presets.
+pub fn preset_names() -> Vec<PresetId> {
+	vec![
+		PresetId::from(sp_genesis_builder::DEV_RUNTIME_PRESET),
+		PresetId::from(sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET),
+	]
+}
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
index b477bb4850d1c60e1550c915bee675da480d1e21..242efd0b9c5e35602fd01b5049c3dcf5b54e4e25 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
@@ -30,13 +30,14 @@ pub mod fast_runtime_binary {
 }
 
 mod coretime;
+mod genesis_config_presets;
 mod weights;
 pub mod xcm_config;
 
 extern crate alloc;
 
 use alloc::{vec, vec::Vec};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
 use cumulus_primitives_core::{AggregateMessageOrigin, ClaimQueueOffset, CoreSelector, ParaId};
 use frame_support::{
@@ -470,6 +471,7 @@ impl pallet_multisig::Config for Runtime {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	MaxEncodedLen,
 	scale_info::TypeInfo,
@@ -953,6 +955,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
@@ -1171,11 +1174,11 @@ impl_runtime_apis! {
 		}
 
 		fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
-			get_preset::<RuntimeGenesisConfig>(id, |_| None)
+			get_preset::<RuntimeGenesisConfig>(id, &genesis_config_presets::get_preset)
 		}
 
 		fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
-			vec![]
+			genesis_config_presets::preset_names()
 		}
 	}
 
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs
index f83cd5fd0e6f8337d72bc27af6fb5566d2116445..aaa8fd5e2a9a41b0e5168893af4275d5e2aa7277 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs
@@ -1,5 +1,4 @@
 // Copyright (C) Parity Technologies (UK) Ltd.
-// This file is part of Cumulus.
 // SPDX-License-Identifier: Apache-2.0
 
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,25 +16,30 @@
 //! Autogenerated weights for `pallet_broker`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-12-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2025-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-acd6uxux-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
-//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-rococo-dev")`, DB CACHE: 1024
+//! HOSTNAME: `2da613459306`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024
 
 // Executed Command:
-// target/production/polkadot-parachain
+// frame-omni-bencher
+// v1
 // benchmark
 // pallet
-// --steps=50
-// --repeat=20
 // --extrinsic=*
+// --runtime=target/production/wbuild/coretime-rococo-runtime/coretime_rococo_runtime.wasm
+// --pallet=pallet_broker
+// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights
 // --wasm-execution=compiled
+// --steps=50
+// --repeat=20
 // --heap-pages=4096
-// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
-// --pallet=pallet_broker
-// --chain=coretime-rococo-dev
-// --header=./cumulus/file_header.txt
-// --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/
+// --no-storage-info
+// --no-min-squares
+// --no-median-slopes
+// --genesis-builder-policy=none
+// --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
@@ -54,8 +58,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 2_250_000 picoseconds.
-		Weight::from_parts(2_419_000, 0)
+		// Minimum execution time: 2_012_000 picoseconds.
+		Weight::from_parts(2_104_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -63,10 +67,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(12021), added: 12516, mode: `MaxEncodedLen`)
 	fn reserve() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `10888`
+		//  Measured:  `10826`
 		//  Estimated: `13506`
-		// Minimum execution time: 25_785_000 picoseconds.
-		Weight::from_parts(26_335_000, 0)
+		// Minimum execution time: 21_764_000 picoseconds.
+		Weight::from_parts(22_375_000, 0)
 			.saturating_add(Weight::from_parts(0, 13506))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -75,10 +79,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(12021), added: 12516, mode: `MaxEncodedLen`)
 	fn unreserve() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `12090`
+		//  Measured:  `12028`
 		//  Estimated: `13506`
-		// Minimum execution time: 24_549_000 picoseconds.
-		Weight::from_parts(25_010_000, 0)
+		// Minimum execution time: 21_047_000 picoseconds.
+		Weight::from_parts(21_450_000, 0)
 			.saturating_add(Weight::from_parts(0, 13506))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -91,14 +95,26 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `ParachainSystem::LastRelayChainBlockNumber` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn set_lease() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `466`
-		//  Estimated: `1951`
-		// Minimum execution time: 14_135_000 picoseconds.
-		Weight::from_parts(14_603_000, 0)
-			.saturating_add(Weight::from_parts(0, 1951))
+		//  Measured:  `400`
+		//  Estimated: `1886`
+		// Minimum execution time: 9_746_000 picoseconds.
+		Weight::from_parts(10_107_000, 0)
+			.saturating_add(Weight::from_parts(0, 1886))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
+	/// Storage: `Broker::Leases` (r:1 w:1)
+	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(401), added: 896, mode: `MaxEncodedLen`)
+	fn remove_lease() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `408`
+		//  Estimated: `1886`
+		// Minimum execution time: 7_825_000 picoseconds.
+		Weight::from_parts(8_367_000, 0)
+			.saturating_add(Weight::from_parts(0, 1886))
+			.saturating_add(T::DbWeight::get().reads(1))
+			.saturating_add(T::DbWeight::get().writes(1))
+	}
 	/// Storage: `Broker::Configuration` (r:1 w:0)
 	/// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Leases` (r:1 w:1)
@@ -107,14 +123,6 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(12021), added: 12516, mode: `MaxEncodedLen`)
 	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
 	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
-	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
-	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
-	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
-	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `ParachainSystem::ValidationData` (r:1 w:0)
 	/// Proof: `ParachainSystem::ValidationData` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `ParachainSystem::LastRelayChainBlockNumber` (r:1 w:0)
@@ -132,15 +140,15 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// The range of component `n` is `[0, 1000]`.
 	fn start_sales(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `12599`
-		//  Estimated: `15065 + n * (1 ±0)`
-		// Minimum execution time: 54_087_000 picoseconds.
-		Weight::from_parts(145_466_213, 0)
-			.saturating_add(Weight::from_parts(0, 15065))
-			// Standard Error: 2_407
-			.saturating_add(Weight::from_parts(20_971, 0).saturating_mul(n.into()))
-			.saturating_add(T::DbWeight::get().reads(14))
-			.saturating_add(T::DbWeight::get().writes(60))
+		//  Measured:  `12505`
+		//  Estimated: `14971 + n * (1 ±0)`
+		// Minimum execution time: 45_856_000 picoseconds.
+		Weight::from_parts(138_813_298, 0)
+			.saturating_add(Weight::from_parts(0, 14971))
+			// Standard Error: 2_476
+			.saturating_add(Weight::from_parts(23_991, 0).saturating_mul(n.into()))
+			.saturating_add(T::DbWeight::get().reads(10))
+			.saturating_add(T::DbWeight::get().writes(58))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
 	}
 	/// Storage: `Broker::Status` (r:1 w:0)
@@ -155,10 +163,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn purchase() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `437`
+		//  Measured:  `356`
 		//  Estimated: `3593`
-		// Minimum execution time: 58_341_000 picoseconds.
-		Weight::from_parts(59_505_000, 0)
+		// Minimum execution time: 58_458_000 picoseconds.
+		Weight::from_parts(60_310_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(4))
 			.saturating_add(T::DbWeight::get().writes(3))
@@ -179,10 +187,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `658`
+		//  Measured:  `577`
 		//  Estimated: `4698`
-		// Minimum execution time: 92_983_000 picoseconds.
-		Weight::from_parts(99_237_000, 0)
+		// Minimum execution time: 95_335_000 picoseconds.
+		Weight::from_parts(102_933_000, 0)
 			.saturating_add(Weight::from_parts(0, 4698))
 			.saturating_add(T::DbWeight::get().reads(6))
 			.saturating_add(T::DbWeight::get().writes(5))
@@ -191,10 +199,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn transfer() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `358`
+		//  Measured:  `337`
 		//  Estimated: `3551`
-		// Minimum execution time: 17_512_000 picoseconds.
-		Weight::from_parts(18_099_000, 0)
+		// Minimum execution time: 18_079_000 picoseconds.
+		Weight::from_parts(19_127_000, 0)
 			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -203,10 +211,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn partition() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `358`
+		//  Measured:  `337`
 		//  Estimated: `3551`
-		// Minimum execution time: 18_715_000 picoseconds.
-		Weight::from_parts(19_768_000, 0)
+		// Minimum execution time: 19_619_000 picoseconds.
+		Weight::from_parts(20_325_000, 0)
 			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -215,10 +223,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn interlace() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `358`
+		//  Measured:  `337`
 		//  Estimated: `3551`
-		// Minimum execution time: 20_349_000 picoseconds.
-		Weight::from_parts(21_050_000, 0)
+		// Minimum execution time: 21_254_000 picoseconds.
+		Weight::from_parts(21_940_000, 0)
 			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(3))
@@ -233,10 +241,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn assign() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `937`
+		//  Measured:  `916`
 		//  Estimated: `4681`
-		// Minimum execution time: 31_876_000 picoseconds.
-		Weight::from_parts(33_536_000, 0)
+		// Minimum execution time: 33_423_000 picoseconds.
+		Weight::from_parts(34_716_000, 0)
 			.saturating_add(Weight::from_parts(0, 4681))
 			.saturating_add(T::DbWeight::get().reads(4))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -253,10 +261,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	fn pool() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `1003`
+		//  Measured:  `982`
 		//  Estimated: `5996`
-		// Minimum execution time: 39_500_000 picoseconds.
-		Weight::from_parts(40_666_000, 0)
+		// Minimum execution time: 40_753_000 picoseconds.
+		Weight::from_parts(41_553_000, 0)
 			.saturating_add(Weight::from_parts(0, 5996))
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(5))
@@ -270,13 +278,13 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// The range of component `m` is `[1, 3]`.
 	fn claim_revenue(m: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `671`
+		//  Measured:  `649`
 		//  Estimated: `6196 + m * (2520 ±0)`
-		// Minimum execution time: 65_843_000 picoseconds.
-		Weight::from_parts(65_768_512, 0)
+		// Minimum execution time: 68_837_000 picoseconds.
+		Weight::from_parts(69_547_275, 0)
 			.saturating_add(Weight::from_parts(0, 6196))
-			// Standard Error: 40_994
-			.saturating_add(Weight::from_parts(2_084_877, 0).saturating_mul(m.into()))
+			// Standard Error: 56_232
+			.saturating_add(Weight::from_parts(1_732_535, 0).saturating_mul(m.into()))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into())))
 			.saturating_add(T::DbWeight::get().writes(5))
@@ -286,23 +294,15 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
 	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
-	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
-	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
-	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
-	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn purchase_credit() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `323`
-		//  Estimated: `3788`
-		// Minimum execution time: 73_250_000 picoseconds.
-		Weight::from_parts(75_059_000, 0)
-			.saturating_add(Weight::from_parts(0, 3788))
-			.saturating_add(T::DbWeight::get().reads(6))
-			.saturating_add(T::DbWeight::get().writes(3))
+		//  Measured:  `103`
+		//  Estimated: `3593`
+		// Minimum execution time: 64_157_000 picoseconds.
+		Weight::from_parts(65_469_000, 0)
+			.saturating_add(Weight::from_parts(0, 3593))
+			.saturating_add(T::DbWeight::get().reads(2))
+			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	/// Storage: `Broker::Status` (r:1 w:0)
 	/// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`)
@@ -310,10 +310,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn drop_region() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `466`
+		//  Measured:  `445`
 		//  Estimated: `3551`
-		// Minimum execution time: 55_088_000 picoseconds.
-		Weight::from_parts(65_329_000, 0)
+		// Minimum execution time: 39_160_000 picoseconds.
+		Weight::from_parts(42_106_000, 0)
 			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -326,10 +326,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	fn drop_contribution() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `463`
+		//  Measured:  `442`
 		//  Estimated: `3533`
-		// Minimum execution time: 102_280_000 picoseconds.
-		Weight::from_parts(130_319_000, 0)
+		// Minimum execution time: 51_875_000 picoseconds.
+		Weight::from_parts(56_175_000, 0)
 			.saturating_add(Weight::from_parts(0, 3533))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -344,10 +344,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn drop_history() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `979`
+		//  Measured:  `855`
 		//  Estimated: `3593`
-		// Minimum execution time: 78_195_000 picoseconds.
-		Weight::from_parts(105_946_000, 0)
+		// Minimum execution time: 67_412_000 picoseconds.
+		Weight::from_parts(75_499_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(4))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -358,47 +358,38 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::PotentialRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`)
 	fn drop_renewal() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `957`
+		//  Measured:  `936`
 		//  Estimated: `4698`
-		// Minimum execution time: 41_642_000 picoseconds.
-		Weight::from_parts(48_286_000, 0)
+		// Minimum execution time: 40_563_000 picoseconds.
+		Weight::from_parts(45_359_000, 0)
 			.saturating_add(Weight::from_parts(0, 4698))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
 	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
-	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
-	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
-	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
-	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// The range of component `n` is `[0, 1000]`.
-	fn request_core_count(_n: u32, ) -> Weight {
+	fn request_core_count(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `74`
-		//  Estimated: `3539`
-		// Minimum execution time: 23_727_000 picoseconds.
-		Weight::from_parts(25_029_439, 0)
-			.saturating_add(Weight::from_parts(0, 3539))
-			.saturating_add(T::DbWeight::get().reads(5))
-			.saturating_add(T::DbWeight::get().writes(2))
+		//  Measured:  `0`
+		//  Estimated: `3465`
+		// Minimum execution time: 21_828_000 picoseconds.
+		Weight::from_parts(35_880_725, 0)
+			.saturating_add(Weight::from_parts(0, 3465))
+			// Standard Error: 1_415
+			.saturating_add(Weight::from_parts(3_256, 0).saturating_mul(n.into()))
+			.saturating_add(T::DbWeight::get().reads(1))
 	}
 	/// Storage: `Broker::CoreCountInbox` (r:1 w:1)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
 	/// The range of component `n` is `[0, 1000]`.
-	fn process_core_count(n: u32, ) -> Weight {
+	fn process_core_count(_n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `266`
+		//  Measured:  `208`
 		//  Estimated: `1487`
-		// Minimum execution time: 7_887_000 picoseconds.
-		Weight::from_parts(8_477_863, 0)
+		// Minimum execution time: 6_911_000 picoseconds.
+		Weight::from_parts(7_609_428, 0)
 			.saturating_add(Weight::from_parts(0, 1487))
-			// Standard Error: 18
-			.saturating_add(Weight::from_parts(76, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -410,10 +401,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn process_revenue() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `461`
+		//  Measured:  `440`
 		//  Estimated: `6196`
-		// Minimum execution time: 52_505_000 picoseconds.
-		Weight::from_parts(53_392_000, 0)
+		// Minimum execution time: 55_057_000 picoseconds.
+		Weight::from_parts(56_475_000, 0)
 			.saturating_add(Weight::from_parts(0, 6196))
 			.saturating_add(T::DbWeight::get().reads(4))
 			.saturating_add(T::DbWeight::get().writes(4))
@@ -443,13 +434,13 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// The range of component `n` is `[0, 1000]`.
 	fn rotate_sale(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `32497`
+		//  Measured:  `32278`
 		//  Estimated: `233641 + n * (198 ±9)`
-		// Minimum execution time: 28_834_000 picoseconds.
-		Weight::from_parts(2_467_159_777, 0)
+		// Minimum execution time: 27_257_000 picoseconds.
+		Weight::from_parts(2_662_011_487, 0)
 			.saturating_add(Weight::from_parts(0, 233641))
-			// Standard Error: 149_483
-			.saturating_add(Weight::from_parts(4_045_956, 0).saturating_mul(n.into()))
+			// Standard Error: 162_108
+			.saturating_add(Weight::from_parts(4_134_195, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(126))
 			.saturating_add(T::DbWeight::get().writes(181))
 			.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into())))
@@ -461,10 +452,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`)
 	fn process_pool() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `42`
+		//  Measured:  `0`
 		//  Estimated: `3493`
-		// Minimum execution time: 7_689_000 picoseconds.
-		Weight::from_parts(7_988_000, 0)
+		// Minimum execution time: 5_245_000 picoseconds.
+		Weight::from_parts(5_537_000, 0)
 			.saturating_add(Weight::from_parts(0, 3493))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -475,43 +466,26 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Workload` (`max_values`: None, `max_size`: Some(1212), added: 3687, mode: `MaxEncodedLen`)
 	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
 	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
-	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
-	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
-	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
-	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn process_core_schedule() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `1321`
-		//  Estimated: `4786`
-		// Minimum execution time: 37_394_000 picoseconds.
-		Weight::from_parts(38_379_000, 0)
-			.saturating_add(Weight::from_parts(0, 4786))
-			.saturating_add(T::DbWeight::get().reads(7))
-			.saturating_add(T::DbWeight::get().writes(4))
+		//  Measured:  `1223`
+		//  Estimated: `4688`
+		// Minimum execution time: 26_782_000 picoseconds.
+		Weight::from_parts(27_767_000, 0)
+			.saturating_add(Weight::from_parts(0, 4688))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(2))
 	}
 	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
 	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
-	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
-	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
-	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
-	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn request_revenue_info_at() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `74`
-		//  Estimated: `3539`
-		// Minimum execution time: 19_203_000 picoseconds.
-		Weight::from_parts(19_797_000, 0)
-			.saturating_add(Weight::from_parts(0, 3539))
-			.saturating_add(T::DbWeight::get().reads(5))
-			.saturating_add(T::DbWeight::get().writes(2))
+		//  Measured:  `0`
+		//  Estimated: `3465`
+		// Minimum execution time: 8_475_000 picoseconds.
+		Weight::from_parts(11_257_000, 0)
+			.saturating_add(Weight::from_parts(0, 3465))
+			.saturating_add(T::DbWeight::get().reads(1))
 	}
 	/// Storage: `Broker::CoreCountInbox` (r:0 w:1)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
@@ -519,8 +493,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 2_129_000 picoseconds.
-		Weight::from_parts(2_266_000, 0)
+		// Minimum execution time: 1_899_000 picoseconds.
+		Weight::from_parts(2_021_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -530,8 +504,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 2_233_000 picoseconds.
-		Weight::from_parts(2_351_000, 0)
+		// Minimum execution time: 1_980_000 picoseconds.
+		Weight::from_parts(2_053_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -547,11 +521,11 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `ParachainSystem::ValidationData` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn do_tick_base() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `408`
-		//  Estimated: `1893`
-		// Minimum execution time: 15_716_000 picoseconds.
-		Weight::from_parts(16_160_000, 0)
-			.saturating_add(Weight::from_parts(0, 1893))
+		//  Measured:  `327`
+		//  Estimated: `1812`
+		// Minimum execution time: 12_474_000 picoseconds.
+		Weight::from_parts(12_970_000, 0)
+			.saturating_add(Weight::from_parts(0, 1812))
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -565,10 +539,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn force_reserve() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `11125`
+		//  Measured:  `11120`
 		//  Estimated: `13506`
-		// Minimum execution time: 32_286_000 picoseconds.
-		Weight::from_parts(33_830_000, 0)
+		// Minimum execution time: 38_182_000 picoseconds.
+		Weight::from_parts(39_394_000, 0)
 			.saturating_add(Weight::from_parts(0, 13506))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(3))
@@ -577,10 +551,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(401), added: 896, mode: `MaxEncodedLen`)
 	fn swap_leases() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `470`
+		//  Measured:  `408`
 		//  Estimated: `1886`
-		// Minimum execution time: 8_887_000 picoseconds.
-		Weight::from_parts(9_178_000, 0)
+		// Minimum execution time: 5_317_000 picoseconds.
+		Weight::from_parts(5_693_000, 0)
 			.saturating_add(Weight::from_parts(0, 1886))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -603,10 +577,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn enable_auto_renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `2829`
+		//  Measured:  `2748`
 		//  Estimated: `6196`
-		// Minimum execution time: 130_799_000 picoseconds.
-		Weight::from_parts(139_893_000, 0)
+		// Minimum execution time: 123_214_000 picoseconds.
+		Weight::from_parts(132_950_000, 0)
 			.saturating_add(Weight::from_parts(0, 6196))
 			.saturating_add(T::DbWeight::get().reads(8))
 			.saturating_add(T::DbWeight::get().writes(7))
@@ -615,10 +589,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::AutoRenewals` (`max_values`: Some(1), `max_size`: Some(1002), added: 1497, mode: `MaxEncodedLen`)
 	fn disable_auto_renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `1307`
+		//  Measured:  `1286`
 		//  Estimated: `2487`
-		// Minimum execution time: 22_945_000 picoseconds.
-		Weight::from_parts(24_855_000, 0)
+		// Minimum execution time: 24_008_000 picoseconds.
+		Weight::from_parts(25_836_000, 0)
 			.saturating_add(Weight::from_parts(0, 2487))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -627,22 +601,26 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
 	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
-	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
-	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
-	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
-	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn on_new_timeslice() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `323`
-		//  Estimated: `3788`
-		// Minimum execution time: 56_864_000 picoseconds.
-		Weight::from_parts(59_119_000, 0)
-			.saturating_add(Weight::from_parts(0, 3788))
-			.saturating_add(T::DbWeight::get().reads(6))
-			.saturating_add(T::DbWeight::get().writes(3))
+		//  Measured:  `103`
+		//  Estimated: `3593`
+		// Minimum execution time: 49_816_000 picoseconds.
+		Weight::from_parts(51_389_000, 0)
+			.saturating_add(Weight::from_parts(0, 3593))
+			.saturating_add(T::DbWeight::get().reads(2))
+			.saturating_add(T::DbWeight::get().writes(1))
+	}
+	/// Storage: `Broker::Workplan` (r:1 w:1)
+	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
+	fn remove_assignment() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `777`
+		//  Estimated: `4681`
+		// Minimum execution time: 18_714_000 picoseconds.
+		Weight::from_parts(19_800_000, 0)
+			.saturating_add(Weight::from_parts(0, 4681))
+			.saturating_add(T::DbWeight::get().reads(1))
+			.saturating_add(T::DbWeight::get().writes(1))
 	}
 }
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_utility.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_utility.rs
index 2619a4180bab7d310e24c70e02ccc56bfe72003d..1bfac221c2c8f6126cf46e71950fdcaf613f501e 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_utility.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_utility.rs
@@ -99,6 +99,11 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
 			// Standard Error: 1_621
 			.saturating_add(Weight::from_parts(3_312_302, 0).saturating_mul(c.into()))
 	}
+
+	fn dispatch_as_fallible() -> Weight {
+		Default::default()
+	}
+
 	fn if_else() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs
index 7c3f8a365856cce2f773223a152200abbdd669f1..35b3b6fb5575717b98960f07b09fcb981573d2dd 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs
@@ -41,12 +41,12 @@ use xcm::latest::{prelude::*, ROCOCO_GENESIS_HASH};
 use xcm_builder::{
 	AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
 	AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
-	DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily,
-	EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter, HashedDescription, IsConcrete,
-	NonFungibleAdapter, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SendXcmFeeToAccount,
-	SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
-	SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId,
-	UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
+	DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal,
+	DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter,
+	HashedDescription, IsConcrete, NonFungibleAdapter, ParentAsSuperuser, ParentIsPreset,
+	RelayChainAsNative, SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
+	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
+	TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
 	XcmFeeManagerFromComponents,
 };
 use xcm_executor::XcmExecutor;
@@ -145,7 +145,7 @@ impl Contains<Location> for ParentOrParentsPlurality {
 
 pub type Barrier = TrailingSetTopicAsId<
 	DenyThenTry<
-		DenyReserveTransferToRelayChain,
+		DenyRecursively<DenyReserveTransferToRelayChain>,
 		(
 			// Allow local users to buy weight credit.
 			TakeWeightCredit,
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
index 915926ff9894ed3164dd37aeee828aa7229bb863..f00009d712b0fa224065f6477cc50a629dbc332d 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
@@ -20,6 +20,7 @@ hex-literal = { workspace = true, default-features = true }
 log = { workspace = true }
 scale-info = { features = ["derive"], workspace = true }
 serde = { optional = true, features = ["derive"], workspace = true, default-features = true }
+serde_json = { features = ["alloc"], workspace = true }
 
 # Substrate
 frame-benchmarking = { optional = true, workspace = true }
@@ -38,6 +39,7 @@ pallet-message-queue = { workspace = true }
 pallet-multisig = { workspace = true }
 pallet-proxy = { workspace = true }
 pallet-session = { workspace = true }
+pallet-sudo = { workspace = true }
 pallet-timestamp = { workspace = true }
 pallet-transaction-payment = { workspace = true }
 pallet-transaction-payment-rpc-runtime-api = { workspace = true }
@@ -48,6 +50,7 @@ sp-consensus-aura = { workspace = true }
 sp-core = { workspace = true }
 sp-genesis-builder = { workspace = true }
 sp-inherents = { workspace = true }
+sp-keyring = { workspace = true }
 sp-offchain = { workspace = true }
 sp-runtime = { workspace = true }
 sp-session = { workspace = true }
@@ -116,6 +119,7 @@ std = [
 	"pallet-multisig/std",
 	"pallet-proxy/std",
 	"pallet-session/std",
+	"pallet-sudo/std",
 	"pallet-timestamp/std",
 	"pallet-transaction-payment-rpc-runtime-api/std",
 	"pallet-transaction-payment/std",
@@ -128,12 +132,14 @@ std = [
 	"polkadot-runtime-common/std",
 	"scale-info/std",
 	"serde",
+	"serde_json/std",
 	"sp-api/std",
 	"sp-block-builder/std",
 	"sp-consensus-aura/std",
 	"sp-core/std",
 	"sp-genesis-builder/std",
 	"sp-inherents/std",
+	"sp-keyring/std",
 	"sp-offchain/std",
 	"sp-runtime/std",
 	"sp-session/std",
@@ -166,6 +172,7 @@ runtime-benchmarks = [
 	"pallet-message-queue/runtime-benchmarks",
 	"pallet-multisig/runtime-benchmarks",
 	"pallet-proxy/runtime-benchmarks",
+	"pallet-sudo/runtime-benchmarks",
 	"pallet-timestamp/runtime-benchmarks",
 	"pallet-transaction-payment/runtime-benchmarks",
 	"pallet-utility/runtime-benchmarks",
@@ -200,6 +207,7 @@ try-runtime = [
 	"pallet-multisig/try-runtime",
 	"pallet-proxy/try-runtime",
 	"pallet-session/try-runtime",
+	"pallet-sudo/try-runtime",
 	"pallet-timestamp/try-runtime",
 	"pallet-transaction-payment/try-runtime",
 	"pallet-utility/try-runtime",
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/genesis_config_presets.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/genesis_config_presets.rs
new file mode 100644
index 0000000000000000000000000000000000000000..da8ecfdfcb6d75595fcdd8d6cbdef02f09d7888f
--- /dev/null
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/genesis_config_presets.rs
@@ -0,0 +1,104 @@
+// 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.
+
+//! # Coretime Westend Runtime genesis config presets
+
+use crate::*;
+use alloc::{vec, vec::Vec};
+use cumulus_primitives_core::ParaId;
+use frame_support::build_struct_json_patch;
+use parachains_common::{AccountId, AuraId};
+use sp_genesis_builder::PresetId;
+use sp_keyring::Sr25519Keyring;
+use testnet_parachains_constants::westend::{
+	currency::UNITS as WND, xcm_version::SAFE_XCM_VERSION,
+};
+
+const CORETIME_WESTEND_ED: Balance = ExistentialDeposit::get();
+pub const CORETIME_PARA_ID: ParaId = ParaId::new(1005);
+
+fn coretime_westend_genesis(
+	invulnerables: Vec<(AccountId, AuraId)>,
+	endowed_accounts: Vec<AccountId>,
+	endowment: Balance,
+	id: ParaId,
+) -> serde_json::Value {
+	build_struct_json_patch!(RuntimeGenesisConfig {
+		balances: BalancesConfig {
+			balances: endowed_accounts.iter().cloned().map(|k| (k, endowment)).collect(),
+		},
+		parachain_info: ParachainInfoConfig { parachain_id: id },
+		collator_selection: CollatorSelectionConfig {
+			invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(),
+			candidacy_bond: CORETIME_WESTEND_ED * 16,
+		},
+		session: SessionConfig {
+			keys: invulnerables
+				.into_iter()
+				.map(|(acc, aura)| {
+					(
+						acc.clone(),          // account id
+						acc,                  // validator id
+						SessionKeys { aura }, // session keys
+					)
+				})
+				.collect(),
+		},
+		polkadot_xcm: PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION) },
+	})
+}
+
+/// Provides the JSON representation of predefined genesis config for given `id`.
+pub fn get_preset(id: &PresetId) -> Option<Vec<u8>> {
+	let patch = match id.as_ref() {
+		sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET => coretime_westend_genesis(
+			// initial collators.
+			vec![
+				(Sr25519Keyring::Alice.to_account_id(), Sr25519Keyring::Alice.public().into()),
+				(Sr25519Keyring::Bob.to_account_id(), Sr25519Keyring::Bob.public().into()),
+			],
+			Sr25519Keyring::well_known().map(|k| k.to_account_id()).collect(),
+			WND * 1_000_000,
+			CORETIME_PARA_ID,
+		),
+		sp_genesis_builder::DEV_RUNTIME_PRESET => coretime_westend_genesis(
+			// initial collators.
+			vec![(Sr25519Keyring::Alice.to_account_id(), Sr25519Keyring::Alice.public().into())],
+			vec![
+				Sr25519Keyring::Alice.to_account_id(),
+				Sr25519Keyring::Bob.to_account_id(),
+				Sr25519Keyring::AliceStash.to_account_id(),
+				Sr25519Keyring::BobStash.to_account_id(),
+			],
+			WND * 1_000_000,
+			CORETIME_PARA_ID,
+		),
+		_ => return None,
+	};
+
+	Some(
+		serde_json::to_string(&patch)
+			.expect("serialization to json is expected to work. qed.")
+			.into_bytes(),
+	)
+}
+
+/// List of supported presets.
+pub fn preset_names() -> Vec<PresetId> {
+	vec![
+		PresetId::from(sp_genesis_builder::DEV_RUNTIME_PRESET),
+		PresetId::from(sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET),
+	]
+}
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
index 964351575de838e42668c64a6733d4e59bbea6c9..e52d8c258a1012caceb131438bd9a378b94f866e 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
@@ -30,13 +30,14 @@ pub mod fast_runtime_binary {
 }
 
 mod coretime;
+mod genesis_config_presets;
 mod weights;
 pub mod xcm_config;
 
 extern crate alloc;
 
 use alloc::{vec, vec::Vec};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
 use cumulus_primitives_core::{AggregateMessageOrigin, ClaimQueueOffset, CoreSelector, ParaId};
 use frame_support::{
@@ -471,6 +472,7 @@ impl pallet_multisig::Config for Runtime {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	MaxEncodedLen,
 	scale_info::TypeInfo,
@@ -601,6 +603,12 @@ impl pallet_utility::Config for Runtime {
 	type WeightInfo = weights::pallet_utility::WeightInfo<Runtime>;
 }
 
+impl pallet_sudo::Config for Runtime {
+	type RuntimeCall = RuntimeCall;
+	type RuntimeEvent = RuntimeEvent;
+	type WeightInfo = pallet_sudo::weights::SubstrateWeight<Runtime>;
+}
+
 pub struct BrokerMigrationV4BlockConversion;
 
 impl pallet_broker::migration::v4::BlockToRelayHeightConversion<Runtime>
@@ -655,6 +663,9 @@ construct_runtime!(
 
 		// The main stage.
 		Broker: pallet_broker = 50,
+
+		// Sudo
+		Sudo: pallet_sudo = 100,
 	}
 );
 
@@ -945,6 +956,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
@@ -1166,11 +1178,11 @@ impl_runtime_apis! {
 		}
 
 		fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
-			get_preset::<RuntimeGenesisConfig>(id, |_| None)
+			get_preset::<RuntimeGenesisConfig>(id, &genesis_config_presets::get_preset)
 		}
 
 		fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
-			vec![]
+			genesis_config_presets::preset_names()
 		}
 	}
 
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs
index e431ccbbc29fde5f3673318d2925e605f9dd4bbd..84b79da713c751beb7420e55ef17adda68a7ceb4 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs
@@ -1,5 +1,4 @@
 // Copyright (C) Parity Technologies (UK) Ltd.
-// This file is part of Cumulus.
 // SPDX-License-Identifier: Apache-2.0
 
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,25 +16,30 @@
 //! Autogenerated weights for `pallet_broker`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-12-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2025-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-acd6uxux-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
-//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-westend-dev")`, DB CACHE: 1024
+//! HOSTNAME: `2da613459306`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024
 
 // Executed Command:
-// target/production/polkadot-parachain
+// frame-omni-bencher
+// v1
 // benchmark
 // pallet
-// --steps=50
-// --repeat=20
 // --extrinsic=*
+// --runtime=target/production/wbuild/coretime-westend-runtime/coretime_westend_runtime.wasm
+// --pallet=pallet_broker
+// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt
+// --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights
 // --wasm-execution=compiled
+// --steps=50
+// --repeat=20
 // --heap-pages=4096
-// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
-// --pallet=pallet_broker
-// --chain=coretime-westend-dev
-// --header=./cumulus/file_header.txt
-// --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/
+// --no-storage-info
+// --no-min-squares
+// --no-median-slopes
+// --genesis-builder-policy=none
+// --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
@@ -54,8 +58,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 2_274_000 picoseconds.
-		Weight::from_parts(2_421_000, 0)
+		// Minimum execution time: 2_220_000 picoseconds.
+		Weight::from_parts(2_304_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -63,10 +67,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(12021), added: 12516, mode: `MaxEncodedLen`)
 	fn reserve() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `10888`
+		//  Measured:  `10826`
 		//  Estimated: `13506`
-		// Minimum execution time: 26_257_000 picoseconds.
-		Weight::from_parts(26_802_000, 0)
+		// Minimum execution time: 22_227_000 picoseconds.
+		Weight::from_parts(22_647_000, 0)
 			.saturating_add(Weight::from_parts(0, 13506))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -75,10 +79,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(12021), added: 12516, mode: `MaxEncodedLen`)
 	fn unreserve() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `12090`
+		//  Measured:  `12028`
 		//  Estimated: `13506`
-		// Minimum execution time: 24_692_000 picoseconds.
-		Weight::from_parts(25_275_000, 0)
+		// Minimum execution time: 21_649_000 picoseconds.
+		Weight::from_parts(22_185_000, 0)
 			.saturating_add(Weight::from_parts(0, 13506))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -91,14 +95,26 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `ParachainSystem::LastRelayChainBlockNumber` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn set_lease() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `146`
-		//  Estimated: `1631`
-		// Minimum execution time: 13_872_000 picoseconds.
-		Weight::from_parts(14_509_000, 0)
-			.saturating_add(Weight::from_parts(0, 1631))
+		//  Measured:  `80`
+		//  Estimated: `1566`
+		// Minimum execution time: 9_208_000 picoseconds.
+		Weight::from_parts(9_647_000, 0)
+			.saturating_add(Weight::from_parts(0, 1566))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
+	/// Storage: `Broker::Leases` (r:1 w:1)
+	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(81), added: 576, mode: `MaxEncodedLen`)
+	fn remove_lease() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `88`
+		//  Estimated: `1566`
+		// Minimum execution time: 7_779_000 picoseconds.
+		Weight::from_parts(8_213_000, 0)
+			.saturating_add(Weight::from_parts(0, 1566))
+			.saturating_add(T::DbWeight::get().reads(1))
+			.saturating_add(T::DbWeight::get().writes(1))
+	}
 	/// Storage: `Broker::Configuration` (r:1 w:0)
 	/// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`)
 	/// Storage: `Broker::Leases` (r:1 w:1)
@@ -107,14 +123,6 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(12021), added: 12516, mode: `MaxEncodedLen`)
 	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
 	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
-	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
-	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
-	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
-	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `ParachainSystem::ValidationData` (r:1 w:0)
 	/// Proof: `ParachainSystem::ValidationData` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// Storage: `ParachainSystem::LastRelayChainBlockNumber` (r:1 w:0)
@@ -132,15 +140,15 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// The range of component `n` is `[0, 1000]`.
 	fn start_sales(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `12279`
-		//  Estimated: `14805 + n * (1 ±0)`
-		// Minimum execution time: 52_916_000 picoseconds.
-		Weight::from_parts(96_122_236, 0)
-			.saturating_add(Weight::from_parts(0, 14805))
-			// Standard Error: 969
-			.saturating_add(Weight::from_parts(5_732, 0).saturating_mul(n.into()))
-			.saturating_add(T::DbWeight::get().reads(14))
-			.saturating_add(T::DbWeight::get().writes(27))
+		//  Measured:  `12185`
+		//  Estimated: `14711 + n * (1 ±0)`
+		// Minimum execution time: 47_150_000 picoseconds.
+		Weight::from_parts(92_303_734, 0)
+			.saturating_add(Weight::from_parts(0, 14711))
+			// Standard Error: 1_006
+			.saturating_add(Weight::from_parts(5_339, 0).saturating_mul(n.into()))
+			.saturating_add(T::DbWeight::get().reads(10))
+			.saturating_add(T::DbWeight::get().writes(25))
 			.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
 	}
 	/// Storage: `Broker::Status` (r:1 w:0)
@@ -155,10 +163,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn purchase() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `437`
+		//  Measured:  `356`
 		//  Estimated: `3593`
-		// Minimum execution time: 56_955_000 picoseconds.
-		Weight::from_parts(59_005_000, 0)
+		// Minimum execution time: 55_570_000 picoseconds.
+		Weight::from_parts(57_144_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(4))
 			.saturating_add(T::DbWeight::get().writes(3))
@@ -179,10 +187,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `658`
+		//  Measured:  `577`
 		//  Estimated: `4698`
-		// Minimum execution time: 108_853_000 picoseconds.
-		Weight::from_parts(117_467_000, 0)
+		// Minimum execution time: 94_812_000 picoseconds.
+		Weight::from_parts(107_167_000, 0)
 			.saturating_add(Weight::from_parts(0, 4698))
 			.saturating_add(T::DbWeight::get().reads(6))
 			.saturating_add(T::DbWeight::get().writes(4))
@@ -191,10 +199,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn transfer() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `358`
+		//  Measured:  `337`
 		//  Estimated: `3551`
-		// Minimum execution time: 16_922_000 picoseconds.
-		Weight::from_parts(17_544_000, 0)
+		// Minimum execution time: 17_630_000 picoseconds.
+		Weight::from_parts(18_504_000, 0)
 			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -203,10 +211,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn partition() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `358`
+		//  Measured:  `337`
 		//  Estimated: `3551`
-		// Minimum execution time: 18_762_000 picoseconds.
-		Weight::from_parts(19_162_000, 0)
+		// Minimum execution time: 19_737_000 picoseconds.
+		Weight::from_parts(20_986_000, 0)
 			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -215,10 +223,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn interlace() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `358`
+		//  Measured:  `337`
 		//  Estimated: `3551`
-		// Minimum execution time: 20_297_000 picoseconds.
-		Weight::from_parts(20_767_000, 0)
+		// Minimum execution time: 20_954_000 picoseconds.
+		Weight::from_parts(21_730_000, 0)
 			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(3))
@@ -233,10 +241,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn assign() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `736`
+		//  Measured:  `715`
 		//  Estimated: `4681`
-		// Minimum execution time: 31_347_000 picoseconds.
-		Weight::from_parts(32_259_000, 0)
+		// Minimum execution time: 32_156_000 picoseconds.
+		Weight::from_parts(33_365_000, 0)
 			.saturating_add(Weight::from_parts(0, 4681))
 			.saturating_add(T::DbWeight::get().reads(4))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -253,10 +261,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	fn pool() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `802`
+		//  Measured:  `781`
 		//  Estimated: `5996`
-		// Minimum execution time: 38_310_000 picoseconds.
-		Weight::from_parts(39_777_000, 0)
+		// Minimum execution time: 38_327_000 picoseconds.
+		Weight::from_parts(39_866_000, 0)
 			.saturating_add(Weight::from_parts(0, 5996))
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(5))
@@ -270,13 +278,13 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// The range of component `m` is `[1, 3]`.
 	fn claim_revenue(m: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `671`
+		//  Measured:  `649`
 		//  Estimated: `6196 + m * (2520 ±0)`
-		// Minimum execution time: 65_960_000 picoseconds.
-		Weight::from_parts(66_194_985, 0)
+		// Minimum execution time: 68_467_000 picoseconds.
+		Weight::from_parts(69_050_766, 0)
 			.saturating_add(Weight::from_parts(0, 6196))
-			// Standard Error: 42_455
-			.saturating_add(Weight::from_parts(1_808_497, 0).saturating_mul(m.into()))
+			// Standard Error: 47_529
+			.saturating_add(Weight::from_parts(1_772_345, 0).saturating_mul(m.into()))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into())))
 			.saturating_add(T::DbWeight::get().writes(5))
@@ -286,23 +294,15 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
 	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
-	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
-	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
-	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
-	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn purchase_credit() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `321`
-		//  Estimated: `3786`
-		// Minimum execution time: 69_918_000 picoseconds.
-		Weight::from_parts(72_853_000, 0)
-			.saturating_add(Weight::from_parts(0, 3786))
-			.saturating_add(T::DbWeight::get().reads(6))
-			.saturating_add(T::DbWeight::get().writes(3))
+		//  Measured:  `103`
+		//  Estimated: `3593`
+		// Minimum execution time: 60_373_000 picoseconds.
+		Weight::from_parts(62_315_000, 0)
+			.saturating_add(Weight::from_parts(0, 3593))
+			.saturating_add(T::DbWeight::get().reads(2))
+			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	/// Storage: `Broker::Status` (r:1 w:0)
 	/// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`)
@@ -310,10 +310,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn drop_region() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `466`
+		//  Measured:  `445`
 		//  Estimated: `3551`
-		// Minimum execution time: 44_775_000 picoseconds.
-		Weight::from_parts(58_978_000, 0)
+		// Minimum execution time: 40_559_000 picoseconds.
+		Weight::from_parts(48_345_000, 0)
 			.saturating_add(Weight::from_parts(0, 3551))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -326,10 +326,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	fn drop_contribution() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `463`
+		//  Measured:  `442`
 		//  Estimated: `3533`
-		// Minimum execution time: 67_098_000 picoseconds.
-		Weight::from_parts(93_626_000, 0)
+		// Minimum execution time: 53_667_000 picoseconds.
+		Weight::from_parts(60_966_000, 0)
 			.saturating_add(Weight::from_parts(0, 3533))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -344,10 +344,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn drop_history() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `979`
+		//  Measured:  `855`
 		//  Estimated: `3593`
-		// Minimum execution time: 89_463_000 picoseconds.
-		Weight::from_parts(113_286_000, 0)
+		// Minimum execution time: 63_550_000 picoseconds.
+		Weight::from_parts(69_714_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(4))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -358,44 +358,36 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::PotentialRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`)
 	fn drop_renewal() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `556`
+		//  Measured:  `535`
 		//  Estimated: `4698`
-		// Minimum execution time: 42_073_000 picoseconds.
-		Weight::from_parts(52_211_000, 0)
+		Weight::from_parts(39_990_000, 0)
 			.saturating_add(Weight::from_parts(0, 4698))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
 	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
 	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
-	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
-	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
-	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
-	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	/// The range of component `n` is `[0, 1000]`.
-	fn request_core_count(_n: u32, ) -> Weight {
+	fn request_core_count(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `74`
-		//  Estimated: `3539`
-		// Minimum execution time: 22_937_000 picoseconds.
-		Weight::from_parts(23_898_154, 0)
-			.saturating_add(Weight::from_parts(0, 3539))
-			.saturating_add(T::DbWeight::get().reads(5))
-			.saturating_add(T::DbWeight::get().writes(2))
+		//  Measured:  `0`
+		//  Estimated: `3465`
+		// Minimum execution time: 13_953_000 picoseconds.
+		Weight::from_parts(17_419_892, 0)
+			.saturating_add(Weight::from_parts(0, 3465))
+			// Standard Error: 54
+			.saturating_add(Weight::from_parts(139, 0).saturating_mul(n.into()))
+			.saturating_add(T::DbWeight::get().reads(1))
 	}
 	/// Storage: `Broker::CoreCountInbox` (r:1 w:1)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
 	/// The range of component `n` is `[0, 1000]`.
 	fn process_core_count(_n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `266`
+		//  Measured:  `208`
 		//  Estimated: `1487`
-		// Minimum execution time: 7_650_000 picoseconds.
-		Weight::from_parts(8_166_809, 0)
+		// Minimum execution time: 6_820_000 picoseconds.
+		Weight::from_parts(7_247_418, 0)
 			.saturating_add(Weight::from_parts(0, 1487))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -408,10 +400,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn process_revenue() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `461`
+		//  Measured:  `440`
 		//  Estimated: `6196`
-		// Minimum execution time: 53_023_000 picoseconds.
-		Weight::from_parts(54_564_000, 0)
+		// Minimum execution time: 55_301_000 picoseconds.
+		Weight::from_parts(56_710_000, 0)
 			.saturating_add(Weight::from_parts(0, 6196))
 			.saturating_add(T::DbWeight::get().reads(4))
 			.saturating_add(T::DbWeight::get().writes(4))
@@ -441,13 +433,13 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// The range of component `n` is `[0, 1000]`.
 	fn rotate_sale(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `16480`
+		//  Measured:  `16294`
 		//  Estimated: `69404 + n * (8 ±1)`
-		// Minimum execution time: 29_313_000 picoseconds.
-		Weight::from_parts(746_062_644, 0)
+		// Minimum execution time: 28_821_000 picoseconds.
+		Weight::from_parts(985_823_650, 0)
 			.saturating_add(Weight::from_parts(0, 69404))
-			// Standard Error: 22_496
-			.saturating_add(Weight::from_parts(1_545_204, 0).saturating_mul(n.into()))
+			// Standard Error: 33_666
+			.saturating_add(Weight::from_parts(1_561_298, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(44))
 			.saturating_add(T::DbWeight::get().writes(57))
 			.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into())))
@@ -459,10 +451,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`)
 	fn process_pool() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `42`
+		//  Measured:  `0`
 		//  Estimated: `3493`
-		// Minimum execution time: 7_625_000 picoseconds.
-		Weight::from_parts(7_910_000, 0)
+		// Minimum execution time: 5_904_000 picoseconds.
+		Weight::from_parts(6_152_000, 0)
 			.saturating_add(Weight::from_parts(0, 3493))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -473,43 +465,26 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Workload` (`max_values`: None, `max_size`: Some(1212), added: 3687, mode: `MaxEncodedLen`)
 	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
 	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
-	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
-	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
-	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
-	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn process_core_schedule() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `1321`
-		//  Estimated: `4786`
-		// Minimum execution time: 36_572_000 picoseconds.
-		Weight::from_parts(37_316_000, 0)
-			.saturating_add(Weight::from_parts(0, 4786))
-			.saturating_add(T::DbWeight::get().reads(7))
-			.saturating_add(T::DbWeight::get().writes(4))
+		//  Measured:  `1223`
+		//  Estimated: `4688`
+		// Minimum execution time: 28_080_000 picoseconds.
+		Weight::from_parts(28_560_000, 0)
+			.saturating_add(Weight::from_parts(0, 4688))
+			.saturating_add(T::DbWeight::get().reads(3))
+			.saturating_add(T::DbWeight::get().writes(2))
 	}
 	/// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0)
 	/// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1)
-	/// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0)
-	/// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0)
-	/// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1)
-	/// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn request_revenue_info_at() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `74`
-		//  Estimated: `3539`
-		// Minimum execution time: 18_362_000 picoseconds.
-		Weight::from_parts(18_653_000, 0)
-			.saturating_add(Weight::from_parts(0, 3539))
-			.saturating_add(T::DbWeight::get().reads(5))
-			.saturating_add(T::DbWeight::get().writes(2))
+		//  Measured:  `0`
+		//  Estimated: `3465`
+		// Minimum execution time: 8_883_000 picoseconds.
+		Weight::from_parts(11_990_000, 0)
+			.saturating_add(Weight::from_parts(0, 3465))
+			.saturating_add(T::DbWeight::get().reads(1))
 	}
 	/// Storage: `Broker::CoreCountInbox` (r:0 w:1)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
@@ -517,8 +492,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 2_193_000 picoseconds.
-		Weight::from_parts(2_393_000, 0)
+		// Minimum execution time: 2_010_000 picoseconds.
+		Weight::from_parts(2_138_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -528,8 +503,8 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 2_344_000 picoseconds.
-		Weight::from_parts(2_486_000, 0)
+		// Minimum execution time: 2_076_000 picoseconds.
+		Weight::from_parts(2_241_000, 0)
 			.saturating_add(Weight::from_parts(0, 0))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -545,11 +520,11 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `ParachainSystem::ValidationData` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
 	fn do_tick_base() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `408`
-		//  Estimated: `1893`
-		// Minimum execution time: 15_443_000 picoseconds.
-		Weight::from_parts(15_753_000, 0)
-			.saturating_add(Weight::from_parts(0, 1893))
+		//  Measured:  `327`
+		//  Estimated: `1812`
+		// Minimum execution time: 12_724_000 picoseconds.
+		Weight::from_parts(13_255_000, 0)
+			.saturating_add(Weight::from_parts(0, 1812))
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
@@ -563,10 +538,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn force_reserve() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `11125`
+		//  Measured:  `11120`
 		//  Estimated: `13506`
-		// Minimum execution time: 31_464_000 picoseconds.
-		Weight::from_parts(32_798_000, 0)
+		// Minimum execution time: 38_508_000 picoseconds.
+		Weight::from_parts(39_408_000, 0)
 			.saturating_add(Weight::from_parts(0, 13506))
 			.saturating_add(T::DbWeight::get().reads(3))
 			.saturating_add(T::DbWeight::get().writes(3))
@@ -575,10 +550,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(81), added: 576, mode: `MaxEncodedLen`)
 	fn swap_leases() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `150`
+		//  Measured:  `88`
 		//  Estimated: `1566`
-		// Minimum execution time: 8_637_000 picoseconds.
-		Weight::from_parts(8_883_000, 0)
+		// Minimum execution time: 5_092_000 picoseconds.
+		Weight::from_parts(5_340_000, 0)
 			.saturating_add(Weight::from_parts(0, 1566))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -601,10 +576,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn enable_auto_renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `1451`
+		//  Measured:  `1370`
 		//  Estimated: `6196`
-		// Minimum execution time: 120_585_000 picoseconds.
-		Weight::from_parts(148_755_000, 0)
+		// Minimum execution time: 143_548_000 picoseconds.
+		Weight::from_parts(150_897_000, 0)
 			.saturating_add(Weight::from_parts(0, 6196))
 			.saturating_add(T::DbWeight::get().reads(8))
 			.saturating_add(T::DbWeight::get().writes(6))
@@ -613,10 +588,10 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 	/// Proof: `Broker::AutoRenewals` (`max_values`: Some(1), `max_size`: Some(201), added: 696, mode: `MaxEncodedLen`)
 	fn disable_auto_renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `506`
+		//  Measured:  `485`
 		//  Estimated: `1686`
-		// Minimum execution time: 18_235_000 picoseconds.
-		Weight::from_parts(19_113_000, 0)
+		// Minimum execution time: 17_438_000 picoseconds.
+		Weight::from_parts(18_326_000, 0)
 			.saturating_add(Weight::from_parts(0, 1686))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -627,9 +602,21 @@ impl<T: frame_system::Config> pallet_broker::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `103`
 		//  Estimated: `3593`
-		// Minimum execution time: 4_863_000 picoseconds.
-		Weight::from_parts(5_045_000, 0)
+		// Minimum execution time: 4_804_000 picoseconds.
+		Weight::from_parts(5_101_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(1))
 	}
+	/// Storage: `Broker::Workplan` (r:1 w:1)
+	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
+	fn remove_assignment() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `581`
+		//  Estimated: `4681`
+		// Minimum execution time: 18_102_000 picoseconds.
+		Weight::from_parts(18_785_000, 0)
+			.saturating_add(Weight::from_parts(0, 4681))
+			.saturating_add(T::DbWeight::get().reads(1))
+			.saturating_add(T::DbWeight::get().writes(1))
+	}
 }
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_utility.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_utility.rs
index f2c40f33711859feb6042c0dd15f5328fc3d4641..7ca8e00c2a7ddbed1b0e6b7a82b48ac82edd8cff 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_utility.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_utility.rs
@@ -99,6 +99,11 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
 			// Standard Error: 740
 			.saturating_add(Weight::from_parts(2_800_888, 0).saturating_mul(c.into()))
 	}
+
+	fn dispatch_as_fallible() -> Weight {
+		Default::default()
+	}
+
 	fn if_else() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs
index a124c1978309e5ed4aca61f14588473c9eaea4d2..bff798259dfeb1bc623a1c9508e2d3b8fa75981d 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs
@@ -42,12 +42,12 @@ use xcm_builder::{
 	AccountId32Aliases, AliasChildLocation, AliasOriginRootUsingFilter,
 	AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
 	AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
-	DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily,
-	EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter, HashedDescription, IsConcrete,
-	NonFungibleAdapter, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SendXcmFeeToAccount,
-	SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
-	SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId,
-	UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
+	DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal,
+	DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter,
+	HashedDescription, IsConcrete, NonFungibleAdapter, ParentAsSuperuser, ParentIsPreset,
+	RelayChainAsNative, SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
+	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
+	TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
 	XcmFeeManagerFromComponents,
 };
 use xcm_executor::XcmExecutor;
@@ -154,7 +154,7 @@ impl Contains<Location> for FellowsPlurality {
 
 pub type Barrier = TrailingSetTopicAsId<
 	DenyThenTry<
-		DenyReserveTransferToRelayChain,
+		DenyRecursively<DenyReserveTransferToRelayChain>,
 		(
 			// Allow local users to buy weight credit.
 			TakeWeightCredit,
diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs
index 4de0c4976ffda93d185da76b40c7f68bf114bb00..bc344dd7766872ddb4a0c48d587e8ad557d35d0a 100644
--- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs
@@ -459,6 +459,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs
index 3766626ba4f632cd8603b51583f41a2782b207bd..4a71735853a86dad1f63376d25f314efbd53a0cd 100644
--- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs
@@ -25,7 +25,7 @@ pub mod xcm_config;
 extern crate alloc;
 
 use alloc::{vec, vec::Vec};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
 use cumulus_primitives_core::{AggregateMessageOrigin, ClaimQueueOffset, CoreSelector, ParaId};
 use frame_support::{
@@ -432,6 +432,7 @@ impl pallet_multisig::Config for Runtime {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	MaxEncodedLen,
 	scale_info::TypeInfo,
@@ -901,6 +902,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/people.rs b/cumulus/parachains/runtimes/people/people-rococo/src/people.rs
index 690bb974bd17a8016207f0c0ddf93228bbc6b6fc..a841d309153a813c1193e3543265f11b8e2cfd2d 100644
--- a/cumulus/parachains/runtimes/people/people-rococo/src/people.rs
+++ b/cumulus/parachains/runtimes/people/people-rococo/src/people.rs
@@ -88,6 +88,7 @@ pub enum IdentityField {
 	CloneNoBound,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	EqNoBound,
 	MaxEncodedLen,
 	PartialEqNoBound,
diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_utility.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_utility.rs
index f30f0776952625dd9c9fa6f5dff2894ab71aa591..0871b257d39c308772e40fe604b61a557bc1d0a8 100644
--- a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_utility.rs
+++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_utility.rs
@@ -96,6 +96,11 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
 			// Standard Error: 3_915
 			.saturating_add(Weight::from_parts(4_372_646, 0).saturating_mul(c.into()))
 	}
+
+	fn dispatch_as_fallible() -> Weight {
+		Default::default()
+	}
+
 	fn if_else() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs
index 724d87587c6c51ac5d7b564862d0694f0dd7141b..9e89cd465e45c06c523a0fccd508a816916f0880 100644
--- a/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs
+++ b/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs
@@ -38,10 +38,10 @@ use xcm::latest::{prelude::*, ROCOCO_GENESIS_HASH};
 use xcm_builder::{
 	AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
 	AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
-	DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily,
-	DescribeTerminus, EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter,
-	HashedDescription, IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
-	SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
+	DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal,
+	DescribeFamily, DescribeTerminus, EnsureXcmOrigin, FrameTransactionalProcessor,
+	FungibleAdapter, HashedDescription, IsConcrete, ParentAsSuperuser, ParentIsPreset,
+	RelayChainAsNative, SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
 	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
 	TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
 	XcmFeeManagerFromComponents,
@@ -153,7 +153,7 @@ impl Contains<Location> for ParentOrParentsPlurality {
 
 pub type Barrier = TrailingSetTopicAsId<
 	DenyThenTry<
-		DenyReserveTransferToRelayChain,
+		DenyRecursively<DenyReserveTransferToRelayChain>,
 		(
 			// Allow local users to buy weight credit.
 			TakeWeightCredit,
diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs
index 34ab85f3d0cdd81d593d24a96ac4a3bbb4c37144..7107aba0a576fd8589972061ba54bcc7467c071b 100644
--- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs
@@ -25,7 +25,7 @@ pub mod xcm_config;
 extern crate alloc;
 
 use alloc::{vec, vec::Vec};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
 use cumulus_primitives_core::{AggregateMessageOrigin, ClaimQueueOffset, CoreSelector, ParaId};
 use frame_support::{
@@ -431,6 +431,7 @@ impl pallet_multisig::Config for Runtime {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	MaxEncodedLen,
 	scale_info::TypeInfo,
@@ -899,6 +900,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
diff --git a/cumulus/parachains/runtimes/people/people-westend/src/people.rs b/cumulus/parachains/runtimes/people/people-westend/src/people.rs
index 47551f6d4bdc3475ad7c377a0fe423d0755e30f7..63cf803e7d3cb541977cb0537d701d1296ba9c2c 100644
--- a/cumulus/parachains/runtimes/people/people-westend/src/people.rs
+++ b/cumulus/parachains/runtimes/people/people-westend/src/people.rs
@@ -88,6 +88,7 @@ pub enum IdentityField {
 	CloneNoBound,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	EqNoBound,
 	MaxEncodedLen,
 	PartialEqNoBound,
diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_utility.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_utility.rs
index c7f98f70fdd84bd88565bb9c133db6c2c36f7b4c..d8def37891d4dfe4f41d6a2f71b5ef0afd5a8e1c 100644
--- a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_utility.rs
+++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_utility.rs
@@ -96,6 +96,11 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
 			// Standard Error: 7_605
 			.saturating_add(Weight::from_parts(4_306_193, 0).saturating_mul(c.into()))
 	}
+
+	fn dispatch_as_fallible() -> Weight {
+		Default::default()
+	}
+
 	fn if_else() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
diff --git a/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs
index 7eaa43c05b208fd9107976572fbd71e1e5b4cd27..bd319e3ac3b4812a00465ec5feb6b03541afe7a9 100644
--- a/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs
+++ b/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs
@@ -39,10 +39,10 @@ use xcm_builder::{
 	AccountId32Aliases, AliasChildLocation, AliasOriginRootUsingFilter,
 	AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
 	AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
-	DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily,
-	DescribeTerminus, EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter,
-	HashedDescription, IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
-	SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
+	DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal,
+	DescribeFamily, DescribeTerminus, EnsureXcmOrigin, FrameTransactionalProcessor,
+	FungibleAdapter, HashedDescription, IsConcrete, ParentAsSuperuser, ParentIsPreset,
+	RelayChainAsNative, SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
 	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
 	TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
 	XcmFeeManagerFromComponents,
@@ -162,7 +162,7 @@ impl Contains<Location> for FellowsPlurality {
 
 pub type Barrier = TrailingSetTopicAsId<
 	DenyThenTry<
-		DenyReserveTransferToRelayChain,
+		DenyRecursively<DenyReserveTransferToRelayChain>,
 		(
 			// Allow local users to buy weight credit.
 			TakeWeightCredit,
diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs
index dfccf3ec9860db1c50d88ca78986010f0c805a39..e5c1dbb936558d6613dc367b8b652bf6361de8ee 100644
--- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs
+++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs
@@ -1140,6 +1140,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
diff --git a/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs b/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs
index 636c845271d548485c7fafa1e290d7bab2c0892d..858275d189a67ee13131ef78934275b5e7cb3e02 100644
--- a/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs
+++ b/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs
@@ -206,6 +206,7 @@ macro_rules! impl_node_runtime_apis {
 					unimplemented!()
 				}
 
+				#[allow(non_local_definitions)]
 				fn dispatch_benchmark(
 					_: frame_benchmarking::BenchmarkConfig
 				) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, String> {
diff --git a/cumulus/polkadot-parachain/src/chain_spec/coretime.rs b/cumulus/polkadot-parachain/src/chain_spec/coretime.rs
index 0b61944444701109cd35c3520591423927fa6275..9894b743805e0d15d7a799260fb1cd35e5f73702 100644
--- a/cumulus/polkadot-parachain/src/chain_spec/coretime.rs
+++ b/cumulus/polkadot-parachain/src/chain_spec/coretime.rs
@@ -145,17 +145,13 @@ pub fn chain_type_name(chain_type: &ChainType) -> Cow<str> {
 
 /// Sub-module for Rococo setup.
 pub mod rococo {
-	use super::{chain_type_name, CoretimeRuntimeType, ParaId};
-	use crate::chain_spec::SAFE_XCM_VERSION;
-	use parachains_common::{AccountId, AuraId, Balance};
+	use super::{chain_type_name, CoretimeRuntimeType};
 	use polkadot_omni_node_lib::chain_spec::{Extensions, GenericChainSpec};
 	use sc_chain_spec::ChainType;
-	use sp_keyring::Sr25519Keyring;
 
 	pub(crate) const CORETIME_ROCOCO: &str = "coretime-rococo";
 	pub(crate) const CORETIME_ROCOCO_LOCAL: &str = "coretime-rococo-local";
 	pub(crate) const CORETIME_ROCOCO_DEVELOPMENT: &str = "coretime-rococo-dev";
-	const CORETIME_ROCOCO_ED: Balance = coretime_rococo_runtime::ExistentialDeposit::get();
 
 	pub fn local_config(runtime_type: CoretimeRuntimeType, relay_chain: &str) -> GenericChainSpec {
 		// Rococo defaults
@@ -182,72 +178,26 @@ pub mod rococo {
 		)
 		.with_name(&chain_name)
 		.with_id(runtime_type.into())
-		.with_chain_type(chain_type)
-		.with_genesis_config_patch(genesis(
-			// initial collators.
-			vec![(Sr25519Keyring::Alice.to_account_id(), Sr25519Keyring::Alice.public().into())],
-			vec![
-				Sr25519Keyring::Alice.to_account_id(),
-				Sr25519Keyring::Bob.to_account_id(),
-				Sr25519Keyring::AliceStash.to_account_id(),
-				Sr25519Keyring::BobStash.to_account_id(),
-			],
-			para_id,
-		))
+		.with_chain_type(chain_type.clone())
+		.with_genesis_config_preset_name(match chain_type {
+			ChainType::Development => sp_genesis_builder::DEV_RUNTIME_PRESET,
+			ChainType::Local => sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET,
+			_ => panic!("chain_type: {chain_type:?} not supported here!"),
+		})
 		.with_properties(properties)
 		.build()
 	}
-
-	fn genesis(
-		invulnerables: Vec<(AccountId, AuraId)>,
-		endowed_accounts: Vec<AccountId>,
-		id: ParaId,
-	) -> serde_json::Value {
-		serde_json::json!({
-			"balances": {
-				"balances": endowed_accounts.iter().cloned().map(|k| (k, CORETIME_ROCOCO_ED * 4096)).collect::<Vec<_>>(),
-			},
-			"parachainInfo": {
-				"parachainId": id,
-			},
-			"collatorSelection": {
-				"invulnerables": invulnerables.iter().cloned().map(|(acc, _)| acc).collect::<Vec<_>>(),
-				"candidacyBond": CORETIME_ROCOCO_ED * 16,
-			},
-			"session": {
-				"keys": invulnerables
-					.into_iter()
-					.map(|(acc, aura)| {
-						(
-							acc.clone(),                                   // account id
-							acc,                                           // validator id
-							coretime_rococo_runtime::SessionKeys { aura }, // session keys
-						)
-					})
-					.collect::<Vec<_>>(),
-			},
-			"polkadotXcm": {
-				"safeXcmVersion": Some(SAFE_XCM_VERSION),
-			},
-			"sudo": {
-				"key": Some(Sr25519Keyring::Alice.to_account_id()),
-			},
-		})
-	}
 }
 
 /// Sub-module for Westend setup.
 pub mod westend {
-	use super::{chain_type_name, CoretimeRuntimeType, GenericChainSpec, ParaId};
-	use crate::chain_spec::SAFE_XCM_VERSION;
-	use parachains_common::{AccountId, AuraId, Balance};
+	use super::{chain_type_name, CoretimeRuntimeType, GenericChainSpec};
 	use polkadot_omni_node_lib::chain_spec::Extensions;
-	use sp_keyring::Sr25519Keyring;
+	use sc_chain_spec::ChainType;
 
 	pub(crate) const CORETIME_WESTEND: &str = "coretime-westend";
 	pub(crate) const CORETIME_WESTEND_LOCAL: &str = "coretime-westend-local";
 	pub(crate) const CORETIME_WESTEND_DEVELOPMENT: &str = "coretime-westend-dev";
-	const CORETIME_WESTEND_ED: Balance = coretime_westend_runtime::ExistentialDeposit::get();
 
 	pub fn local_config(runtime_type: CoretimeRuntimeType, relay_chain: &str) -> GenericChainSpec {
 		// westend defaults
@@ -267,55 +217,15 @@ pub mod westend {
 		)
 		.with_name(&chain_name)
 		.with_id(runtime_type.into())
-		.with_chain_type(chain_type)
-		.with_genesis_config_patch(genesis(
-			// initial collators.
-			vec![(Sr25519Keyring::Alice.to_account_id(), Sr25519Keyring::Alice.public().into())],
-			vec![
-				Sr25519Keyring::Alice.to_account_id(),
-				Sr25519Keyring::Bob.to_account_id(),
-				Sr25519Keyring::AliceStash.to_account_id(),
-				Sr25519Keyring::BobStash.to_account_id(),
-			],
-			para_id,
-		))
+		.with_chain_type(chain_type.clone())
+		.with_genesis_config_preset_name(match chain_type {
+			ChainType::Development => sp_genesis_builder::DEV_RUNTIME_PRESET,
+			ChainType::Local => sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET,
+			_ => panic!("chain_type: {chain_type:?} not supported here!"),
+		})
 		.with_properties(properties)
 		.build()
 	}
-
-	fn genesis(
-		invulnerables: Vec<(AccountId, AuraId)>,
-		endowed_accounts: Vec<AccountId>,
-		id: ParaId,
-	) -> serde_json::Value {
-		serde_json::json!({
-			"balances": {
-				"balances": endowed_accounts.iter().cloned().map(|k| (k, CORETIME_WESTEND_ED * 4096)).collect::<Vec<_>>(),
-			},
-			"parachainInfo": {
-				"parachainId": id,
-			},
-			"collatorSelection": {
-				"invulnerables": invulnerables.iter().cloned().map(|(acc, _)| acc).collect::<Vec<_>>(),
-				"candidacyBond": CORETIME_WESTEND_ED * 16,
-			},
-			"session": {
-				"keys": invulnerables
-					.into_iter()
-					.map(|(acc, aura)| {
-						(
-							acc.clone(),                                    // account id
-							acc,                                            // validator id
-							coretime_westend_runtime::SessionKeys { aura }, // session keys
-						)
-					})
-					.collect::<Vec<_>>(),
-			},
-			"polkadotXcm": {
-				"safeXcmVersion": Some(SAFE_XCM_VERSION),
-			}
-		})
-	}
 }
 
 pub mod kusama {
diff --git a/cumulus/primitives/core/src/lib.rs b/cumulus/primitives/core/src/lib.rs
index 9169c12d8eb133b45b8c3283345ee9b91f574b61..c2b0b9b48ea4ca5901bfec6d36bd2cebd8c28864 100644
--- a/cumulus/primitives/core/src/lib.rs
+++ b/cumulus/primitives/core/src/lib.rs
@@ -21,7 +21,7 @@
 extern crate alloc;
 
 use alloc::vec::Vec;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use polkadot_parachain_primitives::primitives::HeadData;
 use scale_info::TypeInfo;
 use sp_runtime::RuntimeDebug;
@@ -85,7 +85,9 @@ impl From<MessageSendError> for &'static str {
 }
 
 /// The origin of an inbound message.
-#[derive(Encode, Decode, MaxEncodedLen, Clone, Eq, PartialEq, TypeInfo, Debug)]
+#[derive(
+	Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, Clone, Eq, PartialEq, TypeInfo, Debug,
+)]
 pub enum AggregateMessageOrigin {
 	/// The message came from the para-chain itself.
 	Here,
diff --git a/cumulus/primitives/parachain-inherent/src/lib.rs b/cumulus/primitives/parachain-inherent/src/lib.rs
index 4e6e739bb8501ed013de0586fabf7bfc3b7593e7..b5e70c442dd2457513b60af026b5d46b0010a4ba 100644
--- a/cumulus/primitives/parachain-inherent/src/lib.rs
+++ b/cumulus/primitives/parachain-inherent/src/lib.rs
@@ -42,7 +42,15 @@ use sp_inherents::InherentIdentifier;
 pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"sysi1337";
 
 /// The inherent data that is passed by the collator to the parachain runtime.
-#[derive(codec::Encode, codec::Decode, sp_core::RuntimeDebug, Clone, PartialEq, TypeInfo)]
+#[derive(
+	codec::Encode,
+	codec::Decode,
+	codec::DecodeWithMemTracking,
+	sp_core::RuntimeDebug,
+	Clone,
+	PartialEq,
+	TypeInfo,
+)]
 pub struct ParachainInherentData {
 	pub validation_data: PersistedValidationData,
 	/// A storage proof of a predefined set of keys from the relay-chain.
diff --git a/docs/contributor/CONTRIBUTING.md b/docs/contributor/CONTRIBUTING.md
index 53f42b9ae4fb41e995c16ef03f0abcc61a030684..fa391a35fdd735652aa78706fe74ea64f58660a4 100644
--- a/docs/contributor/CONTRIBUTING.md
+++ b/docs/contributor/CONTRIBUTING.md
@@ -7,6 +7,9 @@ The `Polkadot SDK` project is an **OPENISH Open Source Project**
 Individuals making significant and valuable contributions are given commit-access to the project. Contributions are done
 via pull-requests and need to be approved by the maintainers.
 
+> **Note:** Contributors who are part of the organization do not need to fork the repository. They can create a branch
+> directly in the repository to send a pull request.
+
 ## Rules
 
 There are a few basic ground-rules for contributors (including the maintainer(s) of the project):
diff --git a/docs/contributor/container.md b/docs/contributor/container.md
index e387f568d7b51d07aa8e954cac70d69dc0ea0054..bc05bf8b54a50227cd179fadfc3b7314f668926a 100644
--- a/docs/contributor/container.md
+++ b/docs/contributor/container.md
@@ -24,7 +24,7 @@ The command below allows building a Linux binary without having to even install
 docker run --rm -it \
     -w /polkadot-sdk \
     -v $(pwd):/polkadot-sdk \
-    docker.io/paritytech/ci-unified:bullseye-1.81.0-2024-11-19-v202411281558 \
+    docker.io/paritytech/ci-unified:bullseye-1.84.1-2025-01-28-v202502131220 \
     cargo build --release --locked -p polkadot-parachain-bin --bin polkadot-parachain
 sudo chown -R $(id -u):$(id -g) target/
 ```
diff --git a/docs/sdk/src/guides/your_first_node.rs b/docs/sdk/src/guides/your_first_node.rs
index 3c782e4793bab422a0ed06e8705ad58457910414..90fa8639f75776042b2f176bebab039f456d4ca5 100644
--- a/docs/sdk/src/guides/your_first_node.rs
+++ b/docs/sdk/src/guides/your_first_node.rs
@@ -305,4 +305,33 @@ mod tests {
 			test_runtime_preset(FIRST_RUNTIME, 1000, preset);
 		});
 	}
+
+	#[test]
+	fn omni_node_dev_mode_works() {
+		//Omni Node in dev mode works with parachain's template `dev_chain_spec`
+		let dev_chain_spec = std::env::current_dir()
+			.unwrap()
+			.parent()
+			.unwrap()
+			.parent()
+			.unwrap()
+			.join("templates")
+			.join("parachain")
+			.join("dev_chain_spec.json");
+
+		maybe_build_omni_node();
+		let omni_node = find_release_binary(OMNI_NODE).unwrap();
+
+		let output = Command::new(omni_node)
+			.arg("--dev")
+			.args(["--chain", dev_chain_spec.to_str().unwrap()])
+			.timeout(std::time::Duration::from_secs(70))
+			.output()
+			.unwrap();
+
+		// atleast  blocks should be imported
+		assert!(String::from_utf8(output.stderr)
+			.unwrap()
+			.contains(format!("Imported #{}", 7).to_string().as_str()));
+	}
 }
diff --git a/docs/sdk/src/lib.rs b/docs/sdk/src/lib.rs
index d96239ca89424e8a475ab445e488f78ae101aa9e..c1aefe435354d43fb867c1909c9538a50eee3529 100644
--- a/docs/sdk/src/lib.rs
+++ b/docs/sdk/src/lib.rs
@@ -23,6 +23,8 @@
 #![doc = simple_mermaid::mermaid!("../../mermaid/IA.mmd")]
 #![warn(rustdoc::broken_intra_doc_links)]
 #![warn(rustdoc::private_intra_doc_links)]
+// Frame macros reference features which this crate does not have
+#![allow(unexpected_cfgs)]
 #![doc(html_favicon_url = "https://polkadot.com/favicon.ico")]
 #![doc(
 	html_logo_url = "https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/docs/images/Polkadot_Logo_Horizontal_Pink_White.png"
diff --git a/docs/sdk/src/reference_docs/frame_origin.rs b/docs/sdk/src/reference_docs/frame_origin.rs
index a2aac7dd3554fb614658f71a2bf88573379bbf9d..4610eede8df8a89753e4e0c7d7a17f9cca8c55a6 100644
--- a/docs/sdk/src/reference_docs/frame_origin.rs
+++ b/docs/sdk/src/reference_docs/frame_origin.rs
@@ -167,7 +167,17 @@ pub mod pallet_with_custom_origin {
 	#[docify::export(custom_origin)]
 	/// A dummy custom origin.
 	#[pallet::origin]
-	#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]
+	#[derive(
+		PartialEq,
+		Eq,
+		Clone,
+		RuntimeDebug,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		TypeInfo,
+		MaxEncodedLen,
+	)]
 	pub enum Origin {
 		/// If all holders of a particular NFT have agreed upon this.
 		AllNftHolders,
diff --git a/docs/sdk/src/reference_docs/frame_runtime_types.rs b/docs/sdk/src/reference_docs/frame_runtime_types.rs
index ec7196cea662631ba05536ad6c15f3428457e6e1..893d85e89b1f3cf33f9411ea67d907a5dc2b74cb 100644
--- a/docs/sdk/src/reference_docs/frame_runtime_types.rs
+++ b/docs/sdk/src/reference_docs/frame_runtime_types.rs
@@ -168,7 +168,17 @@ pub mod pallet_foo {
 	pub trait Config: frame_system::Config {}
 
 	#[pallet::origin]
-	#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]
+	#[derive(
+		PartialEq,
+		Eq,
+		Clone,
+		RuntimeDebug,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		TypeInfo,
+		MaxEncodedLen,
+	)]
 	pub enum Origin {
 		A,
 		B,
diff --git a/polkadot/core-primitives/src/lib.rs b/polkadot/core-primitives/src/lib.rs
index 666636def46048ad2d97c48d5b82591df3108fcc..fc7db64ed430c1a0aa2c6a0f230606eb93842e41 100644
--- a/polkadot/core-primitives/src/lib.rs
+++ b/polkadot/core-primitives/src/lib.rs
@@ -22,7 +22,7 @@
 
 extern crate alloc;
 
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use scale_info::TypeInfo;
 use sp_runtime::{
 	generic,
@@ -65,7 +65,20 @@ pub type Hash = sp_core::H256;
 /// This type is produced by `CandidateReceipt::hash`.
 ///
 /// This type makes it easy to enforce that a hash is a candidate hash on the type level.
-#[derive(Clone, Copy, Encode, Decode, Hash, Eq, PartialEq, Default, PartialOrd, Ord, TypeInfo)]
+#[derive(
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Hash,
+	Eq,
+	PartialEq,
+	Default,
+	PartialOrd,
+	Ord,
+	TypeInfo,
+)]
 pub struct CandidateHash(pub Hash);
 
 #[cfg(feature = "std")]
@@ -125,7 +138,9 @@ pub type DownwardMessage = alloc::vec::Vec<u8>;
 
 /// A wrapped version of `DownwardMessage`. The difference is that it has attached the block number
 /// when the message was sent.
-#[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq, TypeInfo)]
+#[derive(
+	Encode, Decode, DecodeWithMemTracking, Clone, sp_runtime::RuntimeDebug, PartialEq, TypeInfo,
+)]
 pub struct InboundDownwardMessage<BlockNumber = crate::BlockNumber> {
 	/// The block number at which these messages were put into the downward message queue.
 	pub sent_at: BlockNumber,
@@ -134,7 +149,9 @@ pub struct InboundDownwardMessage<BlockNumber = crate::BlockNumber> {
 }
 
 /// An HRMP message seen from the perspective of a recipient.
-#[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq, TypeInfo)]
+#[derive(
+	Encode, Decode, DecodeWithMemTracking, Clone, sp_runtime::RuntimeDebug, PartialEq, TypeInfo,
+)]
 pub struct InboundHrmpMessage<BlockNumber = crate::BlockNumber> {
 	/// The block number at which this message was sent.
 	/// Specifically, it is the block number at which the candidate that sends this message was
@@ -145,7 +162,17 @@ pub struct InboundHrmpMessage<BlockNumber = crate::BlockNumber> {
 }
 
 /// An HRMP message seen from the perspective of a sender.
-#[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq, Eq, Hash, TypeInfo)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Clone,
+	sp_runtime::RuntimeDebug,
+	PartialEq,
+	Eq,
+	Hash,
+	TypeInfo,
+)]
 pub struct OutboundHrmpMessage<Id> {
 	/// The para that will get this message in its downward message queue.
 	pub recipient: Id,
diff --git a/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs b/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs
index 5a9b8efa2a13b60144a51a8fb9b26ec5358d8e32..da3715e387334fe9bafa11b3cb7162d34473773c 100644
--- a/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs
+++ b/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs
@@ -776,6 +776,7 @@ async fn answer_expected_hypothetical_membership_request(
 	)
 }
 
+/// Assert that the correct peer is reported.
 #[macro_export]
 macro_rules! assert_peer_reported {
 	($virtual_overseer:expr, $peer_id:expr, $rep_change:expr $(,)*) => {
diff --git a/polkadot/node/overseer/src/lib.rs b/polkadot/node/overseer/src/lib.rs
index a8d0ab90f6b91d35fe4967960b9e73ec94a0d1db..92989e2b520e9f131060d282047b06a2e8f84b8f 100644
--- a/polkadot/node/overseer/src/lib.rs
+++ b/polkadot/node/overseer/src/lib.rs
@@ -60,7 +60,8 @@
 // unused dependencies can not work for test and examples at the same time
 // yielding false positives
 #![warn(missing_docs)]
-#![allow(dead_code)] // TODO https://github.com/paritytech/polkadot-sdk/issues/5793
+// TODO https://github.com/paritytech/polkadot-sdk/issues/5793
+#![allow(dead_code, irrefutable_let_patterns)]
 
 use std::{
 	collections::{hash_map, HashMap},
diff --git a/polkadot/parachain/src/primitives.rs b/polkadot/parachain/src/primitives.rs
index 1f2f9e2e9cdc7068a623db6469c935833dbedab0..73844d3c76fd27d0407472540671d264b9d2eda5 100644
--- a/polkadot/parachain/src/primitives.rs
+++ b/polkadot/parachain/src/primitives.rs
@@ -20,7 +20,7 @@
 use alloc::vec::Vec;
 
 use bounded_collections::{BoundedVec, ConstU32};
-use codec::{CompactAs, Decode, Encode, MaxEncodedLen};
+use codec::{CompactAs, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 use serde::{Deserialize, Serialize};
 use sp_core::{bytes, RuntimeDebug, TypeId};
@@ -41,6 +41,7 @@ pub use polkadot_core_primitives::BlockNumber as RelayChainBlockNumber;
 	Ord,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	derive_more::From,
 	TypeInfo,
@@ -66,6 +67,7 @@ impl codec::EncodeLike<HeadData> for alloc::vec::Vec<u8> {}
 	Clone,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	derive_more::From,
 	TypeInfo,
@@ -88,7 +90,19 @@ impl ValidationCode {
 /// This type is produced by [`ValidationCode::hash`].
 ///
 /// This type makes it easy to enforce that a hash is a validation code hash on the type level.
-#[derive(Clone, Copy, Encode, Decode, Hash, Eq, PartialEq, PartialOrd, Ord, TypeInfo)]
+#[derive(
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Hash,
+	Eq,
+	PartialEq,
+	PartialOrd,
+	Ord,
+	TypeInfo,
+)]
 pub struct ValidationCodeHash(Hash);
 
 impl core::fmt::Display for ValidationCodeHash {
@@ -140,6 +154,7 @@ pub struct BlockData(#[cfg_attr(feature = "std", serde(with = "bytes"))] pub Vec
 	CompactAs,
 	Copy,
 	Decode,
+	DecodeWithMemTracking,
 	Default,
 	Encode,
 	Eq,
@@ -298,7 +313,18 @@ impl IsSystem for Sibling {
 /// Only one channel is allowed between two participants in one direction, i.e. there cannot be 2
 /// different channels identified by `(A, B)`. A channel with the same para id in sender and
 /// recipient is invalid. That is, however, not enforced.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, RuntimeDebug, TypeInfo)]
+#[derive(
+	Clone,
+	PartialEq,
+	Eq,
+	PartialOrd,
+	Ord,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	TypeInfo,
+)]
 #[cfg_attr(feature = "std", derive(Hash))]
 pub struct HrmpChannelId {
 	/// The para that acts as the sender in this channel.
diff --git a/polkadot/primitives/src/v8/async_backing.rs b/polkadot/primitives/src/v8/async_backing.rs
index 55d436e30de07812d4b1d722a5cbb9a85cc7d1aa..3b8389c005b568b88cfd6c3d9488442856b77d30 100644
--- a/polkadot/primitives/src/v8/async_backing.rs
+++ b/polkadot/primitives/src/v8/async_backing.rs
@@ -19,7 +19,7 @@
 use super::*;
 
 use alloc::vec::Vec;
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use scale_info::TypeInfo;
 use sp_core::RuntimeDebug;
 
@@ -31,6 +31,7 @@ use sp_core::RuntimeDebug;
 	PartialEq,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	serde::Serialize,
 	serde::Deserialize,
diff --git a/polkadot/primitives/src/v8/executor_params.rs b/polkadot/primitives/src/v8/executor_params.rs
index bfd42ec30bd39dbaa3299cda634fd0f4743ab2e2..f7def658c0846c6f265e00adf030048f0dbbb1a1 100644
--- a/polkadot/primitives/src/v8/executor_params.rs
+++ b/polkadot/primitives/src/v8/executor_params.rs
@@ -23,7 +23,7 @@
 
 use crate::{BlakeTwo256, HashT as _, PvfExecKind, PvfPrepKind};
 use alloc::{collections::btree_map::BTreeMap, vec, vec::Vec};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use core::{ops::Deref, time::Duration};
 use polkadot_core_primitives::Hash;
 use scale_info::TypeInfo;
@@ -67,7 +67,18 @@ const DEFAULT_APPROVAL_EXECUTION_TIMEOUT_MS: u64 =
 	DEFAULT_APPROVAL_EXECUTION_TIMEOUT.as_millis() as u64;
 
 /// The different executor parameters for changing the execution environment semantics.
-#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, TypeInfo, Serialize, Deserialize)]
+#[derive(
+	Clone,
+	Debug,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	PartialEq,
+	Eq,
+	TypeInfo,
+	Serialize,
+	Deserialize,
+)]
 pub enum ExecutorParam {
 	/// Maximum number of memory pages (64KiB bytes per page) the executor can allocate.
 	/// A valid value lies within (0, 65536].
@@ -190,7 +201,17 @@ impl core::fmt::LowerHex for ExecutorParamsPrepHash {
 // !!! Any new parameter that does not affect the prepared artifact must be added to the exclusion
 // !!! list in `prep_hash()` to avoid unneccessary artifact rebuilds.
 #[derive(
-	Clone, Debug, Default, Encode, Decode, PartialEq, Eq, TypeInfo, Serialize, Deserialize,
+	Clone,
+	Debug,
+	Default,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	PartialEq,
+	Eq,
+	TypeInfo,
+	Serialize,
+	Deserialize,
 )]
 pub struct ExecutorParams(Vec<ExecutorParam>);
 
diff --git a/polkadot/primitives/src/v8/mod.rs b/polkadot/primitives/src/v8/mod.rs
index 93bb5ef23667288eb8a4a79e8589a39f32c742fc..313d9d98af813b075ff90c99774e5a94d3e884d2 100644
--- a/polkadot/primitives/src/v8/mod.rs
+++ b/polkadot/primitives/src/v8/mod.rs
@@ -20,7 +20,7 @@ use alloc::{
 	vec::{IntoIter, Vec},
 };
 use bitvec::{field::BitField, slice::BitSlice, vec::BitVec};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use core::{
 	marker::PhantomData,
 	slice::{Iter, IterMut},
@@ -117,7 +117,19 @@ pub trait TypeIndex {
 
 /// Index of the validator is used as a lightweight replacement of the `ValidatorId` when
 /// appropriate.
-#[derive(Eq, Ord, PartialEq, PartialOrd, Copy, Clone, Encode, Decode, TypeInfo, RuntimeDebug)]
+#[derive(
+	Eq,
+	Ord,
+	PartialEq,
+	PartialOrd,
+	Copy,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	RuntimeDebug,
+)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash))]
 pub struct ValidatorIndex(pub u32);
 
@@ -661,7 +673,7 @@ impl Ord for CommittedCandidateReceipt {
 /// The `PersistedValidationData` should be relatively lightweight primarily because it is
 /// constructed during inclusion for each candidate and therefore lies on the critical path of
 /// inclusion.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo, RuntimeDebug)]
 #[cfg_attr(feature = "std", derive(Default))]
 pub struct PersistedValidationData<H = Hash, N = BlockNumber> {
 	/// The parent head-data.
@@ -682,7 +694,7 @@ impl<H: Encode, N: Encode> PersistedValidationData<H, N> {
 }
 
 /// Commitments made in a `CandidateReceipt`. Many of these are outputs of validation.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo, RuntimeDebug)]
 #[cfg_attr(feature = "std", derive(Default, Hash))]
 pub struct CandidateCommitments<N = BlockNumber> {
 	/// Messages destined to be interpreted by the Relay chain itself.
@@ -710,7 +722,7 @@ impl CandidateCommitments {
 /// A bitfield concerning availability of backed candidates.
 ///
 /// Every bit refers to an availability core index.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, TypeInfo)]
 pub struct AvailabilityBitfield(pub BitVec<u8, bitvec::order::Lsb0>);
 
 impl From<BitVec<u8, bitvec::order::Lsb0>> for AvailabilityBitfield {
@@ -919,7 +931,18 @@ pub fn check_candidate_backing<H: AsRef<[u8]> + Clone + Encode + core::fmt::Debu
 
 /// The unique (during session) index of a core.
 #[derive(
-	Encode, Decode, Default, PartialOrd, Ord, Eq, PartialEq, Clone, Copy, TypeInfo, RuntimeDebug,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Default,
+	PartialOrd,
+	Ord,
+	Eq,
+	PartialEq,
+	Clone,
+	Copy,
+	TypeInfo,
+	RuntimeDebug,
 )]
 #[cfg_attr(feature = "std", derive(Hash))]
 pub struct CoreIndex(pub u32);
@@ -937,7 +960,20 @@ impl TypeIndex for CoreIndex {
 }
 
 /// The unique (during session) index of a validator group.
-#[derive(Encode, Decode, Default, Clone, Copy, Debug, PartialEq, Eq, TypeInfo, PartialOrd, Ord)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Default,
+	Clone,
+	Copy,
+	Debug,
+	PartialEq,
+	Eq,
+	TypeInfo,
+	PartialOrd,
+	Ord,
+)]
 #[cfg_attr(feature = "std", derive(Hash))]
 pub struct GroupIndex(pub u32);
 
@@ -1235,6 +1271,7 @@ impl<'a> ApprovalVoteMultipleCandidates<'a> {
 	PartialEq,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	serde::Serialize,
 	serde::Deserialize,
@@ -1417,7 +1454,7 @@ impl From<ConsensusLog> for sp_runtime::DigestItem {
 /// A statement about a candidate, to be used within the dispute resolution process.
 ///
 /// Statements are either in favor of the candidate's validity or against it.
-#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, RuntimeDebug, TypeInfo)]
 pub enum DisputeStatement {
 	/// A valid statement, of the given kind.
 	#[codec(index = 0)]
@@ -1511,7 +1548,7 @@ impl DisputeStatement {
 }
 
 /// Different kinds of statements of validity on  a candidate.
-#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, RuntimeDebug, TypeInfo)]
 pub enum ValidDisputeStatementKind {
 	/// An explicit statement issued as part of a dispute.
 	#[codec(index = 0)]
@@ -1547,7 +1584,7 @@ impl ValidDisputeStatementKind {
 }
 
 /// Different kinds of statements of invalidity on a candidate.
-#[derive(Encode, Decode, Copy, Clone, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Copy, Clone, PartialEq, RuntimeDebug, TypeInfo)]
 pub enum InvalidDisputeStatementKind {
 	/// An explicit statement issued as part of a dispute.
 	#[codec(index = 0)]
@@ -1575,7 +1612,7 @@ impl ExplicitDisputeStatement {
 }
 
 /// A set of statements about a specific candidate.
-#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct DisputeStatementSet {
 	/// The candidate referenced by this set.
 	pub candidate_hash: CandidateHash,
@@ -1655,7 +1692,7 @@ pub struct InherentData<HDR: HeaderT = Header> {
 
 /// An either implicit or explicit attestation to the validity of a parachain
 /// candidate.
-#[derive(Clone, Eq, PartialEq, Decode, Encode, RuntimeDebug, TypeInfo)]
+#[derive(Clone, Eq, PartialEq, Decode, DecodeWithMemTracking, Encode, RuntimeDebug, TypeInfo)]
 pub enum ValidityAttestation {
 	/// Implicit validity attestation by issuing.
 	/// This corresponds to issuance of a `Candidate` statement.
@@ -1944,7 +1981,7 @@ pub struct SessionInfo {
 
 /// A statement from the specified validator whether the given validation code passes PVF
 /// pre-checking or not anchored to the given session index.
-#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct PvfCheckStatement {
 	/// `true` if the subject passed pre-checking and `false` otherwise.
 	pub accept: bool,
@@ -2004,7 +2041,19 @@ impl<T: Encode> WellKnownKey<T> {
 }
 
 /// Type discriminator for PVF preparation.
-#[derive(Encode, Decode, TypeInfo, Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	Clone,
+	Copy,
+	Debug,
+	PartialEq,
+	Eq,
+	Serialize,
+	Deserialize,
+)]
 pub enum PvfPrepKind {
 	/// For prechecking requests.
 	Precheck,
@@ -2014,7 +2063,19 @@ pub enum PvfPrepKind {
 }
 
 /// Type discriminator for PVF execution.
-#[derive(Encode, Decode, TypeInfo, Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	Clone,
+	Copy,
+	Debug,
+	PartialEq,
+	Eq,
+	Serialize,
+	Deserialize,
+)]
 pub enum PvfExecKind {
 	/// For backing requests.
 	Backing,
@@ -2064,6 +2125,7 @@ pub mod node_features {
 	PartialEq,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	serde::Serialize,
 	serde::Deserialize,
diff --git a/polkadot/primitives/src/v8/signed.rs b/polkadot/primitives/src/v8/signed.rs
index f819b379a30ae2dde68d215daea712c7c28ecbb2..4c617155fa80a08339303f7c1329f814e3a4613a 100644
--- a/polkadot/primitives/src/v8/signed.rs
+++ b/polkadot/primitives/src/v8/signed.rs
@@ -14,7 +14,7 @@
 // You should have received a copy of the GNU General Public License
 // along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
 
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use scale_info::TypeInfo;
 
 use alloc::vec::Vec;
@@ -47,7 +47,7 @@ impl<Payload, RealPayload> Signed<Payload, RealPayload> {
 }
 
 /// Unchecked signed data, can be converted to `Signed` by checking the signature.
-#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo)]
+#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
 pub struct UncheckedSigned<Payload, RealPayload = Payload> {
 	/// The payload is part of the signed data. The rest is the signing context,
 	/// which is known both at signing and at validation.
diff --git a/polkadot/primitives/src/v8/slashing.rs b/polkadot/primitives/src/v8/slashing.rs
index 148bc1477ff88fd94565d7b834399500f6a1d17e..bd41f2d9765328b42110a6b73eb9d86473db8a18 100644
--- a/polkadot/primitives/src/v8/slashing.rs
+++ b/polkadot/primitives/src/v8/slashing.rs
@@ -18,11 +18,11 @@
 
 use crate::{CandidateHash, SessionIndex, ValidatorId, ValidatorIndex};
 use alloc::{collections::btree_map::BTreeMap, vec::Vec};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use scale_info::TypeInfo;
 
 /// The kind of the dispute offence.
-#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo, Debug)]
+#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, TypeInfo, Debug)]
 pub enum SlashingOffenceKind {
 	/// A severe offence when a validator backed an invalid block.
 	#[codec(index = 0)]
@@ -34,7 +34,9 @@ pub enum SlashingOffenceKind {
 
 /// Timeslots should uniquely identify offences and are used for the offence
 /// deduplication.
-#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, TypeInfo, Debug)]
+#[derive(
+	Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo, Debug,
+)]
 pub struct DisputesTimeSlot {
 	// The order of the fields matters for `derive(Ord)`.
 	/// Session index when the candidate was backed/included.
@@ -52,7 +54,7 @@ impl DisputesTimeSlot {
 
 /// We store most of the information about a lost dispute on chain. This struct
 /// is required to identify and verify it.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, Debug)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo, Debug)]
 pub struct DisputeProof {
 	/// Time slot when the dispute occurred.
 	pub time_slot: DisputesTimeSlot,
diff --git a/polkadot/primitives/src/vstaging/mod.rs b/polkadot/primitives/src/vstaging/mod.rs
index 5da4595af65801fe8b7d7891a4f990b3e49034e6..4eb44bd23e6e3010a9bb2f905925435d2b6caa98 100644
--- a/polkadot/primitives/src/vstaging/mod.rs
+++ b/polkadot/primitives/src/vstaging/mod.rs
@@ -31,7 +31,7 @@ use alloc::{
 	vec::Vec,
 };
 use bitvec::prelude::*;
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use scale_info::TypeInfo;
 use sp_application_crypto::ByteArray;
 use sp_core::RuntimeDebug;
@@ -45,7 +45,9 @@ pub mod async_backing;
 pub const DEFAULT_CLAIM_QUEUE_OFFSET: u8 = 0;
 
 /// A type representing the version of the candidate descriptor and internal version number.
-#[derive(PartialEq, Eq, Encode, Decode, Clone, TypeInfo, RuntimeDebug, Copy)]
+#[derive(
+	PartialEq, Eq, Encode, Decode, DecodeWithMemTracking, Clone, TypeInfo, RuntimeDebug, Copy,
+)]
 #[cfg_attr(feature = "std", derive(Hash))]
 pub struct InternalVersion(pub u8);
 
@@ -62,7 +64,7 @@ pub enum CandidateDescriptorVersion {
 }
 
 /// A unique descriptor of the candidate receipt.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo, RuntimeDebug)]
 #[cfg_attr(feature = "std", derive(Hash))]
 pub struct CandidateDescriptorV2<H = Hash> {
 	/// The ID of the para this is a candidate for.
@@ -265,7 +267,7 @@ impl<H> MutateDescriptorV2<H> for CandidateDescriptorV2<H> {
 }
 
 /// A candidate-receipt at version 2.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo, RuntimeDebug)]
 #[cfg_attr(feature = "std", derive(Hash))]
 pub struct CandidateReceiptV2<H = Hash> {
 	/// The descriptor of the candidate.
@@ -275,7 +277,7 @@ pub struct CandidateReceiptV2<H = Hash> {
 }
 
 /// A candidate-receipt with commitments directly included.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo, RuntimeDebug)]
 #[cfg_attr(feature = "std", derive(Hash))]
 pub struct CommittedCandidateReceiptV2<H = Hash> {
 	/// The descriptor of the candidate.
@@ -676,7 +678,7 @@ impl<H: Copy> CommittedCandidateReceiptV2<H> {
 }
 
 /// A backed (or backable, depending on context) candidate.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub struct BackedCandidate<H = Hash> {
 	/// The candidate referred to.
 	candidate: CommittedCandidateReceiptV2<H>,
@@ -689,7 +691,7 @@ pub struct BackedCandidate<H = Hash> {
 }
 
 /// Parachains inherent-data passed into the runtime by a block author
-#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct InherentData<HDR: HeaderT = Header> {
 	/// Signed bitfields by validators about availability.
 	pub bitfields: UncheckedSignedAvailabilityBitfields,
diff --git a/polkadot/runtime/common/Cargo.toml b/polkadot/runtime/common/Cargo.toml
index 4ffa5c475ed779fb19e0f777770f5ff72c9ef499..066fd1ef32bfc74634231228dabfb6e1980ed076 100644
--- a/polkadot/runtime/common/Cargo.toml
+++ b/polkadot/runtime/common/Cargo.toml
@@ -120,6 +120,7 @@ std = [
 runtime-benchmarks = [
 	"frame-benchmarking/runtime-benchmarks",
 	"frame-election-provider-support/runtime-benchmarks",
+	"frame-support-test/runtime-benchmarks",
 	"frame-support/runtime-benchmarks",
 	"frame-system/runtime-benchmarks",
 	"libsecp256k1/hmac",
diff --git a/polkadot/runtime/common/src/assigned_slots/mod.rs b/polkadot/runtime/common/src/assigned_slots/mod.rs
index 81e2986ab6b3cd8cde7251caff3e5f826dd0c567..dcde616392b8a24da607b746e6e50bf5df881ecb 100644
--- a/polkadot/runtime/common/src/assigned_slots/mod.rs
+++ b/polkadot/runtime/common/src/assigned_slots/mod.rs
@@ -31,7 +31,7 @@ use crate::{
 	traits::{LeaseError, Leaser, Registrar},
 };
 use alloc::vec::Vec;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_support::{pallet_prelude::*, traits::Currency};
 use frame_system::pallet_prelude::*;
 pub use pallet::*;
@@ -46,7 +46,9 @@ use sp_runtime::traits::{One, Saturating, Zero};
 const LOG_TARGET: &str = "runtime::assigned_slots";
 
 /// Lease period an assigned slot should start from (current, or next one).
-#[derive(Encode, Decode, Clone, Copy, Eq, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(
+	Encode, Decode, DecodeWithMemTracking, Clone, Copy, Eq, PartialEq, RuntimeDebug, TypeInfo,
+)]
 pub enum SlotLeasePeriodStart {
 	Current,
 	Next,
diff --git a/polkadot/runtime/common/src/claims/mod.rs b/polkadot/runtime/common/src/claims/mod.rs
index 9e084688b4e558ec3917e6651e2a15204adaa4cd..1c557051add476a1ee7223ee29c542ac68ac3c3c 100644
--- a/polkadot/runtime/common/src/claims/mod.rs
+++ b/polkadot/runtime/common/src/claims/mod.rs
@@ -19,7 +19,7 @@
 #[cfg(not(feature = "std"))]
 use alloc::{format, string::String};
 use alloc::{vec, vec::Vec};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::fmt::Debug;
 use frame_support::{
 	ensure,
@@ -85,6 +85,7 @@ impl WeightInfo for TestWeightInfo {
 #[derive(
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Clone,
 	Copy,
 	Eq,
@@ -128,7 +129,17 @@ impl Default for StatementKind {
 ///
 /// This gets serialized to the 0x-prefixed hex representation.
 #[derive(
-	Clone, Copy, PartialEq, Eq, Encode, Decode, Default, RuntimeDebug, TypeInfo, MaxEncodedLen,
+	Clone,
+	Copy,
+	PartialEq,
+	Eq,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Default,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
 )]
 pub struct EthereumAddress(pub [u8; 20]);
 
@@ -163,7 +174,7 @@ impl<'de> Deserialize<'de> for EthereumAddress {
 	}
 }
 
-#[derive(Encode, Decode, Clone, TypeInfo, MaxEncodedLen)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, TypeInfo, MaxEncodedLen)]
 pub struct EcdsaSignature(pub [u8; 65]);
 
 impl PartialEq for EcdsaSignature {
diff --git a/polkadot/runtime/common/src/impls.rs b/polkadot/runtime/common/src/impls.rs
index 9a290f08609abe45e801b9770dcc428ee0e5250a..f596a03d66a8f947855be4d67c1217f6ec39b872 100644
--- a/polkadot/runtime/common/src/impls.rs
+++ b/polkadot/runtime/common/src/impls.rs
@@ -16,7 +16,7 @@
 
 //! Auxiliary `struct`/`enum`s for polkadot runtime.
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_support::traits::{
 	fungible::{Balanced, Credit},
 	tokens::imbalance::ResolveTo,
@@ -131,7 +131,15 @@ pub fn relay_era_payout(params: EraPayoutParams) -> (Balance, Balance) {
 /// Versioned locatable asset type which contains both an XCM `location` and `asset_id` to identify
 /// an asset which exists on some chain.
 #[derive(
-	Encode, Decode, Eq, PartialEq, Clone, RuntimeDebug, scale_info::TypeInfo, MaxEncodedLen,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	Clone,
+	RuntimeDebug,
+	scale_info::TypeInfo,
+	MaxEncodedLen,
 )]
 pub enum VersionedLocatableAsset {
 	#[codec(index = 3)]
diff --git a/polkadot/runtime/common/src/purchase/mod.rs b/polkadot/runtime/common/src/purchase/mod.rs
index 71dc5b57967063f349264ca90ce345029512ad10..58822bcdd8f4eebca39ef2bdb5b73ddcde922ce2 100644
--- a/polkadot/runtime/common/src/purchase/mod.rs
+++ b/polkadot/runtime/common/src/purchase/mod.rs
@@ -35,7 +35,9 @@ type BalanceOf<T> =
 	<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
 
 /// The kind of statement an account needs to make for a claim to be valid.
-#[derive(Encode, Decode, Clone, Copy, Eq, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(
+	Encode, Decode, DecodeWithMemTracking, Clone, Copy, Eq, PartialEq, RuntimeDebug, TypeInfo,
+)]
 pub enum AccountValidity {
 	/// Account is not valid.
 	Invalid,
diff --git a/polkadot/runtime/parachains/Cargo.toml b/polkadot/runtime/parachains/Cargo.toml
index 6c87f7773c235dcca7f591791e5295a84e2c26cf..145b533cbb15af10cc7e7ea978a75bbbae342817 100644
--- a/polkadot/runtime/parachains/Cargo.toml
+++ b/polkadot/runtime/parachains/Cargo.toml
@@ -120,6 +120,7 @@ std = [
 ]
 runtime-benchmarks = [
 	"frame-benchmarking/runtime-benchmarks",
+	"frame-support-test/runtime-benchmarks",
 	"frame-support/runtime-benchmarks",
 	"frame-system/runtime-benchmarks",
 	"pallet-babe/runtime-benchmarks",
diff --git a/polkadot/runtime/parachains/src/assigner_coretime/mod.rs b/polkadot/runtime/parachains/src/assigner_coretime/mod.rs
index 866d52dc98484519b733a445b12f3561ceee4412..980fff08cce37405e562a051fd9793bd8776f6d4 100644
--- a/polkadot/runtime/parachains/src/assigner_coretime/mod.rs
+++ b/polkadot/runtime/parachains/src/assigner_coretime/mod.rs
@@ -44,7 +44,19 @@ use sp_runtime::traits::{One, Saturating};
 pub use pallet::*;
 
 /// Fraction expressed as a nominator with an assumed denominator of 57,600.
-#[derive(RuntimeDebug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, TypeInfo)]
+#[derive(
+	RuntimeDebug,
+	Clone,
+	Copy,
+	PartialEq,
+	Eq,
+	PartialOrd,
+	Ord,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+)]
 pub struct PartsOf57600(u16);
 
 impl PartsOf57600 {
diff --git a/polkadot/runtime/parachains/src/coretime/migration.rs b/polkadot/runtime/parachains/src/coretime/migration.rs
index c3a1ebe82432486cf3ce4fc7c3b6d1959f9701ba..cd44451a7c3927bd4c20490ca3469413f9d902f2 100644
--- a/polkadot/runtime/parachains/src/coretime/migration.rs
+++ b/polkadot/runtime/parachains/src/coretime/migration.rs
@@ -250,7 +250,7 @@ mod v_coretime {
 					return None
 				},
 			};
-			let time_slice = (valid_until + TIMESLICE_PERIOD - 1) / TIMESLICE_PERIOD;
+			let time_slice = valid_until.div_ceil(TIMESLICE_PERIOD);
 			log::trace!(target: "coretime-migration", "Sending of lease holding para {:?}, valid_until: {:?}, time_slice: {:?}", p, valid_until, time_slice);
 			Some(mk_coretime_call::<T>(crate::coretime::CoretimeCalls::SetLease(p.into(), time_slice)))
 		});
diff --git a/polkadot/runtime/parachains/src/disputes.rs b/polkadot/runtime/parachains/src/disputes.rs
index d5a3f31e5943f26f784f9b4e58026f8213bdf12f..a3735c6ee3aaf8959bb5a4692f2d8149c49dd1c7 100644
--- a/polkadot/runtime/parachains/src/disputes.rs
+++ b/polkadot/runtime/parachains/src/disputes.rs
@@ -21,7 +21,7 @@ use crate::{
 };
 use alloc::{collections::btree_set::BTreeSet, vec::Vec};
 use bitvec::{bitvec, order::Lsb0 as BitOrderLsb0};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use core::cmp::Ordering;
 use frame_support::{ensure, weights::Weight};
 use frame_system::pallet_prelude::*;
@@ -55,14 +55,14 @@ pub mod migration;
 const LOG_TARGET: &str = "runtime::disputes";
 
 /// Whether the dispute is local or remote.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub enum DisputeLocation {
 	Local,
 	Remote,
 }
 
 /// The result of a dispute, whether the candidate is deemed valid (for) or invalid (against).
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub enum DisputeResult {
 	Valid,
 	Invalid,
diff --git a/polkadot/runtime/parachains/src/inclusion/mod.rs b/polkadot/runtime/parachains/src/inclusion/mod.rs
index 8ad9711a0f388ab7782848111df42e6e8a1003c4..1e9706533cfd8587bdc88ee4c9cb2ba43637faa3 100644
--- a/polkadot/runtime/parachains/src/inclusion/mod.rs
+++ b/polkadot/runtime/parachains/src/inclusion/mod.rs
@@ -33,7 +33,7 @@ use alloc::{
 	vec::Vec,
 };
 use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use core::fmt;
 use frame_support::{
 	defensive,
@@ -216,7 +216,17 @@ impl QueueFootprinter for () {
 ///
 /// Can be extended to serve further use-cases besides just UMP. Is stored in storage, so any change
 /// to existing values will require a migration.
-#[derive(Encode, Decode, Clone, MaxEncodedLen, Eq, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Clone,
+	MaxEncodedLen,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+)]
 pub enum AggregateMessageOrigin {
 	/// Inbound upward message.
 	#[codec(index = 0)]
@@ -227,7 +237,17 @@ pub enum AggregateMessageOrigin {
 ///
 /// It is written in verbose form since future variants like `Here` and `Bridged` are already
 /// foreseeable.
-#[derive(Encode, Decode, Clone, MaxEncodedLen, Eq, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Clone,
+	MaxEncodedLen,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+)]
 pub enum UmpQueueId {
 	/// The message originated from this parachain.
 	#[codec(index = 0)]
diff --git a/polkadot/runtime/parachains/src/origin.rs b/polkadot/runtime/parachains/src/origin.rs
index fd22929b08ff547398c7f731e9a823a780391a6c..a99c56e78968af8ccc6edb79434c77ca41fc92fd 100644
--- a/polkadot/runtime/parachains/src/origin.rs
+++ b/polkadot/runtime/parachains/src/origin.rs
@@ -58,6 +58,7 @@ pub mod pallet {
 		Clone,
 		Encode,
 		Decode,
+		DecodeWithMemTracking,
 		sp_core::RuntimeDebug,
 		scale_info::TypeInfo,
 		MaxEncodedLen,
diff --git a/polkadot/runtime/parachains/src/paras/mod.rs b/polkadot/runtime/parachains/src/paras/mod.rs
index 38ca8fb9389de9121a53e6c80290e088ecd887d1..95bab14651d8a389cd8dddb34eb88f2a30f1ee86 100644
--- a/polkadot/runtime/parachains/src/paras/mod.rs
+++ b/polkadot/runtime/parachains/src/paras/mod.rs
@@ -293,7 +293,18 @@ impl<N: Ord + Copy + PartialEq> ParaPastCodeMeta<N> {
 }
 
 /// Arguments for initializing a para.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, Serialize, Deserialize)]
+#[derive(
+	PartialEq,
+	Eq,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	TypeInfo,
+	Serialize,
+	Deserialize,
+)]
 pub struct ParaGenesisArgs {
 	/// The initial head data to use.
 	pub genesis_head: HeadData,
@@ -305,7 +316,7 @@ pub struct ParaGenesisArgs {
 }
 
 /// Distinguishes between lease holding Parachain and Parathread (on-demand parachain)
-#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
+#[derive(DecodeWithMemTracking, PartialEq, Eq, Clone, RuntimeDebug)]
 pub enum ParaKind {
 	Parathread,
 	Parachain,
diff --git a/polkadot/runtime/rococo/src/governance/origins.rs b/polkadot/runtime/rococo/src/governance/origins.rs
index e4639f40dc432473e1222f6ab1094a31ecd26f68..13bcc8dafded57cbc3348f9d37a7f8736e89dd07 100644
--- a/polkadot/runtime/rococo/src/governance/origins.rs
+++ b/polkadot/runtime/rococo/src/governance/origins.rs
@@ -29,7 +29,17 @@ pub mod pallet_custom_origins {
 	#[pallet::pallet]
 	pub struct Pallet<T>(_);
 
-	#[derive(PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug)]
+	#[derive(
+		PartialEq,
+		Eq,
+		Clone,
+		MaxEncodedLen,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		TypeInfo,
+		RuntimeDebug,
+	)]
 	#[pallet::origin]
 	pub enum Origin {
 		/// Origin for cancelling slashes.
diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs
index 61403c001e21013c1df3c37305015f29b2b8e32a..4123a6a1a3558a8dfbca28d421beedeb606214ec 100644
--- a/polkadot/runtime/rococo/src/lib.rs
+++ b/polkadot/runtime/rococo/src/lib.rs
@@ -38,7 +38,7 @@ use alloc::{
 	vec,
 	vec::Vec,
 };
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::cmp::Ordering;
 use frame_support::{
 	dynamic_params::{dynamic_pallet_params, dynamic_params},
@@ -865,6 +865,7 @@ parameter_types! {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	MaxEncodedLen,
 	TypeInfo,
@@ -2467,6 +2468,7 @@ sp_api::impl_runtime_apis! {
 			return (list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig,
 		) -> Result<
diff --git a/polkadot/runtime/rococo/src/weights/pallet_indices.rs b/polkadot/runtime/rococo/src/weights/pallet_indices.rs
index 434db97d4a79faa0d51dcad13c16d6840f357483..900863d4368449793454300064270ce818c5ec44 100644
--- a/polkadot/runtime/rococo/src/weights/pallet_indices.rs
+++ b/polkadot/runtime/rococo/src/weights/pallet_indices.rs
@@ -17,27 +17,28 @@
 //! Autogenerated weights for `pallet_indices`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2025-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
-//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024
+//! HOSTNAME: `52baa5cae416`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024
 
 // Executed Command:
-// ./target/production/polkadot
+// frame-omni-bencher
+// v1
 // benchmark
 // pallet
-// --chain=rococo-dev
+// --extrinsic=*
+// --runtime=target/production/wbuild/rococo-runtime/rococo_runtime.wasm
+// --pallet=pallet_indices
+// --header=/__w/polkadot-sdk/polkadot-sdk/polkadot/file_header.txt
+// --output=./polkadot/runtime/rococo/src/weights
+// --wasm-execution=compiled
 // --steps=50
 // --repeat=20
+// --heap-pages=4096
 // --no-storage-info
-// --no-median-slopes
 // --no-min-squares
-// --pallet=pallet_indices
-// --extrinsic=*
-// --execution=wasm
-// --wasm-execution=compiled
-// --header=./polkadot/file_header.txt
-// --output=./polkadot/runtime/rococo/src/weights/
+// --no-median-slopes
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
@@ -56,8 +57,8 @@ impl<T: frame_system::Config> pallet_indices::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `4`
 		//  Estimated: `3534`
-		// Minimum execution time: 18_092_000 picoseconds.
-		Weight::from_parts(18_533_000, 0)
+		// Minimum execution time: 22_250_000 picoseconds.
+		Weight::from_parts(23_442_000, 0)
 			.saturating_add(Weight::from_parts(0, 3534))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -70,8 +71,8 @@ impl<T: frame_system::Config> pallet_indices::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `203`
 		//  Estimated: `3593`
-		// Minimum execution time: 31_616_000 picoseconds.
-		Weight::from_parts(32_556_000, 0)
+		// Minimum execution time: 35_315_000 picoseconds.
+		Weight::from_parts(37_456_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -82,8 +83,8 @@ impl<T: frame_system::Config> pallet_indices::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `100`
 		//  Estimated: `3534`
-		// Minimum execution time: 19_593_000 picoseconds.
-		Weight::from_parts(20_100_000, 0)
+		// Minimum execution time: 23_413_000 picoseconds.
+		Weight::from_parts(24_307_000, 0)
 			.saturating_add(Weight::from_parts(0, 3534))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
@@ -96,8 +97,8 @@ impl<T: frame_system::Config> pallet_indices::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `203`
 		//  Estimated: `3593`
-		// Minimum execution time: 21_429_000 picoseconds.
-		Weight::from_parts(22_146_000, 0)
+		// Minimum execution time: 25_799_000 picoseconds.
+		Weight::from_parts(26_614_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
@@ -108,8 +109,20 @@ impl<T: frame_system::Config> pallet_indices::WeightInfo for WeightInfo<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `100`
 		//  Estimated: `3534`
-		// Minimum execution time: 20_425_000 picoseconds.
-		Weight::from_parts(21_023_000, 0)
+		// Minimum execution time: 26_905_000 picoseconds.
+		Weight::from_parts(27_574_000, 0)
+			.saturating_add(Weight::from_parts(0, 3534))
+			.saturating_add(T::DbWeight::get().reads(1))
+			.saturating_add(T::DbWeight::get().writes(1))
+	}
+	/// Storage: `Indices::Accounts` (r:1 w:1)
+	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
+	fn poke_deposit() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `100`
+		//  Estimated: `3534`
+		// Minimum execution time: 23_596_000 picoseconds.
+		Weight::from_parts(24_227_000, 0)
 			.saturating_add(Weight::from_parts(0, 3534))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
diff --git a/polkadot/runtime/rococo/src/weights/pallet_utility.rs b/polkadot/runtime/rococo/src/weights/pallet_utility.rs
index 5e580de6aad54d75381d385f768e12395d65eea6..2b1db130801a437692d7db56884215f0c69d55e2 100644
--- a/polkadot/runtime/rococo/src/weights/pallet_utility.rs
+++ b/polkadot/runtime/rococo/src/weights/pallet_utility.rs
@@ -99,6 +99,11 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
 			// Standard Error: 460
 			.saturating_add(Weight::from_parts(3_173_577, 0).saturating_mul(c.into()))
 	}
+
+	fn dispatch_as_fallible() -> Weight {
+		Default::default()
+	}
+
 	fn if_else() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
diff --git a/polkadot/runtime/westend/src/governance/origins.rs b/polkadot/runtime/westend/src/governance/origins.rs
index e4639f40dc432473e1222f6ab1094a31ecd26f68..13bcc8dafded57cbc3348f9d37a7f8736e89dd07 100644
--- a/polkadot/runtime/westend/src/governance/origins.rs
+++ b/polkadot/runtime/westend/src/governance/origins.rs
@@ -29,7 +29,17 @@ pub mod pallet_custom_origins {
 	#[pallet::pallet]
 	pub struct Pallet<T>(_);
 
-	#[derive(PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug)]
+	#[derive(
+		PartialEq,
+		Eq,
+		Clone,
+		MaxEncodedLen,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		TypeInfo,
+		RuntimeDebug,
+	)]
 	#[pallet::origin]
 	pub enum Origin {
 		/// Origin for cancelling slashes.
diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs
index 8ee9e073f162d56b623b12fb390d45b929034abe..5af67ad9bd70a491e357abb859acb1d767f387af 100644
--- a/polkadot/runtime/westend/src/lib.rs
+++ b/polkadot/runtime/westend/src/lib.rs
@@ -27,7 +27,7 @@ use alloc::{
 	vec,
 	vec::Vec,
 };
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_election_provider_support::{bounds::ElectionBoundsBuilder, onchain, SequentialPhragmen};
 use frame_support::{
 	derive_impl,
@@ -1087,6 +1087,7 @@ parameter_types! {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	MaxEncodedLen,
 	TypeInfo,
@@ -2648,6 +2649,7 @@ sp_api::impl_runtime_apis! {
 			return (list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig,
 		) -> Result<
diff --git a/polkadot/runtime/westend/src/weights/pallet_indices.rs b/polkadot/runtime/westend/src/weights/pallet_indices.rs
index 42316cd90780173f47a9eb4071bdedf6f3e54492..c10ec047953f2fcef7a5d2ac0499899969f3b621 100644
--- a/polkadot/runtime/westend/src/weights/pallet_indices.rs
+++ b/polkadot/runtime/westend/src/weights/pallet_indices.rs
@@ -16,28 +16,29 @@
 
 //! Autogenerated weights for `pallet_indices`
 //!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2023-06-14, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2025-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner--ss9ysm1-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
-//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024
+//! HOSTNAME: `52baa5cae416`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024
 
 // Executed Command:
-// ./target/production/polkadot
+// frame-omni-bencher
+// v1
 // benchmark
 // pallet
-// --chain=westend-dev
+// --extrinsic=*
+// --runtime=target/production/wbuild/westend-runtime/westend_runtime.wasm
+// --pallet=pallet_indices
+// --header=/__w/polkadot-sdk/polkadot-sdk/polkadot/file_header.txt
+// --output=./polkadot/runtime/westend/src/weights
+// --wasm-execution=compiled
 // --steps=50
 // --repeat=20
+// --heap-pages=4096
 // --no-storage-info
-// --no-median-slopes
 // --no-min-squares
-// --pallet=pallet_indices
-// --extrinsic=*
-// --execution=wasm
-// --wasm-execution=compiled
-// --header=./file_header.txt
-// --output=./runtime/westend/src/weights/
+// --no-median-slopes
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
@@ -50,66 +51,78 @@ use core::marker::PhantomData;
 /// Weight functions for `pallet_indices`.
 pub struct WeightInfo<T>(PhantomData<T>);
 impl<T: frame_system::Config> pallet_indices::WeightInfo for WeightInfo<T> {
-	/// Storage: Indices Accounts (r:1 w:1)
-	/// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen)
+	/// Storage: `Indices::Accounts` (r:1 w:1)
+	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
 	fn claim() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `142`
+		//  Measured:  `4`
 		//  Estimated: `3534`
-		// Minimum execution time: 24_553_000 picoseconds.
-		Weight::from_parts(25_288_000, 0)
+		// Minimum execution time: 25_952_000 picoseconds.
+		Weight::from_parts(27_224_000, 0)
 			.saturating_add(Weight::from_parts(0, 3534))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
-	/// Storage: Indices Accounts (r:1 w:1)
-	/// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen)
-	/// Storage: System Account (r:1 w:1)
-	/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
+	/// Storage: `Indices::Accounts` (r:1 w:1)
+	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
+	/// Storage: `System::Account` (r:1 w:1)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn transfer() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `341`
+		//  Measured:  `203`
 		//  Estimated: `3593`
-		// Minimum execution time: 35_932_000 picoseconds.
-		Weight::from_parts(36_801_000, 0)
+		// Minimum execution time: 38_643_000 picoseconds.
+		Weight::from_parts(39_612_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
-	/// Storage: Indices Accounts (r:1 w:1)
-	/// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen)
+	/// Storage: `Indices::Accounts` (r:1 w:1)
+	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
 	fn free() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `238`
+		//  Measured:  `100`
 		//  Estimated: `3534`
-		// Minimum execution time: 25_574_000 picoseconds.
-		Weight::from_parts(26_123_000, 0)
+		// Minimum execution time: 26_744_000 picoseconds.
+		Weight::from_parts(28_195_000, 0)
 			.saturating_add(Weight::from_parts(0, 3534))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
-	/// Storage: Indices Accounts (r:1 w:1)
-	/// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen)
-	/// Storage: System Account (r:1 w:1)
-	/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
+	/// Storage: `Indices::Accounts` (r:1 w:1)
+	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
+	/// Storage: `System::Account` (r:1 w:1)
+	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn force_transfer() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `341`
+		//  Measured:  `203`
 		//  Estimated: `3593`
-		// Minimum execution time: 27_605_000 picoseconds.
-		Weight::from_parts(28_569_000, 0)
+		// Minimum execution time: 29_213_000 picoseconds.
+		Weight::from_parts(30_369_000, 0)
 			.saturating_add(Weight::from_parts(0, 3593))
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
-	/// Storage: Indices Accounts (r:1 w:1)
-	/// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen)
+	/// Storage: `Indices::Accounts` (r:1 w:1)
+	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
 	fn freeze() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `238`
+		//  Measured:  `100`
+		//  Estimated: `3534`
+		// Minimum execution time: 30_370_000 picoseconds.
+		Weight::from_parts(31_164_000, 0)
+			.saturating_add(Weight::from_parts(0, 3534))
+			.saturating_add(T::DbWeight::get().reads(1))
+			.saturating_add(T::DbWeight::get().writes(1))
+	}
+	/// Storage: `Indices::Accounts` (r:1 w:1)
+	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
+	fn poke_deposit() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `100`
 		//  Estimated: `3534`
-		// Minimum execution time: 27_447_000 picoseconds.
-		Weight::from_parts(28_136_000, 0)
+		// Minimum execution time: 27_134_000 picoseconds.
+		Weight::from_parts(28_175_000, 0)
 			.saturating_add(Weight::from_parts(0, 3534))
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
diff --git a/polkadot/runtime/westend/src/weights/pallet_utility.rs b/polkadot/runtime/westend/src/weights/pallet_utility.rs
index 84fa0589a58218da02846794b6ced503316c0096..a13c68545526dac2339d935aec284065fa023a92 100644
--- a/polkadot/runtime/westend/src/weights/pallet_utility.rs
+++ b/polkadot/runtime/westend/src/weights/pallet_utility.rs
@@ -99,6 +99,11 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
 			// Standard Error: 2_817
 			.saturating_add(Weight::from_parts(5_113_539, 0).saturating_mul(c.into()))
 	}
+
+	fn dispatch_as_fallible() -> Weight {
+		Default::default()
+	}
+
 	fn if_else() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
diff --git a/polkadot/xcm/docs/src/lib.rs b/polkadot/xcm/docs/src/lib.rs
index 8d78b9b19452d260c1abbea8f465be71f747213d..77823cad3fd2cf26fd7d82edb550f30166db0742 100644
--- a/polkadot/xcm/docs/src/lib.rs
+++ b/polkadot/xcm/docs/src/lib.rs
@@ -50,6 +50,8 @@
 //!
 //! ## Docs structure
 #![doc = simple_mermaid::mermaid!("../mermaid/structure.mmd")]
+// Frame macros reference features which this crate does not have
+#![allow(unexpected_cfgs)]
 
 /// Fundamentals of the XCM language. The virtual machine, instructions, locations and assets.
 pub mod fundamentals;
diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs
index 6360298b21c3660dd86096968b1d4f0e0327d10b..a422756ed570a6982b481b040af70cfaf70ad553 100644
--- a/polkadot/xcm/pallet-xcm/src/lib.rs
+++ b/polkadot/xcm/pallet-xcm/src/lib.rs
@@ -508,7 +508,17 @@ pub mod pallet {
 	}
 
 	#[pallet::origin]
-	#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+	#[derive(
+		PartialEq,
+		Eq,
+		Clone,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		RuntimeDebug,
+		TypeInfo,
+		MaxEncodedLen,
+	)]
 	pub enum Origin {
 		/// It comes from somewhere in the XCM space wanting to transact.
 		Xcm(Location),
diff --git a/polkadot/xcm/src/double_encoded.rs b/polkadot/xcm/src/double_encoded.rs
index a5eecdee97963530e29a37655ca4d153c6eae5c8..5efb637b9075b1113814a422909349203832f843 100644
--- a/polkadot/xcm/src/double_encoded.rs
+++ b/polkadot/xcm/src/double_encoded.rs
@@ -16,11 +16,11 @@
 
 use crate::MAX_XCM_DECODE_DEPTH;
 use alloc::vec::Vec;
-use codec::{Decode, DecodeLimit, Encode};
+use codec::{Decode, DecodeLimit, DecodeWithMemTracking, Encode};
 
 /// Wrapper around the encoded and decoded versions of a value.
 /// Caches the decoded value once computed.
-#[derive(Encode, Decode, scale_info::TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, scale_info::TypeInfo)]
 #[codec(encode_bound())]
 #[codec(decode_bound())]
 #[scale_info(bounds(), skip_type_params(T))]
diff --git a/polkadot/xcm/src/lib.rs b/polkadot/xcm/src/lib.rs
index 2271835a9a5e87b6616e61f42d35ee8775abdb9b..9d3dc56c7d3cf14365a740b8577f6401a3692b8d 100644
--- a/polkadot/xcm/src/lib.rs
+++ b/polkadot/xcm/src/lib.rs
@@ -24,7 +24,9 @@
 
 extern crate alloc;
 
-use codec::{Decode, DecodeLimit, Encode, Error as CodecError, Input, MaxEncodedLen};
+use codec::{
+	Decode, DecodeLimit, DecodeWithMemTracking, Encode, Error as CodecError, Input, MaxEncodedLen,
+};
 use derive_where::derive_where;
 use frame_support::dispatch::GetDispatchInfo;
 use scale_info::TypeInfo;
@@ -88,7 +90,7 @@ macro_rules! versioned_type {
 		$(#[$index5:meta])+
 		V5($v5:ty),
 	}) => {
-		#[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, TypeInfo)]
+		#[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
 		#[codec(encode_bound())]
 		#[codec(decode_bound())]
 		#[scale_info(replace_segment("staging_xcm", "xcm"))]
@@ -305,7 +307,7 @@ versioned_type! {
 }
 
 /// A single XCM message, together with its version code.
-#[derive(Encode, Decode, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, TypeInfo)]
 #[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[codec(decode_bound())]
diff --git a/polkadot/xcm/src/v3/junction.rs b/polkadot/xcm/src/v3/junction.rs
index 24e9c16bf699a9f2bdbc6221b55c33760ecf2282..c3b0378c871e908b815b68d917ac43b78da02159 100644
--- a/polkadot/xcm/src/v3/junction.rs
+++ b/polkadot/xcm/src/v3/junction.rs
@@ -22,7 +22,7 @@ use crate::{
 	VersionedLocation,
 };
 use bounded_collections::{BoundedSlice, BoundedVec, ConstU32};
-use codec::{self, Decode, Encode, MaxEncodedLen};
+use codec::{self, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 use serde::{Deserialize, Serialize};
 
@@ -39,6 +39,7 @@ use serde::{Deserialize, Serialize};
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
@@ -111,6 +112,7 @@ impl From<NewNetworkId> for NetworkId {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
@@ -157,6 +159,7 @@ pub enum BodyId {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
@@ -220,6 +223,7 @@ impl BodyPart {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
diff --git a/polkadot/xcm/src/v3/junctions.rs b/polkadot/xcm/src/v3/junctions.rs
index 56f5326fe97c6f260d53f66a9bc8ec7b3f169537..3cc1b78553a61147639072c4920e59c97d9ce52d 100644
--- a/polkadot/xcm/src/v3/junctions.rs
+++ b/polkadot/xcm/src/v3/junctions.rs
@@ -17,7 +17,7 @@
 //! XCM `Junctions`/`InteriorMultiLocation` datatype.
 
 use super::{Junction, MultiLocation, NetworkId};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::{mem, result};
 use scale_info::TypeInfo;
 
@@ -38,6 +38,7 @@ pub(crate) const MAX_JUNCTIONS: usize = 8;
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
diff --git a/polkadot/xcm/src/v3/mod.rs b/polkadot/xcm/src/v3/mod.rs
index 6ae987a9830f1c6e426c1030316b97ecf6611262..7d48ae26f60eaf204660475861b85291cba191e5 100644
--- a/polkadot/xcm/src/v3/mod.rs
+++ b/polkadot/xcm/src/v3/mod.rs
@@ -24,8 +24,8 @@ use crate::DoubleEncoded;
 use alloc::{vec, vec::Vec};
 use bounded_collections::{parameter_types, BoundedVec};
 use codec::{
-	self, decode_vec_with_len, Compact, Decode, Encode, Error as CodecError, Input as CodecInput,
-	MaxEncodedLen,
+	self, decode_vec_with_len, Compact, Decode, DecodeWithMemTracking, Encode, Error as CodecError,
+	Input as CodecInput, MaxEncodedLen,
 };
 use core::{fmt::Debug, result};
 use derive_where::derive_where;
@@ -57,7 +57,7 @@ pub const VERSION: super::Version = 3;
 /// An identifier for a query.
 pub type QueryId = u64;
 
-#[derive(Default, Encode, TypeInfo)]
+#[derive(Default, DecodeWithMemTracking, Encode, TypeInfo)]
 #[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[scale_info(bounds(), skip_type_params(Call))]
@@ -236,7 +236,9 @@ parameter_types! {
 	pub MaxPalletsInfo: u32 = 64;
 }
 
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
+)]
 #[scale_info(replace_segment("staging_xcm", "xcm"))]
 #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
 pub struct PalletInfo {
@@ -284,7 +286,9 @@ impl TryInto<NewPalletInfo> for PalletInfo {
 	}
 }
 
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
+)]
 #[scale_info(replace_segment("staging_xcm", "xcm"))]
 #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
 pub enum MaybeErrorCode {
@@ -309,7 +313,9 @@ impl Default for MaybeErrorCode {
 }
 
 /// Response data to a query.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
+)]
 #[scale_info(replace_segment("staging_xcm", "xcm"))]
 #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
 pub enum Response {
@@ -360,7 +366,7 @@ impl TryFrom<NewResponse> for Response {
 }
 
 /// Information regarding the composition of a query response.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
+#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
 #[scale_info(replace_segment("staging_xcm", "xcm"))]
 #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
 pub struct QueryResponseInfo {
@@ -386,7 +392,7 @@ impl TryFrom<NewQueryResponseInfo> for QueryResponseInfo {
 }
 
 /// An optional weight limit.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
+#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
 #[scale_info(replace_segment("staging_xcm", "xcm"))]
 #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
 pub enum WeightLimit {
@@ -415,7 +421,7 @@ impl From<WeightLimit> for Option<Weight> {
 }
 
 /// Basically just the XCM (more general) version of `ParachainDispatchOrigin`.
-#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
+#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
 #[scale_info(replace_segment("staging_xcm", "xcm"))]
 #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
 pub enum OriginKind {
@@ -474,10 +480,18 @@ impl XcmContext {
 ///
 /// This is the inner XCM format and is version-sensitive. Messages are typically passed using the
 /// outer XCM format, known as `VersionedXcm`.
-#[derive(Encode, Decode, TypeInfo, xcm_procedural::XcmWeightInfoTrait, xcm_procedural::Builder)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	xcm_procedural::XcmWeightInfoTrait,
+	xcm_procedural::Builder,
+)]
 #[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[codec(decode_bound())]
+#[codec(decode_with_mem_tracking_bound())]
 #[scale_info(bounds(), skip_type_params(Call))]
 #[scale_info(replace_segment("staging_xcm", "xcm"))]
 #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
diff --git a/polkadot/xcm/src/v3/multiasset.rs b/polkadot/xcm/src/v3/multiasset.rs
index e8bd3e167f61ded225d2f66a4525c6f3c72eff5b..b078c9f456777268c3ba50d9fdd84a93427b4b7b 100644
--- a/polkadot/xcm/src/v3/multiasset.rs
+++ b/polkadot/xcm/src/v3/multiasset.rs
@@ -34,7 +34,7 @@ use crate::v4::{
 };
 use alloc::{vec, vec::Vec};
 use bounded_collections::{BoundedVec, ConstU32};
-use codec::{self as codec, Decode, Encode, MaxEncodedLen};
+use codec::{self as codec, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::cmp::Ordering;
 use scale_info::TypeInfo;
 
@@ -48,6 +48,7 @@ use scale_info::TypeInfo;
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
@@ -256,6 +257,7 @@ impl TryFrom<AssetInstance> for u128 {
 	PartialOrd,
 	Debug,
 	Encode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -338,6 +340,7 @@ impl TryFrom<NewFungibility> for Fungibility {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -374,6 +377,7 @@ impl TryFrom<NewWildFungibility> for WildFungibility {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -451,6 +455,7 @@ impl AssetId {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -561,6 +566,7 @@ impl TryFrom<NewMultiAsset> for MultiAsset {
 	PartialOrd,
 	Debug,
 	Encode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	Default,
 	serde::Serialize,
@@ -776,6 +782,7 @@ impl MultiAssets {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -892,6 +899,7 @@ impl<A: Into<AssetId>, B: Into<WildFungibility>> From<(A, B)> for WildMultiAsset
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
diff --git a/polkadot/xcm/src/v3/multilocation.rs b/polkadot/xcm/src/v3/multilocation.rs
index 8f18312046f8820946bb70154a028d2152a054a2..c2da432797b192e2261b0187eca0dfecedd850bb 100644
--- a/polkadot/xcm/src/v3/multilocation.rs
+++ b/polkadot/xcm/src/v3/multilocation.rs
@@ -18,7 +18,7 @@
 
 use super::{Junction, Junctions};
 use crate::{v4::Location as NewMultiLocation, VersionedLocation};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::result;
 use scale_info::TypeInfo;
 
@@ -53,6 +53,7 @@ use scale_info::TypeInfo;
 	Clone,
 	Decode,
 	Encode,
+	DecodeWithMemTracking,
 	Eq,
 	PartialEq,
 	Ord,
diff --git a/polkadot/xcm/src/v3/traits.rs b/polkadot/xcm/src/v3/traits.rs
index cbf85b454cc6c2ba019c763b0376291c3ae8dd68..387530d5fe463ac2adef7b2ca52eb897d40bcf65 100644
--- a/polkadot/xcm/src/v3/traits.rs
+++ b/polkadot/xcm/src/v3/traits.rs
@@ -32,7 +32,7 @@ use super::*;
 /// Error codes used in XCM. The first errors codes have explicit indices and are part of the XCM
 /// format. Those trailing are merely part of the XCM implementation; there is no expectation that
 /// they will retain the same index over time.
-#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)]
+#[derive(Copy, Clone, Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, Debug, TypeInfo)]
 #[scale_info(replace_segment("staging_xcm", "xcm"))]
 #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
 pub enum Error {
@@ -379,7 +379,9 @@ impl<C> ExecuteXcm<C> for () {
 }
 
 /// Error result value when attempting to send an XCM message.
-#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, scale_info::TypeInfo)]
+#[derive(
+	Clone, Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, Debug, scale_info::TypeInfo,
+)]
 #[scale_info(replace_segment("staging_xcm", "xcm"))]
 pub enum SendError {
 	/// The message and destination combination was not recognized as being reachable.
diff --git a/polkadot/xcm/src/v4/asset.rs b/polkadot/xcm/src/v4/asset.rs
index d7a9297d69322899f7f025e1791c4bc6024c6ca5..414fa29267ccfd3e8f9784b8bb3b931f78dee91e 100644
--- a/polkadot/xcm/src/v4/asset.rs
+++ b/polkadot/xcm/src/v4/asset.rs
@@ -41,7 +41,7 @@ use crate::{
 };
 use alloc::{vec, vec::Vec};
 use bounded_collections::{BoundedVec, ConstU32};
-use codec::{self as codec, Decode, Encode, MaxEncodedLen};
+use codec::{self as codec, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::cmp::Ordering;
 use scale_info::TypeInfo;
 
@@ -55,6 +55,7 @@ use scale_info::TypeInfo;
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
@@ -287,6 +288,7 @@ impl TryFrom<NewFungibility> for Fungibility {
 	PartialOrd,
 	Debug,
 	Encode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -367,6 +369,7 @@ impl TryFrom<OldFungibility> for Fungibility {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -411,6 +414,7 @@ impl TryFrom<NewWildFungibility> for WildFungibility {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -488,6 +492,7 @@ impl Reanchorable for AssetId {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -599,6 +604,7 @@ impl TryFrom<NewAsset> for Asset {
 	PartialOrd,
 	Debug,
 	Encode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	Default,
 	serde::Serialize,
@@ -828,6 +834,7 @@ impl Reanchorable for Assets {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -952,6 +959,7 @@ impl<A: Into<AssetId>, B: Into<WildFungibility>> From<(A, B)> for WildAsset {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
diff --git a/polkadot/xcm/src/v4/junction.rs b/polkadot/xcm/src/v4/junction.rs
index c6e83214328e92f2762e028a62a654cd008080c9..4d85ac79bc7fdc32bbf3ca90d6af767f83b5bf80 100644
--- a/polkadot/xcm/src/v4/junction.rs
+++ b/polkadot/xcm/src/v4/junction.rs
@@ -24,7 +24,7 @@ use crate::{
 	VersionedLocation,
 };
 use bounded_collections::{BoundedSlice, BoundedVec, ConstU32};
-use codec::{self, Decode, Encode, MaxEncodedLen};
+use codec::{self, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 use serde::{Deserialize, Serialize};
 
@@ -40,6 +40,7 @@ use serde::{Deserialize, Serialize};
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
@@ -138,6 +139,7 @@ impl From<NewNetworkId> for NetworkId {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
diff --git a/polkadot/xcm/src/v4/junctions.rs b/polkadot/xcm/src/v4/junctions.rs
index e5c54ecb21a5fd61772a011f6a34d359138a30dd..374d1636009a674482e841860aef3ac07a2aa1aa 100644
--- a/polkadot/xcm/src/v4/junctions.rs
+++ b/polkadot/xcm/src/v4/junctions.rs
@@ -18,7 +18,7 @@
 
 use super::{Junction, Location, NetworkId};
 use alloc::sync::Arc;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::{mem, ops::Range, result};
 use scale_info::TypeInfo;
 
@@ -38,6 +38,7 @@ pub(crate) const MAX_JUNCTIONS: usize = 8;
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
diff --git a/polkadot/xcm/src/v4/location.rs b/polkadot/xcm/src/v4/location.rs
index 3a44b0696be41687a2a0d04a66e39c265501b391..1e31bd3b815f05e291039cd75302324249cdf3fd 100644
--- a/polkadot/xcm/src/v4/location.rs
+++ b/polkadot/xcm/src/v4/location.rs
@@ -18,7 +18,7 @@
 
 use super::{traits::Reanchorable, Junction, Junctions};
 use crate::{v3::MultiLocation as OldLocation, v5::Location as NewLocation, VersionedLocation};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::result;
 use scale_info::TypeInfo;
 
@@ -51,6 +51,7 @@ use scale_info::TypeInfo;
 #[derive(
 	Clone,
 	Decode,
+	DecodeWithMemTracking,
 	Encode,
 	Eq,
 	PartialEq,
diff --git a/polkadot/xcm/src/v4/mod.rs b/polkadot/xcm/src/v4/mod.rs
index 66816e2fb6e7e3e4aaee7cef5de32d647c679d66..b40a161be60b4c83ddae4ad5481493024160d929 100644
--- a/polkadot/xcm/src/v4/mod.rs
+++ b/polkadot/xcm/src/v4/mod.rs
@@ -31,8 +31,8 @@ use crate::DoubleEncoded;
 use alloc::{vec, vec::Vec};
 use bounded_collections::{parameter_types, BoundedVec};
 use codec::{
-	self, decode_vec_with_len, Compact, Decode, Encode, Error as CodecError, Input as CodecInput,
-	MaxEncodedLen,
+	self, decode_vec_with_len, Compact, Decode, DecodeWithMemTracking, Encode, Error as CodecError,
+	Input as CodecInput, MaxEncodedLen,
 };
 use core::{fmt::Debug, result};
 use derive_where::derive_where;
@@ -65,7 +65,7 @@ pub const VERSION: super::Version = 4;
 /// An identifier for a query.
 pub type QueryId = u64;
 
-#[derive(Default, Encode, TypeInfo)]
+#[derive(Default, Encode, DecodeWithMemTracking, TypeInfo)]
 #[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[codec(decode_bound())]
@@ -232,7 +232,9 @@ parameter_types! {
 	pub MaxPalletsInfo: u32 = 64;
 }
 
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
+)]
 pub struct PalletInfo {
 	#[codec(compact)]
 	pub index: u32,
@@ -295,7 +297,9 @@ impl PalletInfo {
 }
 
 /// Response data to a query.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
+)]
 pub enum Response {
 	/// No response. Serves as a neutral default.
 	Null,
@@ -373,7 +377,7 @@ impl TryFrom<NewResponse> for Response {
 }
 
 /// Information regarding the composition of a query response.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
+#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
 pub struct QueryResponseInfo {
 	/// The destination to which the query response message should be send.
 	pub destination: Location,
@@ -436,10 +440,18 @@ impl XcmContext {
 ///
 /// This is the inner XCM format and is version-sensitive. Messages are typically passed using the
 /// outer XCM format, known as `VersionedXcm`.
-#[derive(Encode, Decode, TypeInfo, xcm_procedural::XcmWeightInfoTrait, xcm_procedural::Builder)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	xcm_procedural::XcmWeightInfoTrait,
+	xcm_procedural::Builder,
+)]
 #[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[codec(decode_bound())]
+#[codec(decode_with_mem_tracking_bound())]
 #[scale_info(bounds(), skip_type_params(Call))]
 pub enum Instruction<Call> {
 	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place them into the Holding
diff --git a/polkadot/xcm/src/v5/asset.rs b/polkadot/xcm/src/v5/asset.rs
index d0d9a7cedff0592bf55306af25eb363255236a08..b781ef057504e2c6f0edc123188cb622d7977c97 100644
--- a/polkadot/xcm/src/v5/asset.rs
+++ b/polkadot/xcm/src/v5/asset.rs
@@ -34,7 +34,7 @@ use crate::v4::{
 };
 use alloc::{vec, vec::Vec};
 use bounded_collections::{BoundedVec, ConstU32};
-use codec::{self as codec, Decode, Encode, MaxEncodedLen};
+use codec::{self as codec, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::cmp::Ordering;
 use scale_info::TypeInfo;
 
@@ -48,6 +48,7 @@ use scale_info::TypeInfo;
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
@@ -254,6 +255,7 @@ impl TryFrom<AssetInstance> for u128 {
 	PartialOrd,
 	Debug,
 	Encode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -334,6 +336,7 @@ impl TryFrom<OldFungibility> for Fungibility {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -367,6 +370,7 @@ impl TryFrom<OldWildFungibility> for WildFungibility {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -433,6 +437,7 @@ impl Reanchorable for AssetId {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -537,6 +542,7 @@ impl TryFrom<OldAsset> for Asset {
 	PartialOrd,
 	Debug,
 	Encode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	Default,
 	serde::Serialize,
@@ -754,6 +760,7 @@ impl Reanchorable for Assets {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -864,6 +871,7 @@ impl<A: Into<AssetId>, B: Into<WildFungibility>> From<(A, B)> for WildAsset {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
@@ -962,6 +970,7 @@ impl TryFrom<OldAssetFilter> for AssetFilter {
 	Debug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 	serde::Serialize,
diff --git a/polkadot/xcm/src/v5/junction.rs b/polkadot/xcm/src/v5/junction.rs
index d86a762fcf44514b7b414ecf89e21988ebc3d42a..bd5753d69d2ab9288e1613e434acf7ed5bb26540 100644
--- a/polkadot/xcm/src/v5/junction.rs
+++ b/polkadot/xcm/src/v5/junction.rs
@@ -23,7 +23,7 @@ use crate::{
 	VersionedLocation,
 };
 use bounded_collections::{BoundedSlice, BoundedVec, ConstU32};
-use codec::{self, Decode, Encode, MaxEncodedLen};
+use codec::{self, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use hex_literal::hex;
 use scale_info::TypeInfo;
 use serde::{Deserialize, Serialize};
@@ -40,6 +40,7 @@ use serde::{Deserialize, Serialize};
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
@@ -127,6 +128,7 @@ pub const DUMMY_GENESIS_HASH: [u8; 32] = [0; 32];
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
diff --git a/polkadot/xcm/src/v5/junctions.rs b/polkadot/xcm/src/v5/junctions.rs
index dc93c541d19d59596b75ed6707a9e594b72b5456..ec5381a2472c54068b673d99b39206efdeb055d3 100644
--- a/polkadot/xcm/src/v5/junctions.rs
+++ b/polkadot/xcm/src/v5/junctions.rs
@@ -18,7 +18,7 @@
 
 use super::{Junction, Location, NetworkId};
 use alloc::sync::Arc;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::{mem, ops::Range, result};
 use scale_info::TypeInfo;
 
@@ -38,6 +38,7 @@ pub(crate) const MAX_JUNCTIONS: usize = 8;
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	TypeInfo,
 	MaxEncodedLen,
diff --git a/polkadot/xcm/src/v5/location.rs b/polkadot/xcm/src/v5/location.rs
index 38e8ecdd15ca88155ede9322dd8c714edca7c504..c80cd11b0aac9d8766c0e1c8c94c69723d8be2fc 100644
--- a/polkadot/xcm/src/v5/location.rs
+++ b/polkadot/xcm/src/v5/location.rs
@@ -18,7 +18,7 @@
 
 use super::{traits::Reanchorable, Junction, Junctions};
 use crate::{v4::Location as OldLocation, VersionedLocation};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::result;
 use scale_info::TypeInfo;
 
@@ -52,6 +52,7 @@ use scale_info::TypeInfo;
 	Clone,
 	Decode,
 	Encode,
+	DecodeWithMemTracking,
 	Eq,
 	PartialEq,
 	Ord,
diff --git a/polkadot/xcm/src/v5/mod.rs b/polkadot/xcm/src/v5/mod.rs
index 51f6d839e972abfc3b98e94c7e649f7f2b9426bb..924e514618dd942f054d463884844f32d7ad4867 100644
--- a/polkadot/xcm/src/v5/mod.rs
+++ b/polkadot/xcm/src/v5/mod.rs
@@ -25,8 +25,8 @@ use crate::DoubleEncoded;
 use alloc::{vec, vec::Vec};
 use bounded_collections::{parameter_types, BoundedVec};
 use codec::{
-	self, decode_vec_with_len, Compact, Decode, Encode, Error as CodecError, Input as CodecInput,
-	MaxEncodedLen,
+	self, decode_vec_with_len, Compact, Decode, DecodeWithMemTracking, Encode, Error as CodecError,
+	Input as CodecInput, MaxEncodedLen,
 };
 use core::{fmt::Debug, result};
 use derive_where::derive_where;
@@ -59,7 +59,7 @@ pub const VERSION: super::Version = 5;
 /// An identifier for a query.
 pub type QueryId = u64;
 
-#[derive(Default, Encode, TypeInfo)]
+#[derive(Default, DecodeWithMemTracking, Encode, TypeInfo)]
 #[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[codec(decode_bound())]
@@ -228,7 +228,9 @@ parameter_types! {
 	pub MaxPalletsInfo: u32 = 64;
 }
 
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
+)]
 pub struct PalletInfo {
 	#[codec(compact)]
 	pub index: u32,
@@ -275,7 +277,9 @@ impl PalletInfo {
 }
 
 /// Response data to a query.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
+)]
 pub enum Response {
 	/// No response. Serves as a neutral default.
 	Null,
@@ -327,7 +331,7 @@ impl TryFrom<OldResponse> for Response {
 }
 
 /// Information regarding the composition of a query response.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
+#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
 pub struct QueryResponseInfo {
 	/// The destination to which the query response message should be send.
 	pub destination: Location,
@@ -378,10 +382,18 @@ impl XcmContext {
 ///
 /// This is the inner XCM format and is version-sensitive. Messages are typically passed using the
 /// outer XCM format, known as `VersionedXcm`.
-#[derive(Encode, Decode, TypeInfo, xcm_procedural::XcmWeightInfoTrait, xcm_procedural::Builder)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	xcm_procedural::XcmWeightInfoTrait,
+	xcm_procedural::Builder,
+)]
 #[derive_where(Clone, Eq, PartialEq, Debug)]
 #[codec(encode_bound())]
 #[codec(decode_bound())]
+#[codec(decode_with_mem_tracking_bound())]
 #[scale_info(bounds(), skip_type_params(Call))]
 pub enum Instruction<Call> {
 	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place them into the Holding
@@ -1134,7 +1146,17 @@ pub enum Instruction<Call> {
 	SetHints { hints: BoundedVec<Hint, HintNumVariants> },
 }
 
-#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone, xcm_procedural::NumVariants)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	Debug,
+	PartialEq,
+	Eq,
+	Clone,
+	xcm_procedural::NumVariants,
+)]
 pub enum Hint {
 	/// Set asset claimer for all the trapped assets during the execution.
 	///
diff --git a/polkadot/xcm/src/v5/traits.rs b/polkadot/xcm/src/v5/traits.rs
index 79d3285614287fd98e7cbc8013dd2f45e209c4e5..4ee921589164b6f4520e3c04a6ad4355875b0c32 100644
--- a/polkadot/xcm/src/v5/traits.rs
+++ b/polkadot/xcm/src/v5/traits.rs
@@ -17,7 +17,7 @@
 //! Cross-Consensus Message format data structures.
 
 pub use crate::v3::{Error as OldError, SendError, XcmHash};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use core::result;
 use scale_info::TypeInfo;
 
@@ -28,7 +28,7 @@ use super::*;
 /// Error codes used in XCM. The first errors codes have explicit indices and are part of the XCM
 /// format. Those trailing are merely part of the XCM implementation; there is no expectation that
 /// they will retain the same index over time.
-#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)]
+#[derive(Copy, Clone, Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, Debug, TypeInfo)]
 #[scale_info(replace_segment("staging_xcm", "xcm"))]
 #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
 pub enum Error {
@@ -240,7 +240,7 @@ impl From<SendError> for Error {
 pub type Result = result::Result<(), Error>;
 
 /// Outcome of an XCM execution.
-#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)]
+#[derive(Clone, Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, Debug, TypeInfo)]
 pub enum Outcome {
 	/// Execution completed successfully; given weight was used.
 	Complete { used: Weight },
diff --git a/polkadot/xcm/xcm-builder/Cargo.toml b/polkadot/xcm/xcm-builder/Cargo.toml
index 5169f586d723784e408afc3b4437635a6485ec02..764c788f2d0f4bf393338ec2e56fde4ff36eca9f 100644
--- a/polkadot/xcm/xcm-builder/Cargo.toml
+++ b/polkadot/xcm/xcm-builder/Cargo.toml
@@ -13,6 +13,7 @@ workspace = true
 
 [dependencies]
 codec = { features = ["derive"], workspace = true }
+environmental = { workspace = true }
 frame-support = { workspace = true }
 frame-system = { workspace = true }
 impl-trait-for-tuples = { workspace = true }
@@ -21,6 +22,7 @@ pallet-asset-conversion = { workspace = true }
 pallet-transaction-payment = { workspace = true }
 scale-info = { features = ["derive"], workspace = true }
 sp-arithmetic = { workspace = true }
+sp-core = { workspace = true }
 sp-io = { workspace = true }
 sp-runtime = { workspace = true }
 sp-weights = { workspace = true }
@@ -39,7 +41,6 @@ polkadot-primitives = { workspace = true, default-features = true }
 polkadot-runtime-parachains = { workspace = true, default-features = true }
 polkadot-test-runtime = { workspace = true }
 primitive-types = { features = ["codec", "num-traits", "scale-info"], workspace = true }
-sp-core = { workspace = true, default-features = true }
 
 [features]
 default = ["std"]
@@ -62,6 +63,7 @@ runtime-benchmarks = [
 ]
 std = [
 	"codec/std",
+	"environmental/std",
 	"frame-support/std",
 	"frame-system/std",
 	"log/std",
@@ -71,6 +73,7 @@ std = [
 	"primitive-types/std",
 	"scale-info/std",
 	"sp-arithmetic/std",
+	"sp-core/std",
 	"sp-io/std",
 	"sp-runtime/std",
 	"sp-weights/std",
diff --git a/polkadot/xcm/xcm-builder/src/barriers.rs b/polkadot/xcm/xcm-builder/src/barriers.rs
index 9f9d3c2321228d088ab12078dfec83d7c00e9bc6..6eda6bd2bbeef7ebe8bb191a8006df4895c19393 100644
--- a/polkadot/xcm/xcm-builder/src/barriers.rs
+++ b/polkadot/xcm/xcm-builder/src/barriers.rs
@@ -20,7 +20,7 @@ use crate::{CreateMatcher, MatchXcm};
 use core::{cell::Cell, marker::PhantomData, ops::ControlFlow, result::Result};
 use frame_support::{
 	ensure,
-	traits::{Contains, Get, ProcessMessageError},
+	traits::{Contains, ContainsPair, Get, Nothing, ProcessMessageError},
 };
 use polkadot_parachain_primitives::primitives::IsSystem;
 use xcm::prelude::*;
@@ -290,11 +290,25 @@ impl<T: Contains<Location>> ShouldExecute for AllowUnpaidExecutionFrom<T> {
 }
 
 /// Allows execution from any origin that is contained in `T` (i.e. `T::Contains(origin)`) if the
-/// message begins with the instruction `UnpaidExecution`.
+/// message explicitly includes the `UnpaidExecution` instruction.
 ///
 /// Use only for executions from trusted origin groups.
-pub struct AllowExplicitUnpaidExecutionFrom<T>(PhantomData<T>);
-impl<T: Contains<Location>> ShouldExecute for AllowExplicitUnpaidExecutionFrom<T> {
+///
+/// Allows for the message to receive teleports or reserve asset transfers and altering
+/// the origin before indicating `UnpaidExecution`.
+///
+/// Origin altering instructions are executed so the barrier can more accurately reject messages
+/// whose effective origin at the time of calling `UnpaidExecution` is not allowed.
+/// This means `T` will be checked against the actual origin _after_ being modified by prior
+/// instructions.
+///
+/// In order to execute the `AliasOrigin` instruction, the `Aliasers` type should be set to the same
+/// `Aliasers` item in the XCM configuration. If it isn't, then all messages with an `AliasOrigin`
+/// instruction will be rejected.
+pub struct AllowExplicitUnpaidExecutionFrom<T, Aliasers = Nothing>(PhantomData<(T, Aliasers)>);
+impl<T: Contains<Location>, Aliasers: ContainsPair<Location, Location>> ShouldExecute
+	for AllowExplicitUnpaidExecutionFrom<T, Aliasers>
+{
 	fn should_execute<Call>(
 		origin: &Location,
 		instructions: &mut [Instruction<Call>],
@@ -306,12 +320,69 @@ impl<T: Contains<Location>> ShouldExecute for AllowExplicitUnpaidExecutionFrom<T
 			"AllowExplicitUnpaidExecutionFrom origin: {:?}, instructions: {:?}, max_weight: {:?}, properties: {:?}",
 			origin, instructions, max_weight, _properties,
 		);
-		ensure!(T::contains(origin), ProcessMessageError::Unsupported);
-		instructions.matcher().match_next_inst(|inst| match inst {
-			UnpaidExecution { weight_limit: Limited(m), .. } if m.all_gte(max_weight) => Ok(()),
-			UnpaidExecution { weight_limit: Unlimited, .. } => Ok(()),
-			_ => Err(ProcessMessageError::Overweight(max_weight)),
-		})?;
+		// We will read up to 5 instructions before `UnpaidExecution`.
+		// This allows up to 3 asset transfer instructions, thus covering all possible transfer
+		// types, followed by a potential origin altering instruction, and a potential `SetHints`.
+		let mut actual_origin = origin.clone();
+		let processed = Cell::new(0usize);
+		let instructions_to_process = 5;
+		instructions
+			.matcher()
+			// We skip set hints and all types of asset transfer instructions.
+			.match_next_inst_while(
+				|inst| {
+					processed.get() < instructions_to_process &&
+						matches!(
+							inst,
+							ReceiveTeleportedAsset(_) |
+								ReserveAssetDeposited(_) | WithdrawAsset(_) |
+								SetHints { .. }
+						)
+				},
+				|_| {
+					processed.set(processed.get() + 1);
+					Ok(ControlFlow::Continue(()))
+				},
+			)?
+			// Then we go through all origin altering instructions and we
+			// alter the original origin.
+			.match_next_inst_while(
+				|_| processed.get() < instructions_to_process,
+				|inst| {
+					match inst {
+						ClearOrigin => {
+							// We don't support the `ClearOrigin` instruction since we always need
+							// to know the origin to know if it's allowed unpaid execution.
+							return Err(ProcessMessageError::Unsupported);
+						},
+						AliasOrigin(target) =>
+							if Aliasers::contains(&actual_origin, &target) {
+								actual_origin = target.clone();
+							} else {
+								return Err(ProcessMessageError::Unsupported);
+							},
+						DescendOrigin(child) if child != &Here => {
+							let Ok(_) = actual_origin.append_with(child.clone()) else {
+								return Err(ProcessMessageError::Unsupported);
+							};
+						},
+						_ => return Ok(ControlFlow::Break(())),
+					};
+					processed.set(processed.get() + 1);
+					Ok(ControlFlow::Continue(()))
+				},
+			)?
+			// We finally match on the required `UnpaidExecution` instruction.
+			.match_next_inst(|inst| match inst {
+				UnpaidExecution { weight_limit: Limited(m), .. } if m.all_gte(max_weight) => Ok(()),
+				UnpaidExecution { weight_limit: Unlimited, .. } => Ok(()),
+				_ => Err(ProcessMessageError::Overweight(max_weight)),
+			})?;
+
+		// After processing all the instructions, `actual_origin` was modified and we
+		// check if it's allowed to have unpaid execution.
+		ensure!(T::contains(&actual_origin), ProcessMessageError::Unsupported);
+
 		Ok(())
 	}
 }
@@ -502,3 +573,96 @@ impl DenyExecution for DenyReserveTransferToRelayChain {
 		Ok(())
 	}
 }
+
+environmental::environmental!(recursion_count: u8);
+
+/// Denies execution if the XCM contains instructions not meant to run on this chain,
+/// first checking at the top-level and then **recursively**.
+///
+/// This barrier only applies to **locally executed** XCM instructions (`SetAppendix`,
+/// `SetErrorHandler`, and `ExecuteWithOrigin`). Remote parts of the XCM are expected to be
+/// validated by the receiving chain's barrier.
+///
+/// Note: Ensures that restricted instructions do not execute on the local chain, enforcing stricter
+/// execution policies while allowing remote chains to enforce their own rules.
+pub struct DenyRecursively<Inner>(PhantomData<Inner>);
+
+impl<Inner: DenyExecution> DenyRecursively<Inner> {
+	/// Recursively applies the deny filter to a nested XCM.
+	///
+	/// Ensures that restricted instructions are blocked at any depth within the XCM.
+	/// Uses a **recursion counter** to prevent stack overflows from deep nesting.
+	fn deny_recursively<RuntimeCall>(
+		origin: &Location,
+		xcm: &mut Xcm<RuntimeCall>,
+		max_weight: Weight,
+		properties: &mut Properties,
+	) -> Result<ControlFlow<()>, ProcessMessageError> {
+		// Initialise recursion counter for this execution context.
+		recursion_count::using_once(&mut 1, || {
+			// Prevent stack overflow by enforcing a recursion depth limit.
+			recursion_count::with(|count| {
+				if *count > xcm_executor::RECURSION_LIMIT {
+					log::debug!(
+                    	target: "xcm::barriers",
+                    	"Recursion limit exceeded (count: {count}), origin: {:?}, xcm: {:?}, max_weight: {:?}, properties: {:?}",
+                    	origin, xcm, max_weight, properties
+                	);
+					return None;
+				}
+				*count = count.saturating_add(1);
+				Some(())
+			}).flatten().ok_or(ProcessMessageError::StackLimitReached)?;
+
+			// Ensure the counter is decremented even if an early return occurs.
+			sp_core::defer! {
+				recursion_count::with(|count| {
+					*count = count.saturating_sub(1);
+				});
+			}
+
+			// Recursively check the nested XCM instructions.
+			Self::deny_execution(origin, xcm.inner_mut(), max_weight, properties)
+		})?;
+
+		Ok(ControlFlow::Continue(()))
+	}
+}
+
+impl<Inner: DenyExecution> DenyExecution for DenyRecursively<Inner> {
+	/// Denies execution of restricted local nested XCM instructions.
+	///
+	/// This checks for `SetAppendix`, `SetErrorHandler`, and `ExecuteWithOrigin` instruction
+	/// applying the deny filter **recursively** to any nested XCMs found.
+	fn deny_execution<RuntimeCall>(
+		origin: &Location,
+		instructions: &mut [Instruction<RuntimeCall>],
+		max_weight: Weight,
+		properties: &mut Properties,
+	) -> Result<(), ProcessMessageError> {
+		// First, check if the top-level message should be denied.
+		Inner::deny_execution(origin, instructions, max_weight, properties).inspect_err(|e| {
+			log::warn!(
+				target: "xcm::barriers",
+				"DenyRecursively::Inner denied execution, origin: {:?}, instructions: {:?}, max_weight: {:?}, properties: {:?}, error: {:?}",
+				origin, instructions, max_weight, properties, e
+			);
+		})?;
+
+		// If the top-level check passes, check nested instructions recursively.
+		instructions.matcher().match_next_inst_while(
+			|_| true,
+			|inst| match inst {
+				SetAppendix(nested_xcm) |
+				SetErrorHandler(nested_xcm) |
+				ExecuteWithOrigin { xcm: nested_xcm, .. } => Self::deny_recursively::<RuntimeCall>(
+					origin, nested_xcm, max_weight, properties,
+				),
+				_ => Ok(ControlFlow::Continue(())),
+			},
+		)?;
+
+		// Permit everything else
+		Ok(())
+	}
+}
diff --git a/polkadot/xcm/xcm-builder/src/lib.rs b/polkadot/xcm/xcm-builder/src/lib.rs
index e23412a97ebcb3e6f2999d0f48d555e53d02503e..4c48589e6712714f0abf858447eb72b9536f0a55 100644
--- a/polkadot/xcm/xcm-builder/src/lib.rs
+++ b/polkadot/xcm/xcm-builder/src/lib.rs
@@ -42,9 +42,9 @@ mod barriers;
 pub use barriers::{
 	AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
 	AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
-	AllowUnpaidExecutionFrom, DenyReserveTransferToRelayChain, DenyThenTry, IsChildSystemParachain,
-	IsParentsOnly, IsSiblingSystemParachain, RespectSuspension, TakeWeightCredit,
-	TrailingSetTopicAsId, WithComputedOrigin,
+	AllowUnpaidExecutionFrom, DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry,
+	IsChildSystemParachain, IsParentsOnly, IsSiblingSystemParachain, RespectSuspension,
+	TakeWeightCredit, TrailingSetTopicAsId, WithComputedOrigin,
 };
 
 mod controller;
diff --git a/polkadot/xcm/xcm-builder/src/matcher.rs b/polkadot/xcm/xcm-builder/src/matcher.rs
index ab515f180527da4a3ff0d4c68bf9ab4a337ac33f..2fed64bccde86c1132efe0887f7e920787826081 100644
--- a/polkadot/xcm/xcm-builder/src/matcher.rs
+++ b/polkadot/xcm/xcm-builder/src/matcher.rs
@@ -179,6 +179,20 @@ mod tests {
 	use std::{vec, vec::Vec};
 	use xcm::latest::prelude::*;
 
+	#[test]
+	fn match_next_inst_works() {
+		let test_cases: Vec<(Vec<Instruction<()>>, bool)> =
+			vec![(vec![ClearOrigin], true), (vec![Trap(0)], false)];
+
+		for (mut xcm, expected) in test_cases.into_iter() {
+			let result = xcm.matcher().match_next_inst(|inst| match inst {
+				ClearOrigin => Ok(()),
+				_ => Err(ProcessMessageError::Unsupported),
+			});
+			assert_eq!(result.is_ok(), expected);
+		}
+	}
+
 	#[test]
 	fn match_next_inst_while_works() {
 		let mut xcm: Vec<Instruction<()>> = vec![ClearOrigin];
diff --git a/polkadot/xcm/xcm-builder/src/tests/barriers.rs b/polkadot/xcm/xcm-builder/src/tests/barriers.rs
index 2fb8e8ed0363b09794f7e4720f8eeab58994e0ff..f3da1745d3d1b4efbba030119635feb10b8419e9 100644
--- a/polkadot/xcm/xcm-builder/src/tests/barriers.rs
+++ b/polkadot/xcm/xcm-builder/src/tests/barriers.rs
@@ -14,6 +14,7 @@
 // You should have received a copy of the GNU General Public License
 // along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
 
+use std::marker::PhantomData;
 use xcm_executor::traits::Properties;
 
 use super::*;
@@ -147,9 +148,10 @@ fn allow_explicit_unpaid_should_work() {
 		TransferAsset { assets: (Parent, 100).into(), beneficiary: Here.into() },
 	]);
 
-	AllowExplicitUnpaidFrom::set(vec![Parent.into()]);
+	AllowExplicitUnpaidFrom::set(vec![Parent.into(), (Parent, Parachain(1000)).into()]);
+	type ExplicitUnpaidBarrier<T> = AllowExplicitUnpaidExecutionFrom<T, mock::Aliasers>;
 
-	let r = AllowExplicitUnpaidExecutionFrom::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+	let r = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
 		&Parachain(1).into(),
 		good_message.inner_mut(),
 		Weight::from_parts(20, 20),
@@ -157,7 +159,7 @@ fn allow_explicit_unpaid_should_work() {
 	);
 	assert_eq!(r, Err(ProcessMessageError::Unsupported));
 
-	let r = AllowExplicitUnpaidExecutionFrom::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+	let r = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
 		&Parent.into(),
 		bad_message1.inner_mut(),
 		Weight::from_parts(20, 20),
@@ -165,7 +167,7 @@ fn allow_explicit_unpaid_should_work() {
 	);
 	assert_eq!(r, Err(ProcessMessageError::Overweight(Weight::from_parts(20, 20))));
 
-	let r = AllowExplicitUnpaidExecutionFrom::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+	let r = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
 		&Parent.into(),
 		bad_message2.inner_mut(),
 		Weight::from_parts(20, 20),
@@ -173,7 +175,7 @@ fn allow_explicit_unpaid_should_work() {
 	);
 	assert_eq!(r, Err(ProcessMessageError::Overweight(Weight::from_parts(20, 20))));
 
-	let r = AllowExplicitUnpaidExecutionFrom::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+	let r = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
 		&Parent.into(),
 		good_message.inner_mut(),
 		Weight::from_parts(20, 20),
@@ -189,7 +191,7 @@ fn allow_explicit_unpaid_should_work() {
 		TransferAsset { assets: (Parent, 100).into(), beneficiary: Here.into() },
 	]);
 
-	let r = AllowExplicitUnpaidExecutionFrom::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+	let r = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
 		&Parent.into(),
 		message_with_different_weight_parts.inner_mut(),
 		Weight::from_parts(20, 20),
@@ -197,13 +199,372 @@ fn allow_explicit_unpaid_should_work() {
 	);
 	assert_eq!(r, Err(ProcessMessageError::Overweight(Weight::from_parts(20, 20))));
 
-	let r = AllowExplicitUnpaidExecutionFrom::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+	let r = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
 		&Parent.into(),
 		message_with_different_weight_parts.inner_mut(),
 		Weight::from_parts(10, 10),
 		&mut props(Weight::zero()),
 	);
 	assert_eq!(r, Ok(()));
+
+	// Invalid since location to alias is not allowed.
+	let mut message = Xcm::<()>::builder_unsafe()
+		.receive_teleported_asset((Here, 100u128))
+		.alias_origin(Parachain(1000))
+		.unpaid_execution(Unlimited, None)
+		.build();
+	let result = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(30, 30),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Err(ProcessMessageError::Unsupported));
+
+	// Valid because all parachains are children of the relay chain.
+	let mut message = Xcm::<()>::builder_unsafe()
+		.receive_teleported_asset((Here, 100u128))
+		.alias_origin((Parent, Parachain(1000)))
+		.unpaid_execution(Unlimited, None)
+		.build();
+	let result = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(30, 30),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Ok(()));
+
+	// Valid.
+	let mut message = Xcm::<()>::builder_unsafe()
+		.alias_origin((Parent, Parachain(1000)))
+		.unpaid_execution(Unlimited, None)
+		.build();
+	let result = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(30, 30),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Ok(()));
+
+	// Invalid because `ClearOrigin` clears origin and `UnpaidExecution`
+	// can't know if there are enough permissions.
+	let mut message = Xcm::<()>::builder_unsafe()
+		.receive_teleported_asset((Here, 100u128))
+		.clear_origin()
+		.unpaid_execution(Unlimited, None)
+		.build();
+	let result = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(30, 30),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Err(ProcessMessageError::Unsupported));
+
+	// Valid.
+	let mut message = Xcm::<()>::builder_unsafe()
+		.receive_teleported_asset((Here, 100u128))
+		.reserve_asset_deposited((Parent, 100u128))
+		.descend_origin(Parachain(1000))
+		.unpaid_execution(Unlimited, None)
+		.build();
+	let result = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(40, 40),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Ok(()));
+
+	// Invalid because of `ClearOrigin`.
+	let mut message = Xcm::<()>::builder_unsafe()
+		.receive_teleported_asset((Here, 100u128))
+		.clear_origin()
+		.build();
+	let result = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(30, 30),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Err(ProcessMessageError::Unsupported));
+
+	// Invalid because there is no `UnpaidExecution`.
+	let mut message = Xcm::<()>::builder_unsafe()
+		.receive_teleported_asset((Here, 100u128))
+		.alias_origin((Parent, Parachain(1000)))
+		.build();
+	let result = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(30, 30),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Err(ProcessMessageError::BadFormat));
+
+	// Invalid because even though alias is valid, it can't use `UnpaidExecution`.
+	let assets: Vec<Asset> = vec![
+		(Parent, 100u128).into(),
+		((Parent, PalletInstance(10), GeneralIndex(1000)), 100u128).into(),
+	];
+	let mut message = Xcm::<()>::builder_unsafe()
+		.set_hints(vec![AssetClaimer {
+			location: AccountId32 { id: [100u8; 32], network: None }.into(),
+		}])
+		.receive_teleported_asset((Here, 100u128))
+		.reserve_asset_deposited(assets)
+		.withdraw_asset((GeneralIndex(1), 100u128))
+		.alias_origin((Parent, AccountId32 { id: [128u8; 32], network: None }))
+		.unpaid_execution(Unlimited, None)
+		.build();
+	let result = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(60, 60),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Err(ProcessMessageError::Unsupported));
+
+	// Invalid because `UnpaidExecution` specifies less weight than needed.
+	let assets: Vec<Asset> = vec![
+		(Parent, 100u128).into(),
+		((Parent, PalletInstance(10), GeneralIndex(1000)), 100u128).into(),
+	];
+	let mut message = Xcm::<()>::builder_unsafe()
+		.set_hints(vec![AssetClaimer {
+			location: AccountId32 { id: [100u8; 32], network: None }.into(),
+		}])
+		.receive_teleported_asset((Here, 100u128))
+		.reserve_asset_deposited(assets)
+		.withdraw_asset((GeneralIndex(1), 100u128))
+		.alias_origin((Parent, Parachain(1000)))
+		.unpaid_execution(Limited(Weight::from_parts(50, 50)), None)
+		.build();
+	let result = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(60, 60),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Err(ProcessMessageError::Overweight(Weight::from_parts(60, 60))));
+
+	// Invalid because of too many instructions before `UnpaidExecution`.
+	let assets: Vec<Asset> = vec![
+		(Parent, 100u128).into(),
+		((Parent, PalletInstance(10), GeneralIndex(1000)), 100u128).into(),
+	];
+	let mut message = Xcm::<()>::builder_unsafe()
+		.set_hints(vec![AssetClaimer {
+			location: AccountId32 { id: [100u8; 32], network: None }.into(),
+		}])
+		.receive_teleported_asset((Here, 100u128))
+		.receive_teleported_asset((Here, 100u128))
+		.reserve_asset_deposited(assets)
+		.withdraw_asset((GeneralIndex(1), 100u128))
+		.alias_origin((Parent, AccountId32 { id: [128u8; 32], network: None }))
+		.unpaid_execution(Limited(Weight::from_parts(50, 50)), None)
+		.build();
+	let result = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(70, 70),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Err(ProcessMessageError::Overweight(Weight::from_parts(70, 70))));
+
+	// Valid.
+	let assets: Vec<Asset> = vec![
+		(Parent, 100u128).into(),
+		((Parent, PalletInstance(10), GeneralIndex(1000)), 100u128).into(),
+	];
+	let mut message = Xcm::<()>::builder_unsafe()
+		.set_hints(vec![AssetClaimer {
+			location: AccountId32 { id: [100u8; 32], network: None }.into(),
+		}])
+		.receive_teleported_asset((Here, 100u128))
+		.reserve_asset_deposited(assets)
+		.withdraw_asset((GeneralIndex(1), 100u128))
+		.alias_origin((Parent, Parachain(1000)))
+		.unpaid_execution(Unlimited, None)
+		.build();
+	let result = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(60, 60),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Ok(()));
+
+	// Valid.
+	let assets: Vec<Asset> = vec![
+		(Parent, 100u128).into(),
+		((Parent, PalletInstance(10), GeneralIndex(1000)), 100u128).into(),
+	];
+	let mut message = Xcm::<()>::builder_unsafe()
+		.set_hints(vec![AssetClaimer {
+			location: AccountId32 { id: [100u8; 32], network: None }.into(),
+		}])
+		.receive_teleported_asset((Here, 100u128))
+		.reserve_asset_deposited(assets)
+		.withdraw_asset((GeneralIndex(1), 100u128))
+		.descend_origin(Parachain(1000))
+		.unpaid_execution(Unlimited, None)
+		.build();
+	let result = ExplicitUnpaidBarrier::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(60, 60),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Ok(()));
+}
+
+#[test]
+fn allow_explicit_unpaid_fails_with_alias_origin_if_no_aliasers() {
+	AllowExplicitUnpaidFrom::set(vec![(Parent, Parachain(1000)).into()]);
+
+	let assets: Vec<Asset> = vec![
+		(Parent, 100u128).into(),
+		((Parent, PalletInstance(10), GeneralIndex(1000)), 100u128).into(),
+	];
+	let mut good_message = Xcm::<()>::builder_unsafe()
+		.set_hints(vec![AssetClaimer {
+			location: AccountId32 { id: [100u8; 32], network: None }.into(),
+		}])
+		.receive_teleported_asset((Here, 100u128))
+		.reserve_asset_deposited(assets)
+		.withdraw_asset((GeneralIndex(1), 100u128))
+		.descend_origin(Parachain(1000))
+		.unpaid_execution(Unlimited, None)
+		.build();
+	let result =
+		AllowExplicitUnpaidExecutionFrom::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+			&Parent.into(),
+			good_message.inner_mut(),
+			Weight::from_parts(100, 100),
+			&mut props(Weight::zero()),
+		);
+	assert_eq!(result, Ok(()));
+
+	let assets: Vec<Asset> = vec![
+		(Parent, 100u128).into(),
+		((Parent, PalletInstance(10), GeneralIndex(1000)), 100u128).into(),
+	];
+	let mut bad_message = Xcm::<()>::builder_unsafe()
+		.set_hints(vec![AssetClaimer {
+			location: AccountId32 { id: [100u8; 32], network: None }.into(),
+		}])
+		.receive_teleported_asset((Here, 100u128))
+		.reserve_asset_deposited(assets)
+		.withdraw_asset((GeneralIndex(1), 100u128))
+		.alias_origin((Parent, Parachain(1000)))
+		.unpaid_execution(Unlimited, None)
+		.build();
+	// Barrier has `Aliasers` set as `Nothing` by default, rejecting message if it
+	// has an `AliasOrigin` instruction.
+	let result =
+		AllowExplicitUnpaidExecutionFrom::<IsInVec<AllowExplicitUnpaidFrom>>::should_execute(
+			&Parent.into(),
+			bad_message.inner_mut(),
+			Weight::from_parts(100, 100),
+			&mut props(Weight::zero()),
+		);
+	assert_eq!(result, Err(ProcessMessageError::Unsupported));
+}
+
+#[test]
+fn allow_explicit_unpaid_with_computed_origin() {
+	AllowExplicitUnpaidFrom::set(vec![
+		(Parent, Parachain(1000)).into(),
+		(Parent, Parent, GlobalConsensus(Polkadot), Parachain(1000)).into(),
+	]);
+	type ExplicitUnpaidBarrier<T> = AllowExplicitUnpaidExecutionFrom<T, mock::Aliasers>;
+
+	// Message that passes without `WithComputedOrigin` should also pass with it.
+	let assets: Vec<Asset> = vec![
+		(Parent, 100u128).into(),
+		((Parent, PalletInstance(10), GeneralIndex(1000)), 100u128).into(),
+	];
+	let mut message = Xcm::<()>::builder_unsafe()
+		.set_hints(vec![AssetClaimer {
+			location: AccountId32 { id: [100u8; 32], network: None }.into(),
+		}])
+		.receive_teleported_asset((Here, 100u128))
+		.reserve_asset_deposited(assets)
+		.withdraw_asset((GeneralIndex(1), 100u128))
+		.alias_origin((Parent, Parachain(1000)))
+		.unpaid_execution(Unlimited, None)
+		.build();
+	let result = WithComputedOrigin::<
+		ExplicitUnpaidBarrier<IsInVec<AllowExplicitUnpaidFrom>>,
+		ExecutorUniversalLocation,
+		ConstU32<2>,
+	>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(100, 100),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Ok(()));
+
+	// Can manipulate origin before the inner barrier.
+	// For example, to act as another network.
+	let assets: Vec<Asset> = vec![
+		(Parent, 100u128).into(),
+		((Parent, PalletInstance(10), GeneralIndex(1000)), 100u128).into(),
+	];
+	let mut message = Xcm::<()>::builder_unsafe()
+		.universal_origin(Polkadot)
+		.set_hints(vec![AssetClaimer {
+			location: AccountId32 { id: [100u8; 32], network: None }.into(),
+		}])
+		.receive_teleported_asset((Here, 100u128))
+		.reserve_asset_deposited(assets)
+		.withdraw_asset((GeneralIndex(1), 100u128))
+		.alias_origin((Parent, Parent, GlobalConsensus(Polkadot), Parachain(1000)))
+		.unpaid_execution(Unlimited, None)
+		.build();
+	let result = WithComputedOrigin::<
+		ExplicitUnpaidBarrier<IsInVec<AllowExplicitUnpaidFrom>>,
+		ExecutorUniversalLocation,
+		ConstU32<2>,
+	>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(100, 100),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Ok(()));
+
+	// Any invalid conversions from the new origin fail.
+	let assets: Vec<Asset> = vec![
+		(Parent, 100u128).into(),
+		((Parent, PalletInstance(10), GeneralIndex(1000)), 100u128).into(),
+	];
+	let mut message = Xcm::<()>::builder_unsafe()
+		.universal_origin(Polkadot)
+		.set_hints(vec![AssetClaimer {
+			location: AccountId32 { id: [100u8; 32], network: None }.into(),
+		}])
+		.receive_teleported_asset((Here, 100u128))
+		.reserve_asset_deposited(assets)
+		.withdraw_asset((GeneralIndex(1), 100u128))
+		.alias_origin((Parent, Parachain(1000)))
+		.unpaid_execution(Unlimited, None)
+		.build();
+	let result = WithComputedOrigin::<
+		ExplicitUnpaidBarrier<IsInVec<AllowExplicitUnpaidFrom>>,
+		ExecutorUniversalLocation,
+		ConstU32<2>,
+	>::should_execute(
+		&Parent.into(),
+		message.inner_mut(),
+		Weight::from_parts(100, 100),
+		&mut props(Weight::zero()),
+	);
+	assert_eq!(result, Err(ProcessMessageError::Unsupported));
 }
 
 #[test]
@@ -764,3 +1125,258 @@ fn deny_reserve_transfer_to_relaychain_should_work() {
 	// others instructions should pass
 	assert_deny_execution(vec![ClearOrigin], Here.into_location(), Ok(()));
 }
+
+// Dummy Barriers
+// Dummy filter to allow all
+struct AllowAll;
+impl ShouldExecute for AllowAll {
+	fn should_execute<RuntimeCall>(
+		_: &Location,
+		_: &mut [Instruction<RuntimeCall>],
+		_: Weight,
+		_: &mut Properties,
+	) -> Result<(), ProcessMessageError> {
+		Ok(())
+	}
+}
+
+// Dummy filter which denies `ClearOrigin`
+struct DenyClearOrigin;
+impl DenyExecution for DenyClearOrigin {
+	fn deny_execution<RuntimeCall>(
+		_: &Location,
+		instructions: &mut [Instruction<RuntimeCall>],
+		_: Weight,
+		_: &mut Properties,
+	) -> Result<(), ProcessMessageError> {
+		instructions.matcher().match_next_inst_while(
+			|_| true,
+			|inst| match inst {
+				ClearOrigin => Err(ProcessMessageError::Unsupported),
+				_ => Ok(ControlFlow::Continue(())),
+			},
+		)?;
+		Ok(())
+	}
+}
+
+// Dummy filter which denies nothing
+struct DenyNothing;
+impl DenyExecution for DenyNothing {
+	fn deny_execution<RuntimeCall>(
+		_origin: &Location,
+		_instructions: &mut [Instruction<RuntimeCall>],
+		_max_weight: Weight,
+		_properties: &mut Properties,
+	) -> Result<(), ProcessMessageError> {
+		Ok(())
+	}
+}
+
+// Test helper: Adapts a `DenyExecution` barrier to the `ShouldExecute` trait
+struct Executable<Barrier: DenyExecution>(PhantomData<Barrier>);
+impl<Barrier: DenyExecution> ShouldExecute for Executable<Barrier> {
+	fn should_execute<RuntimeCall>(
+		origin: &Location,
+		instructions: &mut [Instruction<RuntimeCall>],
+		max_weight: Weight,
+		properties: &mut Properties,
+	) -> Result<(), ProcessMessageError> {
+		Barrier::deny_execution(origin, instructions, max_weight, properties)
+	}
+}
+
+#[test]
+fn deny_recursively_then_try_works() {
+	type Barrier = DenyThenTry<DenyRecursively<DenyReserveTransferToRelayChain>, AllowAll>;
+	let xcm = Xcm::<Instruction<()>>(vec![DepositReserveAsset {
+		assets: Wild(All),
+		dest: Location::parent(),
+		xcm: vec![].into(),
+	}]);
+	let origin = Here.into_location();
+	let max_weight = Weight::from_parts(10, 10);
+	let mut properties = props(Weight::zero());
+
+	// Should deny the original XCM
+	let result =
+		Barrier::should_execute(&origin, xcm.clone().inner_mut(), max_weight, &mut properties);
+	assert!(result.is_err());
+
+	// Should deny with `SetAppendix`
+	let mut message = Xcm::<Instruction<()>>(vec![SetAppendix(xcm.clone())]);
+	let result =
+		Barrier::should_execute(&origin, message.clone().inner_mut(), max_weight, &mut properties);
+	assert!(result.is_err());
+
+	// Should allow with `SetAppendix` for the original `DenyThenTry`
+	type OriginalBarrier = DenyThenTry<DenyReserveTransferToRelayChain, AllowAll>;
+	let result =
+		OriginalBarrier::should_execute(&origin, message.inner_mut(), max_weight, &mut properties);
+	assert!(result.is_ok());
+
+	// Should deny with `SetErrorHandler`
+	let mut message = Xcm::<Instruction<()>>(vec![SetErrorHandler(xcm.clone())]);
+	let result = Barrier::should_execute(&origin, message.inner_mut(), max_weight, &mut properties);
+	assert!(result.is_err());
+
+	// Should deny with `ExecuteWithOrigin`
+	let mut message = Xcm::<Instruction<()>>(vec![ExecuteWithOrigin {
+		xcm: xcm.clone(),
+		descendant_origin: None,
+	}]);
+	let result = Barrier::should_execute(&origin, message.inner_mut(), max_weight, &mut properties);
+	assert!(result.is_err());
+
+	// Should deny with more levels
+	let mut message = Xcm::<Instruction<()>>(vec![ExecuteWithOrigin {
+		xcm: vec![SetErrorHandler(vec![SetAppendix(xcm.clone())].into())].into(),
+		descendant_origin: None,
+	}]);
+	let result = Barrier::should_execute(&origin, message.inner_mut(), max_weight, &mut properties);
+	assert!(result.is_err());
+
+	// Should allow for valid XCM with `SetAppendix`
+	let xcm = Xcm::<Instruction<()>>(vec![DepositReserveAsset {
+		assets: Wild(All),
+		dest: Here.into_location(),
+		xcm: vec![].into(),
+	}]);
+	let mut message = Xcm::<Instruction<()>>(vec![SetAppendix(xcm.clone())]);
+	let result = Barrier::should_execute(&origin, message.inner_mut(), max_weight, &mut properties);
+	assert!(result.is_ok());
+
+	// Should ensure unrelated XCMs are not blocked
+	let mut unrelated_xcm = Xcm::<Instruction<()>>(vec![BuyExecution {
+		fees: (Parent, 100).into(),
+		weight_limit: Unlimited,
+	}]);
+	let result =
+		Barrier::should_execute(&origin, unrelated_xcm.inner_mut(), max_weight, &mut properties);
+	assert!(result.is_ok());
+
+	// Should deny recursively before allow
+	type BarrierDenyClearOrigin = DenyThenTry<DenyRecursively<DenyClearOrigin>, AllowAll>;
+	assert_deny_instructions_recursively::<BarrierDenyClearOrigin>();
+}
+
+#[test]
+fn deny_recursively_works() {
+	type Barrier = Executable<DenyRecursively<DenyClearOrigin>>;
+	assert_deny_instructions_recursively::<Barrier>();
+}
+
+#[test]
+fn compare_deny_filters() {
+	type Denies = (DenyNothing, DenyReserveTransferToRelayChain);
+
+	fn assert_barrier<Barrier: ShouldExecute>(
+		top_level_result: Result<(), ProcessMessageError>,
+		nested_result: Result<(), ProcessMessageError>,
+	) {
+		let origin = Here.into_location();
+		let max_weight = Weight::zero();
+		let mut properties = props(Weight::zero());
+
+		// Validate Top-Level
+		let xcm = Xcm::<Instruction<()>>(
+			vec![DepositReserveAsset {
+				assets: Wild(All),
+				dest: Location::parent(),
+				xcm: Xcm(vec![ClearOrigin]),
+			}]
+			.into(),
+		);
+		let result =
+			Barrier::should_execute(&origin, xcm.clone().inner_mut(), max_weight, &mut properties);
+		assert_eq!(top_level_result, result);
+
+		// Validate Nested
+		let mut nested_xcm = Xcm::<Instruction<()>>(vec![SetErrorHandler(xcm.into())].into());
+		let result =
+			Barrier::should_execute(&origin, nested_xcm.inner_mut(), max_weight, &mut properties);
+		assert_eq!(nested_result, result);
+	}
+
+	// `DenyThenTry`: Top-level=Deny, Nested=Allow, TryAllow=Yes
+	assert_barrier::<DenyThenTry<Denies, AllowAll>>(Err(ProcessMessageError::Unsupported), Ok(()));
+
+	// `DenyThenTry<DenyRecursively<Deny>>`: Top-level=Deny, Nested=Deny, TryAllow=Yes
+	assert_barrier::<DenyThenTry<DenyRecursively<Denies>, AllowAll>>(
+		Err(ProcessMessageError::Unsupported),
+		Err(ProcessMessageError::Unsupported),
+	);
+
+	// `DenyRecursively`: Top-level=Deny, Nested=Deny, TryAllow=No
+	assert_barrier::<Executable<DenyRecursively<Denies>>>(
+		Err(ProcessMessageError::Unsupported),
+		Err(ProcessMessageError::Unsupported),
+	);
+}
+
+fn assert_deny_instructions_recursively<Barrier: ShouldExecute>() {
+	// closure for (xcm, origin) testing with `Barrier` which denies `ClearOrigin`
+	// instruction
+	let test_barrier = |mut xcm: Vec<Instruction<()>>, origin| {
+		Barrier::should_execute(
+			&origin,
+			&mut xcm,
+			Weight::from_parts(10, 10),
+			&mut props(Weight::zero()),
+		)
+	};
+
+	// ok
+	assert_eq!(test_barrier(vec![ClearTransactStatus], Location::parent()), Ok(()));
+	// invalid top-level contains `ClearOrigin`
+	assert_eq!(
+		test_barrier(vec![ClearOrigin], Location::parent()),
+		Err(ProcessMessageError::Unsupported)
+	);
+	// ok - SetAppendix with XCM without ClearOrigin
+	assert_eq!(
+		test_barrier(vec![SetAppendix(Xcm(vec![ClearTransactStatus]))], Location::parent()),
+		Ok(())
+	);
+	// ok - DepositReserveAsset with XCM contains ClearOrigin
+	assert_eq!(
+		test_barrier(
+			vec![DepositReserveAsset {
+				assets: Wild(All),
+				dest: Here.into(),
+				xcm: Xcm(vec![ClearOrigin]),
+			}],
+			Location::parent()
+		),
+		Ok(()),
+	);
+
+	// invalid - empty XCM
+	assert_eq!(test_barrier(vec![], Location::parent()), Err(ProcessMessageError::BadFormat));
+	// invalid - SetAppendix with empty XCM
+	assert_eq!(
+		test_barrier(vec![SetAppendix(Xcm(vec![]))], Location::parent()),
+		Err(ProcessMessageError::BadFormat),
+	);
+	// invalid SetAppendix contains `ClearOrigin`
+	assert_eq!(
+		test_barrier(vec![SetAppendix(Xcm(vec![ClearOrigin]))], Location::parent()),
+		Err(ProcessMessageError::Unsupported),
+	);
+	// invalid nested SetAppendix contains `ClearOrigin`
+	assert_eq!(
+		test_barrier(
+			vec![SetAppendix(Xcm(vec![SetAppendix(Xcm(vec![SetAppendix(Xcm(vec![
+				SetAppendix(Xcm(vec![SetAppendix(Xcm(vec![SetAppendix(Xcm(vec![
+					SetAppendix(Xcm(vec![SetAppendix(Xcm(vec![SetAppendix(Xcm(vec![
+						SetAppendix(Xcm(vec![SetAppendix(Xcm(vec![SetAppendix(Xcm(vec![
+							ClearOrigin
+						]))])),]))
+					]))])),]))
+				]))]))]),)
+			]))]))]))],
+			Location::parent()
+		),
+		Err(ProcessMessageError::StackLimitReached),
+	);
+}
diff --git a/polkadot/xcm/xcm-builder/src/tests/mock.rs b/polkadot/xcm/xcm-builder/src/tests/mock.rs
index 127888104a4ad77b0272d8e230f724d3e1cca7ac..2df6bdfe15062324221e66dc8577f2daad61b1f2 100644
--- a/polkadot/xcm/xcm-builder/src/tests/mock.rs
+++ b/polkadot/xcm/xcm-builder/src/tests/mock.rs
@@ -22,9 +22,9 @@ use crate::{
 	EnsureDecodableXcm,
 };
 pub use crate::{
-	AliasForeignAccountId32, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses,
-	AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, FixedRateOfFungible,
-	FixedWeightBounds, TakeWeightCredit,
+	AliasChildLocation, AliasForeignAccountId32, AllowExplicitUnpaidExecutionFrom,
+	AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom,
+	FixedRateOfFungible, FixedWeightBounds, TakeWeightCredit,
 };
 pub use alloc::collections::{btree_map::BTreeMap, btree_set::BTreeSet};
 pub use codec::{Decode, Encode};
@@ -733,6 +733,9 @@ impl Contains<Location> for ParentPrefix {
 	}
 }
 
+/// Pairs (location1, location2) where location1 can alias as location2.
+pub type Aliasers = (AliasForeignAccountId32<SiblingPrefix>, AliasChildLocation);
+
 pub struct TestConfig;
 impl Config for TestConfig {
 	type RuntimeCall = TestCall;
@@ -758,7 +761,7 @@ impl Config for TestConfig {
 	type MessageExporter = TestMessageExporter;
 	type CallDispatcher = TestCall;
 	type SafeCallFilter = Everything;
-	type Aliasers = AliasForeignAccountId32<SiblingPrefix>;
+	type Aliasers = Aliasers;
 	type TransactionalProcessor = ();
 	type HrmpNewChannelOpenRequestHandler = ();
 	type HrmpChannelAcceptedHandler = ();
diff --git a/polkadot/xcm/xcm-builder/tests/scenarios.rs b/polkadot/xcm/xcm-builder/tests/scenarios.rs
index 99c14f5bba1bc8fad67605ce8eddbf8185fa7caf..d7993e89eeebd79b07f5baf2009857d090e3ee3d 100644
--- a/polkadot/xcm/xcm-builder/tests/scenarios.rs
+++ b/polkadot/xcm/xcm-builder/tests/scenarios.rs
@@ -322,3 +322,101 @@ fn reserve_based_transfer_works() {
 		);
 	});
 }
+
+/// Scenario:
+/// A recursive XCM that triggers itself via `SetAppendix`.
+/// The execution should fail due to inner filter.
+#[test]
+fn recursive_xcm_execution_fail() {
+	use crate::mock::*;
+	use frame_support::traits::{Everything, Nothing, ProcessMessageError};
+	use staging_xcm_builder::*;
+	use std::ops::ControlFlow;
+	use xcm::opaque::latest::prelude::*;
+	use xcm_executor::traits::{DenyExecution, Properties, ShouldExecute};
+
+	// Dummy filter to allow all
+	struct AllowAll;
+	impl ShouldExecute for AllowAll {
+		fn should_execute<RuntimeCall>(
+			_: &Location,
+			_: &mut [Instruction<RuntimeCall>],
+			_: Weight,
+			_: &mut Properties,
+		) -> Result<(), ProcessMessageError> {
+			Ok(())
+		}
+	}
+
+	// Dummy filter which denies `ClearOrigin`
+	struct DenyClearOrigin;
+	impl DenyExecution for DenyClearOrigin {
+		fn deny_execution<RuntimeCall>(
+			_: &Location,
+			instructions: &mut [Instruction<RuntimeCall>],
+			_: Weight,
+			_: &mut Properties,
+		) -> Result<(), ProcessMessageError> {
+			instructions.matcher().match_next_inst_while(
+				|_| true,
+				|inst| match inst {
+					ClearOrigin => Err(ProcessMessageError::Unsupported),
+					_ => Ok(ControlFlow::Continue(())),
+				},
+			)?;
+			Ok(())
+		}
+	}
+
+	struct XcmTestConfig;
+	impl xcm_executor::Config for XcmTestConfig {
+		type RuntimeCall = RuntimeCall;
+		type XcmSender = TestXcmRouter;
+		type AssetTransactor = LocalAssetTransactor;
+		type OriginConverter = ();
+		type IsReserve = ();
+		type IsTeleporter = TrustedTeleporters;
+		type UniversalLocation = UniversalLocation;
+		type Barrier = DenyThenTry<DenyRecursively<DenyClearOrigin>, AllowAll>;
+		type Weigher = FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
+		type Trader = FixedRateOfFungible<KsmPerSecondPerByte, ()>;
+		type ResponseHandler = XcmPallet;
+		type AssetTrap = XcmPallet;
+		type AssetLocker = ();
+		type AssetExchanger = ();
+		type AssetClaims = XcmPallet;
+		type SubscriptionService = XcmPallet;
+		type PalletInstancesInfo = AllPalletsWithSystem;
+		type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
+		type FeeManager = ();
+		type MessageExporter = ();
+		type UniversalAliases = Nothing;
+		type CallDispatcher = RuntimeCall;
+		type SafeCallFilter = Everything;
+		type Aliasers = Nothing;
+		type TransactionalProcessor = ();
+		type HrmpNewChannelOpenRequestHandler = ();
+		type HrmpChannelAcceptedHandler = ();
+		type HrmpChannelClosingHandler = ();
+		type XcmRecorder = XcmPallet;
+	}
+
+	let para_acc: AccountId = ParaId::from(PARA_ID).into_account_truncating();
+	let balances = vec![(ALICE, INITIAL_BALANCE), (para_acc.clone(), INITIAL_BALANCE)];
+	let origin = Parachain(PARA_ID);
+	let message = Xcm(vec![SetAppendix(Xcm(vec![SetAppendix(Xcm(vec![ClearOrigin]))]))]);
+	let mut hash = fake_message_hash(&message);
+	let weight = BaseXcmWeight::get() * 3;
+
+	kusama_like_with_balances(balances).execute_with(|| {
+		let outcome = XcmExecutor::<XcmTestConfig>::prepare_and_execute(
+			origin,
+			message,
+			&mut hash,
+			weight,
+			Weight::zero(),
+		);
+
+		assert_eq!(outcome, Outcome::Error { error: XcmError::Barrier });
+	});
+}
diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs
index d0f18aea1ab318e223859cd3ba106cec4c29775d..19a6a645083f2925aa4d4d228808a2c1a12827cd 100644
--- a/polkadot/xcm/xcm-executor/src/lib.rs
+++ b/polkadot/xcm/xcm-executor/src/lib.rs
@@ -60,7 +60,13 @@ pub struct FeesMode {
 	pub jit_withdraw: bool,
 }
 
-const RECURSION_LIMIT: u8 = 10;
+/// The maximum recursion depth allowed when executing nested XCM instructions.
+///
+/// Exceeding this limit results in `XcmError::ExceedsStackLimit` or
+/// `ProcessMessageError::StackLimitReached`.
+///
+/// Also used in the `DenyRecursively` barrier.
+pub const RECURSION_LIMIT: u8 = 10;
 
 environmental::environmental!(recursion_count: u8);
 
@@ -794,13 +800,13 @@ impl<Config: config::Config> XcmExecutor<Config> {
 					let inst_res = recursion_count::using_once(&mut 1, || {
 						recursion_count::with(|count| {
 							if *count > RECURSION_LIMIT {
-								return Err(XcmError::ExceedsStackLimit)
+								return None
 							}
 							*count = count.saturating_add(1);
-							Ok(())
+							Some(())
 						})
-						// This should always return `Some`, but let's play it safe.
-						.unwrap_or(Ok(()))?;
+						.flatten()
+						.ok_or(XcmError::ExceedsStackLimit)?;
 
 						// Ensure that we always decrement the counter whenever we finish processing
 						// the instruction.
@@ -1194,7 +1200,7 @@ impl<Config: config::Config> XcmExecutor<Config> {
 					// transferring the other assets. This is required to satisfy the
 					// `MAX_ASSETS_FOR_BUY_EXECUTION` limit in the `AllowTopLevelPaidExecutionFrom`
 					// barrier.
-					if let Some(remote_fees) = remote_fees {
+					let remote_fees_paid = if let Some(remote_fees) = remote_fees {
 						let reanchored_fees = match remote_fees {
 							AssetTransferFilter::Teleport(fees_filter) => {
 								let teleport_fees = self
@@ -1239,11 +1245,10 @@ impl<Config: config::Config> XcmExecutor<Config> {
 						// move these assets to the fees register for covering execution and paying
 						// any subsequent fees
 						message.push(PayFees { asset: fees });
+						true
 					} else {
-						// unpaid execution
-						message
-							.push(UnpaidExecution { weight_limit: Unlimited, check_origin: None });
-					}
+						false
+					};
 
 					// add any extra asset transfers
 					for asset_filter in assets {
@@ -1270,23 +1275,36 @@ impl<Config: config::Config> XcmExecutor<Config> {
 								)?,
 						};
 					}
+
 					if preserve_origin {
-						// preserve current origin for subsequent user-controlled instructions on
-						// remote chain
-						let original_origin = self
+						// We alias the origin if it's not a noop (origin != `Here`).
+						if let Some(original_origin) = self
 							.origin_ref()
+							.filter(|origin| *origin != &Location::here())
 							.cloned()
-							.and_then(|origin| {
-								Self::try_reanchor(origin, &destination)
-									.map(|(reanchored, _)| reanchored)
-									.ok()
-							})
-							.ok_or(XcmError::BadOrigin)?;
-						message.push(AliasOrigin(original_origin));
+						{
+							// preserve current origin for subsequent user-controlled instructions on
+							// remote chain
+							let reanchored_origin = Self::try_reanchor(original_origin, &destination)?.0;
+							message.push(AliasOrigin(reanchored_origin));
+						}
 					} else {
 						// clear origin for subsequent user-controlled instructions on remote chain
 						message.push(ClearOrigin);
 					}
+
+					// If not intending to pay for fees then we append the `UnpaidExecution`
+					// _AFTER_ origin altering instructions.
+					// When origin is not preserved, it's probably going to fail on the receiver.
+					if !remote_fees_paid {
+						// We push the UnpaidExecution instruction to notify we do not intend to pay
+						// for fees.
+						// The receiving chain must decide based on the origin of the message if they
+						// accept this.
+						message
+							.push(UnpaidExecution { weight_limit: Unlimited, check_origin: None });
+					}
+
 					// append custom instructions
 					message.extend(remote_xcm.0.into_iter());
 					// send the onward XCM
diff --git a/polkadot/xcm/xcm-executor/src/tests/initiate_transfer.rs b/polkadot/xcm/xcm-executor/src/tests/initiate_transfer.rs
index 09ed1f44cc4af4b34b570c5e00aad7bf2770883d..8786186006be9780d2e1f863b122a0ea6aa66643 100644
--- a/polkadot/xcm/xcm-executor/src/tests/initiate_transfer.rs
+++ b/polkadot/xcm/xcm-executor/src/tests/initiate_transfer.rs
@@ -20,6 +20,7 @@
 //! [Fellowship RFC 122](https://github.com/polkadot-fellows/rfCs/pull/122), and the
 //! [specification](https://github.com/polkadot-fellows/xcm-format) for more information.
 
+use codec::Encode;
 use xcm::{latest::AssetTransferFilter, prelude::*};
 
 use super::mock::*;
@@ -104,3 +105,115 @@ fn preserves_origin() {
 	assert!(matches!(instr.next().unwrap(), RefundSurplus));
 	assert!(matches!(instr.next().unwrap(), DepositAsset { .. }));
 }
+
+#[test]
+fn unpaid_execution_goes_after_origin_alteration() {
+	// Make sure the sender has enough funds to withdraw.
+	add_asset(SENDER, (Here, 100u128));
+
+	let xcm_on_destination =
+		Xcm::builder_unsafe().refund_surplus().deposit_asset(All, RECIPIENT).build();
+	let asset: Asset = (Here, 90u128).into();
+	let xcm = Xcm::builder()
+		.withdraw_asset((Here, 100u128))
+		.pay_fees((Here, 10u128))
+		.initiate_transfer(
+			Parent,
+			None, // We specify no remote fees.
+			true, // Preserve origin, necessary for `UnpaidExecution`.
+			vec![AssetTransferFilter::ReserveDeposit(asset.into())],
+			xcm_on_destination,
+		)
+		.build();
+
+	// We initialize the executor with the SENDER origin, which is not waived.
+	let (mut vm, _) = instantiate_executor(SENDER, xcm.clone());
+
+	// Program fails with `BadOrigin`.
+	let result = vm.bench_process(xcm);
+	assert!(result.is_ok(), "execution error {:?}", result);
+
+	let (destination, sent_message) = sent_xcm().pop().unwrap();
+	assert_eq!(destination, Parent.into());
+	assert_eq!(sent_message.len(), 5);
+	let mut instructions = sent_message.inner().iter();
+	assert!(matches!(instructions.next().unwrap(), ReserveAssetDeposited(..)));
+	assert!(matches!(
+		instructions.next().unwrap(),
+		AliasOrigin(origin) if matches!(origin.unpack(), (0, [Parachain(1000), AccountId32 { id: SENDER, network: None }]))
+	));
+	assert!(matches!(instructions.next().unwrap(), UnpaidExecution { .. }));
+	assert!(matches!(instructions.next().unwrap(), RefundSurplus));
+	assert!(matches!(instructions.next().unwrap(), DepositAsset { .. }));
+}
+
+#[test]
+fn no_alias_origin_if_root() {
+	// Make sure the sender has enough funds to withdraw.
+	add_asset(Here, (Here, 100u128));
+
+	let xcm_on_destination =
+		Xcm::builder_unsafe().refund_surplus().deposit_asset(All, RECIPIENT).build();
+	let asset: Asset = (Here, 90u128).into();
+	let xcm = Xcm::builder()
+		.withdraw_asset((Here, 100u128))
+		.pay_fees((Here, 10u128))
+		.initiate_transfer(
+			Parent,
+			None, // We specify no remote fees.
+			true, // Preserve origin, necessary for `UnpaidExecution`.
+			vec![AssetTransferFilter::ReserveDeposit(asset.into())],
+			xcm_on_destination,
+		)
+		.build();
+
+	// We initialize the executor with the SENDER origin, which is not waived.
+	let (mut vm, _) = instantiate_executor(Here, xcm.clone());
+
+	// Program fails with `BadOrigin`.
+	let result = vm.bench_process(xcm);
+	assert!(result.is_ok(), "execution error {:?}", result);
+
+	let (destination, sent_message) = sent_xcm().pop().unwrap();
+	assert_eq!(destination, Parent.into());
+	assert_eq!(sent_message.len(), 4);
+	let mut instructions = sent_message.inner().iter();
+	assert!(matches!(instructions.next().unwrap(), ReserveAssetDeposited(..)));
+	assert!(matches!(instructions.next().unwrap(), UnpaidExecution { .. }));
+	assert!(matches!(instructions.next().unwrap(), RefundSurplus));
+	assert!(matches!(instructions.next().unwrap(), DepositAsset { .. }));
+}
+
+// We simulate going from one system parachain to another without
+// having to pay remote fees.
+#[test]
+fn unpaid_transact() {
+	let to_another_system_para: Location = (Parent, Parachain(1001)).into();
+	// We want to execute some call in the receiving chain.
+	let xcm_on_destination = Xcm::builder_unsafe()
+		.transact(OriginKind::Superuser, None, b"".encode())
+		.build();
+	let xcm = Xcm::builder_unsafe()
+		.initiate_transfer(
+			to_another_system_para.clone(),
+			None,   // We specify no remote fees.
+			true,   // Preserve necessary for `UnpaidExecution`.
+			vec![], // No need for assets.
+			xcm_on_destination,
+		)
+		.build();
+
+	// We initialize the executor with the root origin, which is waived.
+	let (mut vm, _) = instantiate_executor(Here, xcm.clone());
+
+	// Program executes successfully.
+	let result = vm.bench_process(xcm.clone());
+	assert!(result.is_ok(), "execution error: {:?}", result);
+
+	let (destination, sent_message) = sent_xcm().pop().unwrap();
+	assert_eq!(destination, to_another_system_para);
+	assert_eq!(sent_message.len(), 2);
+	let mut instructions = sent_message.inner().iter();
+	assert!(matches!(instructions.next().unwrap(), UnpaidExecution { .. }));
+	assert!(matches!(instructions.next().unwrap(), Transact { .. }));
+}
diff --git a/polkadot/xcm/xcm-executor/src/tests/mock.rs b/polkadot/xcm/xcm-executor/src/tests/mock.rs
index 9cf258331f38a4ff65558c3441b8d3dddbdca638..c0bcfe88d2baa8aff42142c368b52f035a30b552 100644
--- a/polkadot/xcm/xcm-executor/src/tests/mock.rs
+++ b/polkadot/xcm/xcm-executor/src/tests/mock.rs
@@ -29,8 +29,11 @@ use sp_runtime::traits::Dispatchable;
 use xcm::prelude::*;
 
 use crate::{
-	traits::{DropAssets, Properties, ShouldExecute, TransactAsset, WeightBounds, WeightTrader},
-	AssetsInHolding, Config, XcmExecutor,
+	traits::{
+		DropAssets, FeeManager, Properties, ShouldExecute, TransactAsset, WeightBounds,
+		WeightTrader,
+	},
+	AssetsInHolding, Config, FeeReason, XcmExecutor,
 };
 
 /// We create an XCVM instance instead of calling `XcmExecutor::<_>::prepare_and_execute` so we
@@ -244,6 +247,26 @@ pub fn sent_xcm() -> Vec<(Location, Xcm<()>)> {
 	SENT_XCM.with(|q| (*q.borrow()).clone())
 }
 
+/// A mock contract address that doesn't need to pay for fees.
+pub const WAIVED_CONTRACT_ADDRESS: [u8; 20] = [128; 20];
+
+/// Test fee manager that will waive the fee for some origins.
+///
+/// Doesn't do anything with the fee, which effectively burns it.
+pub struct TestFeeManager;
+impl FeeManager for TestFeeManager {
+	fn is_waived(origin: Option<&Location>, _: FeeReason) -> bool {
+		let Some(origin) = origin else { return false };
+		// Match the root origin and a particular smart contract account.
+		matches!(
+			origin.unpack(),
+			(0, []) | (0, [AccountKey20 { network: None, key: WAIVED_CONTRACT_ADDRESS }])
+		)
+	}
+
+	fn handle_fee(_: Assets, _: Option<&XcmContext>, _: FeeReason) {}
+}
+
 /// Test XcmConfig that uses all the test implementations in this file.
 pub struct XcmConfig;
 impl Config for XcmConfig {
@@ -265,7 +288,7 @@ impl Config for XcmConfig {
 	type SubscriptionService = ();
 	type PalletInstancesInfo = ();
 	type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
-	type FeeManager = ();
+	type FeeManager = TestFeeManager;
 	type MessageExporter = ();
 	type UniversalAliases = Nothing;
 	type CallDispatcher = Self::RuntimeCall;
diff --git a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs
index 22e4a3bd61a83d0739b12c2276104b31f6ebe37e..b48f089f598661fca901c61f259e2c50acd47349 100644
--- a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs
+++ b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs
@@ -17,7 +17,7 @@
 use crate::traits::TransactAsset;
 use frame_support::traits::ContainsPair;
 use scale_info::TypeInfo;
-use sp_runtime::codec::{Decode, Encode};
+use sp_runtime::codec::{Decode, DecodeWithMemTracking, Encode};
 use xcm::prelude::*;
 
 /// Errors related to determining asset transfer support.
@@ -28,7 +28,7 @@ pub enum Error {
 }
 
 /// Specify which type of asset transfer is required for a particular `(asset, dest)` combination.
-#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo)]
+#[derive(Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, Debug, TypeInfo)]
 pub enum TransferType {
 	/// should teleport `asset` to `dest`
 	Teleport,
diff --git a/polkadot/xcm/xcm-simulator/example/src/lib.rs b/polkadot/xcm/xcm-simulator/example/src/lib.rs
index 8a05569831b5c1d2adee9a4a03a8c5fb3e790fe3..7d179bd25871428f4f59afec04d63f4bfbbc113c 100644
--- a/polkadot/xcm/xcm-simulator/example/src/lib.rs
+++ b/polkadot/xcm/xcm-simulator/example/src/lib.rs
@@ -14,7 +14,12 @@
 // You should have received a copy of the GNU General Public License
 // along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
 
+// We do not declare all features used by `construct_runtime`
+#[allow(unexpected_cfgs)]
 mod parachain;
+
+// We do not declare all features used by `construct_runtime`
+#[allow(unexpected_cfgs)]
 mod relay_chain;
 
 #[cfg(test)]
diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/fuzz.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/fuzz.rs
index 8ea5e033f3ad7174776afb273f3773ff8d18399d..c49804310dd326802dc5dd8e216103d33c4f20ba 100644
--- a/polkadot/xcm/xcm-simulator/fuzzer/src/fuzz.rs
+++ b/polkadot/xcm/xcm-simulator/fuzzer/src/fuzz.rs
@@ -14,7 +14,12 @@
 // You should have received a copy of the GNU General Public License
 // along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
 
+// We do not declare all features used by `construct_runtime`
+#[allow(unexpected_cfgs)]
 mod parachain;
+
+// We do not declare all features used by `construct_runtime`
+#[allow(unexpected_cfgs)]
 mod relay_chain;
 
 use codec::DecodeLimit;
diff --git a/prdoc/pr_6960.prdoc b/prdoc/pr_6960.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..3cef34ce00d7023a3a28041d7dfc7a61fd11229b
--- /dev/null
+++ b/prdoc/pr_6960.prdoc
@@ -0,0 +1,9 @@
+title: Add sudo pallet to coretime-westend
+doc:
+- audience: Runtime Dev
+  description: Add the sudo pallet to coretime-westend, allowing use in development/testing.
+    Previously the coretime-rococo runtime was used in situations like this, but since
+    Rococo is now gone this can be used instead.
+crates:
+- name: coretime-westend-runtime
+  bump: major
diff --git a/prdoc/pr_7026.prdoc b/prdoc/pr_7026.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..8e50f61ea17bc52f4d00192401c2c47a58da3c3f
--- /dev/null
+++ b/prdoc/pr_7026.prdoc
@@ -0,0 +1,17 @@
+# 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: "[pallet-broker] add extrinsic to remove a lease"
+
+doc:
+  - audience: Runtime User
+    description: |
+      A new `remove_lease` extrinsic is introduced to the broker pallet to allow a lease to be removed by the root origin.
+
+crates:
+  - name: pallet-broker
+    bump: major
+  - name: coretime-rococo-runtime
+    bump: patch
+  - name: coretime-westend-runtime
+    bump: patch
diff --git a/prdoc/pr_7080.prdoc b/prdoc/pr_7080.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..ae4644838576f715ca865dcb59f45205b28ed9c6
--- /dev/null
+++ b/prdoc/pr_7080.prdoc
@@ -0,0 +1,17 @@
+# 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: "[pallet-broker] add extrinsic to remove an assignment"
+
+doc:
+  - audience: Runtime User
+    description: |
+      A new `remove_assignment` extrinsic is introduced to the broker pallet to allow an assignment to be removed by the root origin.
+
+crates:
+  - name: pallet-broker
+    bump: major
+  - name: coretime-rococo-runtime
+    bump: patch
+  - name: coretime-westend-runtime
+    bump: patch
diff --git a/prdoc/pr_7200.prdoc b/prdoc/pr_7200.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..62d010e843075329142924a5a5293a75c510f496
--- /dev/null
+++ b/prdoc/pr_7200.prdoc
@@ -0,0 +1,40 @@
+title: 'XCM: Deny barrier checks for nested XCMs with specific instructions to be
+  executed on the local chain'
+doc:
+- audience: Runtime Dev
+  description: |-
+    This PR improves the validation of nested XCM instructions by introducing a
+    new barrier, `DenyRecursively`, which provides more precise control over
+    instruction denial. Previously, `DenyThenTry<Deny, Allow>`` was used, which
+    primarily applied denial rules at the top level. This has now been replaced
+    with `DenyThenTry<DenyRecursively<Deny>, Allow>`, ensuring that both
+    top-level and nested local instructions are properly checked. This change
+    enhances the security and predictability of XCM execution by enforcing
+    consistent denial policies across all levels of message execution. If you
+    need to deny instructions recursively make sure to change your barrier in
+    the XCM configuration.
+crates:
+- name: staging-xcm-builder
+  bump: minor
+- name: staging-xcm-executor
+  bump: minor
+- name: asset-hub-rococo-runtime
+  bump: patch
+- name: asset-hub-westend-runtime
+  bump: patch
+- name: bridge-hub-rococo-runtime
+  bump: patch
+- name: bridge-hub-westend-runtime
+  bump: patch
+- name: collectives-westend-runtime
+  bump: patch
+- name: contracts-rococo-runtime
+  bump: patch
+- name: coretime-rococo-runtime
+  bump: patch
+- name: coretime-westend-runtime
+  bump: patch
+- name: people-rococo-runtime
+  bump: patch
+- name: people-westend-runtime
+  bump: patch
diff --git a/prdoc/pr_7407.prdoc b/prdoc/pr_7407.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..e99e41769184807bae37bd44ee6826d683cb7b98
--- /dev/null
+++ b/prdoc/pr_7407.prdoc
@@ -0,0 +1,40 @@
+title: 'Fixes #219'
+doc:
+- audience: Runtime Dev
+  description: |-
+    Add a new extrinsic `dispatch_as_fallible`.
+
+    It's almost the same as `dispatch_as` but check the result of the call.
+
+    Closes #219.
+
+    And add more unit tests to cover `dispatch_as` and `dispatch_as_fallible`.
+
+    ---
+
+    Polkadot address: 156HGo9setPcU2qhFMVWLkcmtCEGySLwNqa3DaEiYSWtte4Y
+crates:
+- name: asset-hub-rococo-runtime
+  bump: minor
+- name: asset-hub-westend-runtime
+  bump: minor
+- name: bridge-hub-rococo-runtime
+  bump: minor
+- name: bridge-hub-westend-runtime
+  bump: minor
+- name: collectives-westend-runtime
+  bump: minor
+- name: coretime-rococo-runtime
+  bump: minor
+- name: coretime-westend-runtime
+  bump: minor
+- name: people-rococo-runtime
+  bump: minor
+- name: people-westend-runtime
+  bump: minor
+- name: rococo-runtime
+  bump: minor
+- name: westend-runtime
+  bump: minor
+- name: pallet-utility
+  bump: minor
diff --git a/prdoc/pr_7423.prdoc b/prdoc/pr_7423.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..30e22a7ccf8665db07dcb6cdd72062fec46da6d9
--- /dev/null
+++ b/prdoc/pr_7423.prdoc
@@ -0,0 +1,17 @@
+title: Fix issue with InitiateTransfer and UnpaidExecution
+doc:
+- audience: Runtime Dev
+  description: 
+    Fix issue where setting the `remote_fees` field of `InitiateTransfer` to `None` could lead to unintended bypassing of fees in certain conditions.
+    `UnpaidExecution` is now appended **after** origin alteration.
+    If planning to use `UnpaidExecution`, you need to set `preserve_origin = true`.
+
+    The `AllowExplicitUnpaidExecutionFrom` barrier now allows instructions for receiving funds before origin altering instructions before
+    the actual `UnpaidExecution`.
+    It takes a new generic, `Aliasers`, needed for executing `AliasOrigin` to see if the effective origin is allowed to use `UnpaidExecution`.
+    This should be set to the same value as `Aliasers` in the XCM configuration.
+crates:
+- name: staging-xcm-builder
+  bump: patch
+- name: staging-xcm-executor
+  bump: patch
diff --git a/prdoc/pr_7476.prdoc b/prdoc/pr_7476.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..3bb0970b4c3ddab5a482c0098ee99b70e6aedeee
--- /dev/null
+++ b/prdoc/pr_7476.prdoc
@@ -0,0 +1,14 @@
+title: add genesis presets for coretime parachains
+doc:
+- audience: Runtime Dev
+  description: |-
+    Extracted from #7473.
+
+    Part of: https://github.com/paritytech/polkadot-sdk/issues/5704.
+crates:
+- name: coretime-westend-runtime
+  bump: minor
+- name: coretime-rococo-runtime
+  bump: minor
+- name: polkadot-parachain-bin
+  bump: minor
diff --git a/prdoc/pr_7492.prdoc b/prdoc/pr_7492.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..67871009bddbc47e46835c2e516fb15e79c6852d
--- /dev/null
+++ b/prdoc/pr_7492.prdoc
@@ -0,0 +1,20 @@
+title: Make `pallet-bridge-rewards` generic over `RewardKind`
+doc:
+- audience: Runtime Dev
+  description: |-
+    The PR enhances the pallet-bridge-rewards by making it generic over the `Reward` type (previously hardcoded as `RewardsAccountParams`). This modification allows the pallet to support multiple reward types (e.g., P/K bridge, Snowbridge), increasing its flexibility and applicability across various bridge scenarios.
+
+    Other pallets can register rewards using bp_relayers::RewardLedger, which is implemented by the rewards pallet. The runtime can then be configured with different mechanisms for paying/claiming rewards via bp_relayers::PaymentProcedure (e.g., see the pub struct BridgeRewardPayer; implementation for BridgeHubWestend).
+crates:
+- name: bridge-runtime-common
+  bump: patch
+- name: pallet-bridge-relayers
+  bump: major
+- name: bp-relayers
+  bump: major
+- name: bridge-hub-rococo-runtime
+  bump: minor
+- name: bridge-hub-westend-runtime
+  bump: major
+- name: bridge-hub-test-utils
+  bump: major
diff --git a/prdoc/pr_7545.prdoc b/prdoc/pr_7545.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..6956b09947fca7a258acd21388fc6ab59a139852
--- /dev/null
+++ b/prdoc/pr_7545.prdoc
@@ -0,0 +1,9 @@
+title: '`fatxpool`: event streams moved to view domain'
+doc:
+- audience: Node Dev
+  description: |-
+    This pull request refactors the transaction pool `graph` module by renaming components for better clarity and decouples `graph` module from `view` module related specifics.
+    This PR does not introduce changes in the logic.
+crates:
+- name: sc-transaction-pool
+  bump: minor
diff --git a/prdoc/pr_7587.prdoc b/prdoc/pr_7587.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..22796fde9e0807d89578230c733e2212570c22a4
--- /dev/null
+++ b/prdoc/pr_7587.prdoc
@@ -0,0 +1,11 @@
+title: '[AHM] Poke deposits: Indices pallet'
+doc:
+- audience: Runtime Dev
+  description: Add a new extrinsic `poke_deposit` to `pallet-indices`. This extrinsic will be used to re-adjust the deposits made in the pallet after Asset Hub Migration.
+crates:
+- name: pallet-indices
+  bump: major
+- name: rococo-runtime
+  bump: major
+- name: westend-runtime
+  bump: major
diff --git a/prdoc/pr_7590.prdoc b/prdoc/pr_7590.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..531c5b7cef124d18c1ba6e13afbf8c186fbba843
--- /dev/null
+++ b/prdoc/pr_7590.prdoc
@@ -0,0 +1,7 @@
+title: '[pallet-revive] move exec tests'
+doc:
+- audience: Runtime Dev
+  description: Moving exec tests into a new file
+crates:
+- name: pallet-revive
+  bump: minor
diff --git a/prdoc/pr_7612.prdoc b/prdoc/pr_7612.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..c53dcb5a2a750c0feee480bdba69afbdae726b03
--- /dev/null
+++ b/prdoc/pr_7612.prdoc
@@ -0,0 +1,8 @@
+title: 'HashAndNumber: Ord, Eq, PartialOrd, PartialEq implemented'
+doc:
+- audience: Node Dev
+  description: This PR adds implementation of `Ord, Eq, PartialOrd, PartialEq`  traits
+    for `HashAndNumber` struct.
+crates:
+- name: sp-blockchain
+  bump: minor
diff --git a/prdoc/pr_7614.prdoc b/prdoc/pr_7614.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..7e0dfb092340a024d9751a9e94f9d29e3c2cc95a
--- /dev/null
+++ b/prdoc/pr_7614.prdoc
@@ -0,0 +1,21 @@
+title: '[pallet-revive] tracing improvements'
+doc:
+- audience: Runtime Dev
+  description: |-
+    Various pallet-revive improvements
+
+    - add check for precompiles addresses,
+    So we can easily identified which one are being called and not supported yet
+
+    - fixes debug_call for revert call
+    If a call revert we still want to get the traces for that call, that matches geth behaviors, diff tests will be added to the test suite for this
+
+    - fixes traces for staticcall
+    The call type was not always being reported properly.
+crates:
+- name: asset-hub-westend-runtime
+  bump: minor
+- name: pallet-revive-eth-rpc
+  bump: minor
+- name: pallet-revive
+  bump: minor
diff --git a/prdoc/pr_7625.prdoc b/prdoc/pr_7625.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..d488c6d846d2bbf8a2088ec16e2a3f7f286592dc
--- /dev/null
+++ b/prdoc/pr_7625.prdoc
@@ -0,0 +1,118 @@
+title: Update to Rust stable 1.84.1
+doc:
+- audience: Runtime Dev
+  description: |-
+    Ref https://github.com/paritytech/ci_cd/issues/1107
+
+    We mainly need that so that we can finally compile the `pallet_revive` fixtures on stable. I did my best to keep the commits focused on one thing to make review easier.
+
+    All the changes are needed because rustc introduced more warnings or is more strict about existing ones. Most of the stuff could just be fixed and the commits should be pretty self explanatory. However, there are a few this that are notable:
+
+    ## `non_local_definitions `
+
+    A lot of runtimes to write `impl` blocks inside functions. This makes sense to reduce the amount of conditional compilation. I guess I could have moved them into a module instead. But I think allowing it here makes sense to avoid the code churn.
+
+    ## `unexpected_cfgs`
+
+    The FRAME macros emit code that references various features like `std`, `runtime-benchmarks` or `try-runtime`. If a create that uses those macros does not have those features we get this warning. Those were mostly when defining a `mock` runtime. I opted for silencing the warning in this case rather than adding not needed features.
+
+    For the benchmarking ui tests I opted for adding the `runtime-benchmark` feature to the `Cargo.toml`.
+
+    ## Failing UI test
+
+    I am bumping the `trybuild` version and regenerating the ui tests. The old version seems to be incompatible. This requires us to pass `deny_warnings` in `CARGO_ENCODED_RUSTFLAGS` as `RUSTFLAGS` is ignored in the new version.
+
+    ## Removing toolchain file from the pallet revive fixtures
+
+    This is no longer needed since the latest stable will compile them fine using the `RUSTC_BOOTSTRAP=1`.
+crates:
+- name: asset-hub-rococo-runtime
+  bump: patch
+- name: asset-hub-westend-runtime
+  bump: patch
+- name: bridge-hub-rococo-runtime
+  bump: patch
+- name: bridge-hub-westend-runtime
+  bump: patch
+- name: collectives-westend-runtime
+  bump: patch
+- name: contracts-rococo-runtime
+  bump: patch
+- name: coretime-rococo-runtime
+  bump: patch
+- name: coretime-westend-runtime
+  bump: patch
+- name: glutton-westend-runtime
+  bump: patch
+- name: people-rococo-runtime
+  bump: patch
+- name: people-westend-runtime
+  bump: patch
+- name: penpal-runtime
+  bump: patch
+- name: polkadot-omni-node-lib
+  bump: patch
+- name: rococo-runtime
+  bump: patch
+- name: westend-runtime
+  bump: patch
+- name: pallet-babe
+  bump: patch
+- name: frame-benchmarking
+  bump: patch
+- name: sp-core
+  bump: patch
+- name: sp-runtime
+  bump: patch
+- name: pallet-bridge-grandpa
+  bump: patch
+- name: frame-support
+  bump: patch
+- name: sc-network-types
+  bump: patch
+- name: pallet-migrations
+  bump: patch
+- name: pallet-parameters
+  bump: patch
+- name: bp-test-utils
+  bump: patch
+- name: polkadot-runtime-parachains
+  bump: patch
+- name: sc-allocator
+  bump: patch
+- name: pallet-transaction-storage
+  bump: patch
+- name: pallet-utility
+  bump: patch
+- name: sp-transaction-storage-proof
+  bump: patch
+- name: sp-trie
+  bump: patch
+- name: pallet-revive-fixtures
+  bump: patch
+- name: polkadot-statement-distribution
+  bump: patch
+- name: mmr-gadget
+  bump: patch
+- name: sc-rpc-spec-v2
+  bump: patch
+- name: sp-state-machine
+  bump: patch
+- name: xcm-simulator-example
+  bump: patch
+- name: pallet-node-authorization
+  bump: patch
+- name: pallet-scored-pool
+  bump: patch
+- name: pallet-statement
+  bump: patch
+- name: polkadot-overseer
+  bump: patch
+- name: polkadot-runtime-common
+  bump: patch
+- name: pallet-lottery
+  bump: patch
+- name: pallet-society
+  bump: patch
+- name: sp-runtime-interface
+  bump: patch
diff --git a/prdoc/pr_7634.prdoc b/prdoc/pr_7634.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..f1bdd383b2fc7cc375d9b00e2133560cdc74c577
--- /dev/null
+++ b/prdoc/pr_7634.prdoc
@@ -0,0 +1,16 @@
+# 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: derive `DecodeWithMemTracking` for `RuntimeCall`
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      This PR derives `DecodeWithMemTracking` for `RuntimeCall`.
+      All the types used in the `RuntimeCall` should implement `DecodeWithMemTracking` as well.
+
+crates:
+  - name: frame-support-procedural
+    bump: major
+  - name: bridge-hub-westend-runtime
+    bump: none
diff --git a/prdoc/pr_7640.prdoc b/prdoc/pr_7640.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..ede525d2199967f4210dbec7a943dadcf6fec1ad
--- /dev/null
+++ b/prdoc/pr_7640.prdoc
@@ -0,0 +1,25 @@
+title: Bring the latest compatibility fixes via litep2p v0.9.1
+
+doc:
+  - audience: [Node Dev, Node Operator]
+    description: |
+      This release enhances compatibility between litep2p and libp2p by using the latest Yamux upstream version.
+      Additionally, it includes various improvements and fixes to boost the stability and performance of the WebSocket stream and the multistream-select protocol.
+
+crates:
+  - name: sc-network
+    bump: minor
+  - name: cumulus-client-cli
+    bump: minor
+  - name: sc-network-types
+    bump: minor
+  - name: sc-transaction-pool-api
+    bump: minor
+  - name: sc-transaction-pool
+    bump: minor
+  - name: polkadot-statement-distribution
+    bump: minor
+  - name: polkadot-dispute-distribution
+    bump: minor
+  - name: cumulus-relay-chain-rpc-interface
+    bump: minor
diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index d90d103fdedc20a1eff3b839fe62b581bc11c5cb..7e33f1feeca19e3f516b79dc1703c1d126229020 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -33,7 +33,7 @@ use polkadot_sdk::sp_core::crypto::FromEntropy;
 use polkadot_sdk::*;
 
 use alloc::{vec, vec::Vec};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_election_provider_support::{
 	bounds::{ElectionBounds, ElectionBoundsBuilder},
 	onchain, BalancingConfig, ElectionDataProvider, SequentialPhragmen, VoteWeight,
@@ -417,6 +417,7 @@ parameter_types! {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	MaxEncodedLen,
 	scale_info::TypeInfo,
@@ -3744,11 +3745,15 @@ impl_runtime_apis! {
 		{
 			use pallet_revive::tracing::trace;
 			let mut tracer = config.build(Revive::evm_gas_from_weight);
-			trace(&mut tracer, || {
-				Self::eth_transact(tx)
-			})?;
-
-			Ok(tracer.collect_traces().pop().expect("eth_transact succeeded, trace must exist, qed"))
+			let result = trace(&mut tracer, || Self::eth_transact(tx));
+
+			if let Some(trace) = tracer.collect_traces().pop() {
+				Ok(trace)
+			} else if let Err(err) = result {
+				Err(err)
+			} else {
+				Ok(Default::default())
+			}
 		}
 	}
 
@@ -4058,6 +4063,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
diff --git a/substrate/client/allocator/src/freeing_bump.rs b/substrate/client/allocator/src/freeing_bump.rs
index 405916adc3c3ff1bba878b7513fb1125c2f3462a..f98e540b18c5b3ce0759bd905329dcfff4aaf7d5 100644
--- a/substrate/client/allocator/src/freeing_bump.rs
+++ b/substrate/client/allocator/src/freeing_bump.rs
@@ -350,7 +350,7 @@ pub struct AllocationStats {
 ///
 /// Returns `None` if the number of pages to not fit into `u32`.
 fn pages_from_size(size: u64) -> Option<u32> {
-	u32::try_from((size + PAGE_SIZE as u64 - 1) / PAGE_SIZE as u64).ok()
+	u32::try_from(size.div_ceil(PAGE_SIZE as u64)).ok()
 }
 
 /// An implementation of freeing bump allocator.
@@ -378,7 +378,7 @@ impl FreeingBumpHeapAllocator {
 	///
 	/// - `heap_base` - the offset from the beginning of the linear memory where the heap starts.
 	pub fn new(heap_base: u32) -> Self {
-		let aligned_heap_base = (heap_base + ALIGNMENT - 1) / ALIGNMENT * ALIGNMENT;
+		let aligned_heap_base = heap_base.div_ceil(ALIGNMENT) * ALIGNMENT;
 
 		FreeingBumpHeapAllocator {
 			original_heap_base: aligned_heap_base,
diff --git a/substrate/client/merkle-mountain-range/src/test_utils.rs b/substrate/client/merkle-mountain-range/src/test_utils.rs
index 3b0506ef55d329866fba4af71fb6351caa54c4b2..79879cc09a79e1f945104913defb132cf1b96215 100644
--- a/substrate/client/merkle-mountain-range/src/test_utils.rs
+++ b/substrate/client/merkle-mountain-range/src/test_utils.rs
@@ -16,6 +16,8 @@
 // You should have received a copy of the GNU General Public License
 // along with this program. If not, see <https://www.gnu.org/licenses/>.
 
+//! Test utilities.
+
 use crate::MmrGadget;
 use parking_lot::Mutex;
 use sc_block_builder::BlockBuilderBuilder;
@@ -67,9 +69,12 @@ pub(crate) struct MmrBlock {
 	pub(crate) leaf_data: Vec<u8>,
 }
 
+/// Which kind of key type to use.
 #[derive(Clone, Copy)]
 pub enum OffchainKeyType {
+	/// Temporary key.
 	Temp,
+	/// Cononical key.
 	Canon,
 }
 
diff --git a/substrate/client/network/src/litep2p/mod.rs b/substrate/client/network/src/litep2p/mod.rs
index 4f105936ac5632d40a648a2fe11857dc3d110c48..ee11e90cbc27e3c3063a27f335373d0c5ec1b751 100644
--- a/substrate/client/network/src/litep2p/mod.rs
+++ b/substrate/client/network/src/litep2p/mod.rs
@@ -39,7 +39,6 @@ use crate::{
 		},
 	},
 	peer_store::PeerStoreProvider,
-	protocol,
 	service::{
 		metrics::{register_without_sources, MetricSources, Metrics, NotificationMetrics},
 		out_events,
@@ -277,53 +276,6 @@ impl Litep2pNetworkBackend {
 		};
 		let config_builder = ConfigBuilder::new();
 
-		// The yamux buffer size limit is configured to be equal to the maximum frame size
-		// of all protocols. 10 bytes are added to each limit for the length prefix that
-		// is not included in the upper layer protocols limit but is still present in the
-		// yamux buffer. These 10 bytes correspond to the maximum size required to encode
-		// a variable-length-encoding 64bits number. In other words, we make the
-		// assumption that no notification larger than 2^64 will ever be sent.
-		let yamux_maximum_buffer_size = {
-			let requests_max = config
-				.request_response_protocols
-				.iter()
-				.map(|cfg| usize::try_from(cfg.max_request_size).unwrap_or(usize::MAX));
-			let responses_max = config
-				.request_response_protocols
-				.iter()
-				.map(|cfg| usize::try_from(cfg.max_response_size).unwrap_or(usize::MAX));
-			let notifs_max = config
-				.notification_protocols
-				.iter()
-				.map(|cfg| usize::try_from(cfg.max_notification_size()).unwrap_or(usize::MAX));
-
-			// A "default" max is added to cover all the other protocols: ping, identify,
-			// kademlia, block announces, and transactions.
-			let default_max = cmp::max(
-				1024 * 1024,
-				usize::try_from(protocol::BLOCK_ANNOUNCES_TRANSACTIONS_SUBSTREAM_SIZE)
-					.unwrap_or(usize::MAX),
-			);
-
-			iter::once(default_max)
-				.chain(requests_max)
-				.chain(responses_max)
-				.chain(notifs_max)
-				.max()
-				.expect("iterator known to always yield at least one element; qed")
-				.saturating_add(10)
-		};
-
-		let yamux_config = {
-			let mut yamux_config = litep2p::yamux::Config::default();
-			// Enable proper flow-control: window updates are only sent when
-			// buffered data has been consumed.
-			yamux_config.set_window_update_mode(litep2p::yamux::WindowUpdateMode::OnRead);
-			yamux_config.set_max_buffer_size(yamux_maximum_buffer_size);
-
-			yamux_config
-		};
-
 		let (tcp, websocket): (Vec<Option<_>>, Vec<Option<_>>) = config
 			.network_config
 			.listen_addresses
@@ -372,13 +324,13 @@ impl Litep2pNetworkBackend {
 		config_builder
 			.with_websocket(WebSocketTransportConfig {
 				listen_addresses: websocket.into_iter().flatten().map(Into::into).collect(),
-				yamux_config: yamux_config.clone(),
+				yamux_config: litep2p::yamux::Config::default(),
 				nodelay: true,
 				..Default::default()
 			})
 			.with_tcp(TcpTransportConfig {
 				listen_addresses: tcp.into_iter().flatten().map(Into::into).collect(),
-				yamux_config,
+				yamux_config: litep2p::yamux::Config::default(),
 				nodelay: true,
 				..Default::default()
 			})
diff --git a/substrate/client/network/src/protocol.rs b/substrate/client/network/src/protocol.rs
index 81e1848adefa277d86e6bd05c8941bbda13e8cda..260edf58ba2e990c20fff8359328cf328dc9a207 100644
--- a/substrate/client/network/src/protocol.rs
+++ b/substrate/client/network/src/protocol.rs
@@ -22,7 +22,6 @@ use crate::{
 	protocol_controller::{self, SetId},
 	service::{metrics::NotificationMetrics, traits::Direction},
 	types::ProtocolName,
-	MAX_RESPONSE_SIZE,
 };
 
 use codec::Encode;
@@ -56,10 +55,6 @@ pub mod message;
 // Log target for this file.
 const LOG_TARGET: &str = "sub-libp2p";
 
-/// Maximum size used for notifications in the block announce and transaction protocols.
-// Must be equal to `max(MAX_BLOCK_ANNOUNCE_SIZE, MAX_TRANSACTIONS_SIZE)`.
-pub(crate) const BLOCK_ANNOUNCES_TRANSACTIONS_SUBSTREAM_SIZE: u64 = MAX_RESPONSE_SIZE;
-
 /// Identifier of the peerset for the block announces protocol.
 const HARDCODED_PEERSETS_SYNC: SetId = SetId::from(0);
 
diff --git a/substrate/client/network/types/src/kad.rs b/substrate/client/network/types/src/kad.rs
index 72028d356dc7896ee291ff41e14a78a4a022b856..e844f976740187ef9a5d3e56597e790c7d4d11a1 100644
--- a/substrate/client/network/types/src/kad.rs
+++ b/substrate/client/network/types/src/kad.rs
@@ -101,7 +101,7 @@ impl Record {
 
 	/// Checks whether the record is expired w.r.t. the given `Instant`.
 	pub fn is_expired(&self, now: Instant) -> bool {
-		self.expires.map_or(false, |t| now >= t)
+		self.expires.is_some_and(|t| now >= t)
 	}
 }
 
diff --git a/substrate/client/network/types/src/multiaddr/protocol.rs b/substrate/client/network/types/src/multiaddr/protocol.rs
index aca3a31136860d56d5058301a85ced87fa5ab0f3..35fcaa5493a47c82a1406e7b5f2f709eca6476ae 100644
--- a/substrate/client/network/types/src/multiaddr/protocol.rs
+++ b/substrate/client/network/types/src/multiaddr/protocol.rs
@@ -66,14 +66,14 @@ pub enum Protocol<'a> {
 	Wss(Cow<'a, str>),
 }
 
-impl<'a> Display for Protocol<'a> {
+impl Display for Protocol<'_> {
 	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 		let protocol = LiteP2pProtocol::from(self.clone());
 		Display::fmt(&protocol, f)
 	}
 }
 
-impl<'a> From<IpAddr> for Protocol<'a> {
+impl From<IpAddr> for Protocol<'_> {
 	#[inline]
 	fn from(addr: IpAddr) -> Self {
 		match addr {
@@ -83,14 +83,14 @@ impl<'a> From<IpAddr> for Protocol<'a> {
 	}
 }
 
-impl<'a> From<Ipv4Addr> for Protocol<'a> {
+impl From<Ipv4Addr> for Protocol<'_> {
 	#[inline]
 	fn from(addr: Ipv4Addr) -> Self {
 		Protocol::Ip4(addr)
 	}
 }
 
-impl<'a> From<Ipv6Addr> for Protocol<'a> {
+impl From<Ipv6Addr> for Protocol<'_> {
 	#[inline]
 	fn from(addr: Ipv6Addr) -> Self {
 		Protocol::Ip6(addr)
diff --git a/substrate/client/rpc-spec-v2/src/chain_head/test_utils.rs b/substrate/client/rpc-spec-v2/src/chain_head/test_utils.rs
index fa10fde388f97a915881fd3f08010b8c91a012b6..48259f10ffc076c03bfc43e457086121f8efeaf9 100644
--- a/substrate/client/rpc-spec-v2/src/chain_head/test_utils.rs
+++ b/substrate/client/rpc-spec-v2/src/chain_head/test_utils.rs
@@ -16,6 +16,8 @@
 // You should have received a copy of the GNU General Public License
 // along with this program. If not, see <https://www.gnu.org/licenses/>.
 
+//! Test utilities.
+
 use parking_lot::Mutex;
 use sc_client_api::{
 	execution_extensions::ExecutionExtensions, BlockBackend, BlockImportNotification,
@@ -36,6 +38,7 @@ use sp_version::RuntimeVersion;
 use std::sync::Arc;
 use substrate_test_runtime::{Block, Hash, Header, H256};
 
+/// A mock client used for testing.
 pub struct ChainHeadMockClient<Client> {
 	client: Arc<Client>,
 	import_sinks: Mutex<Vec<TracingUnboundedSender<BlockImportNotification<Block>>>>,
@@ -44,6 +47,7 @@ pub struct ChainHeadMockClient<Client> {
 }
 
 impl<Client> ChainHeadMockClient<Client> {
+	/// Create a new mock client.
 	pub fn new(client: Arc<Client>) -> Self {
 		ChainHeadMockClient {
 			client,
@@ -53,6 +57,7 @@ impl<Client> ChainHeadMockClient<Client> {
 		}
 	}
 
+	/// Trigger the import stram from a header.
 	pub async fn trigger_import_stream(&self, header: Header) {
 		// Ensure the client called the `import_notification_stream`.
 		while self.import_sinks.lock().is_empty() {
@@ -69,6 +74,7 @@ impl<Client> ChainHeadMockClient<Client> {
 		}
 	}
 
+	/// Trigger the import stram from a header and a list of stale heads.
 	pub async fn trigger_finality_stream(&self, header: Header, stale_heads: Vec<Hash>) {
 		// Ensure the client called the `finality_notification_stream`.
 		while self.finality_sinks.lock().is_empty() {
diff --git a/substrate/client/transaction-pool/benches/basics.rs b/substrate/client/transaction-pool/benches/basics.rs
index 5ba9dd40c15680ee2c5c83803f8bc62b59e96c57..74dd69a8aaf8d560b862aaa0df44eae4a57adc5f 100644
--- a/substrate/client/transaction-pool/benches/basics.rs
+++ b/substrate/client/transaction-pool/benches/basics.rs
@@ -151,7 +151,7 @@ fn uxt(transfer: TransferData) -> Extrinsic {
 	ExtrinsicBuilder::new_bench_call(transfer).build()
 }
 
-fn bench_configured(pool: Pool<TestApi>, number: u64, api: Arc<TestApi>) {
+fn bench_configured(pool: Pool<TestApi, ()>, number: u64, api: Arc<TestApi>) {
 	let source = TimedTransactionSource::new_external(false);
 	let mut futures = Vec::new();
 	let mut tags = Vec::new();
diff --git a/substrate/client/transaction-pool/src/common/tests.rs b/substrate/client/transaction-pool/src/common/tests.rs
index 7f2cbe24d8ef62bae4ccb4ffda8d974d92c38c97..c391beb21b07fcd6dd82ded7015529df503c78ae 100644
--- a/substrate/client/transaction-pool/src/common/tests.rs
+++ b/substrate/client/transaction-pool/src/common/tests.rs
@@ -18,7 +18,7 @@
 
 //! Testing related primitives for internal usage in this crate.
 
-use crate::graph::{BlockHash, ChainApi, ExtrinsicFor, NumberFor, Pool, RawExtrinsicFor};
+use crate::graph::{BlockHash, ChainApi, ExtrinsicFor, NumberFor, RawExtrinsicFor};
 use codec::Encode;
 use parking_lot::Mutex;
 use sc_transaction_pool_api::error;
@@ -36,6 +36,8 @@ use substrate_test_runtime::{
 	ExtrinsicBuilder, Hashing, RuntimeCall, Transfer, TransferData, H256,
 };
 
+type Pool<Api> = crate::graph::Pool<Api, ()>;
+
 pub(crate) const INVALID_NONCE: u64 = 254;
 
 /// Test api that implements [`ChainApi`].
diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/dropped_watcher.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/dropped_watcher.rs
index e04c826a1d522aa55e9e8a9e9ca2810ab3da65ba..91237910adc1f59f3129f2ce73c7cd7ad021716a 100644
--- a/substrate/client/transaction-pool/src/fork_aware_txpool/dropped_watcher.rs
+++ b/substrate/client/transaction-pool/src/fork_aware_txpool/dropped_watcher.rs
@@ -81,7 +81,8 @@ pub enum DroppedReason<Hash> {
 }
 
 /// Dropped-logic related event from the single view.
-pub type ViewStreamEvent<C> = crate::graph::TransactionStatusEvent<ExtrinsicHash<C>, BlockHash<C>>;
+pub type ViewStreamEvent<C> =
+	crate::fork_aware_txpool::view::TransactionStatusEvent<ExtrinsicHash<C>, BlockHash<C>>;
 
 /// Dropped-logic stream of events coming from the single view.
 type ViewStream<C> = Pin<Box<dyn futures::Stream<Item = ViewStreamEvent<C>> + Send>>;
diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/fork_aware_txpool.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/fork_aware_txpool.rs
index 5b43d900848abecacdd599806eb9d9cb24bf042f..c21e0b8df6ff54afd5a55ee77ca5629d2d7a1b45 100644
--- a/substrate/client/transaction-pool/src/fork_aware_txpool/fork_aware_txpool.rs
+++ b/substrate/client/transaction-pool/src/fork_aware_txpool/fork_aware_txpool.rs
@@ -478,7 +478,7 @@ where
 		};
 
 		if let Ok((Some(best_tree_route), Some(best_view))) = best_result {
-			let tmp_view: View<ChainApi> =
+			let (tmp_view, _, _): (View<ChainApi>, _, _) =
 				View::new_from_other(&best_view, &HashAndNumber { hash: at, number: block_number });
 
 			let mut all_extrinsics = vec![];
@@ -1085,26 +1085,28 @@ where
 			?tree_route,
 			"build_new_view"
 		);
-		let mut view = if let Some(origin_view) = origin_view {
-			let mut view = View::new_from_other(&origin_view, at);
-			if !tree_route.retracted().is_empty() {
-				view.pool.clear_recently_pruned();
-			}
-			view
-		} else {
-			debug!(
-				target: LOG_TARGET,
-				?at,
-				"creating non-cloned view"
-			);
-			View::new(
-				self.api.clone(),
-				at.clone(),
-				self.options.clone(),
-				self.metrics.clone(),
-				self.is_validator.clone(),
-			)
-		};
+		let (mut view, view_dropped_stream, view_aggregated_stream) =
+			if let Some(origin_view) = origin_view {
+				let (mut view, view_dropped_stream, view_aggragated_stream) =
+					View::new_from_other(&origin_view, at);
+				if !tree_route.retracted().is_empty() {
+					view.pool.clear_recently_pruned();
+				}
+				(view, view_dropped_stream, view_aggragated_stream)
+			} else {
+				debug!(
+					target: LOG_TARGET,
+					?at,
+					"creating non-cloned view"
+				);
+				View::new(
+					self.api.clone(),
+					at.clone(),
+					self.options.clone(),
+					self.metrics.clone(),
+					self.is_validator.clone(),
+				)
+			};
 
 		let start = Instant::now();
 		// 1. Capture all import notification from the very beginning, so first register all
@@ -1114,15 +1116,13 @@ where
 			view.pool.validated_pool().import_notification_stream().boxed(),
 		);
 
-		self.view_store.dropped_stream_controller.add_view(
-			view.at.hash,
-			view.pool.validated_pool().create_dropped_by_limits_stream().boxed(),
-		);
+		self.view_store
+			.dropped_stream_controller
+			.add_view(view.at.hash, view_dropped_stream.boxed());
 
-		self.view_store.listener.add_view_aggregated_stream(
-			view.at.hash,
-			view.pool.validated_pool().create_aggregated_stream().boxed(),
-		);
+		self.view_store
+			.listener
+			.add_view_aggregated_stream(view.at.hash, view_aggregated_stream.boxed());
 		// sync the transactions statuses and referencing views in all the listeners with newly
 		// cloned view.
 		view.pool.validated_pool().retrigger_notifications();
diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/mod.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/mod.rs
index 2c4da0182a2524431077ed3284b406bc6fc8869c..fce2d4ad6b27e05ae75bd9345b649576db4714fe 100644
--- a/substrate/client/transaction-pool/src/fork_aware_txpool/mod.rs
+++ b/substrate/client/transaction-pool/src/fork_aware_txpool/mod.rs
@@ -323,7 +323,7 @@
 //! [`MultiViewListener`]: crate::fork_aware_txpool::multi_view_listener::MultiViewListener
 //! [`Pool`]: crate::graph::Pool
 //! [`Watcher`]: crate::graph::watcher::Watcher
-//! [`AggregatedStream`]: crate::graph::AggregatedStream
+//! [`AggregatedStream`]: crate::fork_aware_txpool::view::AggregatedStream
 //! [`Options`]: crate::graph::Options
 //! [`vp::import_notification_stream`]: ../graph/validated_pool/struct.ValidatedPool.html#method.import_notification_stream
 //! [`vp::enforce_limits`]: ../graph/validated_pool/struct.ValidatedPool.html#method.enforce_limits
diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/multi_view_listener.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/multi_view_listener.rs
index 62c4320e5d3531abe22c531b90fa99dfcb30d585..5216f494ffa55e22aeffaeaee50985b08407e340 100644
--- a/substrate/client/transaction-pool/src/fork_aware_txpool/multi_view_listener.rs
+++ b/substrate/client/transaction-pool/src/fork_aware_txpool/multi_view_listener.rs
@@ -22,8 +22,8 @@
 
 use crate::{
 	common::tracing_log_xt::log_xt_trace,
-	fork_aware_txpool::stream_map_util::next_event,
-	graph::{self, BlockHash, ExtrinsicHash, TransactionStatusEvent},
+	fork_aware_txpool::{stream_map_util::next_event, view::TransactionStatusEvent},
+	graph::{self, BlockHash, ExtrinsicHash},
 	LOG_TARGET,
 };
 use futures::{Future, FutureExt, Stream, StreamExt};
diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/revalidation_worker.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/revalidation_worker.rs
index 2f3d31d0e6fde7484a9fbbabfa3a54aa43ec0448..24f71982c7816e12e7395cd7d00216bc90c02847 100644
--- a/substrate/client/transaction-pool/src/fork_aware_txpool/revalidation_worker.rs
+++ b/substrate/client/transaction-pool/src/fork_aware_txpool/revalidation_worker.rs
@@ -211,13 +211,9 @@ mod tests {
 		let api = Arc::new(TestApi::default());
 		let block0 = api.expect_hash_and_number(0);
 
-		let view = Arc::new(View::new(
-			api.clone(),
-			block0,
-			Default::default(),
-			Default::default(),
-			false.into(),
-		));
+		let view = Arc::new(
+			View::new(api.clone(), block0, Default::default(), Default::default(), false.into()).0,
+		);
 		let queue = Arc::new(RevalidationQueue::new());
 
 		let uxt = uxt(Transfer {
diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/view.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/view.rs
index 4fa83ccc79bfa4a0348043ff547e10718b7fe30b..348108e24dcfc21b61c6ec18b44dd13925d8a2cc 100644
--- a/substrate/client/transaction-pool/src/fork_aware_txpool/view.rs
+++ b/substrate/client/transaction-pool/src/fork_aware_txpool/view.rs
@@ -27,14 +27,16 @@ use super::metrics::MetricsLink as PrometheusMetrics;
 use crate::{
 	common::tracing_log_xt::log_xt_trace,
 	graph::{
-		self, base_pool::TimedTransactionSource, ExtrinsicFor, ExtrinsicHash, IsValidator,
-		TransactionFor, ValidatedPoolSubmitOutcome, ValidatedTransaction, ValidatedTransactionFor,
+		self, base_pool::TimedTransactionSource, BlockHash, ExtrinsicFor, ExtrinsicHash,
+		IsValidator, TransactionFor, ValidatedPoolSubmitOutcome, ValidatedTransaction,
+		ValidatedTransactionFor,
 	},
 	LOG_TARGET,
 };
 use indexmap::IndexMap;
 use parking_lot::Mutex;
-use sc_transaction_pool_api::{error::Error as TxPoolError, PoolStatus};
+use sc_transaction_pool_api::{error::Error as TxPoolError, PoolStatus, TransactionStatus};
+use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
 use sp_blockchain::HashAndNumber;
 use sp_runtime::{
 	generic::BlockId, traits::Block as BlockT, transaction_validity::TransactionValidityError,
@@ -109,13 +111,139 @@ impl<ChainApi: graph::ChainApi> FinishRevalidationWorkerChannels<ChainApi> {
 	}
 }
 
+/// Single event used in aggregated stream. Tuple containing hash of transactions and its status.
+pub(super) type TransactionStatusEvent<H, BH> = (H, TransactionStatus<H, BH>);
+/// Warning threshold for (unbounded) channel used in aggregated view's streams.
+const VIEW_STREAM_WARN_THRESHOLD: usize = 100_000;
+
+/// Stream of events providing statuses of all the transactions within the pool.
+pub(super) type AggregatedStream<H, BH> = TracingUnboundedReceiver<TransactionStatusEvent<H, BH>>;
+
+/// Type alias for a stream of events intended to track dropped transactions.
+type DroppedMonitoringStream<H, BH> = TracingUnboundedReceiver<TransactionStatusEvent<H, BH>>;
+
+/// Notification handler for transactions updates triggered in `ValidatedPool`.
+///
+/// `ViewPoolObserver` handles transaction status changes notifications coming from an instance of
+/// validated pool associated with the `View` and forwards them through specified channels
+/// into the View's streams.
+pub(super) struct ViewPoolObserver<ChainApi: graph::ChainApi> {
+	/// The sink used to notify dropped by enforcing limits or by being usurped, or invalid
+	/// transactions.
+	///
+	/// Note: Ready and future statuses are alse communicated through this channel, enabling the
+	/// stream consumer to track views that reference the transaction.
+	dropped_stream_sink: TracingUnboundedSender<
+		TransactionStatusEvent<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>,
+	>,
+
+	/// The sink of the single, merged stream providing updates for all the transactions in the
+	/// associated pool.
+	///
+	/// Note: some of the events which are currently ignored on the other side of this channel
+	/// (external watcher) are not relayed.
+	aggregated_stream_sink: TracingUnboundedSender<
+		TransactionStatusEvent<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>,
+	>,
+}
+
+impl<C: graph::ChainApi> graph::EventHandler<C> for ViewPoolObserver<C> {
+	// note: skipped, notified by ForkAwareTxPool directly to multi view listener.
+	fn broadcasted(&self, _: ExtrinsicHash<C>, _: Vec<String>) {}
+	fn dropped(&self, _: ExtrinsicHash<C>) {}
+	fn finalized(&self, _: ExtrinsicHash<C>, _: BlockHash<C>, _: usize) {}
+	fn retracted(&self, _: ExtrinsicHash<C>, _: BlockHash<C>) {
+		// note: [#5479], we do not send to aggregated stream.
+	}
+
+	fn ready(&self, tx: ExtrinsicHash<C>) {
+		let status = TransactionStatus::Ready;
+		self.send_to_dropped_stream_sink(tx, status.clone());
+		self.send_to_aggregated_stream_sink(tx, status);
+	}
+
+	fn future(&self, tx: ExtrinsicHash<C>) {
+		let status = TransactionStatus::Future;
+		self.send_to_dropped_stream_sink(tx, status.clone());
+		self.send_to_aggregated_stream_sink(tx, status);
+	}
+
+	fn limits_enforced(&self, tx: ExtrinsicHash<C>) {
+		self.send_to_dropped_stream_sink(tx, TransactionStatus::Dropped);
+	}
+
+	fn usurped(&self, tx: ExtrinsicHash<C>, by: ExtrinsicHash<C>) {
+		self.send_to_dropped_stream_sink(tx, TransactionStatus::Usurped(by));
+	}
+
+	fn invalid(&self, tx: ExtrinsicHash<C>) {
+		self.send_to_dropped_stream_sink(tx, TransactionStatus::Invalid);
+	}
+
+	fn pruned(&self, tx: ExtrinsicHash<C>, block_hash: BlockHash<C>, tx_index: usize) {
+		self.send_to_aggregated_stream_sink(tx, TransactionStatus::InBlock((block_hash, tx_index)));
+	}
+
+	fn finality_timeout(&self, tx: ExtrinsicHash<C>, hash: BlockHash<C>) {
+		//todo: do we need this? [related issue: #5482]
+		self.send_to_aggregated_stream_sink(tx, TransactionStatus::FinalityTimeout(hash));
+	}
+}
+
+impl<ChainApi: graph::ChainApi> ViewPoolObserver<ChainApi> {
+	/// Creates an instance of `ViewPoolObserver` together with associated view's streams.
+	///
+	/// This methods creates an event handler that shall be registered in the `ValidatedPool`
+	/// instance associated with the view. It also creates new view's streams:
+	/// - a single stream intended to watch dropped transactions only. The stream can be used to
+	///   subscribe to events related to dropping of all extrinsics in the pool.
+	/// - a single merged stream for all extrinsics in the associated pool. The stream can be used
+	/// to subscribe to life-cycle events of all extrinsics in the pool. For fork-aware
+	/// pool implementation this approach seems to be more efficient than using individual
+	/// streams for every transaction.
+	fn new() -> (
+		Self,
+		DroppedMonitoringStream<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>,
+		AggregatedStream<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>,
+	) {
+		let (dropped_stream_sink, dropped_stream) =
+			tracing_unbounded("mpsc_txpool_watcher", VIEW_STREAM_WARN_THRESHOLD);
+		let (aggregated_stream_sink, aggregated_stream) =
+			tracing_unbounded("mpsc_txpool_aggregated_stream", VIEW_STREAM_WARN_THRESHOLD);
+
+		(Self { dropped_stream_sink, aggregated_stream_sink }, dropped_stream, aggregated_stream)
+	}
+
+	/// Sends given event to the `dropped_stream_sink`.
+	fn send_to_dropped_stream_sink(
+		&self,
+		tx: ExtrinsicHash<ChainApi>,
+		status: TransactionStatus<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>,
+	) {
+		if let Err(e) = self.dropped_stream_sink.unbounded_send((tx, status.clone())) {
+			trace!(target: LOG_TARGET, "[{:?}] dropped_sink: {:?} send message failed: {:?}", tx, status, e);
+		}
+	}
+
+	/// Sends given event to the `aggregated_stream_sink`.
+	fn send_to_aggregated_stream_sink(
+		&self,
+		tx: ExtrinsicHash<ChainApi>,
+		status: TransactionStatus<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>,
+	) {
+		if let Err(e) = self.aggregated_stream_sink.unbounded_send((tx, status.clone())) {
+			trace!(target: LOG_TARGET, "[{:?}] aggregated_stream {:?} send message failed: {:?}", tx, status, e);
+		}
+	}
+}
+
 /// Represents the state of transaction pool for given block.
 ///
 /// Refer to [*View*](../index.html#view) section for more details on the purpose and life cycle of
 /// the `View`.
 pub(super) struct View<ChainApi: graph::ChainApi> {
 	/// The internal pool keeping the set of ready and future transaction at the given block.
-	pub(super) pool: graph::Pool<ChainApi>,
+	pub(super) pool: graph::Pool<ChainApi, ViewPoolObserver<ChainApi>>,
 	/// The hash and number of the block with which this view is associated.
 	pub(super) at: HashAndNumber<ChainApi::Block>,
 	/// Endpoints of communication channel with background worker.
@@ -136,24 +264,50 @@ where
 		options: graph::Options,
 		metrics: PrometheusMetrics,
 		is_validator: IsValidator,
-	) -> Self {
+	) -> (
+		Self,
+		DroppedMonitoringStream<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>,
+		AggregatedStream<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>,
+	) {
 		metrics.report(|metrics| metrics.non_cloned_views.inc());
-		Self {
-			pool: graph::Pool::new(options, is_validator, api),
-			at,
-			revalidation_worker_channels: Mutex::from(None),
-			metrics,
-		}
+		let (event_handler, dropped_stream, aggregated_stream) = ViewPoolObserver::new();
+		(
+			Self {
+				pool: graph::Pool::new_with_event_handler(
+					options,
+					is_validator,
+					api,
+					event_handler,
+				),
+				at,
+				revalidation_worker_channels: Mutex::from(None),
+				metrics,
+			},
+			dropped_stream,
+			aggregated_stream,
+		)
 	}
 
 	/// Creates a copy of the other view.
-	pub(super) fn new_from_other(&self, at: &HashAndNumber<ChainApi::Block>) -> Self {
-		View {
-			at: at.clone(),
-			pool: self.pool.deep_clone(),
-			revalidation_worker_channels: Mutex::from(None),
-			metrics: self.metrics.clone(),
-		}
+	pub(super) fn new_from_other(
+		&self,
+		at: &HashAndNumber<ChainApi::Block>,
+	) -> (
+		Self,
+		DroppedMonitoringStream<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>,
+		AggregatedStream<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>,
+	) {
+		let (event_handler, dropped_stream, aggregated_stream) = ViewPoolObserver::new();
+		(
+			View {
+				at: at.clone(),
+				pool: self.pool.deep_clone_with_event_handler(event_handler),
+				revalidation_worker_channels: Mutex::from(None),
+				metrics: self.metrics.clone(),
+			},
+			dropped_stream,
+			aggregated_stream,
+		)
 	}
 
 	/// Imports single unvalidated extrinsic into the view.
@@ -504,7 +658,10 @@ where
 		listener_action: F,
 	) -> Vec<TransactionFor<ChainApi>>
 	where
-		F: Fn(&mut crate::graph::Listener<ChainApi>, ExtrinsicHash<ChainApi>),
+		F: Fn(
+			&mut crate::graph::EventDispatcher<ChainApi, ViewPoolObserver<ChainApi>>,
+			ExtrinsicHash<ChainApi>,
+		),
 	{
 		self.pool.validated_pool().remove_subtree(hashes, listener_action)
 	}
diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/view_store.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/view_store.rs
index 96cf9f7106894d43e17e2f089f3a513e6f0c3e9d..a1585741839fae866f45b91d394aeea1e2a844e4 100644
--- a/substrate/client/transaction-pool/src/fork_aware_txpool/view_store.rs
+++ b/substrate/client/transaction-pool/src/fork_aware_txpool/view_store.rs
@@ -20,7 +20,7 @@
 
 use super::{
 	multi_view_listener::{MultiViewListener, TxStatusStream},
-	view::View,
+	view::{View, ViewPoolObserver},
 };
 use crate::{
 	fork_aware_txpool::dropped_watcher::MultiViewDroppedWatcherController,
@@ -62,8 +62,13 @@ where
 
 /// Helper type representing the callback allowing to trigger per-transaction events on
 /// `ValidatedPool`'s listener.
-type RemovalListener<ChainApi> =
-	Arc<dyn Fn(&mut crate::graph::Listener<ChainApi>, ExtrinsicHash<ChainApi>) + Send + Sync>;
+type RemovalCallback<ChainApi> = Arc<
+	dyn Fn(
+			&mut crate::graph::EventDispatcher<ChainApi, ViewPoolObserver<ChainApi>>,
+			ExtrinsicHash<ChainApi>,
+		) + Send
+		+ Sync,
+>;
 
 /// Helper struct to maintain the context for pending transaction removal, executed for
 /// newly inserted views.
@@ -74,7 +79,7 @@ where
 	/// Hash of the transaction that will be removed,
 	xt_hash: ExtrinsicHash<ChainApi>,
 	/// Action that shall be executed on underlying `ValidatedPool`'s listener.
-	listener_action: RemovalListener<ChainApi>,
+	listener_action: RemovalCallback<ChainApi>,
 }
 
 /// This enum represents an action that should be executed on the newly built
@@ -119,7 +124,7 @@ where
 	/// Creates new unprocessed instance of pending transaction removal.
 	fn new_removal_action(
 		xt_hash: ExtrinsicHash<ChainApi>,
-		listener: RemovalListener<ChainApi>,
+		listener: RemovalCallback<ChainApi>,
 	) -> Self {
 		Self {
 			processed: false,
@@ -876,8 +881,10 @@ where
 		listener_action: F,
 	) -> Vec<TransactionFor<ChainApi>>
 	where
-		F: Fn(&mut crate::graph::Listener<ChainApi>, ExtrinsicHash<ChainApi>)
-			+ Clone
+		F: Fn(
+				&mut crate::graph::EventDispatcher<ChainApi, ViewPoolObserver<ChainApi>>,
+				ExtrinsicHash<ChainApi>,
+			) + Clone
 			+ Send
 			+ Sync
 			+ 'static,
diff --git a/substrate/client/transaction-pool/src/graph/listener.rs b/substrate/client/transaction-pool/src/graph/listener.rs
index 340b6d429ae7e969f81b59ea2bf5ed58ac313758..a40a708edaf05539c871a866e508c62484a94ff8 100644
--- a/substrate/client/transaction-pool/src/graph/listener.rs
+++ b/substrate/client/transaction-pool/src/graph/listener.rs
@@ -20,59 +20,91 @@ use std::{collections::HashMap, fmt::Debug, hash};
 
 use linked_hash_map::LinkedHashMap;
 use log::trace;
-use sc_transaction_pool_api::TransactionStatus;
-use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
-use serde::Serialize;
-use sp_runtime::traits;
 
 use super::{watcher, BlockHash, ChainApi, ExtrinsicHash};
 
 static LOG_TARGET: &str = "txpool::watcher";
 
-/// Single event used in aggregated stream. Tuple containing hash of transactions and its status.
-pub type TransactionStatusEvent<H, BH> = (H, TransactionStatus<H, BH>);
-/// Stream of events providing statuses of all the transactions within the pool.
-pub type AggregatedStream<H, BH> = TracingUnboundedReceiver<TransactionStatusEvent<H, BH>>;
+/// The `EventHandler` trait provides a mechanism for clients to respond to various
+/// transaction-related events. It offers a set of callback methods that are invoked by the
+/// transaction pool's event dispatcher to notify about changes in the status of transactions.
+///
+/// This trait can be implemented by any component that needs to respond to transaction lifecycle
+/// events, enabling custom logic and handling of these events.
+pub trait EventHandler<C: ChainApi> {
+	/// Called when a transaction is broadcasted.
+	fn broadcasted(&self, _hash: ExtrinsicHash<C>, _peers: Vec<String>) {}
 
-/// Warning threshold for (unbounded) channel used in aggregated stream.
-const AGGREGATED_STREAM_WARN_THRESHOLD: usize = 100_000;
+	/// Called when a transaction is ready for execution.
+	fn ready(&self, _tx: ExtrinsicHash<C>) {}
 
-/// Extrinsic pool default listener.
-pub struct Listener<H: hash::Hash + Eq, C: ChainApi> {
+	/// Called when a transaction is deemed to be executable in the future.
+	fn future(&self, _tx: ExtrinsicHash<C>) {}
+
+	/// Called when transaction pool limits result in a transaction being affected.
+	fn limits_enforced(&self, _tx: ExtrinsicHash<C>) {}
+
+	/// Called when a transaction is replaced by another.
+	fn usurped(&self, _tx: ExtrinsicHash<C>, _by: ExtrinsicHash<C>) {}
+
+	/// Called when a transaction is dropped from the pool.
+	fn dropped(&self, _tx: ExtrinsicHash<C>) {}
+
+	/// Called when a transaction is found to be invalid.
+	fn invalid(&self, _tx: ExtrinsicHash<C>) {}
+
+	/// Called when a transaction was pruned from the pool due to its presence in imported block.
+	fn pruned(&self, _tx: ExtrinsicHash<C>, _block_hash: BlockHash<C>, _tx_index: usize) {}
+
+	/// Called when a transaction is retracted from inclusion in a block.
+	fn retracted(&self, _tx: ExtrinsicHash<C>, _block_hash: BlockHash<C>) {}
+
+	/// Called when a transaction has not been finalized within a timeout period.
+	fn finality_timeout(&self, _tx: ExtrinsicHash<C>, _hash: BlockHash<C>) {}
+
+	/// Called when a transaction is finalized in a block.
+	fn finalized(&self, _tx: ExtrinsicHash<C>, _block_hash: BlockHash<C>, _tx_index: usize) {}
+}
+
+impl<C: ChainApi> EventHandler<C> for () {}
+
+/// The `EventDispatcher` struct is responsible for dispatching transaction-related events from the
+/// validated pool to interested observers and an optional event handler. It acts as the primary
+/// liaison between the transaction pool and clients that are monitoring transaction statuses.
+pub struct EventDispatcher<H: hash::Hash + Eq, C: ChainApi, L: EventHandler<C>> {
 	/// Map containing per-transaction sinks for emitting transaction status events.
 	watchers: HashMap<H, watcher::Sender<H, BlockHash<C>>>,
 	finality_watchers: LinkedHashMap<ExtrinsicHash<C>, Vec<H>>,
 
-	/// The sink used to notify dropped by enforcing limits or by being usurped, or invalid
-	/// transactions.
-	///
-	/// Note: Ready and future statuses are alse communicated through this channel, enabling the
-	/// stream consumer to track views that reference the transaction.
-	dropped_stream_sink: Option<TracingUnboundedSender<TransactionStatusEvent<H, BlockHash<C>>>>,
-
-	/// The sink of the single, merged stream providing updates for all the transactions in the
-	/// associated pool.
-	aggregated_stream_sink: Option<TracingUnboundedSender<TransactionStatusEvent<H, BlockHash<C>>>>,
+	/// Optional event handler (listener) that will be notified about all transactions status
+	/// changes from the pool.
+	event_handler: Option<L>,
 }
 
 /// Maximum number of blocks awaiting finality at any time.
 const MAX_FINALITY_WATCHERS: usize = 512;
 
-impl<H: hash::Hash + Eq + Debug, C: ChainApi> Default for Listener<H, C> {
+impl<H: hash::Hash + Eq + Debug, C: ChainApi, L: EventHandler<C>> Default
+	for EventDispatcher<H, C, L>
+{
 	fn default() -> Self {
 		Self {
 			watchers: Default::default(),
 			finality_watchers: Default::default(),
-			dropped_stream_sink: None,
-			aggregated_stream_sink: None,
+			event_handler: None,
 		}
 	}
 }
 
-impl<H: hash::Hash + traits::Member + Serialize + Clone, C: ChainApi> Listener<H, C> {
-	fn fire<F>(&mut self, hash: &H, fun: F)
+impl<C: ChainApi, L: EventHandler<C>> EventDispatcher<ExtrinsicHash<C>, C, L> {
+	/// Creates a new instance with provided event handler.
+	pub fn new_with_event_handler(event_handler: Option<L>) -> Self {
+		Self { event_handler, ..Default::default() }
+	}
+
+	fn fire<F>(&mut self, hash: &ExtrinsicHash<C>, fun: F)
 	where
-		F: FnOnce(&mut watcher::Sender<H, ExtrinsicHash<C>>),
+		F: FnOnce(&mut watcher::Sender<ExtrinsicHash<C>, ExtrinsicHash<C>>),
 	{
 		let clean = if let Some(h) = self.watchers.get_mut(hash) {
 			fun(h);
@@ -89,138 +121,88 @@ impl<H: hash::Hash + traits::Member + Serialize + Clone, C: ChainApi> Listener<H
 	/// Creates a new watcher for given verified extrinsic.
 	///
 	/// The watcher can be used to subscribe to life-cycle events of that extrinsic.
-	pub fn create_watcher(&mut self, hash: H) -> watcher::Watcher<H, ExtrinsicHash<C>> {
-		let sender = self.watchers.entry(hash.clone()).or_insert_with(watcher::Sender::default);
+	pub fn create_watcher(
+		&mut self,
+		hash: ExtrinsicHash<C>,
+	) -> watcher::Watcher<ExtrinsicHash<C>, ExtrinsicHash<C>> {
+		let sender = self.watchers.entry(hash).or_insert_with(watcher::Sender::default);
 		sender.new_watcher(hash)
 	}
 
-	/// Creates a new single stream intended to watch dropped transactions only.
-	///
-	/// The stream can be used to subscribe to events related to dropping of all extrinsics in the
-	/// pool.
-	pub fn create_dropped_by_limits_stream(&mut self) -> AggregatedStream<H, BlockHash<C>> {
-		let (sender, single_stream) =
-			tracing_unbounded("mpsc_txpool_watcher", AGGREGATED_STREAM_WARN_THRESHOLD);
-		self.dropped_stream_sink = Some(sender);
-		single_stream
-	}
-
-	/// Creates a new single merged stream for all extrinsics in the associated pool.
-	///
-	/// The stream can be used to subscribe to life-cycle events of all extrinsics in the pool. For
-	/// some implementations (e.g. fork-aware pool) this approach may be more efficient than using
-	/// individual streams for every transaction.
-	///
-	/// Note: some of the events which are currently ignored on the other side of this channel
-	/// (external watcher) are not sent.
-	pub fn create_aggregated_stream(&mut self) -> AggregatedStream<H, BlockHash<C>> {
-		let (sender, aggregated_stream) =
-			tracing_unbounded("mpsc_txpool_aggregated_stream", AGGREGATED_STREAM_WARN_THRESHOLD);
-		self.aggregated_stream_sink = Some(sender);
-		aggregated_stream
-	}
-
 	/// Notify the listeners about the extrinsic broadcast.
-	pub fn broadcasted(&mut self, hash: &H, peers: Vec<String>) {
+	pub fn broadcasted(&mut self, hash: &ExtrinsicHash<C>, peers: Vec<String>) {
 		trace!(target: LOG_TARGET, "[{:?}] Broadcasted", hash);
-		self.fire(hash, |watcher| watcher.broadcast(peers));
-	}
-
-	/// Sends given event to the `dropped_stream_sink`.
-	fn send_to_dropped_stream_sink(&mut self, tx: &H, status: TransactionStatus<H, BlockHash<C>>) {
-		if let Some(ref sink) = self.dropped_stream_sink {
-			if let Err(e) = sink.unbounded_send((tx.clone(), status.clone())) {
-				trace!(target: LOG_TARGET, "[{:?}] dropped_sink: {:?} send message failed: {:?}", tx, status, e);
-			}
-		}
-	}
-
-	/// Sends given event to the `aggregated_stream_sink`.
-	fn send_to_aggregated_stream_sink(
-		&mut self,
-		tx: &H,
-		status: TransactionStatus<H, BlockHash<C>>,
-	) {
-		if let Some(ref sink) = self.aggregated_stream_sink {
-			if let Err(e) = sink.unbounded_send((tx.clone(), status.clone())) {
-				trace!(target: LOG_TARGET, "[{:?}] aggregated_stream {:?} send message failed: {:?}", tx, status, e);
-			}
-		}
+		self.fire(hash, |watcher| watcher.broadcast(peers.clone()));
+		self.event_handler.as_ref().map(|l| l.broadcasted(*hash, peers));
 	}
 
 	/// New transaction was added to the ready pool or promoted from the future pool.
-	pub fn ready(&mut self, tx: &H, old: Option<&H>) {
-		trace!(target: LOG_TARGET, "[{:?}] Ready (replaced with {:?})", tx, old);
+	pub fn ready(&mut self, tx: &ExtrinsicHash<C>, old: Option<&ExtrinsicHash<C>>) {
+		trace!(target: LOG_TARGET, "[{:?}] Ready (replaced with {:?})", *tx, old);
 		self.fire(tx, |watcher| watcher.ready());
 		if let Some(old) = old {
-			self.fire(old, |watcher| watcher.usurped(tx.clone()));
+			self.fire(old, |watcher| watcher.usurped(*tx));
 		}
 
-		self.send_to_dropped_stream_sink(tx, TransactionStatus::Ready);
-		self.send_to_aggregated_stream_sink(tx, TransactionStatus::Ready);
+		self.event_handler.as_ref().map(|l| l.ready(*tx));
 	}
 
 	/// New transaction was added to the future pool.
-	pub fn future(&mut self, tx: &H) {
+	pub fn future(&mut self, tx: &ExtrinsicHash<C>) {
 		trace!(target: LOG_TARGET, "[{:?}] Future", tx);
 		self.fire(tx, |watcher| watcher.future());
 
-		self.send_to_dropped_stream_sink(tx, TransactionStatus::Future);
-		self.send_to_aggregated_stream_sink(tx, TransactionStatus::Future);
+		self.event_handler.as_ref().map(|l| l.future(*tx));
 	}
 
 	/// Transaction was dropped from the pool because of enforcing the limit.
-	pub fn limits_enforced(&mut self, tx: &H) {
+	pub fn limits_enforced(&mut self, tx: &ExtrinsicHash<C>) {
 		trace!(target: LOG_TARGET, "[{:?}] Dropped (limits enforced)", tx);
 		self.fire(tx, |watcher| watcher.limit_enforced());
 
-		self.send_to_dropped_stream_sink(tx, TransactionStatus::Dropped);
+		self.event_handler.as_ref().map(|l| l.limits_enforced(*tx));
 	}
 
 	/// Transaction was replaced with other extrinsic.
-	pub fn usurped(&mut self, tx: &H, by: &H) {
+	pub fn usurped(&mut self, tx: &ExtrinsicHash<C>, by: &ExtrinsicHash<C>) {
 		trace!(target: LOG_TARGET, "[{:?}] Dropped (replaced with {:?})", tx, by);
-		self.fire(tx, |watcher| watcher.usurped(by.clone()));
+		self.fire(tx, |watcher| watcher.usurped(*by));
 
-		self.send_to_dropped_stream_sink(tx, TransactionStatus::Usurped(by.clone()));
+		self.event_handler.as_ref().map(|l| l.usurped(*tx, *by));
 	}
 
 	/// Transaction was dropped from the pool because of the failure during the resubmission of
 	/// revalidate transactions or failure during pruning tags.
-	pub fn dropped(&mut self, tx: &H) {
+	pub fn dropped(&mut self, tx: &ExtrinsicHash<C>) {
 		trace!(target: LOG_TARGET, "[{:?}] Dropped", tx);
 		self.fire(tx, |watcher| watcher.dropped());
+		self.event_handler.as_ref().map(|l| l.dropped(*tx));
 	}
 
 	/// Transaction was removed as invalid.
-	pub fn invalid(&mut self, tx: &H) {
+	pub fn invalid(&mut self, tx: &ExtrinsicHash<C>) {
 		trace!(target: LOG_TARGET, "[{:?}] Extrinsic invalid", tx);
 		self.fire(tx, |watcher| watcher.invalid());
-
-		self.send_to_dropped_stream_sink(tx, TransactionStatus::Invalid);
+		self.event_handler.as_ref().map(|l| l.invalid(*tx));
 	}
 
 	/// Transaction was pruned from the pool.
-	pub fn pruned(&mut self, block_hash: BlockHash<C>, tx: &H) {
+	pub fn pruned(&mut self, block_hash: BlockHash<C>, tx: &ExtrinsicHash<C>) {
 		trace!(target: LOG_TARGET, "[{:?}] Pruned at {:?}", tx, block_hash);
 		// Get the transactions included in the given block hash.
 		let txs = self.finality_watchers.entry(block_hash).or_insert(vec![]);
-		txs.push(tx.clone());
+		txs.push(*tx);
 		// Current transaction is the last one included.
 		let tx_index = txs.len() - 1;
 
 		self.fire(tx, |watcher| watcher.in_block(block_hash, tx_index));
-		self.send_to_aggregated_stream_sink(tx, TransactionStatus::InBlock((block_hash, tx_index)));
+		self.event_handler.as_ref().map(|l| l.pruned(*tx, block_hash, tx_index));
 
 		while self.finality_watchers.len() > MAX_FINALITY_WATCHERS {
 			if let Some((hash, txs)) = self.finality_watchers.pop_front() {
 				for tx in txs {
 					self.fire(&tx, |watcher| watcher.finality_timeout(hash));
-					//todo: do we need this? [related issue: #5482]
-					self.send_to_aggregated_stream_sink(
-						&tx,
-						TransactionStatus::FinalityTimeout(hash),
-					);
+					self.event_handler.as_ref().map(|l| l.finality_timeout(tx, block_hash));
 				}
 			}
 		}
@@ -231,7 +213,7 @@ impl<H: hash::Hash + traits::Member + Serialize + Clone, C: ChainApi> Listener<H
 		if let Some(hashes) = self.finality_watchers.remove(&block_hash) {
 			for hash in hashes {
 				self.fire(&hash, |watcher| watcher.retracted(block_hash));
-				// note: [#5479], we do not send to aggregated stream.
+				self.event_handler.as_ref().map(|l| l.retracted(hash, block_hash));
 			}
 		}
 	}
@@ -246,13 +228,14 @@ impl<H: hash::Hash + traits::Member + Serialize + Clone, C: ChainApi> Listener<H
 					hash,
 					block_hash,
 				);
-				self.fire(&hash, |watcher| watcher.finalized(block_hash, tx_index))
+				self.fire(&hash, |watcher| watcher.finalized(block_hash, tx_index));
+				self.event_handler.as_ref().map(|l| l.finalized(hash, block_hash, tx_index));
 			}
 		}
 	}
 
 	/// Provides hashes of all watched transactions.
-	pub fn watched_transactions(&self) -> impl Iterator<Item = &H> {
+	pub fn watched_transactions(&self) -> impl Iterator<Item = &ExtrinsicHash<C>> {
 		self.watchers.keys()
 	}
 }
diff --git a/substrate/client/transaction-pool/src/graph/mod.rs b/substrate/client/transaction-pool/src/graph/mod.rs
index c3161799785a97f668c93c8773257e57d3dfe91d..3e6a63babc99c86b0effd0c59bdb51d3e6da80e4 100644
--- a/substrate/client/transaction-pool/src/graph/mod.rs
+++ b/substrate/client/transaction-pool/src/graph/mod.rs
@@ -42,13 +42,12 @@ pub use self::pool::{
 	TransactionFor, ValidatedTransactionFor,
 };
 pub use validated_pool::{
-	BaseSubmitOutcome, IsValidator, Listener, ValidatedPoolSubmitOutcome, ValidatedTransaction,
+	BaseSubmitOutcome, EventDispatcher, IsValidator, ValidatedPoolSubmitOutcome,
+	ValidatedTransaction,
 };
 
 pub(crate) use self::pool::CheckBannedBeforeVerify;
-pub(crate) use listener::TransactionStatusEvent;
+pub(crate) use listener::EventHandler;
 
-#[cfg(doc)]
-pub(crate) use listener::AggregatedStream;
 #[cfg(doc)]
 pub(crate) use validated_pool::ValidatedPool;
diff --git a/substrate/client/transaction-pool/src/graph/pool.rs b/substrate/client/transaction-pool/src/graph/pool.rs
index d938e9bf06e7d84b75bb9173c9304a2e47ded5ce..afd46617b366cce0d38833eb0b18bcbc8cd56b60 100644
--- a/substrate/client/transaction-pool/src/graph/pool.rs
+++ b/substrate/client/transaction-pool/src/graph/pool.rs
@@ -36,7 +36,7 @@ use std::{
 use super::{
 	base_pool as base,
 	validated_pool::{IsValidator, ValidatedPool, ValidatedTransaction},
-	ValidatedPoolSubmitOutcome,
+	EventHandler, ValidatedPoolSubmitOutcome,
 };
 
 /// Modification notification event stream type;
@@ -173,11 +173,11 @@ pub(crate) enum CheckBannedBeforeVerify {
 }
 
 /// Extrinsics pool that performs validation.
-pub struct Pool<B: ChainApi> {
-	validated_pool: Arc<ValidatedPool<B>>,
+pub struct Pool<B: ChainApi, L: EventHandler<B>> {
+	validated_pool: Arc<ValidatedPool<B, L>>,
 }
 
-impl<B: ChainApi> Pool<B> {
+impl<B: ChainApi, L: EventHandler<B>> Pool<B, L> {
 	/// Create a new transaction pool with statically sized rotator.
 	pub fn new_with_staticly_sized_rotator(
 		options: Options,
@@ -198,6 +198,23 @@ impl<B: ChainApi> Pool<B> {
 		Self { validated_pool: Arc::new(ValidatedPool::new(options, is_validator, api)) }
 	}
 
+	/// Create a new transaction pool.
+	pub fn new_with_event_handler(
+		options: Options,
+		is_validator: IsValidator,
+		api: Arc<B>,
+		event_handler: L,
+	) -> Self {
+		Self {
+			validated_pool: Arc::new(ValidatedPool::new_with_event_handler(
+				options,
+				is_validator,
+				api,
+				event_handler,
+			)),
+		}
+	}
+
 	/// Imports a bunch of unverified extrinsics to the pool
 	pub async fn submit_at(
 		&self,
@@ -481,7 +498,7 @@ impl<B: ChainApi> Pool<B> {
 	}
 
 	/// Get a reference to the underlying validated pool.
-	pub fn validated_pool(&self) -> &ValidatedPool<B> {
+	pub fn validated_pool(&self) -> &ValidatedPool<B, L> {
 		&self.validated_pool
 	}
 
@@ -491,12 +508,13 @@ impl<B: ChainApi> Pool<B> {
 	}
 }
 
-impl<B: ChainApi> Pool<B> {
+impl<B: ChainApi, L: EventHandler<B>> Pool<B, L> {
 	/// Deep clones the pool.
 	///
 	/// Must be called on purpose: it duplicates all the internal structures.
-	pub fn deep_clone(&self) -> Self {
-		let other: ValidatedPool<B> = (*self.validated_pool).clone();
+	pub fn deep_clone_with_event_handler(&self, event_handler: L) -> Self {
+		let other: ValidatedPool<B, L> =
+			self.validated_pool().deep_clone_with_event_handler(event_handler);
 		Self { validated_pool: Arc::from(other) }
 	}
 }
@@ -519,6 +537,8 @@ mod tests {
 	const SOURCE: TimedTransactionSource =
 		TimedTransactionSource { source: TransactionSource::External, timestamp: None };
 
+	type Pool<Api> = super::Pool<Api, ()>;
+
 	#[test]
 	fn should_validate_and_import_transaction() {
 		// given
diff --git a/substrate/client/transaction-pool/src/graph/validated_pool.rs b/substrate/client/transaction-pool/src/graph/validated_pool.rs
index 174b69da7611b46a4981ea568dcbefecfed34b87..8eb967421bd70e00529758a6de936e360fb7bafc 100644
--- a/substrate/client/transaction-pool/src/graph/validated_pool.rs
+++ b/substrate/client/transaction-pool/src/graph/validated_pool.rs
@@ -35,6 +35,7 @@ use std::time::Instant;
 
 use super::{
 	base_pool::{self as base, PruneStatus},
+	listener::EventHandler,
 	pool::{
 		BlockHash, ChainApi, EventStream, ExtrinsicFor, ExtrinsicHash, Options, TransactionFor,
 	},
@@ -91,8 +92,8 @@ impl<Hash, Ex, Error> ValidatedTransaction<Hash, Ex, Error> {
 pub type ValidatedTransactionFor<B> =
 	ValidatedTransaction<ExtrinsicHash<B>, ExtrinsicFor<B>, <B as ChainApi>::Error>;
 
-/// A type alias representing ValidatedPool listener for given ChainApi type.
-pub type Listener<B> = super::listener::Listener<ExtrinsicHash<B>, B>;
+/// A type alias representing ValidatedPool event dispatcher for given ChainApi type.
+pub type EventDispatcher<B, L> = super::listener::EventDispatcher<ExtrinsicHash<B>, B, L>;
 
 /// A closure that returns true if the local node is a validator that can author blocks.
 #[derive(Clone)]
@@ -155,23 +156,23 @@ impl<B: ChainApi, W> BaseSubmitOutcome<B, W> {
 }
 
 /// Pool that deals with validated transactions.
-pub struct ValidatedPool<B: ChainApi> {
+pub struct ValidatedPool<B: ChainApi, L: EventHandler<B>> {
 	api: Arc<B>,
 	is_validator: IsValidator,
 	options: Options,
-	listener: RwLock<Listener<B>>,
+	event_dispatcher: RwLock<EventDispatcher<B, L>>,
 	pub(crate) pool: RwLock<base::BasePool<ExtrinsicHash<B>, ExtrinsicFor<B>>>,
 	import_notification_sinks: Mutex<Vec<Sender<ExtrinsicHash<B>>>>,
 	rotator: PoolRotator<ExtrinsicHash<B>>,
 }
 
-impl<B: ChainApi> Clone for ValidatedPool<B> {
+impl<B: ChainApi, L: EventHandler<B>> Clone for ValidatedPool<B, L> {
 	fn clone(&self) -> Self {
 		Self {
 			api: self.api.clone(),
 			is_validator: self.is_validator.clone(),
 			options: self.options.clone(),
-			listener: Default::default(),
+			event_dispatcher: Default::default(),
 			pool: RwLock::from(self.pool.read().clone()),
 			import_notification_sinks: Default::default(),
 			rotator: self.rotator.clone(),
@@ -179,7 +180,16 @@ impl<B: ChainApi> Clone for ValidatedPool<B> {
 	}
 }
 
-impl<B: ChainApi> ValidatedPool<B> {
+impl<B: ChainApi, L: EventHandler<B>> ValidatedPool<B, L> {
+	pub fn deep_clone_with_event_handler(&self, event_handler: L) -> Self {
+		Self {
+			event_dispatcher: RwLock::new(EventDispatcher::new_with_event_handler(Some(
+				event_handler,
+			))),
+			..self.clone()
+		}
+	}
+
 	/// Create a new transaction pool with statically sized rotator.
 	pub fn new_with_staticly_sized_rotator(
 		options: Options,
@@ -187,7 +197,7 @@ impl<B: ChainApi> ValidatedPool<B> {
 		api: Arc<B>,
 	) -> Self {
 		let ban_time = options.ban_time;
-		Self::new_with_rotator(options, is_validator, api, PoolRotator::new(ban_time))
+		Self::new_with_rotator(options, is_validator, api, PoolRotator::new(ban_time), None)
 	}
 
 	/// Create a new transaction pool.
@@ -199,6 +209,25 @@ impl<B: ChainApi> ValidatedPool<B> {
 			is_validator,
 			api,
 			PoolRotator::new_with_expected_size(ban_time, total_count),
+			None,
+		)
+	}
+
+	/// Create a new transaction pool with given event handler.
+	pub fn new_with_event_handler(
+		options: Options,
+		is_validator: IsValidator,
+		api: Arc<B>,
+		event_handler: L,
+	) -> Self {
+		let ban_time = options.ban_time;
+		let total_count = options.total_count();
+		Self::new_with_rotator(
+			options,
+			is_validator,
+			api,
+			PoolRotator::new_with_expected_size(ban_time, total_count),
+			Some(event_handler),
 		)
 	}
 
@@ -207,12 +236,13 @@ impl<B: ChainApi> ValidatedPool<B> {
 		is_validator: IsValidator,
 		api: Arc<B>,
 		rotator: PoolRotator<ExtrinsicHash<B>>,
+		event_handler: Option<L>,
 	) -> Self {
 		let base_pool = base::BasePool::new(options.reject_future_transactions);
 		Self {
 			is_validator,
 			options,
-			listener: Default::default(),
+			event_dispatcher: RwLock::new(EventDispatcher::new_with_event_handler(event_handler)),
 			api,
 			pool: RwLock::new(base_pool),
 			import_notification_sinks: Default::default(),
@@ -309,8 +339,8 @@ impl<B: ChainApi> ValidatedPool<B> {
 					});
 				}
 
-				let mut listener = self.listener.write();
-				fire_events(&mut *listener, &imported);
+				let mut event_dispatcher = self.event_dispatcher.write();
+				fire_events(&mut *event_dispatcher, &imported);
 				Ok(ValidatedPoolSubmitOutcome::new(*imported.hash(), Some(priority)))
 			},
 			ValidatedTransaction::Invalid(hash, err) => {
@@ -320,7 +350,7 @@ impl<B: ChainApi> ValidatedPool<B> {
 			},
 			ValidatedTransaction::Unknown(hash, err) => {
 				log::trace!(target: LOG_TARGET, "[{:?}] ValidatedPool::submit_one unknown {:?}", hash, err);
-				self.listener.write().invalid(&hash);
+				self.event_dispatcher.write().invalid(&hash);
 				Err(err)
 			},
 		}
@@ -360,9 +390,9 @@ impl<B: ChainApi> ValidatedPool<B> {
 			}
 
 			// run notifications
-			let mut listener = self.listener.write();
+			let mut event_dispatcher = self.event_dispatcher.write();
 			for h in &removed {
-				listener.limits_enforced(h);
+				event_dispatcher.limits_enforced(h);
 			}
 
 			removed
@@ -398,12 +428,12 @@ impl<B: ChainApi> ValidatedPool<B> {
 		&self,
 		tx_hash: ExtrinsicHash<B>,
 	) -> Watcher<ExtrinsicHash<B>, ExtrinsicHash<B>> {
-		self.listener.write().create_watcher(tx_hash)
+		self.event_dispatcher.write().create_watcher(tx_hash)
 	}
 
 	/// Provides a list of hashes for all watched transactions in the pool.
 	pub fn watched_transactions(&self) -> Vec<ExtrinsicHash<B>> {
-		self.listener.read().watched_transactions().map(Clone::clone).collect()
+		self.event_dispatcher.read().watched_transactions().map(Clone::clone).collect()
 	}
 
 	/// Resubmits revalidated transactions back to the pool.
@@ -528,15 +558,15 @@ impl<B: ChainApi> ValidatedPool<B> {
 		};
 
 		// and now let's notify listeners about status changes
-		let mut listener = self.listener.write();
+		let mut event_dispatcher = self.event_dispatcher.write();
 		for (hash, final_status) in final_statuses {
 			let initial_status = initial_statuses.remove(&hash);
 			if initial_status.is_none() || Some(final_status) != initial_status {
 				match final_status {
-					Status::Future => listener.future(&hash),
-					Status::Ready => listener.ready(&hash, None),
-					Status::Dropped => listener.dropped(&hash),
-					Status::Failed => listener.invalid(&hash),
+					Status::Future => event_dispatcher.future(&hash),
+					Status::Ready => event_dispatcher.ready(&hash, None),
+					Status::Dropped => event_dispatcher.dropped(&hash),
+					Status::Failed => event_dispatcher.invalid(&hash),
 				}
 			}
 		}
@@ -569,12 +599,12 @@ impl<B: ChainApi> ValidatedPool<B> {
 		// Notify event listeners of all transactions
 		// that were promoted to `Ready` or were dropped.
 		{
-			let mut listener = self.listener.write();
+			let mut event_dispatcher = self.event_dispatcher.write();
 			for promoted in &status.promoted {
-				fire_events(&mut *listener, promoted);
+				fire_events(&mut *event_dispatcher, promoted);
 			}
 			for f in &status.failed {
-				listener.dropped(f);
+				event_dispatcher.dropped(f);
 			}
 		}
 
@@ -618,13 +648,13 @@ impl<B: ChainApi> ValidatedPool<B> {
 		at: &HashAndNumber<B::Block>,
 		hashes: impl Iterator<Item = ExtrinsicHash<B>>,
 	) {
-		let mut listener = self.listener.write();
+		let mut event_dispatcher = self.event_dispatcher.write();
 		let mut set = HashSet::with_capacity(hashes.size_hint().0);
 		for h in hashes {
 			// `hashes` has possibly duplicate hashes.
 			// we'd like to send out the `InBlock` notification only once.
 			if !set.contains(&h) {
-				listener.pruned(at.hash, &h);
+				event_dispatcher.pruned(at.hash, &h);
 				set.insert(h);
 			}
 		}
@@ -681,9 +711,9 @@ impl<B: ChainApi> ValidatedPool<B> {
 
 	/// Invoked when extrinsics are broadcasted.
 	pub fn on_broadcasted(&self, propagated: HashMap<ExtrinsicHash<B>, Vec<String>>) {
-		let mut listener = self.listener.write();
+		let mut event_dispatcher = self.event_dispatcher.write();
 		for (hash, peers) in propagated.into_iter() {
-			listener.broadcasted(&hash, peers);
+			event_dispatcher.broadcasted(&hash, peers);
 		}
 	}
 
@@ -736,27 +766,13 @@ impl<B: ChainApi> ValidatedPool<B> {
 			"Attempting to notify watchers of finalization for {}",
 			block_hash,
 		);
-		self.listener.write().finalized(block_hash);
+		self.event_dispatcher.write().finalized(block_hash);
 		Ok(())
 	}
 
-	/// Notify the listener of retracted blocks
+	/// Notify the event_dispatcher of retracted blocks
 	pub fn on_block_retracted(&self, block_hash: BlockHash<B>) {
-		self.listener.write().retracted(block_hash)
-	}
-
-	/// Refer to [`Listener::create_dropped_by_limits_stream`] for details.
-	pub fn create_dropped_by_limits_stream(
-		&self,
-	) -> super::listener::AggregatedStream<ExtrinsicHash<B>, BlockHash<B>> {
-		self.listener.write().create_dropped_by_limits_stream()
-	}
-
-	/// Refer to [`Listener::create_aggregated_stream`]
-	pub fn create_aggregated_stream(
-		&self,
-	) -> super::listener::AggregatedStream<ExtrinsicHash<B>, BlockHash<B>> {
-		self.listener.write().create_aggregated_stream()
+		self.event_dispatcher.write().retracted(block_hash)
 	}
 
 	/// Resends ready and future events for all the ready and future transactions that are already
@@ -765,12 +781,12 @@ impl<B: ChainApi> ValidatedPool<B> {
 	/// Intended to be called after cloning the instance of `ValidatedPool`.
 	pub fn retrigger_notifications(&self) {
 		let pool = self.pool.read();
-		let mut listener = self.listener.write();
+		let mut event_dispatcher = self.event_dispatcher.write();
 		pool.ready().for_each(|r| {
-			listener.ready(&r.hash, None);
+			event_dispatcher.ready(&r.hash, None);
 		});
 		pool.futures().for_each(|f| {
-			listener.future(&f.hash);
+			event_dispatcher.future(&f.hash);
 		});
 	}
 
@@ -782,21 +798,21 @@ impl<B: ChainApi> ValidatedPool<B> {
 	/// The root transaction will be banned from re-entrering the pool. Descendant transactions may
 	/// be re-submitted to the pool if required.
 	///
-	/// A `listener_action` callback function is invoked for every transaction that is removed,
-	/// providing a reference to the pool's listener and the hash of the removed transaction. This
-	/// allows to trigger the required events.
+	/// A `event_disaptcher_action` callback function is invoked for every transaction that is
+	/// removed, providing a reference to the pool's event dispatcher and the hash of the removed
+	/// transaction. This allows to trigger the required events.
 	///
 	/// Returns a vector containing the hashes of all removed transactions, including the root
 	/// transaction specified by `tx_hash`.
 	pub fn remove_subtree<F>(
 		&self,
 		hashes: &[ExtrinsicHash<B>],
-		listener_action: F,
+		event_dispatcher_action: F,
 	) -> Vec<TransactionFor<B>>
 	where
-		F: Fn(&mut Listener<B>, ExtrinsicHash<B>),
+		F: Fn(&mut EventDispatcher<B, L>, ExtrinsicHash<B>),
 	{
-		// temporarily ban invalid transactions
+		// temporarily ban removed transactions
 		self.rotator.ban(&Instant::now(), hashes.iter().cloned());
 		let removed = self.pool.write().remove_subtree(hashes);
 
@@ -804,25 +820,28 @@ impl<B: ChainApi> ValidatedPool<B> {
 			.into_iter()
 			.map(|tx| {
 				let removed_tx_hash = tx.hash;
-				let mut listener = self.listener.write();
-				listener_action(&mut *listener, removed_tx_hash);
+				let mut event_dispatcher = self.event_dispatcher.write();
+				event_dispatcher_action(&mut *event_dispatcher, removed_tx_hash);
 				tx.clone()
 			})
 			.collect::<Vec<_>>()
 	}
 }
 
-fn fire_events<B, Ex>(listener: &mut Listener<B>, imported: &base::Imported<ExtrinsicHash<B>, Ex>)
-where
+fn fire_events<B, L, Ex>(
+	event_dispatcher: &mut EventDispatcher<B, L>,
+	imported: &base::Imported<ExtrinsicHash<B>, Ex>,
+) where
 	B: ChainApi,
+	L: EventHandler<B>,
 {
 	match *imported {
 		base::Imported::Ready { ref promoted, ref failed, ref removed, ref hash } => {
-			listener.ready(hash, None);
-			failed.iter().for_each(|f| listener.invalid(f));
-			removed.iter().for_each(|r| listener.usurped(&r.hash, hash));
-			promoted.iter().for_each(|p| listener.ready(p, None));
+			event_dispatcher.ready(hash, None);
+			failed.iter().for_each(|f| event_dispatcher.invalid(f));
+			removed.iter().for_each(|r| event_dispatcher.usurped(&r.hash, hash));
+			promoted.iter().for_each(|p| event_dispatcher.ready(p, None));
 		},
-		base::Imported::Future { ref hash } => listener.future(hash),
+		base::Imported::Future { ref hash } => event_dispatcher.future(hash),
 	}
 }
diff --git a/substrate/client/transaction-pool/src/single_state_txpool/revalidation.rs b/substrate/client/transaction-pool/src/single_state_txpool/revalidation.rs
index ffcade085916041d4a936a53b0f6ee0298faed75..413d97b11b0e1b65f5176621d8b6bc6069a59f74 100644
--- a/substrate/client/transaction-pool/src/single_state_txpool/revalidation.rs
+++ b/substrate/client/transaction-pool/src/single_state_txpool/revalidation.rs
@@ -18,7 +18,8 @@
 
 //! Pool periodic revalidation.
 
-use crate::graph::{BlockHash, ChainApi, ExtrinsicHash, Pool, ValidatedTransaction};
+use crate::graph::{BlockHash, ChainApi, ExtrinsicHash, ValidatedTransaction};
+use futures::prelude::*;
 use indexmap::IndexMap;
 use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
 use sp_runtime::{
@@ -28,17 +29,17 @@ use std::{
 	collections::{BTreeMap, HashMap, HashSet},
 	pin::Pin,
 	sync::Arc,
+	time::Duration,
 };
 
-use futures::prelude::*;
-use std::time::Duration;
-
 const BACKGROUND_REVALIDATION_INTERVAL: Duration = Duration::from_millis(200);
 
 const MIN_BACKGROUND_REVALIDATION_BATCH_SIZE: usize = 20;
 
 const LOG_TARGET: &str = "txpool::revalidation";
 
+type Pool<Api> = crate::graph::Pool<Api, ()>;
+
 /// Payload from queue to worker.
 struct WorkerPayload<Api: ChainApi> {
 	at: BlockHash<Api>,
diff --git a/substrate/client/transaction-pool/src/single_state_txpool/single_state_txpool.rs b/substrate/client/transaction-pool/src/single_state_txpool/single_state_txpool.rs
index 9f4d63f3ba3a9ab4354b14f25f1eb9d7d901127a..745b57d0c85bf440142b6be9165cd532c79562c4 100644
--- a/substrate/client/transaction-pool/src/single_state_txpool/single_state_txpool.rs
+++ b/substrate/client/transaction-pool/src/single_state_txpool/single_state_txpool.rs
@@ -29,7 +29,7 @@ use crate::{
 		error,
 		log_xt::log_xt_trace,
 	},
-	graph::{self, base_pool::TimedTransactionSource, ExtrinsicHash, IsValidator},
+	graph::{self, base_pool::TimedTransactionSource, EventHandler, ExtrinsicHash, IsValidator},
 	ReadyIteratorFor, LOG_TARGET,
 };
 use async_trait::async_trait;
@@ -64,7 +64,7 @@ where
 	Block: BlockT,
 	PoolApi: graph::ChainApi<Block = Block>,
 {
-	pool: Arc<graph::Pool<PoolApi>>,
+	pool: Arc<graph::Pool<PoolApi, ()>>,
 	api: Arc<PoolApi>,
 	revalidation_strategy: Arc<Mutex<RevalidationStrategy<NumberFor<Block>>>>,
 	revalidation_queue: Arc<revalidation::RevalidationQueue<PoolApi>>,
@@ -225,7 +225,7 @@ where
 	}
 
 	/// Gets shared reference to the underlying pool.
-	pub fn pool(&self) -> &Arc<graph::Pool<PoolApi>> {
+	pub fn pool(&self) -> &Arc<graph::Pool<PoolApi, ()>> {
 		&self.pool
 	}
 
@@ -583,10 +583,14 @@ impl<N: Clone + Copy + AtLeast32Bit> RevalidationStatus<N> {
 }
 
 /// Prune the known txs for the given block.
-pub async fn prune_known_txs_for_block<Block: BlockT, Api: graph::ChainApi<Block = Block>>(
+pub async fn prune_known_txs_for_block<
+	Block: BlockT,
+	Api: graph::ChainApi<Block = Block>,
+	L: EventHandler<Api>,
+>(
 	at: &HashAndNumber<Block>,
 	api: &Api,
-	pool: &graph::Pool<Api>,
+	pool: &graph::Pool<Api, L>,
 ) -> Vec<ExtrinsicHash<Api>> {
 	let extrinsics = api
 		.block_body(at.hash)
diff --git a/substrate/client/transaction-pool/tests/pool.rs b/substrate/client/transaction-pool/tests/pool.rs
index c70f4548331454f166e8112df00e42e1652e1fb6..1403ea06df791691591348a0e16184ac49fddef1 100644
--- a/substrate/client/transaction-pool/tests/pool.rs
+++ b/substrate/client/transaction-pool/tests/pool.rs
@@ -45,6 +45,8 @@ use substrate_test_runtime_client::{
 };
 use substrate_test_runtime_transaction_pool::{uxt, TestApi};
 
+type Pool<Api> = sc_transaction_pool::Pool<Api, ()>;
+
 const LOG_TARGET: &str = "txpool";
 
 fn pool() -> (Pool<TestApi>, Arc<TestApi>) {
diff --git a/substrate/frame/alliance/src/lib.rs b/substrate/frame/alliance/src/lib.rs
index be65f49e6e4ea406cc742f153009fb8d22ca4fd5..234fd59ef89fdc8ec602f69ab483fd30782efc2d 100644
--- a/substrate/frame/alliance/src/lib.rs
+++ b/substrate/frame/alliance/src/lib.rs
@@ -204,7 +204,17 @@ pub enum MemberRole {
 }
 
 /// The type of item that may be deemed unscrupulous.
-#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum UnscrupulousItem<AccountId, Url> {
 	AccountId(AccountId),
 	Website(Url),
diff --git a/substrate/frame/alliance/src/mock.rs b/substrate/frame/alliance/src/mock.rs
index 069c29a88d38c1ad1dad483d78e931df0cce90db..b2b4ba4d5bf91aa87caa32d05f2b288704e67e64 100644
--- a/substrate/frame/alliance/src/mock.rs
+++ b/substrate/frame/alliance/src/mock.rs
@@ -126,7 +126,7 @@ impl pallet_identity::Config for Test {
 	type WeightInfo = ();
 }
 
-#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, TypeInfo)]
+#[derive(Clone, Debug, Encode, Decode, DecodeWithMemTracking, PartialEq, Eq, TypeInfo)]
 pub struct AccountU64(u64);
 impl IdentifyAccount for AccountU64 {
 	type AccountId = u64;
diff --git a/substrate/frame/alliance/src/types.rs b/substrate/frame/alliance/src/types.rs
index 75b949c19b3256d0276679662fb8b1fc8a81acc1..2c7112652d664d5e332fcaaa06a5f25cee4d040a 100644
--- a/substrate/frame/alliance/src/types.rs
+++ b/substrate/frame/alliance/src/types.rs
@@ -16,14 +16,24 @@
 // limitations under the License.
 
 use alloc::vec::Vec;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_support::{traits::ConstU32, BoundedVec};
 use scale_info::TypeInfo;
 use sp_runtime::RuntimeDebug;
 
 /// A Multihash instance that only supports the basic functionality and no hashing.
 #[derive(
-	Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen,
+	Clone,
+	PartialEq,
+	Eq,
+	PartialOrd,
+	Ord,
+	RuntimeDebug,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	MaxEncodedLen,
 )]
 pub struct Multihash {
 	/// The code of the Multihash.
@@ -50,6 +60,7 @@ impl Multihash {
 	RuntimeDebug,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	TypeInfo,
 	MaxEncodedLen,
 )]
@@ -64,7 +75,17 @@ pub enum Version {
 ///
 /// The generic is about the allocated size of the multihash.
 #[derive(
-	Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen,
+	Clone,
+	PartialEq,
+	Eq,
+	PartialOrd,
+	Ord,
+	RuntimeDebug,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	MaxEncodedLen,
 )]
 pub struct Cid {
 	/// The version of CID.
@@ -96,7 +117,17 @@ impl Cid {
 
 /// Witness data for the `disband` call.
 #[derive(
-	Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo, Default,
+	Copy,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	MaxEncodedLen,
+	TypeInfo,
+	Default,
 )]
 pub struct DisbandWitness {
 	/// Total number of fellow members in the current Alliance.
diff --git a/substrate/frame/assets-holder/src/mock.rs b/substrate/frame/assets-holder/src/mock.rs
index 8d9ea1f51a3d9eb3d1bf5b3366a4c0616e6fb244..b3a5f9635d1359f7b7e3c6e65db74e338ce2606b 100644
--- a/substrate/frame/assets-holder/src/mock.rs
+++ b/substrate/frame/assets-holder/src/mock.rs
@@ -74,7 +74,18 @@ impl pallet_assets::Config for Test {
 }
 
 #[derive(
-	Decode, Encode, MaxEncodedLen, PartialEq, Eq, Ord, PartialOrd, TypeInfo, Debug, Clone, Copy,
+	Decode,
+	DecodeWithMemTracking,
+	Encode,
+	MaxEncodedLen,
+	PartialEq,
+	Eq,
+	Ord,
+	PartialOrd,
+	TypeInfo,
+	Debug,
+	Clone,
+	Copy,
 )]
 pub enum DummyHoldReason {
 	Governance,
diff --git a/substrate/frame/atomic-swap/src/lib.rs b/substrate/frame/atomic-swap/src/lib.rs
index 9521f20fe0092c30c946c0b91c32e3c70c83404b..f35f0efa618abbb5db4812e4e2ca501a4c24de7e 100644
--- a/substrate/frame/atomic-swap/src/lib.rs
+++ b/substrate/frame/atomic-swap/src/lib.rs
@@ -45,7 +45,7 @@ mod tests;
 extern crate alloc;
 
 use alloc::vec::Vec;
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use core::{
 	marker::PhantomData,
 	ops::{Deref, DerefMut},
@@ -57,7 +57,17 @@ use frame::{
 use scale_info::TypeInfo;
 
 /// Pending atomic swap operation.
-#[derive(Clone, Eq, PartialEq, RuntimeDebugNoBound, Encode, Decode, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone,
+	Eq,
+	PartialEq,
+	RuntimeDebugNoBound,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 #[scale_info(skip_type_params(T))]
 #[codec(mel_bound())]
 pub struct PendingSwap<T: Config> {
@@ -92,7 +102,17 @@ pub trait SwapAction<AccountId, T: Config> {
 }
 
 /// A swap action that only allows transferring balances.
-#[derive(Clone, RuntimeDebug, Eq, PartialEq, Encode, Decode, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone,
+	RuntimeDebug,
+	Eq,
+	PartialEq,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 #[scale_info(skip_type_params(C))]
 #[codec(mel_bound())]
 pub struct BalanceSwapAction<AccountId, C: ReservableCurrency<AccountId>> {
diff --git a/substrate/frame/babe/src/tests.rs b/substrate/frame/babe/src/tests.rs
index 5210d9289bcdb6f1ba1922ad3f9a0be3f4109893..bfcd3540ae3ef269224499df4e8a1dee6422b665 100644
--- a/substrate/frame/babe/src/tests.rs
+++ b/substrate/frame/babe/src/tests.rs
@@ -35,6 +35,12 @@ const EMPTY_RANDOMNESS: [u8; RANDOMNESS_LENGTH] = [
 	161, 164, 127, 217, 153, 138, 37, 48, 192, 248, 0,
 ];
 
+impl crate::migrations::BabePalletPrefix for Test {
+	fn pallet_prefix() -> &'static str {
+		"Babe"
+	}
+}
+
 #[test]
 fn empty_randomness_is_correct() {
 	let s = compute_randomness([0; RANDOMNESS_LENGTH], 0, std::iter::empty(), None);
@@ -943,12 +949,6 @@ fn valid_equivocation_reports_dont_pay_fees() {
 fn add_epoch_configurations_migration_works() {
 	use frame_support::storage::migration::{get_storage_value, put_storage_value};
 
-	impl crate::migrations::BabePalletPrefix for Test {
-		fn pallet_prefix() -> &'static str {
-			"Babe"
-		}
-	}
-
 	new_test_ext(1).execute_with(|| {
 		let next_config_descriptor =
 			NextConfigDescriptor::V1 { c: (3, 4), allowed_slots: AllowedSlots::PrimarySlots };
diff --git a/substrate/frame/bags-list/src/list/mod.rs b/substrate/frame/bags-list/src/list/mod.rs
index 6bcc8efbd5d4a941ec6b25c36ac73d0d94d2fdd0..1fe4ffffaa65804fe03cdaf3296dbf92ca680fd3 100644
--- a/substrate/frame/bags-list/src/list/mod.rs
+++ b/substrate/frame/bags-list/src/list/mod.rs
@@ -29,7 +29,7 @@ use alloc::{
 	boxed::Box,
 	collections::{btree_map::BTreeMap, btree_set::BTreeSet},
 };
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::{iter, marker::PhantomData};
 use frame_election_provider_support::ScoreProvider;
 use frame_support::{
@@ -51,7 +51,17 @@ use alloc::vec::Vec;
 #[cfg(any(test, feature = "try-runtime", feature = "fuzz"))]
 use sp_runtime::TryRuntimeError;
 
-#[derive(Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo, PalletError)]
+#[derive(
+	Debug,
+	PartialEq,
+	Eq,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	TypeInfo,
+	PalletError,
+)]
 pub enum ListError {
 	/// A duplicate id has been detected.
 	Duplicate,
diff --git a/substrate/frame/balances/src/types.rs b/substrate/frame/balances/src/types.rs
index 917b7507d7c941156a080163bf029f468c75b097..7f39274789118c688526604d7bd58f6af121f8dd 100644
--- a/substrate/frame/balances/src/types.rs
+++ b/substrate/frame/balances/src/types.rs
@@ -18,7 +18,7 @@
 //! Types used in the pallet.
 
 use crate::{Config, CreditOf, Event, Pallet};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::ops::BitOr;
 use frame_support::traits::{Imbalance, LockIdentifier, OnUnbalanced, WithdrawReasons};
 use scale_info::TypeInfo;
@@ -145,7 +145,17 @@ impl<T: Config<I>, I: 'static> Drop for DustCleaner<T, I> {
 }
 
 /// Whether something should be interpreted as an increase or a decrease.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Clone,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	MaxEncodedLen,
+	TypeInfo,
+)]
 pub enum AdjustmentDirection {
 	/// Increase the amount.
 	Increase,
diff --git a/substrate/frame/beefy/src/mock.rs b/substrate/frame/beefy/src/mock.rs
index 655a36ab14612900b68b6d12e94155a388373f8a..275bf18fe873d7278f490b41832bae0664276a0a 100644
--- a/substrate/frame/beefy/src/mock.rs
+++ b/substrate/frame/beefy/src/mock.rs
@@ -15,7 +15,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use frame_election_provider_support::{
 	bounds::{ElectionBounds, ElectionBoundsBuilder},
 	onchain, SequentialPhragmen, Weight,
@@ -95,7 +95,7 @@ pub struct MockAncestryProofContext {
 	pub is_valid: bool,
 }
 
-#[derive(Clone, Debug, Decode, Encode, PartialEq, TypeInfo)]
+#[derive(Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, TypeInfo)]
 pub struct MockAncestryProof {
 	pub is_optimal: bool,
 	pub is_non_canonical: bool,
diff --git a/substrate/frame/benchmarking/src/tests_instance.rs b/substrate/frame/benchmarking/src/tests_instance.rs
index 428f29e2bc161da4b0afbfac93d24fb7713b0381..11062813e33ce9b2e39fc0a56be72f3e09cb78bc 100644
--- a/substrate/frame/benchmarking/src/tests_instance.rs
+++ b/substrate/frame/benchmarking/src/tests_instance.rs
@@ -86,6 +86,11 @@ frame_support::construct_runtime!(
 	}
 );
 
+crate::define_benchmarks!(
+	[pallet_test, TestPallet]
+	[pallet_test, TestPallet2]
+);
+
 #[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
 impl frame_system::Config for Test {
 	type BaseCallFilter = frame_support::traits::Everything;
@@ -187,11 +192,6 @@ mod benchmarks {
 fn ensure_correct_instance_is_selected() {
 	use crate::utils::Benchmarking;
 
-	crate::define_benchmarks!(
-		[pallet_test, TestPallet]
-		[pallet_test, TestPallet2]
-	);
-
 	let whitelist = vec![];
 
 	let mut batches = Vec::<crate::BenchmarkBatch>::new();
diff --git a/substrate/frame/broker/src/benchmarking.rs b/substrate/frame/broker/src/benchmarking.rs
index 49003afcdd8bc357f0e4f1fe469167b91561ad69..58c8689c54966caaf003129d615d7ce55c8c3cb4 100644
--- a/substrate/frame/broker/src/benchmarking.rs
+++ b/substrate/frame/broker/src/benchmarking.rs
@@ -191,6 +191,31 @@ mod benches {
 		Ok(())
 	}
 
+	#[benchmark]
+	fn remove_lease() -> Result<(), BenchmarkError> {
+		let task = 1u32;
+		let until = 10u32;
+
+		// Assume Leases to be almost filled for worst case
+		let mut leases = vec![
+			LeaseRecordItem { task, until };
+			T::MaxLeasedCores::get().saturating_sub(1) as usize
+		];
+		let task = 2u32;
+		leases.push(LeaseRecordItem { task, until });
+		Leases::<T>::put(BoundedVec::try_from(leases).unwrap());
+
+		let origin =
+			T::AdminOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
+
+		#[extrinsic_call]
+		_(origin as T::RuntimeOrigin, task);
+
+		assert_eq!(Leases::<T>::get().len(), T::MaxLeasedCores::get().saturating_sub(1) as usize);
+
+		Ok(())
+	}
+
 	#[benchmark]
 	fn start_sales(n: Linear<0, { MAX_CORE_COUNT.into() }>) -> Result<(), BenchmarkError> {
 		let config = new_config_record::<T>();
@@ -1200,6 +1225,33 @@ mod benches {
 		Ok(())
 	}
 
+	#[benchmark]
+	fn remove_assignment() -> Result<(), BenchmarkError> {
+		setup_and_start_sale::<T>()?;
+
+		advance_to::<T>(2);
+
+		let caller: T::AccountId = whitelisted_caller();
+		T::Currency::set_balance(
+			&caller.clone(),
+			T::Currency::minimum_balance().saturating_add(10_000_000u32.into()),
+		);
+
+		let region = Broker::<T>::do_purchase(caller.clone(), 10_000_000u32.into())
+			.expect("Offer not high enough for configuration.");
+
+		Broker::<T>::do_assign(region, None, 1000, Provisional)
+			.map_err(|_| BenchmarkError::Weightless)?;
+
+		let origin =
+			T::AdminOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
+
+		#[extrinsic_call]
+		_(origin as T::RuntimeOrigin, region);
+
+		Ok(())
+	}
+
 	// Implements a test for each benchmark. Execute with:
 	// `cargo test -p pallet-broker --features runtime-benchmarks`.
 	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
diff --git a/substrate/frame/broker/src/core_mask.rs b/substrate/frame/broker/src/core_mask.rs
index b8d045077d8285c1b7998e109733d25f4f946d5d..507bc0897bd21f9a955a04605fef2780db86f454 100644
--- a/substrate/frame/broker/src/core_mask.rs
+++ b/substrate/frame/broker/src/core_mask.rs
@@ -15,7 +15,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
 use scale_info::TypeInfo;
 use sp_core::RuntimeDebug;
@@ -25,7 +25,17 @@ pub const CORE_MASK_BITS: usize = 80;
 
 // TODO: Use BitArr instead; for this, we'll need to ensure Codec is impl'ed for `BitArr`.
 #[derive(
-	Encode, Decode, Default, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Default,
+	Copy,
+	Clone,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
 )]
 pub struct CoreMask([u8; 10]);
 impl CoreMask {
diff --git a/substrate/frame/broker/src/coretime_interface.rs b/substrate/frame/broker/src/coretime_interface.rs
index 9c18e2c4ff0b33ce2357f8c1ba6860f2d56efc49..618c3d70fc561650ca4c139ba875bac60e4e2bef 100644
--- a/substrate/frame/broker/src/coretime_interface.rs
+++ b/substrate/frame/broker/src/coretime_interface.rs
@@ -18,7 +18,7 @@
 #![deny(missing_docs)]
 
 use alloc::vec::Vec;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::fmt::Debug;
 use frame_support::Parameter;
 use scale_info::TypeInfo;
@@ -39,7 +39,17 @@ pub type PartsOf57600 = u16;
 
 /// An element to which a core can be assigned.
 #[derive(
-	Encode, Decode, Clone, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug, TypeInfo, MaxEncodedLen,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Clone,
+	Eq,
+	PartialEq,
+	Ord,
+	PartialOrd,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
 )]
 pub enum CoreAssignment {
 	/// Core need not be used for anything.
diff --git a/substrate/frame/broker/src/dispatchable_impls.rs b/substrate/frame/broker/src/dispatchable_impls.rs
index 77bbf0878b4fa0f3a454d08d419c9fcc9f33fab5..79d671d7432c49de2e2d396b22301bf135f54476 100644
--- a/substrate/frame/broker/src/dispatchable_impls.rs
+++ b/substrate/frame/broker/src/dispatchable_impls.rs
@@ -91,6 +91,15 @@ impl<T: Config> Pallet<T> {
 		Ok(())
 	}
 
+	pub(crate) fn do_remove_lease(task: TaskId) -> DispatchResult {
+		let mut r = Leases::<T>::get();
+		let i = r.iter().position(|lease| lease.task == task).ok_or(Error::<T>::LeaseNotFound)?;
+		r.remove(i);
+		Leases::<T>::put(r);
+		Self::deposit_event(Event::<T>::LeaseRemoved { task });
+		Ok(())
+	}
+
 	pub(crate) fn do_start_sales(
 		end_price: BalanceOf<T>,
 		extra_cores: CoreIndex,
@@ -341,6 +350,14 @@ impl<T: Config> Pallet<T> {
 		Ok(())
 	}
 
+	pub(crate) fn do_remove_assignment(region_id: RegionId) -> DispatchResult {
+		let workplan_key = (region_id.begin, region_id.core);
+		ensure!(Workplan::<T>::contains_key(&workplan_key), Error::<T>::AssignmentNotFound);
+		Workplan::<T>::remove(&workplan_key);
+		Self::deposit_event(Event::<T>::AssignmentRemoved { region_id });
+		Ok(())
+	}
+
 	pub(crate) fn do_pool(
 		region_id: RegionId,
 		maybe_check_owner: Option<T::AccountId>,
diff --git a/substrate/frame/broker/src/lib.rs b/substrate/frame/broker/src/lib.rs
index f605815a421cac6668b7ce9052a3f8353db100e7..3ecfec6b643d3744afb94cdd6c05590a756da0e1 100644
--- a/substrate/frame/broker/src/lib.rs
+++ b/substrate/frame/broker/src/lib.rs
@@ -279,6 +279,11 @@ pub mod pallet {
 			/// The task to which the Region was assigned.
 			task: TaskId,
 		},
+		/// An assignment has been removed from the workplan.
+		AssignmentRemoved {
+			/// The Region which was removed from the workplan.
+			region_id: RegionId,
+		},
 		/// A Region has been added to the Instantaneous Coretime Pool.
 		Pooled {
 			/// The Region which was added to the Instantaneous Coretime Pool.
@@ -340,6 +345,11 @@ pub mod pallet {
 			/// longer apply).
 			until: Timeslice,
 		},
+		/// A lease has been removed.
+		LeaseRemoved {
+			/// The task to which a core was assigned.
+			task: TaskId,
+		},
 		/// A lease is about to end.
 		LeaseEnding {
 			/// The task to which a core was assigned.
@@ -519,6 +529,8 @@ pub mod pallet {
 		TooManyReservations,
 		/// The maximum amount of leases has already been reached.
 		TooManyLeases,
+		/// The lease does not exist.
+		LeaseNotFound,
 		/// The revenue for the Instantaneous Core Sales of this period is not (yet) known and thus
 		/// this operation cannot proceed.
 		UnknownRevenue,
@@ -551,6 +563,8 @@ pub mod pallet {
 		SovereignAccountNotFound,
 		/// Attempted to disable auto-renewal for a core that didn't have it enabled.
 		AutoRenewalNotEnabled,
+		/// Attempted to force remove an assignment that doesn't exist.
+		AssignmentNotFound,
 		/// Needed to prevent spam attacks.The amount of credits the user attempted to purchase is
 		/// below `T::MinimumCreditPurchase`.
 		CreditPurchaseTooSmall,
@@ -979,6 +993,26 @@ pub mod pallet {
 			Ok(Pays::No.into())
 		}
 
+		/// Remove a lease.
+		///
+		/// - `origin`: Must be Root or pass `AdminOrigin`.
+		/// - `task`: The task id of the lease which should be removed.
+		#[pallet::call_index(24)]
+		pub fn remove_lease(origin: OriginFor<T>, task: TaskId) -> DispatchResult {
+			T::AdminOrigin::ensure_origin_or_root(origin)?;
+			Self::do_remove_lease(task)
+		}
+
+		/// Remove an assignment from the Workplan.
+		///
+		/// - `origin`: Must be Root or pass `AdminOrigin`.
+		/// - `region_id`: The Region to be removed from the workplan.
+		#[pallet::call_index(26)]
+		pub fn remove_assignment(origin: OriginFor<T>, region_id: RegionId) -> DispatchResult {
+			T::AdminOrigin::ensure_origin_or_root(origin)?;
+			Self::do_remove_assignment(region_id)
+		}
+
 		#[pallet::call_index(99)]
 		#[pallet::weight(T::WeightInfo::swap_leases())]
 		pub fn swap_leases(origin: OriginFor<T>, id: TaskId, other: TaskId) -> DispatchResult {
diff --git a/substrate/frame/broker/src/tests.rs b/substrate/frame/broker/src/tests.rs
index 984650aac08edeadf3c9eaead83b56d991733865..2e04f7201f87b4284643fb72847f7f90e892a732 100644
--- a/substrate/frame/broker/src/tests.rs
+++ b/substrate/frame/broker/src/tests.rs
@@ -25,7 +25,10 @@ use frame_support::{
 };
 use frame_system::RawOrigin::Root;
 use pretty_assertions::assert_eq;
-use sp_runtime::{traits::Get, Perbill, TokenError};
+use sp_runtime::{
+	traits::{BadOrigin, Get},
+	Perbill, TokenError,
+};
 use CoreAssignment::*;
 use CoretimeTraceItem::*;
 use Finality::*;
@@ -1223,6 +1226,18 @@ fn leases_are_limited() {
 	});
 }
 
+#[test]
+fn remove_lease_works() {
+	TestExt::new().execute_with(|| {
+		Leases::<Test>::put(
+			BoundedVec::try_from(vec![LeaseRecordItem { task: 1u32, until: 10u32 }]).unwrap(),
+		);
+		assert_noop!(Broker::do_remove_lease(2), Error::<Test>::LeaseNotFound);
+		assert_ok!(Broker::do_remove_lease(1));
+		assert_noop!(Broker::do_remove_lease(1), Error::<Test>::LeaseNotFound);
+	});
+}
+
 #[test]
 fn purchase_requires_valid_status_and_sale_info() {
 	TestExt::new().execute_with(|| {
@@ -1836,6 +1851,25 @@ fn disable_auto_renew_works() {
 	});
 }
 
+#[test]
+fn remove_assignment_works() {
+	TestExt::new().endow(1, 1000).execute_with(|| {
+		assert_ok!(Broker::do_start_sales(100, 1));
+		advance_to(2);
+		let region_id = Broker::do_purchase(1, u64::max_value()).unwrap();
+		assert_ok!(Broker::do_assign(region_id, Some(1), 1001, Final));
+		let workplan_key = (region_id.begin, region_id.core);
+		assert_ne!(Workplan::<Test>::get(workplan_key), None);
+		assert_noop!(Broker::remove_assignment(RuntimeOrigin::signed(2), region_id), BadOrigin);
+		assert_ok!(Broker::remove_assignment(RuntimeOrigin::root(), region_id));
+		assert_eq!(Workplan::<Test>::get(workplan_key), None);
+		assert_noop!(
+			Broker::remove_assignment(RuntimeOrigin::root(), region_id),
+			Error::<Test>::AssignmentNotFound
+		);
+	});
+}
+
 #[test]
 fn start_sales_sets_correct_core_count() {
 	TestExt::new().endow(1, 1000).execute_with(|| {
diff --git a/substrate/frame/broker/src/types.rs b/substrate/frame/broker/src/types.rs
index f970b310a3cba1dd987c85bdd0a72f0181ccce1c..ec04b9d9b1f6246f10cef19a7764ab909f5b5e05 100644
--- a/substrate/frame/broker/src/types.rs
+++ b/substrate/frame/broker/src/types.rs
@@ -19,7 +19,7 @@ use crate::{
 	Config, CoreAssignment, CoreIndex, CoreMask, CoretimeInterface, RCBlockNumberOf, TaskId,
 	CORE_MASK_BITS,
 };
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_support::traits::fungible::Inspect;
 use frame_system::Config as SConfig;
 use scale_info::TypeInfo;
@@ -42,7 +42,18 @@ pub type CoreMaskBitCount = u32;
 pub type SignedCoreMaskBitCount = i32;
 
 /// Whether a core assignment is revokable or not.
-#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Copy,
+	Clone,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum Finality {
 	/// The region remains with the same owner allowing the assignment to be altered.
 	Provisional,
@@ -51,7 +62,18 @@ pub enum Finality {
 }
 
 /// Self-describing identity for a Region of Bulk Coretime.
-#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Copy,
+	Clone,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct RegionId {
 	/// The timeslice at which this Region begins.
 	pub begin: Timeslice,
@@ -91,7 +113,17 @@ pub struct RegionRecord<AccountId, Balance> {
 pub type RegionRecordOf<T> = RegionRecord<<T as SConfig>::AccountId, BalanceOf<T>>;
 
 /// An distinct item which can be scheduled on a Polkadot Core.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Clone,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct ScheduleItem {
 	/// The regularity parts in which this Item will be scheduled on the Core.
 	pub mask: CoreMask,
@@ -259,7 +291,17 @@ pub type LeasesRecordOf<T> = LeasesRecord<<T as Config>::MaxLeasedCores>;
 ///
 /// The blocknumber is the relay chain block height `until` which the original request
 /// for revenue was made.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Clone,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct OnDemandRevenueRecord<RelayBlockNumber, RelayBalance> {
 	/// The height of the Relay-chain at the time the revenue request was made.
 	pub until: RelayBlockNumber,
@@ -271,7 +313,17 @@ pub type OnDemandRevenueRecordOf<T> =
 	OnDemandRevenueRecord<RelayBlockNumberOf<T>, RelayBalanceOf<T>>;
 
 /// Configuration of this pallet.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Clone,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct ConfigRecord<RelayBlockNumber> {
 	/// The number of Relay-chain blocks in advance which scheduling should be fixed and the
 	/// `Coretime::assign` API used to inform the Relay-chain.
diff --git a/substrate/frame/broker/src/weights.rs b/substrate/frame/broker/src/weights.rs
index 87e588551661b335d1bb2aaa20f6b4369e90b2e9..d26cbcb1426c32f9043a16b0bdc78047286806c9 100644
--- a/substrate/frame/broker/src/weights.rs
+++ b/substrate/frame/broker/src/weights.rs
@@ -18,31 +18,37 @@
 //! Autogenerated weights for `pallet_broker`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-12-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2025-02-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-acd6uxux-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
-//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024`
+//! HOSTNAME: `9f21ee06036e`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024`
 
 // Executed Command:
-// target/production/substrate-node
+// frame-omni-bencher
+// v1
 // benchmark
 // pallet
-// --steps=50
-// --repeat=20
 // --extrinsic=*
+// --runtime=target/production/wbuild/kitchensink-runtime/kitchensink_runtime.wasm
+// --pallet=pallet_broker
+// --header=/__w/polkadot-sdk/polkadot-sdk/substrate/HEADER-APACHE2
+// --output=/__w/polkadot-sdk/polkadot-sdk/substrate/frame/broker/src/weights.rs
 // --wasm-execution=compiled
+// --steps=50
+// --repeat=20
 // --heap-pages=4096
-// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json
-// --pallet=pallet_broker
-// --chain=dev
-// --header=./substrate/HEADER-APACHE2
-// --output=./substrate/frame/broker/src/weights.rs
-// --template=./substrate/.maintain/frame-weight-template.hbs
+// --template=substrate/.maintain/frame-weight-template.hbs
+// --no-storage-info
+// --no-min-squares
+// --no-median-slopes
+// --genesis-builder-policy=none
+// --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic,pallet_nomination_pools,pallet_remark,pallet_transaction_storage
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
 #![allow(unused_imports)]
 #![allow(missing_docs)]
+#![allow(dead_code)]
 
 use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
 use core::marker::PhantomData;
@@ -53,6 +59,7 @@ pub trait WeightInfo {
 	fn reserve() -> Weight;
 	fn unreserve() -> Weight;
 	fn set_lease() -> Weight;
+	fn remove_lease() -> Weight;
 	fn start_sales(n: u32, ) -> Weight;
 	fn purchase() -> Weight;
 	fn renew() -> Weight;
@@ -82,6 +89,7 @@ pub trait WeightInfo {
 	fn enable_auto_renew() -> Weight;
 	fn disable_auto_renew() -> Weight;
 	fn on_new_timeslice() -> Weight;
+	fn remove_assignment() -> Weight;
 }
 
 /// Weights for `pallet_broker` using the Substrate node and recommended hardware.
@@ -93,18 +101,18 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 2_498_000 picoseconds.
-		Weight::from_parts(2_660_000, 0)
+		// Minimum execution time: 1_970_000 picoseconds.
+		Weight::from_parts(2_010_000, 0)
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
 	/// Storage: `Broker::Reservations` (r:1 w:1)
 	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`)
 	fn reserve() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `5016`
+		//  Measured:  `4816`
 		//  Estimated: `7496`
-		// Minimum execution time: 23_090_000 picoseconds.
-		Weight::from_parts(23_664_000, 7496)
+		// Minimum execution time: 15_223_000 picoseconds.
+		Weight::from_parts(15_546_000, 7496)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -112,10 +120,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`)
 	fn unreserve() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `6218`
+		//  Measured:  `6018`
 		//  Estimated: `7496`
-		// Minimum execution time: 21_782_000 picoseconds.
-		Weight::from_parts(22_708_000, 7496)
+		// Minimum execution time: 14_410_000 picoseconds.
+		Weight::from_parts(14_781_000, 7496)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -123,10 +131,21 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`)
 	fn set_lease() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `239`
+		//  Measured:  `39`
+		//  Estimated: `1526`
+		// Minimum execution time: 7_751_000 picoseconds.
+		Weight::from_parts(8_066_000, 1526)
+			.saturating_add(T::DbWeight::get().reads(1_u64))
+			.saturating_add(T::DbWeight::get().writes(1_u64))
+	}
+	/// Storage: `Broker::Leases` (r:1 w:1)
+	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`)
+	fn remove_lease() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `47`
 		//  Estimated: `1526`
-		// Minimum execution time: 14_966_000 picoseconds.
-		Weight::from_parts(15_592_000, 1526)
+		// Minimum execution time: 7_307_000 picoseconds.
+		Weight::from_parts(7_597_000, 1526)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -149,12 +168,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// The range of component `n` is `[0, 1000]`.
 	fn start_sales(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `6330`
+		//  Measured:  `6134`
 		//  Estimated: `8499`
-		// Minimum execution time: 31_757_000 picoseconds.
-		Weight::from_parts(57_977_268, 8499)
-			// Standard Error: 576
-			.saturating_add(Weight::from_parts(3_102, 0).saturating_mul(n.into()))
+		// Minimum execution time: 27_824_000 picoseconds.
+		Weight::from_parts(50_610_414, 8499)
+			// Standard Error: 515
+			.saturating_add(Weight::from_parts(3_396, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(7_u64))
 			.saturating_add(T::DbWeight::get().writes(16_u64))
 	}
@@ -166,10 +185,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn purchase() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `470`
+		//  Measured:  `274`
 		//  Estimated: `1542`
-		// Minimum execution time: 40_469_000 picoseconds.
-		Weight::from_parts(41_360_000, 1542)
+		// Minimum execution time: 36_411_000 picoseconds.
+		Weight::from_parts(38_093_000, 1542)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 	}
@@ -185,10 +204,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `588`
+		//  Measured:  `392`
 		//  Estimated: `4698`
-		// Minimum execution time: 60_724_000 picoseconds.
-		Weight::from_parts(63_445_000, 4698)
+		// Minimum execution time: 61_900_000 picoseconds.
+		Weight::from_parts(63_344_000, 4698)
 			.saturating_add(T::DbWeight::get().reads(4_u64))
 			.saturating_add(T::DbWeight::get().writes(4_u64))
 	}
@@ -196,10 +215,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn transfer() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `496`
+		//  Measured:  `300`
 		//  Estimated: `3551`
-		// Minimum execution time: 23_734_000 picoseconds.
-		Weight::from_parts(25_080_000, 3551)
+		// Minimum execution time: 15_522_000 picoseconds.
+		Weight::from_parts(16_609_000, 3551)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -207,10 +226,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn partition() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `496`
+		//  Measured:  `300`
 		//  Estimated: `3551`
-		// Minimum execution time: 25_917_000 picoseconds.
-		Weight::from_parts(26_715_000, 3551)
+		// Minimum execution time: 17_308_000 picoseconds.
+		Weight::from_parts(18_043_000, 3551)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 	}
@@ -218,10 +237,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn interlace() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `496`
+		//  Measured:  `300`
 		//  Estimated: `3551`
-		// Minimum execution time: 26_764_000 picoseconds.
-		Weight::from_parts(27_770_000, 3551)
+		// Minimum execution time: 18_042_000 picoseconds.
+		Weight::from_parts(18_911_000, 3551)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(3_u64))
 	}
@@ -235,10 +254,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn assign() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `741`
+		//  Measured:  `545`
 		//  Estimated: `4681`
-		// Minimum execution time: 37_617_000 picoseconds.
-		Weight::from_parts(39_333_000, 4681)
+		// Minimum execution time: 30_363_000 picoseconds.
+		Weight::from_parts(31_434_000, 4681)
 			.saturating_add(T::DbWeight::get().reads(4_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 	}
@@ -254,10 +273,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	fn pool() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `776`
+		//  Measured:  `580`
 		//  Estimated: `5996`
-		// Minimum execution time: 43_168_000 picoseconds.
-		Weight::from_parts(44_741_000, 5996)
+		// Minimum execution time: 36_648_000 picoseconds.
+		Weight::from_parts(37_773_000, 5996)
 			.saturating_add(T::DbWeight::get().reads(5_u64))
 			.saturating_add(T::DbWeight::get().writes(5_u64))
 	}
@@ -270,12 +289,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// The range of component `m` is `[1, 3]`.
 	fn claim_revenue(m: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `878`
+		//  Measured:  `682`
 		//  Estimated: `6196 + m * (2520 ±0)`
-		// Minimum execution time: 75_317_000 picoseconds.
-		Weight::from_parts(76_792_860, 6196)
-			// Standard Error: 55_267
-			.saturating_add(Weight::from_parts(1_878_133, 0).saturating_mul(m.into()))
+		// Minimum execution time: 68_215_000 picoseconds.
+		Weight::from_parts(69_303_342, 6196)
+			// Standard Error: 60_821
+			.saturating_add(Weight::from_parts(1_916_553, 0).saturating_mul(m.into()))
 			.saturating_add(T::DbWeight::get().reads(3_u64))
 			.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into())))
 			.saturating_add(T::DbWeight::get().writes(5_u64))
@@ -287,8 +306,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `103`
 		//  Estimated: `3593`
-		// Minimum execution time: 44_248_000 picoseconds.
-		Weight::from_parts(45_201_000, 3593)
+		// Minimum execution time: 43_439_000 picoseconds.
+		Weight::from_parts(44_278_000, 3593)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -298,10 +317,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn drop_region() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `604`
+		//  Measured:  `408`
 		//  Estimated: `3551`
-		// Minimum execution time: 39_853_000 picoseconds.
-		Weight::from_parts(44_136_000, 3551)
+		// Minimum execution time: 28_074_000 picoseconds.
+		Weight::from_parts(31_676_000, 3551)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -313,10 +332,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	fn drop_contribution() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `601`
+		//  Measured:  `405`
 		//  Estimated: `3533`
-		// Minimum execution time: 46_452_000 picoseconds.
-		Weight::from_parts(52_780_000, 3533)
+		// Minimum execution time: 36_964_000 picoseconds.
+		Weight::from_parts(38_784_000, 3533)
 			.saturating_add(T::DbWeight::get().reads(3_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -330,10 +349,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn drop_history() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `1117`
+		//  Measured:  `818`
 		//  Estimated: `3593`
-		// Minimum execution time: 64_905_000 picoseconds.
-		Weight::from_parts(72_914_000, 3593)
+		// Minimum execution time: 49_077_000 picoseconds.
+		Weight::from_parts(54_396_000, 3593)
 			.saturating_add(T::DbWeight::get().reads(4_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -343,30 +362,34 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::PotentialRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`)
 	fn drop_renewal() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `661`
+		//  Measured:  `465`
 		//  Estimated: `4698`
-		// Minimum execution time: 38_831_000 picoseconds.
-		Weight::from_parts(41_420_000, 4698)
+		// Minimum execution time: 29_487_000 picoseconds.
+		Weight::from_parts(32_079_000, 4698)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
 	/// The range of component `n` is `[0, 1000]`.
-	fn request_core_count(_n: u32, ) -> Weight {
+	fn request_core_count(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 4_595_000 picoseconds.
-		Weight::from_parts(4_964_606, 0)
+		// Minimum execution time: 3_718_000 picoseconds.
+		Weight::from_parts(3_944_873, 0)
+			// Standard Error: 8
+			.saturating_add(Weight::from_parts(2, 0).saturating_mul(n.into()))
 	}
 	/// Storage: `Broker::CoreCountInbox` (r:1 w:1)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
 	/// The range of component `n` is `[0, 1000]`.
-	fn process_core_count(_n: u32, ) -> Weight {
+	fn process_core_count(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `404`
+		//  Measured:  `208`
 		//  Estimated: `1487`
-		// Minimum execution time: 8_640_000 picoseconds.
-		Weight::from_parts(9_153_332, 1487)
+		// Minimum execution time: 5_828_000 picoseconds.
+		Weight::from_parts(6_199_804, 1487)
+			// Standard Error: 13
+			.saturating_add(Weight::from_parts(45, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -378,10 +401,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn process_revenue() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `667`
+		//  Measured:  `471`
 		//  Estimated: `3593`
-		// Minimum execution time: 40_570_000 picoseconds.
-		Weight::from_parts(41_402_000, 3593)
+		// Minimum execution time: 38_383_000 picoseconds.
+		Weight::from_parts(39_390_000, 3593)
 			.saturating_add(T::DbWeight::get().reads(3_u64))
 			.saturating_add(T::DbWeight::get().writes(3_u64))
 	}
@@ -408,12 +431,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// The range of component `n` is `[0, 1000]`.
 	fn rotate_sale(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `8548`
+		//  Measured:  `8126`
 		//  Estimated: `38070`
-		// Minimum execution time: 29_370_000 picoseconds.
-		Weight::from_parts(334_030_189, 38070)
-			// Standard Error: 6_912
-			.saturating_add(Weight::from_parts(1_268_750, 0).saturating_mul(n.into()))
+		// Minimum execution time: 22_037_000 picoseconds.
+		Weight::from_parts(323_459_518, 38070)
+			// Standard Error: 6_945
+			.saturating_add(Weight::from_parts(1_356_460, 0).saturating_mul(n.into()))
 			.saturating_add(T::DbWeight::get().reads(26_u64))
 			.saturating_add(T::DbWeight::get().writes(34_u64))
 			.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into())))
@@ -424,10 +447,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`)
 	fn process_pool() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `180`
+		//  Measured:  `0`
 		//  Estimated: `3493`
-		// Minimum execution time: 9_005_000 picoseconds.
-		Weight::from_parts(9_392_000, 3493)
+		// Minimum execution time: 4_928_000 picoseconds.
+		Weight::from_parts(5_182_000, 3493)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -437,10 +460,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Workload` (`max_values`: None, `max_size`: Some(1212), added: 3687, mode: `MaxEncodedLen`)
 	fn process_core_schedule() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `1423`
+		//  Measured:  `1223`
 		//  Estimated: `4681`
-		// Minimum execution time: 19_043_000 picoseconds.
-		Weight::from_parts(20_089_000, 4681)
+		// Minimum execution time: 11_814_000 picoseconds.
+		Weight::from_parts(12_194_000, 4681)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 	}
@@ -448,8 +471,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 149_000 picoseconds.
-		Weight::from_parts(183_000, 0)
+		// Minimum execution time: 130_000 picoseconds.
+		Weight::from_parts(138_000, 0)
 	}
 	/// Storage: `Broker::CoreCountInbox` (r:0 w:1)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
@@ -457,8 +480,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 2_248_000 picoseconds.
-		Weight::from_parts(2_425_000, 0)
+		// Minimum execution time: 1_791_000 picoseconds.
+		Weight::from_parts(1_898_000, 0)
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
 	/// Storage: `Broker::RevenueInbox` (r:0 w:1)
@@ -467,8 +490,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 2_413_000 picoseconds.
-		Weight::from_parts(2_640_000, 0)
+		// Minimum execution time: 1_973_000 picoseconds.
+		Weight::from_parts(2_069_000, 0)
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
 	/// Storage: `Broker::Status` (r:1 w:1)
@@ -481,10 +504,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
 	fn do_tick_base() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `441`
+		//  Measured:  `245`
 		//  Estimated: `1516`
-		// Minimum execution time: 17_083_000 picoseconds.
-		Weight::from_parts(18_077_000, 1516)
+		// Minimum execution time: 10_337_000 picoseconds.
+		Weight::from_parts(10_769_000, 1516)
 			.saturating_add(T::DbWeight::get().reads(4_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -498,10 +521,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn force_reserve() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `5253`
+		//  Measured:  `5073`
 		//  Estimated: `7496`
-		// Minimum execution time: 28_363_000 picoseconds.
-		Weight::from_parts(29_243_000, 7496)
+		// Minimum execution time: 27_540_000 picoseconds.
+		Weight::from_parts(28_141_000, 7496)
 			.saturating_add(T::DbWeight::get().reads(3_u64))
 			.saturating_add(T::DbWeight::get().writes(3_u64))
 	}
@@ -509,10 +532,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`)
 	fn swap_leases() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `239`
+		//  Measured:  `39`
 		//  Estimated: `1526`
-		// Minimum execution time: 11_620_000 picoseconds.
-		Weight::from_parts(12_063_000, 1526)
+		// Minimum execution time: 4_651_000 picoseconds.
+		Weight::from_parts(4_874_000, 1526)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -532,10 +555,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn enable_auto_renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `1121`
+		//  Measured:  `888`
 		//  Estimated: `4698`
-		// Minimum execution time: 85_270_000 picoseconds.
-		Weight::from_parts(90_457_000, 4698)
+		// Minimum execution time: 76_761_000 picoseconds.
+		Weight::from_parts(81_115_000, 4698)
 			.saturating_add(T::DbWeight::get().reads(6_u64))
 			.saturating_add(T::DbWeight::get().writes(6_u64))
 	}
@@ -543,10 +566,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Broker::AutoRenewals` (`max_values`: Some(1), `max_size`: Some(101), added: 596, mode: `MaxEncodedLen`)
 	fn disable_auto_renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `578`
+		//  Measured:  `382`
 		//  Estimated: `1586`
-		// Minimum execution time: 22_479_000 picoseconds.
-		Weight::from_parts(23_687_000, 1586)
+		// Minimum execution time: 13_934_000 picoseconds.
+		Weight::from_parts(14_716_000, 1586)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -554,8 +577,19 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 245_000 picoseconds.
-		Weight::from_parts(290_000, 0)
+		// Minimum execution time: 241_000 picoseconds.
+		Weight::from_parts(260_000, 0)
+	}
+	/// Storage: `Broker::Workplan` (r:1 w:1)
+	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
+	fn remove_assignment() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `408`
+		//  Estimated: `4681`
+		// Minimum execution time: 14_586_000 picoseconds.
+		Weight::from_parts(15_270_000, 4681)
+			.saturating_add(T::DbWeight::get().reads(1_u64))
+			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
 }
 
@@ -567,18 +601,18 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 2_498_000 picoseconds.
-		Weight::from_parts(2_660_000, 0)
+		// Minimum execution time: 1_970_000 picoseconds.
+		Weight::from_parts(2_010_000, 0)
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
 	/// Storage: `Broker::Reservations` (r:1 w:1)
 	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`)
 	fn reserve() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `5016`
+		//  Measured:  `4816`
 		//  Estimated: `7496`
-		// Minimum execution time: 23_090_000 picoseconds.
-		Weight::from_parts(23_664_000, 7496)
+		// Minimum execution time: 15_223_000 picoseconds.
+		Weight::from_parts(15_546_000, 7496)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -586,10 +620,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`)
 	fn unreserve() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `6218`
+		//  Measured:  `6018`
 		//  Estimated: `7496`
-		// Minimum execution time: 21_782_000 picoseconds.
-		Weight::from_parts(22_708_000, 7496)
+		// Minimum execution time: 14_410_000 picoseconds.
+		Weight::from_parts(14_781_000, 7496)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -597,10 +631,21 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`)
 	fn set_lease() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `239`
+		//  Measured:  `39`
+		//  Estimated: `1526`
+		// Minimum execution time: 7_751_000 picoseconds.
+		Weight::from_parts(8_040_000, 1526)
+			.saturating_add(RocksDbWeight::get().reads(1_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
+	/// Storage: `Broker::Leases` (r:1 w:1)
+	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`)
+	fn remove_lease() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `47`
 		//  Estimated: `1526`
-		// Minimum execution time: 14_966_000 picoseconds.
-		Weight::from_parts(15_592_000, 1526)
+		// Minimum execution time: 7_307_000 picoseconds.
+		Weight::from_parts(7_597_000, 1526)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -623,12 +668,12 @@ impl WeightInfo for () {
 	/// The range of component `n` is `[0, 1000]`.
 	fn start_sales(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `6330`
+		//  Measured:  `6134`
 		//  Estimated: `8499`
-		// Minimum execution time: 31_757_000 picoseconds.
-		Weight::from_parts(57_977_268, 8499)
-			// Standard Error: 576
-			.saturating_add(Weight::from_parts(3_102, 0).saturating_mul(n.into()))
+		// Minimum execution time: 27_824_000 picoseconds.
+		Weight::from_parts(50_610_414, 8499)
+			// Standard Error: 515
+			.saturating_add(Weight::from_parts(3_396, 0).saturating_mul(n.into()))
 			.saturating_add(RocksDbWeight::get().reads(7_u64))
 			.saturating_add(RocksDbWeight::get().writes(16_u64))
 	}
@@ -640,10 +685,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn purchase() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `470`
+		//  Measured:  `274`
 		//  Estimated: `1542`
-		// Minimum execution time: 40_469_000 picoseconds.
-		Weight::from_parts(41_360_000, 1542)
+		// Minimum execution time: 36_411_000 picoseconds.
+		Weight::from_parts(38_093_000, 1542)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
@@ -659,10 +704,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `588`
+		//  Measured:  `392`
 		//  Estimated: `4698`
-		// Minimum execution time: 60_724_000 picoseconds.
-		Weight::from_parts(63_445_000, 4698)
+		// Minimum execution time: 61_900_000 picoseconds.
+		Weight::from_parts(63_344_000, 4698)
 			.saturating_add(RocksDbWeight::get().reads(4_u64))
 			.saturating_add(RocksDbWeight::get().writes(4_u64))
 	}
@@ -670,10 +715,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn transfer() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `496`
+		//  Measured:  `300`
 		//  Estimated: `3551`
-		// Minimum execution time: 23_734_000 picoseconds.
-		Weight::from_parts(25_080_000, 3551)
+		// Minimum execution time: 15_522_000 picoseconds.
+		Weight::from_parts(16_609_000, 3551)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -681,10 +726,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn partition() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `496`
+		//  Measured:  `300`
 		//  Estimated: `3551`
-		// Minimum execution time: 25_917_000 picoseconds.
-		Weight::from_parts(26_715_000, 3551)
+		// Minimum execution time: 17_308_000 picoseconds.
+		Weight::from_parts(18_043_000, 3551)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
@@ -692,10 +737,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn interlace() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `496`
+		//  Measured:  `300`
 		//  Estimated: `3551`
-		// Minimum execution time: 26_764_000 picoseconds.
-		Weight::from_parts(27_770_000, 3551)
+		// Minimum execution time: 18_042_000 picoseconds.
+		Weight::from_parts(18_911_000, 3551)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(3_u64))
 	}
@@ -709,10 +754,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn assign() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `741`
+		//  Measured:  `545`
 		//  Estimated: `4681`
-		// Minimum execution time: 37_617_000 picoseconds.
-		Weight::from_parts(39_333_000, 4681)
+		// Minimum execution time: 30_363_000 picoseconds.
+		Weight::from_parts(31_434_000, 4681)
 			.saturating_add(RocksDbWeight::get().reads(4_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
@@ -728,10 +773,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	fn pool() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `776`
+		//  Measured:  `580`
 		//  Estimated: `5996`
-		// Minimum execution time: 43_168_000 picoseconds.
-		Weight::from_parts(44_741_000, 5996)
+		// Minimum execution time: 36_648_000 picoseconds.
+		Weight::from_parts(37_773_000, 5996)
 			.saturating_add(RocksDbWeight::get().reads(5_u64))
 			.saturating_add(RocksDbWeight::get().writes(5_u64))
 	}
@@ -744,12 +789,12 @@ impl WeightInfo for () {
 	/// The range of component `m` is `[1, 3]`.
 	fn claim_revenue(m: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `878`
+		//  Measured:  `682`
 		//  Estimated: `6196 + m * (2520 ±0)`
-		// Minimum execution time: 75_317_000 picoseconds.
-		Weight::from_parts(76_792_860, 6196)
-			// Standard Error: 55_267
-			.saturating_add(Weight::from_parts(1_878_133, 0).saturating_mul(m.into()))
+		// Minimum execution time: 68_215_000 picoseconds.
+		Weight::from_parts(69_303_342, 6196)
+			// Standard Error: 60_821
+			.saturating_add(Weight::from_parts(1_916_553, 0).saturating_mul(m.into()))
 			.saturating_add(RocksDbWeight::get().reads(3_u64))
 			.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(m.into())))
 			.saturating_add(RocksDbWeight::get().writes(5_u64))
@@ -761,8 +806,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `103`
 		//  Estimated: `3593`
-		// Minimum execution time: 44_248_000 picoseconds.
-		Weight::from_parts(45_201_000, 3593)
+		// Minimum execution time: 43_439_000 picoseconds.
+		Weight::from_parts(44_278_000, 3593)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -772,10 +817,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`)
 	fn drop_region() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `604`
+		//  Measured:  `408`
 		//  Estimated: `3551`
-		// Minimum execution time: 39_853_000 picoseconds.
-		Weight::from_parts(44_136_000, 3551)
+		// Minimum execution time: 28_074_000 picoseconds.
+		Weight::from_parts(31_676_000, 3551)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -787,10 +832,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
 	fn drop_contribution() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `601`
+		//  Measured:  `405`
 		//  Estimated: `3533`
-		// Minimum execution time: 46_452_000 picoseconds.
-		Weight::from_parts(52_780_000, 3533)
+		// Minimum execution time: 36_964_000 picoseconds.
+		Weight::from_parts(38_784_000, 3533)
 			.saturating_add(RocksDbWeight::get().reads(3_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -804,10 +849,10 @@ impl WeightInfo for () {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn drop_history() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `1117`
+		//  Measured:  `818`
 		//  Estimated: `3593`
-		// Minimum execution time: 64_905_000 picoseconds.
-		Weight::from_parts(72_914_000, 3593)
+		// Minimum execution time: 49_077_000 picoseconds.
+		Weight::from_parts(54_396_000, 3593)
 			.saturating_add(RocksDbWeight::get().reads(4_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -817,30 +862,34 @@ impl WeightInfo for () {
 	/// Proof: `Broker::PotentialRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`)
 	fn drop_renewal() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `661`
+		//  Measured:  `465`
 		//  Estimated: `4698`
-		// Minimum execution time: 38_831_000 picoseconds.
-		Weight::from_parts(41_420_000, 4698)
+		// Minimum execution time: 29_487_000 picoseconds.
+		Weight::from_parts(32_079_000, 4698)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
 	/// The range of component `n` is `[0, 1000]`.
-	fn request_core_count(_n: u32, ) -> Weight {
+	fn request_core_count(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 4_595_000 picoseconds.
-		Weight::from_parts(4_964_606, 0)
+		// Minimum execution time: 3_718_000 picoseconds.
+		Weight::from_parts(3_944_873, 0)
+			// Standard Error: 8
+			.saturating_add(Weight::from_parts(2, 0).saturating_mul(n.into()))
 	}
 	/// Storage: `Broker::CoreCountInbox` (r:1 w:1)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
 	/// The range of component `n` is `[0, 1000]`.
-	fn process_core_count(_n: u32, ) -> Weight {
+	fn process_core_count(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `404`
+		//  Measured:  `208`
 		//  Estimated: `1487`
-		// Minimum execution time: 8_640_000 picoseconds.
-		Weight::from_parts(9_153_332, 1487)
+		// Minimum execution time: 5_828_000 picoseconds.
+		Weight::from_parts(6_199_804, 1487)
+			// Standard Error: 13
+			.saturating_add(Weight::from_parts(45, 0).saturating_mul(n.into()))
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -852,10 +901,10 @@ impl WeightInfo for () {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn process_revenue() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `667`
+		//  Measured:  `471`
 		//  Estimated: `3593`
-		// Minimum execution time: 40_570_000 picoseconds.
-		Weight::from_parts(41_402_000, 3593)
+		// Minimum execution time: 38_383_000 picoseconds.
+		Weight::from_parts(39_390_000, 3593)
 			.saturating_add(RocksDbWeight::get().reads(3_u64))
 			.saturating_add(RocksDbWeight::get().writes(3_u64))
 	}
@@ -882,12 +931,12 @@ impl WeightInfo for () {
 	/// The range of component `n` is `[0, 1000]`.
 	fn rotate_sale(n: u32, ) -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `8548`
+		//  Measured:  `8126`
 		//  Estimated: `38070`
-		// Minimum execution time: 29_370_000 picoseconds.
-		Weight::from_parts(334_030_189, 38070)
-			// Standard Error: 6_912
-			.saturating_add(Weight::from_parts(1_268_750, 0).saturating_mul(n.into()))
+		// Minimum execution time: 22_037_000 picoseconds.
+		Weight::from_parts(323_459_518, 38070)
+			// Standard Error: 6_945
+			.saturating_add(Weight::from_parts(1_356_460, 0).saturating_mul(n.into()))
 			.saturating_add(RocksDbWeight::get().reads(26_u64))
 			.saturating_add(RocksDbWeight::get().writes(34_u64))
 			.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into())))
@@ -898,10 +947,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`)
 	fn process_pool() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `180`
+		//  Measured:  `0`
 		//  Estimated: `3493`
-		// Minimum execution time: 9_005_000 picoseconds.
-		Weight::from_parts(9_392_000, 3493)
+		// Minimum execution time: 4_928_000 picoseconds.
+		Weight::from_parts(5_182_000, 3493)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -911,10 +960,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Workload` (`max_values`: None, `max_size`: Some(1212), added: 3687, mode: `MaxEncodedLen`)
 	fn process_core_schedule() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `1423`
+		//  Measured:  `1223`
 		//  Estimated: `4681`
-		// Minimum execution time: 19_043_000 picoseconds.
-		Weight::from_parts(20_089_000, 4681)
+		// Minimum execution time: 11_814_000 picoseconds.
+		Weight::from_parts(12_194_000, 4681)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
@@ -922,8 +971,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 149_000 picoseconds.
-		Weight::from_parts(183_000, 0)
+		// Minimum execution time: 130_000 picoseconds.
+		Weight::from_parts(138_000, 0)
 	}
 	/// Storage: `Broker::CoreCountInbox` (r:0 w:1)
 	/// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`)
@@ -931,8 +980,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 2_248_000 picoseconds.
-		Weight::from_parts(2_425_000, 0)
+		// Minimum execution time: 1_791_000 picoseconds.
+		Weight::from_parts(1_898_000, 0)
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
 	/// Storage: `Broker::RevenueInbox` (r:0 w:1)
@@ -941,8 +990,8 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 2_413_000 picoseconds.
-		Weight::from_parts(2_640_000, 0)
+		// Minimum execution time: 1_973_000 picoseconds.
+		Weight::from_parts(2_069_000, 0)
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
 	/// Storage: `Broker::Status` (r:1 w:1)
@@ -955,10 +1004,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::RevenueInbox` (`max_values`: Some(1), `max_size`: Some(20), added: 515, mode: `MaxEncodedLen`)
 	fn do_tick_base() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `441`
+		//  Measured:  `245`
 		//  Estimated: `1516`
-		// Minimum execution time: 17_083_000 picoseconds.
-		Weight::from_parts(18_077_000, 1516)
+		// Minimum execution time: 10_337_000 picoseconds.
+		Weight::from_parts(10_769_000, 1516)
 			.saturating_add(RocksDbWeight::get().reads(4_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -972,10 +1021,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn force_reserve() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `5253`
+		//  Measured:  `5073`
 		//  Estimated: `7496`
-		// Minimum execution time: 28_363_000 picoseconds.
-		Weight::from_parts(29_243_000, 7496)
+		// Minimum execution time: 27_540_000 picoseconds.
+		Weight::from_parts(28_141_000, 7496)
 			.saturating_add(RocksDbWeight::get().reads(3_u64))
 			.saturating_add(RocksDbWeight::get().writes(3_u64))
 	}
@@ -983,10 +1032,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`)
 	fn swap_leases() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `239`
+		//  Measured:  `39`
 		//  Estimated: `1526`
-		// Minimum execution time: 11_620_000 picoseconds.
-		Weight::from_parts(12_063_000, 1526)
+		// Minimum execution time: 4_651_000 picoseconds.
+		Weight::from_parts(4_874_000, 1526)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -1006,10 +1055,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
 	fn enable_auto_renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `1121`
+		//  Measured:  `888`
 		//  Estimated: `4698`
-		// Minimum execution time: 85_270_000 picoseconds.
-		Weight::from_parts(90_457_000, 4698)
+		// Minimum execution time: 76_761_000 picoseconds.
+		Weight::from_parts(81_115_000, 4698)
 			.saturating_add(RocksDbWeight::get().reads(6_u64))
 			.saturating_add(RocksDbWeight::get().writes(6_u64))
 	}
@@ -1017,10 +1066,10 @@ impl WeightInfo for () {
 	/// Proof: `Broker::AutoRenewals` (`max_values`: Some(1), `max_size`: Some(101), added: 596, mode: `MaxEncodedLen`)
 	fn disable_auto_renew() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `578`
+		//  Measured:  `382`
 		//  Estimated: `1586`
-		// Minimum execution time: 22_479_000 picoseconds.
-		Weight::from_parts(23_687_000, 1586)
+		// Minimum execution time: 13_934_000 picoseconds.
+		Weight::from_parts(14_716_000, 1586)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -1028,7 +1077,18 @@ impl WeightInfo for () {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
 		//  Estimated: `0`
-		// Minimum execution time: 245_000 picoseconds.
-		Weight::from_parts(290_000, 0)
+		// Minimum execution time: 241_000 picoseconds.
+		Weight::from_parts(260_000, 0)
+	}
+	/// Storage: `Broker::Workplan` (r:1 w:1)
+	/// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`)
+	fn remove_assignment() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `408`
+		//  Estimated: `4681`
+		// Minimum execution time: 14_586_000 picoseconds.
+		Weight::from_parts(15_270_000, 4681)
+			.saturating_add(RocksDbWeight::get().reads(1_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
 }
diff --git a/substrate/frame/collective/src/lib.rs b/substrate/frame/collective/src/lib.rs
index 8e533a7b290432b17eed5f142e9f234f3d1d9d5c..a7bd00a7f4114f067ab1233b9706ace760b12edc 100644
--- a/substrate/frame/collective/src/lib.rs
+++ b/substrate/frame/collective/src/lib.rs
@@ -44,7 +44,7 @@
 extern crate alloc;
 
 use alloc::{boxed::Box, vec, vec::Vec};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::{marker::PhantomData, result};
 use scale_info::TypeInfo;
 use sp_io::storage;
@@ -137,7 +137,17 @@ impl DefaultVote for MoreThanMajorityThenPrimeDefaultVote {
 }
 
 /// Origin for the collective module.
-#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]
+#[derive(
+	PartialEq,
+	Eq,
+	Clone,
+	RuntimeDebug,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 #[scale_info(skip_type_params(I))]
 #[codec(mel_bound(AccountId: MaxEncodedLen))]
 pub enum RawOrigin<AccountId, I> {
diff --git a/substrate/frame/contracts/fixtures/contracts/crypto_hashes.rs b/substrate/frame/contracts/fixtures/contracts/crypto_hashes.rs
index 35cc03f1e72377cd919471fb02824f1710cda6f0..69b1671bbe2f88df33a5af94b887a3f91790ecad 100644
--- a/substrate/frame/contracts/fixtures/contracts/crypto_hashes.rs
+++ b/substrate/frame/contracts/fixtures/contracts/crypto_hashes.rs
@@ -48,7 +48,6 @@ pub extern "C" fn deploy() {}
 /// |     2 |    BLAKE2 |       256 |
 /// |     3 |    BLAKE2 |       128 |
 /// ---------------------------------
-
 #[no_mangle]
 #[polkavm_derive::polkavm_export]
 pub extern "C" fn call() {
diff --git a/substrate/frame/contracts/src/lib.rs b/substrate/frame/contracts/src/lib.rs
index 7bb5b46cf527f24dc89d2d17d796a77bcefea4a5..627aca17c9c94dc34dd82f50fb2fbcaea21a29ef 100644
--- a/substrate/frame/contracts/src/lib.rs
+++ b/substrate/frame/contracts/src/lib.rs
@@ -116,7 +116,7 @@ use crate::{
 	storage::{meter::Meter as StorageMeter, ContractInfo, DeletionQueueManager},
 	wasm::{CodeInfo, RuntimeCosts, WasmBlob},
 };
-use codec::{Codec, Decode, Encode, HasCompact, MaxEncodedLen};
+use codec::{Codec, Decode, DecodeWithMemTracking, Encode, HasCompact, MaxEncodedLen};
 use core::fmt::Debug;
 use environmental::*;
 use frame_support::{
@@ -1382,7 +1382,9 @@ pub mod pallet {
 }
 
 /// The type of origins supported by the contracts pallet.
-#[derive(Clone, Encode, Decode, PartialEq, TypeInfo, RuntimeDebugNoBound)]
+#[derive(
+	Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, TypeInfo, RuntimeDebugNoBound,
+)]
 pub enum Origin<T: Config> {
 	Root,
 	Signed(T::AccountId),
diff --git a/substrate/frame/contracts/src/wasm/mod.rs b/substrate/frame/contracts/src/wasm/mod.rs
index c9786fa1516b52e58dfc5aaed7b2f100cead576f..399ed1ccded75465d01ff66a20714de4e7f9bed5 100644
--- a/substrate/frame/contracts/src/wasm/mod.rs
+++ b/substrate/frame/contracts/src/wasm/mod.rs
@@ -49,7 +49,7 @@ use crate::{
 	HoldReason, Pallet, PristineCode, Schedule, Weight, LOG_TARGET,
 };
 use alloc::vec::Vec;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_support::{
 	dispatch::DispatchResult,
 	ensure,
@@ -106,7 +106,16 @@ pub struct CodeInfo<T: Config> {
 
 /// Defines the required determinism level of a wasm blob when either running or uploading code.
 #[derive(
-	Clone, Copy, Encode, Decode, scale_info::TypeInfo, MaxEncodedLen, RuntimeDebug, PartialEq, Eq,
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	scale_info::TypeInfo,
+	MaxEncodedLen,
+	RuntimeDebug,
+	PartialEq,
+	Eq,
 )]
 pub enum Determinism {
 	/// The execution should be deterministic and hence no indeterministic instructions are
diff --git a/substrate/frame/conviction-voting/src/conviction.rs b/substrate/frame/conviction-voting/src/conviction.rs
index b5c9a3a705f6b306a6f1d596d1e58f427ad4e23e..4332c8e4a0a7c6263c44bb654825f5bb47ce6e58 100644
--- a/substrate/frame/conviction-voting/src/conviction.rs
+++ b/substrate/frame/conviction-voting/src/conviction.rs
@@ -17,7 +17,7 @@
 
 //! The conviction datatype.
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{Bounded, CheckedDiv, CheckedMul, Zero},
@@ -30,6 +30,7 @@ use crate::types::Delegations;
 #[derive(
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Copy,
 	Clone,
 	Eq,
diff --git a/substrate/frame/conviction-voting/src/types.rs b/substrate/frame/conviction-voting/src/types.rs
index aa7dd578fbad6bce4a74b753f48817f969d8ab01..fc212186af72f768cad9a8b7f9f950fc1c916861 100644
--- a/substrate/frame/conviction-voting/src/types.rs
+++ b/substrate/frame/conviction-voting/src/types.rs
@@ -17,7 +17,7 @@
 
 //! Miscellaneous additional datatypes.
 
-use codec::{Codec, Decode, Encode, MaxEncodedLen};
+use codec::{Codec, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::{fmt::Debug, marker::PhantomData};
 use frame_support::{
 	traits::VoteTally, CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound,
@@ -40,6 +40,7 @@ use crate::{AccountVote, Conviction, Vote};
 	TypeInfo,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	MaxEncodedLen,
 )]
 #[scale_info(skip_type_params(Total))]
diff --git a/substrate/frame/conviction-voting/src/vote.rs b/substrate/frame/conviction-voting/src/vote.rs
index 1c5b742ba12b16714b7c886d94b374c8d2dde5a3..84c7dafd52c4ad5c92338580fcfd410525a339c2 100644
--- a/substrate/frame/conviction-voting/src/vote.rs
+++ b/substrate/frame/conviction-voting/src/vote.rs
@@ -18,7 +18,7 @@
 //! The vote datatype.
 
 use crate::{Conviction, Delegations};
-use codec::{Decode, Encode, EncodeLike, Input, MaxEncodedLen, Output};
+use codec::{Decode, DecodeWithMemTracking, Encode, EncodeLike, Input, MaxEncodedLen, Output};
 use frame_support::{pallet_prelude::Get, BoundedVec};
 use scale_info::TypeInfo;
 use sp_runtime::{
@@ -27,7 +27,9 @@ use sp_runtime::{
 };
 
 /// A number of lock periods, plus a vote, one way or the other.
-#[derive(Copy, Clone, Eq, PartialEq, Default, RuntimeDebug, MaxEncodedLen)]
+#[derive(
+	DecodeWithMemTracking, Copy, Clone, Eq, PartialEq, Default, RuntimeDebug, MaxEncodedLen,
+)]
 pub struct Vote {
 	pub aye: bool,
 	pub conviction: Conviction,
@@ -66,7 +68,18 @@ impl TypeInfo for Vote {
 }
 
 /// A vote for a referendum of a particular account.
-#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Copy,
+	Clone,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum AccountVote<Balance> {
 	/// A standard vote, one-way (approve or reject) with a given amount of conviction.
 	Standard { vote: Vote, balance: Balance },
diff --git a/substrate/frame/core-fellowship/src/lib.rs b/substrate/frame/core-fellowship/src/lib.rs
index 77ea937eac7a9519ef50971fa38cbbcb41bde6fe..3d2da6e9f717e9f5869eed8eb8f1872350164bc6 100644
--- a/substrate/frame/core-fellowship/src/lib.rs
+++ b/substrate/frame/core-fellowship/src/lib.rs
@@ -62,7 +62,7 @@
 extern crate alloc;
 
 use alloc::boxed::Box;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::{fmt::Debug, marker::PhantomData};
 use scale_info::TypeInfo;
 use sp_arithmetic::traits::{Saturating, Zero};
@@ -91,7 +91,18 @@ pub use pallet::*;
 pub use weights::*;
 
 /// The desired outcome for which evidence is presented.
-#[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	Copy,
+	Clone,
+	TypeInfo,
+	MaxEncodedLen,
+	RuntimeDebug,
+)]
 pub enum Wish {
 	/// Member wishes only to retain their current rank.
 	Retention,
@@ -109,6 +120,7 @@ pub type Evidence<T, I> = BoundedVec<u8, <T as Config<I>>::EvidenceSize>;
 #[derive(
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	CloneNoBound,
 	EqNoBound,
 	PartialEqNoBound,
diff --git a/substrate/frame/democracy/src/conviction.rs b/substrate/frame/democracy/src/conviction.rs
index 54f4ff524f2a9be397a12eadb4bb0c9e88cbf501..64c062ce9434c868d8b8cd1c27eea3f3a504f1d5 100644
--- a/substrate/frame/democracy/src/conviction.rs
+++ b/substrate/frame/democracy/src/conviction.rs
@@ -18,7 +18,7 @@
 //! The conviction datatype.
 
 use crate::types::Delegations;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::result::Result;
 use scale_info::TypeInfo;
 use sp_runtime::{
@@ -31,6 +31,7 @@ use sp_runtime::{
 	Encode,
 	MaxEncodedLen,
 	Decode,
+	DecodeWithMemTracking,
 	Copy,
 	Clone,
 	Eq,
diff --git a/substrate/frame/democracy/src/types.rs b/substrate/frame/democracy/src/types.rs
index ee6e2e0aa253793751053a4393a2409b42bbee0f..88a7435a3b1628e9eade2e49fa3956b433356a82 100644
--- a/substrate/frame/democracy/src/types.rs
+++ b/substrate/frame/democracy/src/types.rs
@@ -18,7 +18,7 @@
 //! Miscellaneous additional datatypes.
 
 use crate::{AccountVote, Conviction, Vote, VoteThreshold};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Saturating, Zero},
@@ -214,7 +214,17 @@ pub enum UnvoteScope {
 }
 
 /// Identifies an owner of a metadata.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Clone,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum MetadataOwner {
 	/// External proposal.
 	External,
diff --git a/substrate/frame/democracy/src/vote.rs b/substrate/frame/democracy/src/vote.rs
index 779f7ecd570f060f29d53ebd05471eb37b531ff1..c1103d4da32e58e63a4f0a3d5c297f172ae413a1 100644
--- a/substrate/frame/democracy/src/vote.rs
+++ b/substrate/frame/democracy/src/vote.rs
@@ -18,7 +18,7 @@
 //! The vote datatype.
 
 use crate::{Conviction, Delegations, ReferendumIndex};
-use codec::{Decode, Encode, EncodeLike, Input, MaxEncodedLen, Output};
+use codec::{Decode, DecodeWithMemTracking, Encode, EncodeLike, Input, MaxEncodedLen, Output};
 use frame_support::traits::Get;
 use scale_info::TypeInfo;
 use sp_runtime::{
@@ -27,7 +27,7 @@ use sp_runtime::{
 };
 
 /// A number of lock periods, plus a vote, one way or the other.
-#[derive(Copy, Clone, Eq, PartialEq, Default, RuntimeDebug)]
+#[derive(DecodeWithMemTracking, Copy, Clone, Eq, PartialEq, Default, RuntimeDebug)]
 pub struct Vote {
 	pub aye: bool,
 	pub conviction: Conviction,
@@ -72,7 +72,18 @@ impl TypeInfo for Vote {
 }
 
 /// A vote for a referendum of a particular account.
-#[derive(Encode, MaxEncodedLen, Decode, Copy, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(
+	Encode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	Decode,
+	Copy,
+	Clone,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+)]
 pub enum AccountVote<Balance> {
 	/// A standard vote, one-way (approve or reject) with a given amount of conviction.
 	Standard { vote: Vote, balance: Balance },
diff --git a/substrate/frame/democracy/src/vote_threshold.rs b/substrate/frame/democracy/src/vote_threshold.rs
index 82d6ed178f13783f2e9495ce064378b3f8de5ecf..9e4e66897a06a287f56fcb5589ef448f4db9b35a 100644
--- a/substrate/frame/democracy/src/vote_threshold.rs
+++ b/substrate/frame/democracy/src/vote_threshold.rs
@@ -18,7 +18,7 @@
 //! Voting thresholds.
 
 use crate::Tally;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::ops::{Add, Div, Mul, Rem};
 use scale_info::TypeInfo;
 #[cfg(feature = "std")]
@@ -27,7 +27,16 @@ use sp_runtime::traits::{IntegerSquareRoot, Zero};
 
 /// A means of determining if a vote is past pass threshold.
 #[derive(
-	Clone, Copy, PartialEq, Eq, Encode, MaxEncodedLen, Decode, sp_runtime::RuntimeDebug, TypeInfo,
+	Clone,
+	Copy,
+	PartialEq,
+	Eq,
+	Encode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	Decode,
+	sp_runtime::RuntimeDebug,
+	TypeInfo,
 )]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub enum VoteThreshold {
diff --git a/substrate/frame/election-provider-multi-block/src/lib.rs b/substrate/frame/election-provider-multi-block/src/lib.rs
index ea30fb239aee3ac986858e1bc1392fa947d75347..86a94c67c5844b30aa84ade16e328e3712ae68c7 100644
--- a/substrate/frame/election-provider-multi-block/src/lib.rs
+++ b/substrate/frame/election-provider-multi-block/src/lib.rs
@@ -324,7 +324,15 @@ impl<T: Config> From<verifier::FeasibilityError> for ElectionError<T> {
 
 /// Different operations that the [`Config::AdminOrigin`] can perform on the pallet.
 #[derive(
-	Encode, Decode, MaxEncodedLen, TypeInfo, DebugNoBound, CloneNoBound, PartialEqNoBound, EqNoBound,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	TypeInfo,
+	DebugNoBound,
+	CloneNoBound,
+	PartialEqNoBound,
+	EqNoBound,
 )]
 #[codec(mel_bound(T: Config))]
 #[scale_info(skip_type_params(T))]
diff --git a/substrate/frame/election-provider-multi-block/src/types.rs b/substrate/frame/election-provider-multi-block/src/types.rs
index 9657277a79e422aa61cf916addc9a90323baf3c0..f74c9aee05311b2b3ddc635b67ecccb46bc08766 100644
--- a/substrate/frame/election-provider-multi-block/src/types.rs
+++ b/substrate/frame/election-provider-multi-block/src/types.rs
@@ -22,7 +22,7 @@ use sp_core::Get;
 use sp_std::{collections::btree_set::BTreeSet, fmt::Debug, prelude::*};
 
 use crate::unsigned::miner::MinerConfig;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_election_provider_support::ElectionProvider;
 pub use frame_election_provider_support::{NposSolution, PageIndex};
 use scale_info::TypeInfo;
@@ -53,6 +53,7 @@ pub type AssignmentOf<T> =
 	TypeInfo,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	DebugNoBound,
 	CloneNoBound,
 	EqNoBound,
@@ -230,7 +231,18 @@ impl Default for ElectionCompute {
 }
 
 /// Current phase of the pallet.
-#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, MaxEncodedLen, Debug, TypeInfo)]
+#[derive(
+	PartialEq,
+	Eq,
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	Debug,
+	TypeInfo,
+)]
 pub enum Phase<Bn> {
 	/// Nothing is happening, and nothing will happen.
 	Halted,
diff --git a/substrate/frame/election-provider-multi-block/src/verifier/mod.rs b/substrate/frame/election-provider-multi-block/src/verifier/mod.rs
index 98391daa546c49f39cf9f4691c0be0e33f8861b0..a5f7c4aa5c3daca47fb276afd2538abcc61148e3 100644
--- a/substrate/frame/election-provider-multi-block/src/verifier/mod.rs
+++ b/substrate/frame/election-provider-multi-block/src/verifier/mod.rs
@@ -78,7 +78,16 @@ use sp_std::{fmt::Debug, prelude::*};
 pub use crate::weights::measured::pallet_election_provider_multi_block_verifier::*;
 
 /// Errors that can happen in the feasibility check.
-#[derive(Debug, Eq, PartialEq, codec::Encode, codec::Decode, scale_info::TypeInfo, Clone)]
+#[derive(
+	Debug,
+	Eq,
+	PartialEq,
+	codec::Encode,
+	codec::Decode,
+	codec::DecodeWithMemTracking,
+	scale_info::TypeInfo,
+	Clone,
+)]
 pub enum FeasibilityError {
 	/// Wrong number of winners presented.
 	WrongWinnerCount,
diff --git a/substrate/frame/election-provider-multi-phase/src/lib.rs b/substrate/frame/election-provider-multi-phase/src/lib.rs
index 3a5103d2bb8abe1a5253dd2f5e83ac850ed4b70a..c0e256c3e65253c34fa891b92586ec487b161fb1 100644
--- a/substrate/frame/election-provider-multi-phase/src/lib.rs
+++ b/substrate/frame/election-provider-multi-phase/src/lib.rs
@@ -244,7 +244,7 @@
 extern crate alloc;
 
 use alloc::{boxed::Box, vec::Vec};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use frame_election_provider_support::{
 	bounds::{CountBound, ElectionBounds, SizeBound},
 	BoundedSupports, BoundedSupportsOf, ElectionDataProvider, ElectionProvider,
@@ -336,7 +336,7 @@ pub trait BenchmarkingConfig {
 }
 
 /// Current phase of the pallet.
-#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo)]
+#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
 pub enum Phase<Bn> {
 	/// Nothing, the election is not happening.
 	Off,
@@ -398,7 +398,7 @@ impl<Bn: PartialEq + Eq> Phase<Bn> {
 }
 
 /// The type of `Computation` that provided this election data.
-#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo)]
+#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
 pub enum ElectionCompute {
 	/// Election was computed on-chain.
 	OnChain,
@@ -424,7 +424,18 @@ impl Default for ElectionCompute {
 ///
 /// Such a solution should never become effective in anyway before being checked by the
 /// `Pallet::feasibility_check`.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, PartialOrd, Ord, TypeInfo)]
+#[derive(
+	PartialEq,
+	Eq,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	PartialOrd,
+	Ord,
+	TypeInfo,
+)]
 pub struct RawSolution<S> {
 	/// the solution itself.
 	pub solution: S,
@@ -490,7 +501,9 @@ pub struct RoundSnapshot<AccountId, DataProvider> {
 /// This is stored automatically on-chain, and it contains the **size of the entire snapshot**.
 /// This is also used in dispatchables as weight witness data and should **only contain the size of
 /// the presented solution**, not the entire snapshot.
-#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug, Default, TypeInfo)]
+#[derive(
+	PartialEq, Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, Default, TypeInfo,
+)]
 pub struct SolutionOrSnapshotSize {
 	/// The length of voters.
 	#[codec(compact)]
diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs
index fa64dd6f7d6ebd32998f93e95e2aba8b685fa916..c0e7efc6623795aba8f9fd8656c6e9e8e57adabe 100644
--- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs
+++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs
@@ -16,6 +16,9 @@
 // limitations under the License.
 
 #![cfg(test)]
+
+// We do not declare all features used by `construct_runtime`
+#[allow(unexpected_cfgs)]
 mod mock;
 
 pub(crate) const LOG_TARGET: &str = "tests::e2e-epm";
diff --git a/substrate/frame/election-provider-support/solution-type/src/single_page.rs b/substrate/frame/election-provider-support/solution-type/src/single_page.rs
index f57dcb9694a83c58eb25a930315df495f1e67209..c921be34b34304b9e65683b7d2f67bbcb6e7b15c 100644
--- a/substrate/frame/election-provider-support/solution-type/src/single_page.rs
+++ b/substrate/frame/election-provider-support/solution-type/src/single_page.rs
@@ -74,7 +74,7 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result<TokenStream2> {
 		);
 		quote! {
 			#compact_impl
-			#[derive(Default, PartialEq, Eq, Clone, Debug, PartialOrd, Ord)]
+			#[derive(Default, PartialEq, Eq, Clone, Debug, PartialOrd, Ord, _fepsp::codec::DecodeWithMemTracking)]
 		}
 	} else {
 		// automatically derived.
@@ -88,6 +88,7 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result<TokenStream2> {
 			PartialOrd,
 			_fepsp::codec::Encode,
 			_fepsp::codec::Decode,
+			_fepsp::codec::DecodeWithMemTracking,
 			_fepsp::scale_info::TypeInfo,
 		)])
 	};
diff --git a/substrate/frame/election-provider-support/src/lib.rs b/substrate/frame/election-provider-support/src/lib.rs
index 68aee2c82e62b4e9c3c9ccb16a4a2dbcf4e85d75..27f8d96e5e791155ed5fee004afde17f325aebd3 100644
--- a/substrate/frame/election-provider-support/src/lib.rs
+++ b/substrate/frame/election-provider-support/src/lib.rs
@@ -209,7 +209,7 @@ use sp_runtime::{
 };
 
 pub use bounds::DataProviderBounds;
-pub use codec::{Decode, Encode, MaxEncodedLen};
+pub use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 /// Re-export the solution generation macro.
 pub use frame_election_provider_solution_type::generate_solution_type;
 pub use frame_support::{traits::Get, weights::Weight, BoundedVec, DefaultNoBound};
@@ -830,7 +830,9 @@ pub type VoterOf<D> =
 	Voter<<D as ElectionDataProvider>::AccountId, <D as ElectionDataProvider>::MaxVotesPerVoter>;
 
 /// A bounded vector of supports. Bounded equivalent to [`sp_npos_elections::Supports`].
-#[derive(Default, Debug, Encode, Decode, scale_info::TypeInfo, MaxEncodedLen)]
+#[derive(
+	Default, Debug, Encode, Decode, DecodeWithMemTracking, scale_info::TypeInfo, MaxEncodedLen,
+)]
 #[codec(mel_bound(AccountId: MaxEncodedLen, Bound: Get<u32>))]
 #[scale_info(skip_type_params(Bound))]
 pub struct BoundedSupport<AccountId, Bound: Get<u32>> {
@@ -906,7 +908,7 @@ impl<AccountId: Clone, Bound: Get<u32>> BoundedSupport<AccountId, Bound> {
 /// corresponds to the bound of the maximum winners that the bounded supports may contain.
 ///
 /// With the bounds, we control the maximum size of a bounded supports instance.
-#[derive(Encode, Decode, TypeInfo, DefaultNoBound, MaxEncodedLen)]
+#[derive(Encode, Decode, DecodeWithMemTracking, TypeInfo, DefaultNoBound, MaxEncodedLen)]
 #[codec(mel_bound(AccountId: MaxEncodedLen, BOuter: Get<u32>, BInner: Get<u32>))]
 #[scale_info(skip_type_params(BOuter, BInner))]
 pub struct BoundedSupports<AccountId, BOuter: Get<u32>, BInner: Get<u32>>(
diff --git a/substrate/frame/elections-phragmen/src/lib.rs b/substrate/frame/elections-phragmen/src/lib.rs
index 4a40d44e407761d08b4e9c2741ced71153a80555..d73cd510f820de2cc3b96266b4f05f8358bb572a 100644
--- a/substrate/frame/elections-phragmen/src/lib.rs
+++ b/substrate/frame/elections-phragmen/src/lib.rs
@@ -101,7 +101,7 @@
 extern crate alloc;
 
 use alloc::{vec, vec::Vec};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use core::cmp::Ordering;
 use frame_support::{
 	traits::{
@@ -139,7 +139,7 @@ type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<
 >>::NegativeImbalance;
 
 /// An indication that the renouncing account currently has which of the below roles.
-#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, RuntimeDebug, TypeInfo)]
 pub enum Renouncing {
 	/// A member is renouncing.
 	Member,
diff --git a/substrate/frame/examples/authorization-tx-extension/src/lib.rs b/substrate/frame/examples/authorization-tx-extension/src/lib.rs
index 4eaf94a5c734fd9656dea657c44385a5143e2b27..8b878fcbf3c60b69213ce42efa04b8a3b06578ef 100644
--- a/substrate/frame/examples/authorization-tx-extension/src/lib.rs
+++ b/substrate/frame/examples/authorization-tx-extension/src/lib.rs
@@ -97,7 +97,17 @@ pub mod pallet_coownership {
 	/// Origin that this pallet can authorize. For the purposes of this example, it's just two
 	/// accounts that own something together.
 	#[pallet::origin]
-	#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
+	#[derive(
+		Clone,
+		PartialEq,
+		Eq,
+		RuntimeDebug,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		MaxEncodedLen,
+		TypeInfo,
+	)]
 	pub enum Origin<T: Config> {
 		Coowners(T::AccountId, T::AccountId),
 	}
diff --git a/substrate/frame/examples/offchain-worker/src/lib.rs b/substrate/frame/examples/offchain-worker/src/lib.rs
index 60322b569dfa5a5a72cef8bc3872747110d3d2fe..9976a5256afa9c544ab691110278df8379c24437 100644
--- a/substrate/frame/examples/offchain-worker/src/lib.rs
+++ b/substrate/frame/examples/offchain-worker/src/lib.rs
@@ -54,7 +54,7 @@
 extern crate alloc;
 
 use alloc::vec::Vec;
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use frame_support::traits::Get;
 use frame_system::{
 	self as system,
@@ -355,7 +355,9 @@ pub mod pallet {
 
 /// Payload used by this example crate to hold price
 /// data required to submit a transaction.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, scale_info::TypeInfo)]
+#[derive(
+	Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, RuntimeDebug, scale_info::TypeInfo,
+)]
 pub struct PricePayload<Public, BlockNumber> {
 	block_number: BlockNumber,
 	price: u32,
diff --git a/substrate/frame/identity/src/legacy.rs b/substrate/frame/identity/src/legacy.rs
index de5b9f79b559b0de80894f8574854644c7dc239c..a5ef069f9268c4bf31a58caf1422addc4bc63b3a 100644
--- a/substrate/frame/identity/src/legacy.rs
+++ b/substrate/frame/identity/src/legacy.rs
@@ -17,7 +17,7 @@
 
 #[cfg(feature = "runtime-benchmarks")]
 use alloc::vec;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 #[cfg(feature = "runtime-benchmarks")]
 use enumflags2::BitFlag;
 use enumflags2::{bitflags, BitFlags};
@@ -69,6 +69,7 @@ impl TypeInfo for IdentityField {
 	CloneNoBound,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	EqNoBound,
 	MaxEncodedLen,
 	PartialEqNoBound,
diff --git a/substrate/frame/identity/src/types.rs b/substrate/frame/identity/src/types.rs
index ece3c34f82efc78a86534a901374fab851d20105..85f2f8f8597bc4faac25497969a0bf2018d1cd1b 100644
--- a/substrate/frame/identity/src/types.rs
+++ b/substrate/frame/identity/src/types.rs
@@ -17,7 +17,7 @@
 
 use super::*;
 use alloc::{vec, vec::Vec};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::{fmt::Debug, iter::once, ops::Add};
 use frame_support::{
 	traits::{ConstU32, Get},
@@ -39,7 +39,7 @@ pub type RegistrarIndex = u32;
 /// than 32-bytes then it will be truncated when encoding.
 ///
 /// Can also be `None`.
-#[derive(Clone, Eq, PartialEq, RuntimeDebug, MaxEncodedLen)]
+#[derive(Clone, DecodeWithMemTracking, Eq, PartialEq, RuntimeDebug, MaxEncodedLen)]
 pub enum Data {
 	/// No data here.
 	None,
@@ -190,7 +190,18 @@ impl Default for Data {
 ///
 /// NOTE: Registrars may pay little attention to some fields. Registrars may want to make clear
 /// which fields their attestation is relevant for by off-chain means.
-#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
+#[derive(
+	Copy,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	MaxEncodedLen,
+	TypeInfo,
+)]
 pub enum Judgement<Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq>
 {
 	/// The default value; no opinion is held.
diff --git a/substrate/frame/im-online/src/lib.rs b/substrate/frame/im-online/src/lib.rs
index 74d3bc6484dd47217be4bdc31d2a68f97e687a8e..28d97489d98148193280b8704c78c5ed15355441 100644
--- a/substrate/frame/im-online/src/lib.rs
+++ b/substrate/frame/im-online/src/lib.rs
@@ -85,7 +85,7 @@ pub mod weights;
 extern crate alloc;
 
 use alloc::{vec, vec::Vec};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_support::{
 	pallet_prelude::*,
 	traits::{
@@ -218,7 +218,7 @@ impl<BlockNumber: core::fmt::Debug> core::fmt::Debug for OffchainErr<BlockNumber
 pub type AuthIndex = u32;
 
 /// Heartbeat which is sent/received.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub struct Heartbeat<BlockNumber>
 where
 	BlockNumber: PartialEq + Eq + Decode + Encode,
diff --git a/substrate/frame/indices/src/benchmarking.rs b/substrate/frame/indices/src/benchmarking.rs
index 28f5e3bf5cf08be62e76ba8ccf1206ff22d20783..9e81915df153b5c14bcccb0556f61afffd2e5da3 100644
--- a/substrate/frame/indices/src/benchmarking.rs
+++ b/substrate/frame/indices/src/benchmarking.rs
@@ -21,6 +21,7 @@
 
 use crate::*;
 use frame_benchmarking::v2::*;
+use frame_support::traits::Get;
 use frame_system::RawOrigin;
 use sp_runtime::traits::Bounded;
 
@@ -112,6 +113,59 @@ mod benchmarks {
 		Ok(())
 	}
 
+	#[benchmark]
+	fn poke_deposit() -> Result<(), BenchmarkError> {
+		let account_index = T::AccountIndex::from(SEED);
+		// Setup accounts
+		let caller: T::AccountId = whitelisted_caller();
+		T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
+
+		let original_deposit = T::Deposit::get();
+
+		// Claim the index
+		Pallet::<T>::claim(RawOrigin::Signed(caller.clone()).into(), account_index)?;
+
+		// Verify the initial deposit amount in storage and reserved balance
+		assert_eq!(Accounts::<T>::get(account_index).unwrap().1, original_deposit);
+		assert_eq!(T::Currency::reserved_balance(&caller), original_deposit);
+
+		// The additional amount we'll add to the deposit for the index
+		let additional_amount = 2u32.into();
+
+		// Reserve the additional amount from the caller's balance
+		T::Currency::reserve(&caller, additional_amount)?;
+
+		// Verify the additional amount was reserved
+		assert_eq!(
+			T::Currency::reserved_balance(&caller),
+			original_deposit.saturating_add(additional_amount)
+		);
+
+		// Increase the deposited amount in storage by additional_amount
+		Accounts::<T>::try_mutate(account_index, |maybe_value| -> Result<(), BenchmarkError> {
+			let (account, amount, perm) = maybe_value
+				.take()
+				.ok_or(BenchmarkError::Stop("Mutating storage to change deposits failed"))?;
+			*maybe_value = Some((account, amount.saturating_add(additional_amount), perm));
+			Ok(())
+		})?;
+
+		// Verify the deposit was increased by additional_amount
+		assert_eq!(
+			Accounts::<T>::get(account_index).unwrap().1,
+			original_deposit.saturating_add(additional_amount)
+		);
+
+		#[extrinsic_call]
+		_(RawOrigin::Signed(caller.clone()), account_index);
+
+		assert!(Accounts::<T>::contains_key(account_index));
+		assert_eq!(Accounts::<T>::get(account_index).unwrap().0, caller);
+		assert_eq!(Accounts::<T>::get(account_index).unwrap().1, original_deposit);
+		assert_eq!(T::Currency::reserved_balance(&caller), original_deposit);
+		Ok(())
+	}
+
 	// TODO in another PR: lookup and unlookup trait weights (not critical)
 
 	impl_benchmark_test_suite!(Pallet, mock::new_test_ext(), mock::Test);
diff --git a/substrate/frame/indices/src/lib.rs b/substrate/frame/indices/src/lib.rs
index 740d69365df3e4a4539dd6fed3d18aadc0b7bddc..1629a730176f7e8b367042e591999c53abcc1c2d 100644
--- a/substrate/frame/indices/src/lib.rs
+++ b/substrate/frame/indices/src/lib.rs
@@ -232,6 +232,64 @@ pub mod pallet {
 			Self::deposit_event(Event::IndexFrozen { index, who });
 			Ok(())
 		}
+
+		/// Poke the deposit reserved for an index.
+		///
+		/// The dispatch origin for this call must be _Signed_ and the signing account must have a
+		/// non-frozen account `index`.
+		///
+		/// The transaction fees is waived if the deposit is changed after poking/reconsideration.
+		///
+		/// - `index`: the index whose deposit is to be poked/reconsidered.
+		///
+		/// Emits `DepositPoked` if successful.
+		#[pallet::call_index(5)]
+		#[pallet::weight(T::WeightInfo::poke_deposit())]
+		pub fn poke_deposit(
+			origin: OriginFor<T>,
+			index: T::AccountIndex,
+		) -> DispatchResultWithPostInfo {
+			let who = ensure_signed(origin)?;
+
+			Accounts::<T>::try_mutate(index, |maybe_value| -> DispatchResultWithPostInfo {
+				let (account, old_amount, perm) =
+					maybe_value.take().ok_or(Error::<T>::NotAssigned)?;
+				ensure!(!perm, Error::<T>::Permanent);
+				ensure!(account == who, Error::<T>::NotOwner);
+
+				let new_amount = T::Deposit::get();
+
+				if old_amount == new_amount {
+					*maybe_value = Some((account, old_amount, perm));
+					return Ok(Pays::Yes.into());
+				} else if new_amount > old_amount {
+					// Need to reserve more
+					let extra = new_amount.saturating_sub(old_amount);
+					T::Currency::reserve(&who, extra)?;
+				} else if new_amount < old_amount {
+					// Need to unreserve some
+					let excess = old_amount.saturating_sub(new_amount);
+					let remaining_unreserved = T::Currency::unreserve(&who, excess);
+					// Defensive logging if we can't unreserve the full amount.
+					if !remaining_unreserved.is_zero() {
+						defensive!(
+							"Failed to unreserve full amount. (Index, Requested, Actual): ",
+							(index, excess, excess - remaining_unreserved)
+						);
+					}
+				}
+
+				*maybe_value = Some((account, new_amount, perm));
+
+				Self::deposit_event(Event::DepositPoked {
+					who,
+					index,
+					old_deposit: old_amount,
+					new_deposit: new_amount,
+				});
+				Ok(Pays::No.into())
+			})
+		}
 	}
 
 	#[pallet::event]
@@ -243,6 +301,13 @@ pub mod pallet {
 		IndexFreed { index: T::AccountIndex },
 		/// A account index has been frozen to its current account ID.
 		IndexFrozen { index: T::AccountIndex, who: T::AccountId },
+		/// A deposit to reserve an index has been poked/reconsidered.
+		DepositPoked {
+			who: T::AccountId,
+			index: T::AccountIndex,
+			old_deposit: BalanceOf<T>,
+			new_deposit: BalanceOf<T>,
+		},
 	}
 
 	#[pallet::error]
diff --git a/substrate/frame/indices/src/mock.rs b/substrate/frame/indices/src/mock.rs
index 80d0a88881f97cf284959b54b4b47adc05e38d56..41cd0603c4af84d989dfe891a340e48980105d85 100644
--- a/substrate/frame/indices/src/mock.rs
+++ b/substrate/frame/indices/src/mock.rs
@@ -20,11 +20,15 @@
 #![cfg(test)]
 
 use crate::{self as pallet_indices, Config};
-use frame_support::{derive_impl, traits::ConstU64};
+use frame_support::{derive_impl, parameter_types};
 use sp_runtime::BuildStorage;
 
 type Block = frame_system::mocking::MockBlock<Test>;
 
+parameter_types! {
+	pub static IndexDeposit: u64 = 1;
+}
+
 frame_support::construct_runtime!(
 	pub enum Test
 	{
@@ -50,7 +54,7 @@ impl pallet_balances::Config for Test {
 impl Config for Test {
 	type AccountIndex = u64;
 	type Currency = Balances;
-	type Deposit = ConstU64<1>;
+	type Deposit = IndexDeposit;
 	type RuntimeEvent = RuntimeEvent;
 	type WeightInfo = ();
 }
@@ -63,5 +67,8 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
 	}
 	.assimilate_storage(&mut t)
 	.unwrap();
-	t.into()
+	let mut ext: sp_io::TestExternalities = t.into();
+	// Initialize the block number to 1 for event registration
+	ext.execute_with(|| System::set_block_number(1));
+	ext
 }
diff --git a/substrate/frame/indices/src/tests.rs b/substrate/frame/indices/src/tests.rs
index 56b1019000389e18834e11bdf5b43d1fef5adbd0..5792737f275362af9306246b73cf2a03085a849d 100644
--- a/substrate/frame/indices/src/tests.rs
+++ b/substrate/frame/indices/src/tests.rs
@@ -20,7 +20,7 @@
 #![cfg(test)]
 
 use super::{mock::*, *};
-use frame_support::{assert_noop, assert_ok};
+use frame_support::{assert_noop, assert_ok, pallet_prelude::Pays};
 use pallet_balances::Error as BalancesError;
 use sp_runtime::MultiAddress::Id;
 
@@ -119,3 +119,119 @@ fn force_transfer_index_on_free_should_work() {
 		assert_eq!(Indices::lookup_index(0), Some(3));
 	});
 }
+
+#[test]
+fn poke_deposit_should_fail_for_unassigned_index() {
+	new_test_ext().execute_with(|| {
+		assert_noop!(Indices::poke_deposit(Some(1).into(), 0), Error::<Test>::NotAssigned);
+	});
+}
+
+#[test]
+fn poke_deposit_should_fail_for_wrong_owner() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Indices::claim(Some(1).into(), 0));
+		assert_noop!(Indices::poke_deposit(Some(2).into(), 0), Error::<Test>::NotOwner);
+	});
+}
+
+#[test]
+fn poke_deposit_should_fail_for_permanent_index() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Indices::claim(Some(1).into(), 0));
+		assert_ok!(Indices::freeze(Some(1).into(), 0));
+		assert_noop!(Indices::poke_deposit(Some(1).into(), 0), Error::<Test>::Permanent);
+	});
+}
+
+#[test]
+fn poke_deposit_should_fail_for_insufficient_balance() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Indices::claim(Some(1).into(), 0));
+
+		// Set deposit higher than available balance
+		IndexDeposit::set(1000);
+
+		assert_noop!(
+			Indices::poke_deposit(Some(1).into(), 0),
+			BalancesError::<Test, _>::InsufficientBalance
+		);
+	});
+}
+
+#[test]
+fn poke_deposit_should_work_when_deposit_increases() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Indices::claim(Some(1).into(), 0));
+		assert_eq!(Balances::reserved_balance(1), 1);
+
+		// Change deposit to 3
+		IndexDeposit::set(3);
+
+		// poke_deposit should work and be free
+		let initial_balance = Balances::free_balance(1);
+		let result = Indices::poke_deposit(Some(1).into(), 0);
+		assert_ok!(result.as_ref());
+		let post_info = result.unwrap();
+		assert_eq!(post_info.pays_fee, Pays::No);
+		assert_eq!(Balances::reserved_balance(1), 3);
+
+		// Balance should only reduce by the deposit difference
+		assert_eq!(Balances::free_balance(1), initial_balance - 2);
+
+		System::assert_has_event(
+			Event::DepositPoked { who: 1, index: 0, old_deposit: 1, new_deposit: 3 }.into(),
+		);
+	});
+}
+
+#[test]
+fn poke_deposit_should_work_when_deposit_decreases() {
+	new_test_ext().execute_with(|| {
+		// Set initial deposit to 3
+		IndexDeposit::set(3);
+		assert_ok!(Indices::claim(Some(1).into(), 0));
+		assert_eq!(Balances::reserved_balance(1), 3);
+
+		// Change deposit to 1
+		IndexDeposit::set(1);
+
+		let initial_balance = Balances::free_balance(1);
+		let result = Indices::poke_deposit(Some(1).into(), 0);
+		assert_ok!(result.as_ref());
+		let post_info = result.unwrap();
+		assert_eq!(post_info.pays_fee, Pays::No);
+		assert_eq!(Balances::reserved_balance(1), 1);
+
+		// Balance should increase by the unreserved amount
+		assert_eq!(Balances::free_balance(1), initial_balance + 2);
+
+		System::assert_has_event(
+			Event::DepositPoked { who: 1, index: 0, old_deposit: 3, new_deposit: 1 }.into(),
+		);
+	});
+}
+
+#[test]
+fn poke_deposit_should_charge_fee_when_deposit_unchanged() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Indices::claim(Some(1).into(), 0));
+		assert_eq!(Balances::reserved_balance(1), 1);
+
+		// poke_deposit with same deposit amount
+		let result = Indices::poke_deposit(Some(1).into(), 0);
+		assert_ok!(result.as_ref());
+		// Verify fee payment
+		let post_info = result.unwrap();
+		assert_eq!(post_info.pays_fee, Pays::Yes);
+
+		// Reserved balance should remain the same
+		assert_eq!(Balances::reserved_balance(1), 1);
+
+		// Verify no DepositPoked event was emitted
+		assert!(!System::events().iter().any(|record| matches!(
+			record.event,
+			RuntimeEvent::Indices(Event::DepositPoked { .. })
+		)));
+	});
+}
diff --git a/substrate/frame/indices/src/weights.rs b/substrate/frame/indices/src/weights.rs
index 567e9bab54bdf9c7a5102ab71f3cdb1b9d658b53..f868e3f9c627b33cac79344a8f7be1070c1398da 100644
--- a/substrate/frame/indices/src/weights.rs
+++ b/substrate/frame/indices/src/weights.rs
@@ -15,36 +15,57 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 //! Autogenerated weights for `pallet_indices`
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
-//! DATE: 2024-11-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2025-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! WORST CASE MAP SIZE: `1000000`
-//! HOSTNAME: `runner-wiukf8gn-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
-//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024`
+//! HOSTNAME: `52baa5cae416`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
+//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024`
 
 // Executed Command:
-// ./target/production/substrate-node
+// frame-omni-bencher
+// v1
 // benchmark
 // pallet
-// --chain=dev
+// --extrinsic=*
+// --runtime=target/production/wbuild/kitchensink-runtime/kitchensink_runtime.wasm
+// --pallet=pallet_indices
+// --header=/__w/polkadot-sdk/polkadot-sdk/substrate/HEADER-APACHE2
+// --output=/__w/polkadot-sdk/polkadot-sdk/substrate/frame/indices/src/weights.rs
+// --wasm-execution=compiled
 // --steps=50
 // --repeat=20
-// --pallet=pallet_indices
+// --heap-pages=4096
+// --template=substrate/.maintain/frame-weight-template.hbs
 // --no-storage-info
-// --no-median-slopes
 // --no-min-squares
-// --extrinsic=*
-// --wasm-execution=compiled
-// --heap-pages=4096
-// --output=./substrate/frame/indices/src/weights.rs
-// --header=./substrate/HEADER-APACHE2
-// --template=./substrate/.maintain/frame-weight-template.hbs
+// --no-median-slopes
+// --genesis-builder-policy=none
+// --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic,pallet_nomination_pools,pallet_remark,pallet_transaction_storage,pallet_election_provider_multi_block,pallet_election_provider_multi_block::signed,pallet_election_provider_multi_block::unsigned,pallet_election_provider_multi_block::verifier
 
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
 #![allow(unused_imports)]
 #![allow(missing_docs)]
+#![allow(dead_code)]
 
 use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
 use core::marker::PhantomData;
@@ -56,6 +77,7 @@ pub trait WeightInfo {
 	fn free() -> Weight;
 	fn force_transfer() -> Weight;
 	fn freeze() -> Weight;
+	fn poke_deposit() -> Weight;
 }
 
 /// Weights for `pallet_indices` using the Substrate node and recommended hardware.
@@ -65,10 +87,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
 	fn claim() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `76`
+		//  Measured:  `0`
 		//  Estimated: `3534`
-		// Minimum execution time: 23_283_000 picoseconds.
-		Weight::from_parts(24_326_000, 3534)
+		// Minimum execution time: 19_421_000 picoseconds.
+		Weight::from_parts(19_829_000, 3534)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -78,10 +100,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn transfer() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `312`
+		//  Measured:  `178`
 		//  Estimated: `3593`
-		// Minimum execution time: 40_906_000 picoseconds.
-		Weight::from_parts(42_117_000, 3593)
+		// Minimum execution time: 33_020_000 picoseconds.
+		Weight::from_parts(33_682_000, 3593)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 	}
@@ -89,10 +111,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
 	fn free() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `172`
+		//  Measured:  `75`
 		//  Estimated: `3534`
-		// Minimum execution time: 27_419_000 picoseconds.
-		Weight::from_parts(28_544_000, 3534)
+		// Minimum execution time: 20_137_000 picoseconds.
+		Weight::from_parts(20_374_000, 3534)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -102,10 +124,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn force_transfer() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `275`
+		//  Measured:  `177`
 		//  Estimated: `3593`
-		// Minimum execution time: 30_098_000 picoseconds.
-		Weight::from_parts(31_368_000, 3593)
+		// Minimum execution time: 23_914_000 picoseconds.
+		Weight::from_parts(24_248_000, 3593)
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 			.saturating_add(T::DbWeight::get().writes(2_u64))
 	}
@@ -113,10 +135,21 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
 	fn freeze() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `172`
+		//  Measured:  `75`
+		//  Estimated: `3534`
+		// Minimum execution time: 23_055_000 picoseconds.
+		Weight::from_parts(23_461_000, 3534)
+			.saturating_add(T::DbWeight::get().reads(1_u64))
+			.saturating_add(T::DbWeight::get().writes(1_u64))
+	}
+	/// Storage: `Indices::Accounts` (r:1 w:1)
+	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
+	fn poke_deposit() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `75`
 		//  Estimated: `3534`
-		// Minimum execution time: 30_356_000 picoseconds.
-		Weight::from_parts(31_036_000, 3534)
+		// Minimum execution time: 20_179_000 picoseconds.
+		Weight::from_parts(20_464_000, 3534)
 			.saturating_add(T::DbWeight::get().reads(1_u64))
 			.saturating_add(T::DbWeight::get().writes(1_u64))
 	}
@@ -128,10 +161,10 @@ impl WeightInfo for () {
 	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
 	fn claim() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `76`
+		//  Measured:  `0`
 		//  Estimated: `3534`
-		// Minimum execution time: 23_283_000 picoseconds.
-		Weight::from_parts(24_326_000, 3534)
+		// Minimum execution time: 19_421_000 picoseconds.
+		Weight::from_parts(19_829_000, 3534)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -141,10 +174,10 @@ impl WeightInfo for () {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn transfer() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `312`
+		//  Measured:  `178`
 		//  Estimated: `3593`
-		// Minimum execution time: 40_906_000 picoseconds.
-		Weight::from_parts(42_117_000, 3593)
+		// Minimum execution time: 33_020_000 picoseconds.
+		Weight::from_parts(33_682_000, 3593)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
@@ -152,10 +185,10 @@ impl WeightInfo for () {
 	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
 	fn free() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `172`
+		//  Measured:  `75`
 		//  Estimated: `3534`
-		// Minimum execution time: 27_419_000 picoseconds.
-		Weight::from_parts(28_544_000, 3534)
+		// Minimum execution time: 20_137_000 picoseconds.
+		Weight::from_parts(20_374_000, 3534)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
@@ -165,10 +198,10 @@ impl WeightInfo for () {
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
 	fn force_transfer() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `275`
+		//  Measured:  `177`
 		//  Estimated: `3593`
-		// Minimum execution time: 30_098_000 picoseconds.
-		Weight::from_parts(31_368_000, 3593)
+		// Minimum execution time: 23_914_000 picoseconds.
+		Weight::from_parts(24_248_000, 3593)
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
@@ -176,10 +209,21 @@ impl WeightInfo for () {
 	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
 	fn freeze() -> Weight {
 		// Proof Size summary in bytes:
-		//  Measured:  `172`
+		//  Measured:  `75`
+		//  Estimated: `3534`
+		// Minimum execution time: 23_055_000 picoseconds.
+		Weight::from_parts(23_461_000, 3534)
+			.saturating_add(RocksDbWeight::get().reads(1_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
+	/// Storage: `Indices::Accounts` (r:1 w:1)
+	/// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`)
+	fn poke_deposit() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `75`
 		//  Estimated: `3534`
-		// Minimum execution time: 30_356_000 picoseconds.
-		Weight::from_parts(31_036_000, 3534)
+		// Minimum execution time: 20_179_000 picoseconds.
+		Weight::from_parts(20_464_000, 3534)
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
diff --git a/substrate/frame/lottery/Cargo.toml b/substrate/frame/lottery/Cargo.toml
index 23eb19c7ffa7d29634a5748e22ed8d376be87e2a..f59bd8003e310552b69343401145da586fa9142d 100644
--- a/substrate/frame/lottery/Cargo.toml
+++ b/substrate/frame/lottery/Cargo.toml
@@ -46,6 +46,7 @@ std = [
 ]
 runtime-benchmarks = [
 	"frame-benchmarking/runtime-benchmarks",
+	"frame-support-test/runtime-benchmarks",
 	"frame-support/runtime-benchmarks",
 	"frame-system/runtime-benchmarks",
 	"pallet-balances/runtime-benchmarks",
diff --git a/substrate/frame/message-queue/src/lib.rs b/substrate/frame/message-queue/src/lib.rs
index 9cd3e42d70dd2af61ff2d7897be32f696c14a1c5..0e2a2f6b01b4a602e32f3fa62a61a3bec0701485 100644
--- a/substrate/frame/message-queue/src/lib.rs
+++ b/substrate/frame/message-queue/src/lib.rs
@@ -206,7 +206,7 @@ pub mod weights;
 extern crate alloc;
 
 use alloc::{vec, vec::Vec};
-use codec::{Codec, Decode, Encode, MaxEncodedLen};
+use codec::{Codec, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::{fmt::Debug, ops::Deref};
 use frame_support::{
 	defensive,
diff --git a/substrate/frame/message-queue/src/mock_helpers.rs b/substrate/frame/message-queue/src/mock_helpers.rs
index 873add776e2093977962a084e35b921a92ba7338..9730d0c6fd22e9525affd6401feada9b03d7c265 100644
--- a/substrate/frame/message-queue/src/mock_helpers.rs
+++ b/substrate/frame/message-queue/src/mock_helpers.rs
@@ -37,7 +37,18 @@ impl IntoWeight for u64 {
 }
 
 /// Mocked message origin for testing.
-#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, MaxEncodedLen, TypeInfo, Debug)]
+#[derive(
+	Copy,
+	Clone,
+	Eq,
+	PartialEq,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	TypeInfo,
+	Debug,
+)]
 pub enum MessageOrigin {
 	Here,
 	There,
diff --git a/substrate/frame/migrations/src/lib.rs b/substrate/frame/migrations/src/lib.rs
index fef61468e6e4ebe6c70626d13e23800f3e65f84e..5f321b6c8a1b961b9e86f27913701e9177f3e6a2 100644
--- a/substrate/frame/migrations/src/lib.rs
+++ b/substrate/frame/migrations/src/lib.rs
@@ -157,7 +157,7 @@ pub use pallet::*;
 pub use weights::WeightInfo;
 
 use alloc::vec::Vec;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::ops::ControlFlow;
 use frame_support::{
 	defensive, defensive_assert,
@@ -174,7 +174,17 @@ use frame_system::{
 use sp_runtime::Saturating;
 
 /// Points to the next migration to execute.
-#[derive(Debug, Clone, Eq, PartialEq, Encode, Decode, scale_info::TypeInfo, MaxEncodedLen)]
+#[derive(
+	Debug,
+	Clone,
+	Eq,
+	PartialEq,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	scale_info::TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum MigrationCursor<Cursor, BlockNumber> {
 	/// Points to the currently active migration and its inner cursor.
 	Active(ActiveCursor<Cursor, BlockNumber>),
@@ -202,7 +212,17 @@ impl<Cursor, BlockNumber> From<ActiveCursor<Cursor, BlockNumber>>
 }
 
 /// Points to the currently active migration and its inner cursor.
-#[derive(Debug, Clone, Eq, PartialEq, Encode, Decode, scale_info::TypeInfo, MaxEncodedLen)]
+#[derive(
+	Debug,
+	Clone,
+	Eq,
+	PartialEq,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	scale_info::TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct ActiveCursor<Cursor, BlockNumber> {
 	/// The index of the migration in the MBM tuple.
 	pub index: u32,
@@ -224,7 +244,9 @@ impl<Cursor, BlockNumber> ActiveCursor<Cursor, BlockNumber> {
 }
 
 /// How to clear the records of historic migrations.
-#[derive(Debug, Clone, Eq, PartialEq, Encode, Decode, scale_info::TypeInfo)]
+#[derive(
+	Debug, Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, scale_info::TypeInfo,
+)]
 pub enum HistoricCleanupSelector<Id> {
 	/// Clear exactly these entries.
 	///
@@ -762,7 +784,7 @@ impl<T: Config> Pallet<T> {
 				Self::deposit_event(Event::MigrationAdvanced { index: cursor.index, took });
 				cursor.inner_cursor = Some(bound_next_cursor);
 
-				if max_steps.map_or(false, |max| took > max.into()) {
+				if max_steps.is_some_and(|max| took > max.into()) {
 					Self::deposit_event(Event::MigrationFailed { index: cursor.index, took });
 					Self::upgrade_failed(Some(cursor.index));
 					None
diff --git a/substrate/frame/mixnet/src/lib.rs b/substrate/frame/mixnet/src/lib.rs
index 9849818176760cf9dfadb0a72d94b8c0206cc758..7e728b8fba3fd751b148383a88448c640d1c2675 100644
--- a/substrate/frame/mixnet/src/lib.rs
+++ b/substrate/frame/mixnet/src/lib.rs
@@ -52,7 +52,16 @@ pub type AuthorityIndex = u32;
 
 /// Like [`Mixnode`], but encoded size is bounded.
 #[derive(
-	Clone, Decode, Encode, MaxEncodedLen, PartialEq, TypeInfo, RuntimeDebug, Serialize, Deserialize,
+	Clone,
+	Decode,
+	DecodeWithMemTracking,
+	Encode,
+	MaxEncodedLen,
+	PartialEq,
+	TypeInfo,
+	RuntimeDebug,
+	Serialize,
+	Deserialize,
 )]
 pub struct BoundedMixnode<ExternalAddresses> {
 	/// Key-exchange public key for the mixnode.
@@ -121,7 +130,7 @@ pub type BoundedMixnodeFor<T> = BoundedMixnode<
 
 /// A mixnode registration. A registration transaction is formed from one of these plus an
 /// [`AuthoritySignature`].
-#[derive(Clone, Decode, Encode, PartialEq, TypeInfo, RuntimeDebug)]
+#[derive(Clone, Decode, DecodeWithMemTracking, Encode, PartialEq, TypeInfo, RuntimeDebug)]
 pub struct Registration<BlockNumber, BoundedMixnode> {
 	/// Block number at the time of creation. When a registration transaction fails to make it on
 	/// to the chain for whatever reason, we send out another one. We want this one to have a
diff --git a/substrate/frame/multisig/src/lib.rs b/substrate/frame/multisig/src/lib.rs
index 2da5ab9c337f0dd7ca75ff8635a1077ae745e852..6fdc52d6887d03895199fe1351066901e2d45e7e 100644
--- a/substrate/frame/multisig/src/lib.rs
+++ b/substrate/frame/multisig/src/lib.rs
@@ -84,7 +84,17 @@ pub type BlockNumberFor<T> =
 /// block's height. This allows a transaction in which a multisig operation of a particular
 /// composite was created to be uniquely identified.
 #[derive(
-	Copy, Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo, MaxEncodedLen,
+	Copy,
+	Clone,
+	Eq,
+	PartialEq,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Default,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
 )]
 pub struct Timepoint<BlockNumber> {
 	/// The height of the chain at the point in time.
diff --git a/substrate/frame/nfts/src/types.rs b/substrate/frame/nfts/src/types.rs
index 3ab85993473a2030ed0430ff569b5b5c5904e826..b263cc0b9f16b7196e2ecb2ab0cc22cb68be18e2 100644
--- a/substrate/frame/nfts/src/types.rs
+++ b/substrate/frame/nfts/src/types.rs
@@ -20,7 +20,7 @@
 use super::*;
 use crate::macros::*;
 use alloc::{vec, vec::Vec};
-use codec::EncodeLike;
+use codec::{DecodeWithMemTracking, EncodeLike};
 use enumflags2::{bitflags, BitFlags};
 use frame_support::{
 	pallet_prelude::{BoundedVec, MaxEncodedLen},
@@ -108,7 +108,18 @@ pub struct CollectionDetails<AccountId, DepositBalance> {
 }
 
 /// Witness data for the destroy transactions.
-#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Copy,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct DestroyWitness {
 	/// The total number of items in this collection that have outstanding item metadata.
 	#[codec(compact)]
@@ -132,7 +143,9 @@ impl<AccountId, DepositBalance> CollectionDetails<AccountId, DepositBalance> {
 }
 
 /// Witness data for items mint transactions.
-#[derive(Clone, Encode, Decode, Default, Eq, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(
+	Clone, Encode, Decode, DecodeWithMemTracking, Default, Eq, PartialEq, RuntimeDebug, TypeInfo,
+)]
 pub struct MintWitness<ItemId, Balance> {
 	/// Provide the id of the item in a required collection.
 	pub owned_item: Option<ItemId>,
@@ -191,7 +204,17 @@ pub struct ItemMetadata<Deposit, StringLimit: Get<u32>> {
 }
 
 /// Information about the tip.
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct ItemTip<CollectionId, ItemId, AccountId, Amount> {
 	/// The collection of the item.
 	pub collection: CollectionId,
@@ -235,7 +258,17 @@ pub struct ItemMetadataDeposit<DepositBalance, AccountId> {
 }
 
 /// Specifies whether the tokens will be sent or received.
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum PriceDirection {
 	/// Tokens will be sent.
 	Send,
@@ -244,7 +277,17 @@ pub enum PriceDirection {
 }
 
 /// Holds the details about the price.
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct PriceWithDirection<Amount> {
 	/// An amount.
 	pub amount: Amount,
@@ -289,11 +332,25 @@ impl CollectionSettings {
 }
 
 impl_codec_bitflags!(CollectionSettings, u64, CollectionSetting);
+// We can implement `DecodeWithMemTracking` for `CollectionSettings`
+// since `u64` also implements `DecodeWithMemTracking`.
+impl DecodeWithMemTracking for CollectionSettings {}
 
 /// Mint type. Can the NFT be create by anyone, or only the creator of the collection,
 /// or only by wallets that already hold an NFT from a certain collection?
 /// The ownership of a privately minted NFT is still publicly visible.
-#[derive(Clone, Copy, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum MintType<CollectionId> {
 	/// Only an `Issuer` could mint items.
 	Issuer,
@@ -304,7 +361,18 @@ pub enum MintType<CollectionId> {
 }
 
 /// Holds the information about minting.
-#[derive(Clone, Copy, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct MintSettings<Price, BlockNumber, CollectionId> {
 	/// Whether anyone can mint or if minters are restricted to some subset.
 	pub mint_type: MintType<CollectionId>,
@@ -332,7 +400,15 @@ impl<Price, BlockNumber, CollectionId> Default for MintSettings<Price, BlockNumb
 
 /// Attribute namespaces for non-fungible tokens.
 #[derive(
-	Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, scale_info::TypeInfo, MaxEncodedLen,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	scale_info::TypeInfo,
+	MaxEncodedLen,
 )]
 pub enum AttributeNamespace<AccountId> {
 	/// An attribute was set by the pallet.
@@ -346,14 +422,24 @@ pub enum AttributeNamespace<AccountId> {
 }
 
 /// A witness data to cancel attributes approval operation.
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
+#[derive(Clone, Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct CancelAttributesApprovalWitness {
 	/// An amount of attributes previously created by account.
 	pub account_attributes: u32,
 }
 
 /// A list of possible pallet-level attributes.
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum PalletAttributes<CollectionId> {
 	/// Marks an item as being used in order to claim another item.
 	UsedToClaim(CollectionId),
@@ -363,7 +449,16 @@ pub enum PalletAttributes<CollectionId> {
 
 /// Collection's configuration.
 #[derive(
-	Clone, Copy, Decode, Default, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo,
+	Clone,
+	Copy,
+	Decode,
+	DecodeWithMemTracking,
+	Default,
+	Encode,
+	MaxEncodedLen,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
 )]
 pub struct CollectionConfig<Price, BlockNumber, CollectionId> {
 	/// Collection's settings.
@@ -422,10 +517,22 @@ impl ItemSettings {
 }
 
 impl_codec_bitflags!(ItemSettings, u64, ItemSetting);
+// We can implement `DecodeWithMemTracking` for `ItemSettings`
+// since `u64` also implements `DecodeWithMemTracking`.
+impl DecodeWithMemTracking for ItemSettings {}
 
 /// Item's configuration.
 #[derive(
-	Encode, Decode, Default, PartialEq, RuntimeDebug, Clone, Copy, MaxEncodedLen, TypeInfo,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Default,
+	PartialEq,
+	RuntimeDebug,
+	Clone,
+	Copy,
+	MaxEncodedLen,
+	TypeInfo,
 )]
 pub struct ItemConfig {
 	/// Item's settings.
@@ -516,7 +623,7 @@ impl CollectionRoles {
 }
 impl_codec_bitflags!(CollectionRoles, u8, CollectionRole);
 
-#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
+#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, TypeInfo)]
 pub struct PreSignedMint<CollectionId, ItemId, AccountId, Deadline, Balance> {
 	/// A collection of the item to be minted.
 	pub collection: CollectionId,
@@ -534,7 +641,7 @@ pub struct PreSignedMint<CollectionId, ItemId, AccountId, Deadline, Balance> {
 	pub mint_price: Option<Balance>,
 }
 
-#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
+#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, TypeInfo)]
 pub struct PreSignedAttributes<CollectionId, ItemId, AccountId, Deadline> {
 	/// Collection's ID.
 	pub collection: CollectionId,
diff --git a/substrate/frame/node-authorization/src/lib.rs b/substrate/frame/node-authorization/src/lib.rs
index 3cec0d3bcb63d7ea6944e923a64163f3c1831ae0..4fbb9555deeb25eee6abe25b6f922ebc8e7064b4 100644
--- a/substrate/frame/node-authorization/src/lib.rs
+++ b/substrate/frame/node-authorization/src/lib.rs
@@ -38,6 +38,8 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 
 #[cfg(test)]
+// We do not declare all features used by `construct_runtime`
+#[allow(unexpected_cfgs)]
 mod mock;
 #[cfg(test)]
 mod tests;
diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs
index 86545cdee8583c2e29984c9df792bceafc9bce9c..39a7cf05b3abadff82aeb8ab8b34d9918eccbb23 100644
--- a/substrate/frame/nomination-pools/src/lib.rs
+++ b/substrate/frame/nomination-pools/src/lib.rs
@@ -355,7 +355,7 @@ extern crate alloc;
 
 use adapter::{Member, Pool, StakeStrategy};
 use alloc::{collections::btree_map::BTreeMap, vec::Vec};
-use codec::Codec;
+use codec::{Codec, DecodeWithMemTracking};
 use core::{fmt::Debug, ops::Div};
 use frame_support::{
 	defensive, defensive_assert, ensure,
@@ -422,7 +422,16 @@ pub type BlockNumberFor<T> =
 pub const POINTS_TO_BALANCE_INIT_RATIO: u32 = 1;
 
 /// Possible operations on the configuration values of this pallet.
-#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, RuntimeDebugNoBound, PartialEq, Clone)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	TypeInfo,
+	RuntimeDebugNoBound,
+	PartialEq,
+	Clone,
+)]
 pub enum ConfigOp<T: Codec + Debug> {
 	/// Don't change.
 	Noop,
@@ -441,7 +450,7 @@ pub enum BondType {
 }
 
 /// How to increase the bond of a member.
-#[derive(Encode, Decode, Clone, Copy, Debug, PartialEq, Eq, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, Copy, Debug, PartialEq, Eq, TypeInfo)]
 pub enum BondExtra<Balance> {
 	/// Take from the free balance.
 	FreeBalance(Balance),
@@ -457,7 +466,18 @@ enum AccountType {
 }
 
 /// The permission a pool member can set for other accounts to claim rewards on their behalf.
-#[derive(Encode, Decode, MaxEncodedLen, Clone, Copy, Debug, PartialEq, Eq, TypeInfo)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	Clone,
+	Copy,
+	Debug,
+	PartialEq,
+	Eq,
+	TypeInfo,
+)]
 pub enum ClaimPermission {
 	/// Only the pool member themselves can claim their rewards.
 	Permissioned,
@@ -671,7 +691,17 @@ impl<T: Config> PoolMember<T> {
 }
 
 /// A pool's possible states.
-#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, RuntimeDebugNoBound, Clone, Copy)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	TypeInfo,
+	PartialEq,
+	RuntimeDebugNoBound,
+	Clone,
+	Copy,
+)]
 pub enum PoolState {
 	/// The pool is open to be joined, and is working normally.
 	Open,
@@ -704,7 +734,18 @@ pub struct PoolRoles<AccountId> {
 }
 
 // A pool's possible commission claiming permissions.
-#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	PartialEq,
+	Eq,
+	Copy,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum CommissionClaimPermission<AccountId> {
 	Permissionless,
 	Account(AccountId),
@@ -918,7 +959,9 @@ impl<T: Config> Commission<T> {
 /// blocks that must elapse before commission updates are allowed again.
 ///
 /// Commission change rates are not applied to decreases in commission.
-#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Debug, PartialEq, Copy, Clone)]
+#[derive(
+	Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, TypeInfo, Debug, PartialEq, Copy, Clone,
+)]
 pub struct CommissionChangeRate<BlockNumber> {
 	/// The maximum amount the commission can be updated by per `min_delay` period.
 	pub max_increase: Perbill,
@@ -2008,7 +2051,9 @@ pub mod pallet {
 		NotSupported,
 	}
 
-	#[derive(Encode, Decode, PartialEq, TypeInfo, PalletError, RuntimeDebug)]
+	#[derive(
+		Encode, Decode, DecodeWithMemTracking, PartialEq, TypeInfo, PalletError, RuntimeDebug,
+	)]
 	pub enum DefensiveError {
 		/// There isn't enough space in the unbond pool.
 		NotEnoughSpaceInUnbondPool,
diff --git a/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs
index b43a41cd0f980dbe19916e104a8d3b51551e2154..cabffa45461dfd43a5c35e1780554a8bbb9c6543 100644
--- a/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs
+++ b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs
@@ -17,6 +17,8 @@
 
 #![cfg(test)]
 
+// We do not declare all features used by `construct_runtime`
+#[allow(unexpected_cfgs)]
 mod mock;
 
 use frame_support::{
diff --git a/substrate/frame/parameters/src/tests/mock.rs b/substrate/frame/parameters/src/tests/mock.rs
index 8d6f7d25ceac5e02ee4a067d77e4b8a5f88c1599..b7c391f383c223a935bbe95191cc2469f1ddede8 100644
--- a/substrate/frame/parameters/src/tests/mock.rs
+++ b/substrate/frame/parameters/src/tests/mock.rs
@@ -107,7 +107,7 @@ mod custom_origin {
 		) -> Result<Self::Success, RuntimeOrigin> {
 			// Account 123 is allowed to set parameters in benchmarking only:
 			#[cfg(feature = "runtime-benchmarks")]
-			if ensure_signed(origin.clone()).map_or(false, |acc| acc == 123) {
+			if ensure_signed(origin.clone()).is_ok_and(|acc| acc == 123) {
 				return Ok(());
 			}
 
diff --git a/substrate/frame/proxy/src/tests.rs b/substrate/frame/proxy/src/tests.rs
index 14389b03ac7e2593bcc37188d21a8a44974cac2f..b52dc5ce0e3989d00873d838e5f84cacc6cb2f30 100644
--- a/substrate/frame/proxy/src/tests.rs
+++ b/substrate/frame/proxy/src/tests.rs
@@ -64,6 +64,7 @@ impl pallet_utility::Config for Test {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	MaxEncodedLen,
 	scale_info::TypeInfo,
diff --git a/substrate/frame/ranked-collective/src/lib.rs b/substrate/frame/ranked-collective/src/lib.rs
index e34cf3d8df7114099ee02da5731012a81e38f1d7..4b1b3d9010db188348d30c4f8b2c07071544f867 100644
--- a/substrate/frame/ranked-collective/src/lib.rs
+++ b/substrate/frame/ranked-collective/src/lib.rs
@@ -42,7 +42,7 @@
 
 extern crate alloc;
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::marker::PhantomData;
 use scale_info::TypeInfo;
 use sp_arithmetic::traits::Saturating;
@@ -90,6 +90,7 @@ pub type Votes = u32;
 	TypeInfo,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	MaxEncodedLen,
 )]
 #[scale_info(skip_type_params(T, I, M))]
@@ -189,7 +190,18 @@ impl MemberRecord {
 }
 
 /// Record needed for every vote.
-#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	PartialEq,
+	Eq,
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum VoteRecord {
 	/// Vote was an aye with given vote weight.
 	Aye(Votes),
diff --git a/substrate/frame/referenda/src/mock.rs b/substrate/frame/referenda/src/mock.rs
index 5c9c12dee445cc0889a3a718ec7ac780c4250d89..52a89d3f7cb7d2e7f11d2578a13819aabb3e309b 100644
--- a/substrate/frame/referenda/src/mock.rs
+++ b/substrate/frame/referenda/src/mock.rs
@@ -20,7 +20,7 @@
 use super::*;
 use crate::{self as pallet_referenda, types::Track};
 use alloc::borrow::Cow;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use frame_support::{
 	assert_ok, derive_impl, ord_parameter_types, parameter_types,
 	traits::{
@@ -239,7 +239,9 @@ impl ExtBuilder {
 	}
 }
 
-#[derive(Encode, Debug, Decode, TypeInfo, Eq, PartialEq, Clone, MaxEncodedLen)]
+#[derive(
+	Encode, Debug, Decode, DecodeWithMemTracking, TypeInfo, Eq, PartialEq, Clone, MaxEncodedLen,
+)]
 pub struct Tally {
 	pub ayes: u32,
 	pub nays: u32,
diff --git a/substrate/frame/referenda/src/types.rs b/substrate/frame/referenda/src/types.rs
index 6a1eb8e82e4e3bf6d516c6c731fc30c4cc39db74..7bf290786cab833198bbcc2d73161e1f4aa2ede3 100644
--- a/substrate/frame/referenda/src/types.rs
+++ b/substrate/frame/referenda/src/types.rs
@@ -19,7 +19,7 @@
 
 use super::*;
 use alloc::borrow::Cow;
-use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, EncodeLike, MaxEncodedLen};
 use core::fmt::Debug;
 use frame_support::{
 	traits::{schedule::v3::Anon, Bounded},
@@ -119,7 +119,9 @@ pub struct Deposit<AccountId, Balance> {
 pub const DEFAULT_MAX_TRACK_NAME_LEN: usize = 25;
 
 /// Detailed information about the configuration of a referenda track
-#[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo, Eq, PartialEq, Debug)]
+#[derive(
+	Clone, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, TypeInfo, Eq, PartialEq, Debug,
+)]
 pub struct TrackInfo<Balance, Moment, const N: usize = DEFAULT_MAX_TRACK_NAME_LEN> {
 	/// Name of this track.
 	pub name: [u8; N],
@@ -145,7 +147,9 @@ pub struct TrackInfo<Balance, Moment, const N: usize = DEFAULT_MAX_TRACK_NAME_LE
 }
 
 /// Track groups the information of a voting track with its corresponding identifier
-#[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo, Eq, PartialEq, Debug)]
+#[derive(
+	Clone, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, TypeInfo, Eq, PartialEq, Debug,
+)]
 pub struct Track<Id, Balance, Moment, const N: usize = DEFAULT_MAX_TRACK_NAME_LEN> {
 	pub id: Id,
 	pub info: TrackInfo<Balance, Moment, N>,
@@ -324,7 +328,7 @@ impl<
 
 /// Type for describing a curve over the 2-dimensional space of axes between 0-1, as represented
 /// by `(Perbill, Perbill)`.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo, MaxEncodedLen)]
+#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, TypeInfo, MaxEncodedLen)]
 #[cfg_attr(not(feature = "std"), derive(RuntimeDebug))]
 pub enum Curve {
 	/// Linear curve starting at `(0, ceil)`, proceeding linearly to `(length, floor)`, then
diff --git a/substrate/frame/revive/README.md b/substrate/frame/revive/README.md
index 7538f77d10bc07cbed79dbc6eff82869f1a73673..77114ecd5d0224a06398c9cf8f3984f481ef13e4 100644
--- a/substrate/frame/revive/README.md
+++ b/substrate/frame/revive/README.md
@@ -41,7 +41,7 @@ to handle that failure, either proceeding or reverting A's changes.
 ### Dispatchable functions
 
 Those are documented in the [reference
-documentation](https://paritytech.github.io/substrate/master/pallet_revive/index.html#dispatchable-functions).
+documentation](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/pallet/dispatchables/index.html).
 
 ## Usage
 
diff --git a/substrate/frame/revive/fixtures/Cargo.toml b/substrate/frame/revive/fixtures/Cargo.toml
index eaa2deefdc7574791be952c4447e4763b7564d8a..ab5030b4a09b7e9ca31ca4a5897705a06b35362e 100644
--- a/substrate/frame/revive/fixtures/Cargo.toml
+++ b/substrate/frame/revive/fixtures/Cargo.toml
@@ -7,6 +7,7 @@ license.workspace = true
 description = "Fixtures for testing and benchmarking"
 homepage.workspace = true
 repository.workspace = true
+rust-version = "1.84"
 
 [package.metadata.polkadot-sdk]
 exclude-from-umbrella = true
diff --git a/substrate/frame/revive/fixtures/build.rs b/substrate/frame/revive/fixtures/build.rs
index fe420ba40da6318e722f608c409de34b414379de..38d3b6439ec0ec6d7f7b104e2938b91245337702 100644
--- a/substrate/frame/revive/fixtures/build.rs
+++ b/substrate/frame/revive/fixtures/build.rs
@@ -109,11 +109,6 @@ fn create_cargo_toml<'a>(
 	let cargo_toml = toml::to_string_pretty(&cargo_toml)?;
 	fs::write(output_dir.join("Cargo.toml"), cargo_toml.clone())
 		.with_context(|| format!("Failed to write {cargo_toml:?}"))?;
-	fs::copy(
-		fixtures_dir.join("build/_rust-toolchain.toml"),
-		output_dir.join("rust-toolchain.toml"),
-	)
-	.context("Failed to write toolchain file")?;
 	Ok(())
 }
 
diff --git a/substrate/frame/revive/fixtures/build/_rust-toolchain.toml b/substrate/frame/revive/fixtures/build/_rust-toolchain.toml
deleted file mode 100644
index 4c757c708d58bbd18c54f1be50210a34cb525022..0000000000000000000000000000000000000000
--- a/substrate/frame/revive/fixtures/build/_rust-toolchain.toml
+++ /dev/null
@@ -1,4 +0,0 @@
-[toolchain]
-channel = "nightly-2024-11-19"
-components = ["rust-src"]
-profile = "minimal"
diff --git a/substrate/frame/revive/rpc/revive_chain.metadata b/substrate/frame/revive/rpc/revive_chain.metadata
index 80f1000125a17482c2f3f052412b7ca805f928ed..0e053a0dbb4d3101e106f539631deb6ed2d0b712 100644
Binary files a/substrate/frame/revive/rpc/revive_chain.metadata and b/substrate/frame/revive/rpc/revive_chain.metadata differ
diff --git a/substrate/frame/revive/src/evm/api/debug_rpc_types.rs b/substrate/frame/revive/src/evm/api/debug_rpc_types.rs
index e9518f6b6400b5dd83e2f8c014b66f628bee40cb..13f91e3ed3e9b464d7deaae85fe1e39a4a66bad9 100644
--- a/substrate/frame/revive/src/evm/api/debug_rpc_types.rs
+++ b/substrate/frame/revive/src/evm/api/debug_rpc_types.rs
@@ -181,7 +181,8 @@ pub struct CallTrace<Gas = U256> {
 	#[serde(skip_serializing_if = "Vec::is_empty")]
 	pub logs: Vec<CallLog>,
 	/// Amount of value transferred.
-	pub value: U256,
+	#[serde(skip_serializing_if = "Option::is_none")]
+	pub value: Option<U256>,
 	/// Type of call.
 	#[serde(rename = "type")]
 	pub call_type: CallType,
diff --git a/substrate/frame/revive/src/evm/tracing.rs b/substrate/frame/revive/src/evm/tracing.rs
index 7eae64db79fb105583b810978357fb1c9e1ab307..0cdf2f05682b2a0919fcae7b3d83f42c7abf1798 100644
--- a/substrate/frame/revive/src/evm/tracing.rs
+++ b/substrate/frame/revive/src/evm/tracing.rs
@@ -70,7 +70,7 @@ impl<Gas: Default, GasMapper: Fn(Weight) -> Gas> Tracer for CallTracer<Gas, GasM
 		self.traces.push(CallTrace {
 			from,
 			to,
-			value,
+			value: if is_read_only { None } else { Some(value) },
 			call_type,
 			input: input.to_vec().into(),
 			gas: (self.gas_mapper)(gas_left),
diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs
index d7e16dea4564361b0dfa21ab1cea61ea08004e17..721254180bf5d69fcb0d941d7bcf6270eba29fc7 100644
--- a/substrate/frame/revive/src/exec.rs
+++ b/substrate/frame/revive/src/exec.rs
@@ -56,6 +56,9 @@ use sp_runtime::{
 	DispatchError, SaturatedConversion,
 };
 
+#[cfg(test)]
+mod tests;
+
 pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
 pub type MomentOf<T> = <<T as Config>::Time as Time>::Moment;
 pub type ExecResult = Result<ExecReturnValue, ExecError>;
@@ -1370,6 +1373,13 @@ where
 	}
 }
 
+/// Determine if the given address is a precompile.
+/// For now, we consider that all addresses between 0x1 and 0xff are reserved for precompiles.
+fn is_precompile(address: &H160) -> bool {
+	let bytes = address.as_bytes();
+	bytes.starts_with(&[0u8; 19]) && bytes[19] != 0
+}
+
 impl<'a, T, E> Ext for Stack<'a, T, E>
 where
 	T: Config,
@@ -1400,6 +1410,11 @@ where
 		*self.last_frame_output_mut() = Default::default();
 
 		let try_call = || {
+			if is_precompile(dest_addr) {
+				log::debug!(target: crate::LOG_TARGET, "Unsupported precompile address {dest_addr:?}");
+				return Err(Error::<T>::UnsupportedPrecompileAddress.into());
+			}
+
 			let dest = T::AddressMapper::to_account_id(dest_addr);
 			if !self.allows_reentry(&dest) {
 				return Err(<Error<T>>::ReentranceDenied.into());
@@ -1417,28 +1432,38 @@ where
 					CachedContract::Cached(contract) => Some(contract.clone()),
 					_ => None,
 				});
+
+			// Enable read-only access if requested; cannot disable it if already set.
+			let is_read_only = read_only || self.is_read_only();
+
 			if let Some(executable) = self.push_frame(
 				FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None },
 				value,
 				gas_limit,
 				deposit_limit.saturated_into::<BalanceOf<T>>(),
-				// Enable read-only access if requested; cannot disable it if already set.
-				read_only || self.is_read_only(),
+				is_read_only,
 			)? {
 				self.run(executable, input_data)
 			} else {
-				let result = Self::transfer_from_origin(
-					&self.origin,
-					&Origin::from_account_id(self.account_id().clone()),
-					&dest,
-					value,
-				);
+				let result = if is_read_only && value.is_zero() {
+					Ok(Default::default())
+				} else if is_read_only {
+					Err(Error::<T>::StateChangeDenied.into())
+				} else {
+					Self::transfer_from_origin(
+						&self.origin,
+						&Origin::from_account_id(self.account_id().clone()),
+						&dest,
+						value,
+					)
+				};
+
 				if_tracing(|t| {
 					t.enter_child_span(
 						T::AddressMapper::to_address(self.account_id()),
 						T::AddressMapper::to_address(&dest),
 						false,
-						false,
+						is_read_only,
 						value,
 						&input_data,
 						Weight::zero(),
@@ -1833,3004 +1858,3 @@ mod sealing {
 
 	impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
 }
-
-/// These tests exercise the executive layer.
-///
-/// In these tests the VM/loader are mocked. Instead of dealing with wasm bytecode they use simple
-/// closures. This allows you to tackle executive logic more thoroughly without writing a
-/// wasm VM code.
-#[cfg(test)]
-mod tests {
-	use super::*;
-	use crate::{
-		exec::ExportedFunction::*,
-		gas::GasMeter,
-		test_utils::*,
-		tests::{
-			test_utils::{get_balance, place_contract, set_balance},
-			ExtBuilder, RuntimeCall, RuntimeEvent as MetaEvent, Test, TestFilter,
-		},
-		AddressMapper, Error,
-	};
-	use assert_matches::assert_matches;
-	use frame_support::{assert_err, assert_noop, assert_ok, parameter_types};
-	use frame_system::{AccountInfo, EventRecord, Phase};
-	use pallet_revive_uapi::ReturnFlags;
-	use pretty_assertions::assert_eq;
-	use sp_io::hashing::keccak_256;
-	use sp_runtime::{traits::Hash, DispatchError};
-	use std::{cell::RefCell, collections::hash_map::HashMap, rc::Rc};
-
-	type System = frame_system::Pallet<Test>;
-
-	type MockStack<'a> = Stack<'a, Test, MockExecutable>;
-
-	parameter_types! {
-		static Loader: MockLoader = MockLoader::default();
-	}
-
-	fn events() -> Vec<Event<Test>> {
-		System::events()
-			.into_iter()
-			.filter_map(|meta| match meta.event {
-				MetaEvent::Contracts(contract_event) => Some(contract_event),
-				_ => None,
-			})
-			.collect()
-	}
-
-	struct MockCtx<'a> {
-		ext: &'a mut MockStack<'a>,
-		input_data: Vec<u8>,
-	}
-
-	#[derive(Clone)]
-	struct MockExecutable {
-		func: Rc<dyn for<'a> Fn(MockCtx<'a>, &Self) -> ExecResult + 'static>,
-		constructor: Rc<dyn for<'a> Fn(MockCtx<'a>, &Self) -> ExecResult + 'static>,
-		code_hash: H256,
-		code_info: CodeInfo<Test>,
-	}
-
-	#[derive(Default, Clone)]
-	pub struct MockLoader {
-		map: HashMap<H256, MockExecutable>,
-		counter: u64,
-	}
-
-	impl MockLoader {
-		fn code_hashes() -> Vec<H256> {
-			Loader::get().map.keys().copied().collect()
-		}
-
-		fn insert(
-			func_type: ExportedFunction,
-			f: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static,
-		) -> H256 {
-			Loader::mutate(|loader| {
-				// Generate code hashes from contract index value.
-				let hash = H256(keccak_256(&loader.counter.to_le_bytes()));
-				loader.counter += 1;
-				if func_type == ExportedFunction::Constructor {
-					loader.map.insert(
-						hash,
-						MockExecutable {
-							func: Rc::new(|_, _| exec_success()),
-							constructor: Rc::new(f),
-							code_hash: hash,
-							code_info: CodeInfo::<Test>::new(ALICE),
-						},
-					);
-				} else {
-					loader.map.insert(
-						hash,
-						MockExecutable {
-							func: Rc::new(f),
-							constructor: Rc::new(|_, _| exec_success()),
-							code_hash: hash,
-							code_info: CodeInfo::<Test>::new(ALICE),
-						},
-					);
-				}
-				hash
-			})
-		}
-
-		fn insert_both(
-			constructor: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static,
-			call: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static,
-		) -> H256 {
-			Loader::mutate(|loader| {
-				// Generate code hashes from contract index value.
-				let hash = H256(keccak_256(&loader.counter.to_le_bytes()));
-				loader.counter += 1;
-				loader.map.insert(
-					hash,
-					MockExecutable {
-						func: Rc::new(call),
-						constructor: Rc::new(constructor),
-						code_hash: hash,
-						code_info: CodeInfo::<Test>::new(ALICE),
-					},
-				);
-				hash
-			})
-		}
-	}
-
-	impl Executable<Test> for MockExecutable {
-		fn from_storage(
-			code_hash: H256,
-			_gas_meter: &mut GasMeter<Test>,
-		) -> Result<Self, DispatchError> {
-			Loader::mutate(|loader| {
-				loader.map.get(&code_hash).cloned().ok_or(Error::<Test>::CodeNotFound.into())
-			})
-		}
-
-		fn execute<E: Ext<T = Test>>(
-			self,
-			ext: &mut E,
-			function: ExportedFunction,
-			input_data: Vec<u8>,
-		) -> ExecResult {
-			// # Safety
-			//
-			// We know that we **always** call execute with a `MockStack` in this test.
-			//
-			// # Note
-			//
-			// The transmute is necessary because `execute` has to be generic over all
-			// `E: Ext`. However, `MockExecutable` can't be generic over `E` as it would
-			// constitute a cycle.
-			let ext = unsafe { mem::transmute(ext) };
-			if function == ExportedFunction::Constructor {
-				(self.constructor)(MockCtx { ext, input_data }, &self)
-			} else {
-				(self.func)(MockCtx { ext, input_data }, &self)
-			}
-		}
-
-		fn code(&self) -> &[u8] {
-			// The mock executable doesn't have code", so we return the code hash.
-			self.code_hash.as_ref()
-		}
-
-		fn code_hash(&self) -> &H256 {
-			&self.code_hash
-		}
-
-		fn code_info(&self) -> &CodeInfo<Test> {
-			&self.code_info
-		}
-	}
-
-	fn exec_success() -> ExecResult {
-		Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
-	}
-
-	fn exec_trapped() -> ExecResult {
-		Err(ExecError { error: <Error<Test>>::ContractTrapped.into(), origin: ErrorOrigin::Callee })
-	}
-
-	#[test]
-	fn it_works() {
-		parameter_types! {
-			static TestData: Vec<usize> = vec![0];
-		}
-
-		let value = Default::default();
-		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-		let exec_ch = MockLoader::insert(Call, |_ctx, _executable| {
-			TestData::mutate(|data| data.push(1));
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, exec_ch);
-			let mut storage_meter =
-				storage::meter::Meter::new(&Origin::from_account_id(ALICE), 0, value).unwrap();
-
-			assert_matches!(
-				MockStack::run_call(
-					Origin::from_account_id(ALICE),
-					BOB_ADDR,
-					&mut gas_meter,
-					&mut storage_meter,
-					value.into(),
-					vec![],
-					false,
-				),
-				Ok(_)
-			);
-		});
-
-		assert_eq!(TestData::get(), vec![0, 1]);
-	}
-
-	#[test]
-	fn transfer_works() {
-		// This test verifies that a contract is able to transfer
-		// some funds to another account.
-		ExtBuilder::default().build().execute_with(|| {
-			set_balance(&ALICE, 100);
-			set_balance(&BOB, 0);
-
-			let origin = Origin::from_account_id(ALICE);
-			MockStack::transfer(&origin, &ALICE, &BOB, 55u64.into()).unwrap();
-
-			let min_balance = <Test as Config>::Currency::minimum_balance();
-			assert_eq!(get_balance(&ALICE), 45 - min_balance);
-			assert_eq!(get_balance(&BOB), 55 + min_balance);
-		});
-	}
-
-	#[test]
-	fn transfer_to_nonexistent_account_works() {
-		// This test verifies that a contract is able to transfer
-		// some funds to a nonexistant account and that those transfers
-		// are not able to reap accounts.
-		ExtBuilder::default().build().execute_with(|| {
-			let ed = <Test as Config>::Currency::minimum_balance();
-			let value = 1024;
-
-			// Transfers to nonexistant accounts should work
-			set_balance(&ALICE, ed * 2);
-			set_balance(&BOB, ed + value);
-
-			assert_ok!(MockStack::transfer(
-				&Origin::from_account_id(ALICE),
-				&BOB,
-				&CHARLIE,
-				value.into()
-			));
-			assert_eq!(get_balance(&ALICE), ed);
-			assert_eq!(get_balance(&BOB), ed);
-			assert_eq!(get_balance(&CHARLIE), ed + value);
-
-			// Do not reap the origin account
-			set_balance(&ALICE, ed);
-			set_balance(&BOB, ed + value);
-			assert_err!(
-				MockStack::transfer(&Origin::from_account_id(ALICE), &BOB, &DJANGO, value.into()),
-				<Error<Test>>::TransferFailed
-			);
-
-			// Do not reap the sender account
-			set_balance(&ALICE, ed * 2);
-			set_balance(&BOB, value);
-			assert_err!(
-				MockStack::transfer(&Origin::from_account_id(ALICE), &BOB, &EVE, value.into()),
-				<Error<Test>>::TransferFailed
-			);
-			// The ED transfer would work. But it should only be executed with the actual transfer
-			assert!(!System::account_exists(&EVE));
-		});
-	}
-
-	#[test]
-	fn correct_transfer_on_call() {
-		let value = 55;
-
-		let success_ch = MockLoader::insert(Call, move |ctx, _| {
-			assert_eq!(ctx.ext.value_transferred(), U256::from(value));
-			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, success_ch);
-			set_balance(&ALICE, 100);
-			let balance = get_balance(&BOB_FALLBACK);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, value).unwrap();
-
-			let _ = MockStack::run_call(
-				origin.clone(),
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				value.into(),
-				vec![],
-				false,
-			)
-			.unwrap();
-
-			assert_eq!(get_balance(&ALICE), 100 - value);
-			assert_eq!(get_balance(&BOB_FALLBACK), balance + value);
-		});
-	}
-
-	#[test]
-	fn correct_transfer_on_delegate_call() {
-		let value = 35;
-
-		let success_ch = MockLoader::insert(Call, move |ctx, _| {
-			assert_eq!(ctx.ext.value_transferred(), U256::from(value));
-			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
-		});
-
-		let delegate_ch = MockLoader::insert(Call, move |ctx, _| {
-			assert_eq!(ctx.ext.value_transferred(), U256::from(value));
-			let _ =
-				ctx.ext.delegate_call(Weight::zero(), U256::zero(), CHARLIE_ADDR, Vec::new())?;
-			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, delegate_ch);
-			place_contract(&CHARLIE, success_ch);
-			set_balance(&ALICE, 100);
-			let balance = get_balance(&BOB_FALLBACK);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 55).unwrap();
-
-			assert_ok!(MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				value.into(),
-				vec![],
-				false,
-			));
-
-			assert_eq!(get_balance(&ALICE), 100 - value);
-			assert_eq!(get_balance(&BOB_FALLBACK), balance + value);
-		});
-	}
-
-	#[test]
-	fn delegate_call_missing_contract() {
-		let missing_ch = MockLoader::insert(Call, move |_ctx, _| {
-			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
-		});
-
-		let delegate_ch = MockLoader::insert(Call, move |ctx, _| {
-			let _ =
-				ctx.ext.delegate_call(Weight::zero(), U256::zero(), CHARLIE_ADDR, Vec::new())?;
-			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, delegate_ch);
-			set_balance(&ALICE, 100);
-
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 55).unwrap();
-
-			// contract code missing
-			assert_noop!(
-				MockStack::run_call(
-					origin.clone(),
-					BOB_ADDR,
-					&mut GasMeter::<Test>::new(GAS_LIMIT),
-					&mut storage_meter,
-					U256::zero(),
-					vec![],
-					false,
-				),
-				ExecError {
-					error: Error::<Test>::CodeNotFound.into(),
-					origin: ErrorOrigin::Callee,
-				}
-			);
-
-			// add missing contract code
-			place_contract(&CHARLIE, missing_ch);
-			assert_ok!(MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			));
-		});
-	}
-
-	#[test]
-	fn changes_are_reverted_on_failing_call() {
-		// This test verifies that changes are reverted on a call which fails (or equally, returns
-		// a non-zero status code).
-
-		let return_ch = MockLoader::insert(Call, |_, _| {
-			Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: Vec::new() })
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, return_ch);
-			set_balance(&ALICE, 100);
-			let balance = get_balance(&BOB);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 55).unwrap();
-
-			let output = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				55u64.into(),
-				vec![],
-				false,
-			)
-			.unwrap();
-
-			assert!(output.did_revert());
-			assert_eq!(get_balance(&ALICE), 100);
-			assert_eq!(get_balance(&BOB), balance);
-		});
-	}
-
-	#[test]
-	fn balance_too_low() {
-		// This test verifies that a contract can't send value if it's
-		// balance is too low.
-		let from = ALICE;
-		let origin = Origin::from_account_id(ALICE);
-		let dest = BOB;
-
-		ExtBuilder::default().build().execute_with(|| {
-			set_balance(&from, 0);
-
-			let result = MockStack::transfer(&origin, &from, &dest, 100u64.into());
-
-			assert_eq!(result, Err(Error::<Test>::TransferFailed.into()));
-			assert_eq!(get_balance(&from), 0);
-			assert_eq!(get_balance(&dest), 0);
-		});
-	}
-
-	#[test]
-	fn output_is_returned_on_success() {
-		// Verifies that if a contract returns data with a successful exit status, this data
-		// is returned from the execution context.
-		let return_ch = MockLoader::insert(Call, |_, _| {
-			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![1, 2, 3, 4] })
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			place_contract(&BOB, return_ch);
-
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			);
-
-			let output = result.unwrap();
-			assert!(!output.did_revert());
-			assert_eq!(output.data, vec![1, 2, 3, 4]);
-		});
-	}
-
-	#[test]
-	fn output_is_returned_on_failure() {
-		// Verifies that if a contract returns data with a failing exit status, this data
-		// is returned from the execution context.
-		let return_ch = MockLoader::insert(Call, |_, _| {
-			Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![1, 2, 3, 4] })
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, return_ch);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			);
-
-			let output = result.unwrap();
-			assert!(output.did_revert());
-			assert_eq!(output.data, vec![1, 2, 3, 4]);
-		});
-	}
-
-	#[test]
-	fn input_data_to_call() {
-		let input_data_ch = MockLoader::insert(Call, |ctx, _| {
-			assert_eq!(ctx.input_data, &[1, 2, 3, 4]);
-			exec_success()
-		});
-
-		// This one tests passing the input data into a contract via call.
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, input_data_ch);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![1, 2, 3, 4],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn input_data_to_instantiate() {
-		let input_data_ch = MockLoader::insert(Constructor, |ctx, _| {
-			assert_eq!(ctx.input_data, &[1, 2, 3, 4]);
-			exec_success()
-		});
-
-		// This one tests passing the input data into a contract via instantiate.
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.build()
-			.execute_with(|| {
-				let min_balance = <Test as Config>::Currency::minimum_balance();
-				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-				let executable =
-					MockExecutable::from_storage(input_data_ch, &mut gas_meter).unwrap();
-				set_balance(&ALICE, min_balance * 10_000);
-				let origin = Origin::from_account_id(ALICE);
-				let mut storage_meter =
-					storage::meter::Meter::new(&origin, deposit_limit::<Test>(), min_balance)
-						.unwrap();
-
-				let result = MockStack::run_instantiate(
-					ALICE,
-					executable,
-					&mut gas_meter,
-					&mut storage_meter,
-					min_balance.into(),
-					vec![1, 2, 3, 4],
-					Some(&[0; 32]),
-					false,
-				);
-				assert_matches!(result, Ok(_));
-			});
-	}
-
-	#[test]
-	fn max_depth() {
-		// This test verifies that when we reach the maximal depth creation of an
-		// yet another context fails.
-		parameter_types! {
-			static ReachedBottom: bool = false;
-		}
-		let value = Default::default();
-		let recurse_ch = MockLoader::insert(Call, |ctx, _| {
-			// Try to call into yourself.
-			let r = ctx.ext.call(
-				Weight::zero(),
-				U256::zero(),
-				&BOB_ADDR,
-				U256::zero(),
-				vec![],
-				true,
-				false,
-			);
-
-			ReachedBottom::mutate(|reached_bottom| {
-				if !*reached_bottom {
-					// We are first time here, it means we just reached bottom.
-					// Verify that we've got proper error and set `reached_bottom`.
-					assert_eq!(r, Err(Error::<Test>::MaxCallDepthReached.into()));
-					*reached_bottom = true;
-				} else {
-					// We just unwinding stack here.
-					assert_matches!(r, Ok(_));
-				}
-			});
-
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			set_balance(&BOB, 1);
-			place_contract(&BOB, recurse_ch);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, value).unwrap();
-
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				value.into(),
-				vec![],
-				false,
-			);
-
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn caller_returns_proper_values() {
-		parameter_types! {
-			static WitnessedCallerBob: Option<H160> = None;
-			static WitnessedCallerCharlie: Option<H160> = None;
-		}
-
-		let bob_ch = MockLoader::insert(Call, |ctx, _| {
-			// Record the caller for bob.
-			WitnessedCallerBob::mutate(|caller| {
-				let origin = ctx.ext.caller();
-				*caller =
-					Some(<<Test as Config>::AddressMapper as AddressMapper<Test>>::to_address(
-						&origin.account_id().unwrap(),
-					));
-			});
-
-			// Call into CHARLIE contract.
-			assert_matches!(
-				ctx.ext.call(
-					Weight::zero(),
-					U256::zero(),
-					&CHARLIE_ADDR,
-					U256::zero(),
-					vec![],
-					true,
-					false
-				),
-				Ok(_)
-			);
-			exec_success()
-		});
-		let charlie_ch = MockLoader::insert(Call, |ctx, _| {
-			// Record the caller for charlie.
-			WitnessedCallerCharlie::mutate(|caller| {
-				let origin = ctx.ext.caller();
-				*caller =
-					Some(<<Test as Config>::AddressMapper as AddressMapper<Test>>::to_address(
-						&origin.account_id().unwrap(),
-					));
-			});
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, bob_ch);
-			place_contract(&CHARLIE, charlie_ch);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			);
-
-			assert_matches!(result, Ok(_));
-		});
-
-		assert_eq!(WitnessedCallerBob::get(), Some(ALICE_ADDR));
-		assert_eq!(WitnessedCallerCharlie::get(), Some(BOB_ADDR));
-	}
-
-	#[test]
-	fn origin_returns_proper_values() {
-		parameter_types! {
-			static WitnessedCallerBob: Option<H160> = None;
-			static WitnessedCallerCharlie: Option<H160> = None;
-		}
-
-		let bob_ch = MockLoader::insert(Call, |ctx, _| {
-			// Record the origin for bob.
-			WitnessedCallerBob::mutate(|witness| {
-				let origin = ctx.ext.origin();
-				*witness = Some(<Test as Config>::AddressMapper::to_address(
-					&origin.account_id().unwrap(),
-				));
-			});
-
-			// Call into CHARLIE contract.
-			assert_matches!(
-				ctx.ext.call(
-					Weight::zero(),
-					U256::zero(),
-					&CHARLIE_ADDR,
-					U256::zero(),
-					vec![],
-					true,
-					false
-				),
-				Ok(_)
-			);
-			exec_success()
-		});
-		let charlie_ch = MockLoader::insert(Call, |ctx, _| {
-			// Record the origin for charlie.
-			WitnessedCallerCharlie::mutate(|witness| {
-				let origin = ctx.ext.origin();
-				*witness = Some(<Test as Config>::AddressMapper::to_address(
-					&origin.account_id().unwrap(),
-				));
-			});
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, bob_ch);
-			place_contract(&CHARLIE, charlie_ch);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			);
-
-			assert_matches!(result, Ok(_));
-		});
-
-		assert_eq!(WitnessedCallerBob::get(), Some(ALICE_ADDR));
-		assert_eq!(WitnessedCallerCharlie::get(), Some(ALICE_ADDR));
-	}
-
-	#[test]
-	fn is_contract_returns_proper_values() {
-		let bob_ch = MockLoader::insert(Call, |ctx, _| {
-			// Verify that BOB is a contract
-			assert!(ctx.ext.is_contract(&BOB_ADDR));
-			// Verify that ALICE is not a contract
-			assert!(!ctx.ext.is_contract(&ALICE_ADDR));
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, bob_ch);
-
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn to_account_id_returns_proper_values() {
-		let bob_code_hash = MockLoader::insert(Call, |ctx, _| {
-			let alice_account_id = <Test as Config>::AddressMapper::to_account_id(&ALICE_ADDR);
-			assert_eq!(ctx.ext.to_account_id(&ALICE_ADDR), alice_account_id);
-
-			const UNMAPPED_ADDR: H160 = H160([99u8; 20]);
-			let mut unmapped_fallback_account_id = [0xEE; 32];
-			unmapped_fallback_account_id[..20].copy_from_slice(UNMAPPED_ADDR.as_bytes());
-			assert_eq!(
-				ctx.ext.to_account_id(&UNMAPPED_ADDR),
-				AccountId32::new(unmapped_fallback_account_id)
-			);
-
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, bob_code_hash);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![0],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn code_hash_returns_proper_values() {
-		let bob_code_hash = MockLoader::insert(Call, |ctx, _| {
-			// ALICE is not a contract but account exists so it returns hash of empty data
-			assert_eq!(ctx.ext.code_hash(&ALICE_ADDR), EMPTY_CODE_HASH);
-			// BOB is a contract (this function) and hence it has a code_hash.
-			// `MockLoader` uses contract index to generate the code hash.
-			assert_eq!(ctx.ext.code_hash(&BOB_ADDR), H256(keccak_256(&0u64.to_le_bytes())));
-			// [0xff;20] doesn't exist and returns hash zero
-			assert!(ctx.ext.code_hash(&H160([0xff; 20])).is_zero());
-
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			// add alice account info to test case EOA code hash
-			frame_system::Account::<Test>::insert(
-				<Test as Config>::AddressMapper::to_account_id(&ALICE_ADDR),
-				AccountInfo { consumers: 1, providers: 1, ..Default::default() },
-			);
-			place_contract(&BOB, bob_code_hash);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			// ALICE (not contract) -> BOB (contract)
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![0],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn own_code_hash_returns_proper_values() {
-		let bob_ch = MockLoader::insert(Call, |ctx, _| {
-			let code_hash = ctx.ext.code_hash(&BOB_ADDR);
-			assert_eq!(*ctx.ext.own_code_hash(), code_hash);
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, bob_ch);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			// ALICE (not contract) -> BOB (contract)
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![0],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn caller_is_origin_returns_proper_values() {
-		let code_charlie = MockLoader::insert(Call, |ctx, _| {
-			// BOB is not the origin of the stack call
-			assert!(!ctx.ext.caller_is_origin());
-			exec_success()
-		});
-
-		let code_bob = MockLoader::insert(Call, |ctx, _| {
-			// ALICE is the origin of the call stack
-			assert!(ctx.ext.caller_is_origin());
-			// BOB calls CHARLIE
-			ctx.ext
-				.call(
-					Weight::zero(),
-					U256::zero(),
-					&CHARLIE_ADDR,
-					U256::zero(),
-					vec![],
-					true,
-					false,
-				)
-				.map(|_| ctx.ext.last_frame_output().clone())
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, code_bob);
-			place_contract(&CHARLIE, code_charlie);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			// ALICE -> BOB (caller is origin) -> CHARLIE (caller is not origin)
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![0],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn root_caller_succeeds() {
-		let code_bob = MockLoader::insert(Call, |ctx, _| {
-			// root is the origin of the call stack.
-			assert!(ctx.ext.caller_is_root());
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, code_bob);
-			let origin = Origin::Root;
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			// root -> BOB (caller is root)
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![0],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn root_caller_does_not_succeed_when_value_not_zero() {
-		let code_bob = MockLoader::insert(Call, |ctx, _| {
-			// root is the origin of the call stack.
-			assert!(ctx.ext.caller_is_root());
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, code_bob);
-			let origin = Origin::Root;
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			// root -> BOB (caller is root)
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				1u64.into(),
-				vec![0],
-				false,
-			);
-			assert_matches!(result, Err(_));
-		});
-	}
-
-	#[test]
-	fn root_caller_succeeds_with_consecutive_calls() {
-		let code_charlie = MockLoader::insert(Call, |ctx, _| {
-			// BOB is not root, even though the origin is root.
-			assert!(!ctx.ext.caller_is_root());
-			exec_success()
-		});
-
-		let code_bob = MockLoader::insert(Call, |ctx, _| {
-			// root is the origin of the call stack.
-			assert!(ctx.ext.caller_is_root());
-			// BOB calls CHARLIE.
-			ctx.ext
-				.call(
-					Weight::zero(),
-					U256::zero(),
-					&CHARLIE_ADDR,
-					U256::zero(),
-					vec![],
-					true,
-					false,
-				)
-				.map(|_| ctx.ext.last_frame_output().clone())
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, code_bob);
-			place_contract(&CHARLIE, code_charlie);
-			let origin = Origin::Root;
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			// root -> BOB (caller is root) -> CHARLIE (caller is not root)
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![0],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn address_returns_proper_values() {
-		let bob_ch = MockLoader::insert(Call, |ctx, _| {
-			// Verify that address matches BOB.
-			assert_eq!(ctx.ext.address(), BOB_ADDR);
-
-			// Call into charlie contract.
-			assert_matches!(
-				ctx.ext.call(
-					Weight::zero(),
-					U256::zero(),
-					&CHARLIE_ADDR,
-					U256::zero(),
-					vec![],
-					true,
-					false
-				),
-				Ok(_)
-			);
-			exec_success()
-		});
-		let charlie_ch = MockLoader::insert(Call, |ctx, _| {
-			assert_eq!(ctx.ext.address(), CHARLIE_ADDR);
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, bob_ch);
-			place_contract(&CHARLIE, charlie_ch);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			);
-
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn refuse_instantiate_with_value_below_existential_deposit() {
-		let dummy_ch = MockLoader::insert(Constructor, |_, _| exec_success());
-
-		ExtBuilder::default().existential_deposit(15).build().execute_with(|| {
-			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-			let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-
-			assert_matches!(
-				MockStack::run_instantiate(
-					ALICE,
-					executable,
-					&mut gas_meter,
-					&mut storage_meter,
-					U256::zero(), // <- zero value
-					vec![],
-					Some(&[0; 32]),
-					false,
-				),
-				Err(_)
-			);
-		});
-	}
-
-	#[test]
-	fn instantiation_work_with_success_output() {
-		let dummy_ch = MockLoader::insert(Constructor, |_, _| {
-			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![80, 65, 83, 83] })
-		});
-
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.existential_deposit(15)
-			.build()
-			.execute_with(|| {
-				let min_balance = <Test as Config>::Currency::minimum_balance();
-				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-				let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
-				set_balance(&ALICE, min_balance * 1000);
-				let origin = Origin::from_account_id(ALICE);
-				let mut storage_meter =
-					storage::meter::Meter::new(&origin, min_balance * 100, min_balance).unwrap();
-
-				let instantiated_contract_address = assert_matches!(
-					MockStack::run_instantiate(
-						ALICE,
-						executable,
-						&mut gas_meter,
-						&mut storage_meter,
-						min_balance.into(),
-						vec![],
-						Some(&[0 ;32]),
-						false,
-					),
-					Ok((address, ref output)) if output.data == vec![80, 65, 83, 83] => address
-				);
-				let instantiated_contract_id = <<Test as Config>::AddressMapper as AddressMapper<
-					Test,
-				>>::to_fallback_account_id(
-					&instantiated_contract_address
-				);
-
-				// Check that the newly created account has the expected code hash and
-				// there are instantiation event.
-				assert_eq!(
-					ContractInfo::<Test>::load_code_hash(&instantiated_contract_id).unwrap(),
-					dummy_ch
-				);
-			});
-	}
-
-	#[test]
-	fn instantiation_fails_with_failing_output() {
-		let dummy_ch = MockLoader::insert(Constructor, |_, _| {
-			Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70, 65, 73, 76] })
-		});
-
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.existential_deposit(15)
-			.build()
-			.execute_with(|| {
-				let min_balance = <Test as Config>::Currency::minimum_balance();
-				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-				let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
-				set_balance(&ALICE, min_balance * 1000);
-				let origin = Origin::from_account_id(ALICE);
-				let mut storage_meter =
-					storage::meter::Meter::new(&origin, min_balance * 100, min_balance).unwrap();
-
-				let instantiated_contract_address = assert_matches!(
-					MockStack::run_instantiate(
-						ALICE,
-						executable,
-						&mut gas_meter,
-						&mut storage_meter,
-						min_balance.into(),
-						vec![],
-						Some(&[0; 32]),
-						false,
-					),
-					Ok((address, ref output)) if output.data == vec![70, 65, 73, 76] => address
-				);
-
-				let instantiated_contract_id = <<Test as Config>::AddressMapper as AddressMapper<
-					Test,
-				>>::to_fallback_account_id(
-					&instantiated_contract_address
-				);
-
-				// Check that the account has not been created.
-				assert!(ContractInfo::<Test>::load_code_hash(&instantiated_contract_id).is_none());
-				assert!(events().is_empty());
-			});
-	}
-
-	#[test]
-	fn instantiation_from_contract() {
-		let dummy_ch = MockLoader::insert(Call, |_, _| exec_success());
-		let instantiated_contract_address = Rc::new(RefCell::new(None::<H160>));
-		let instantiator_ch = MockLoader::insert(Call, {
-			let instantiated_contract_address = Rc::clone(&instantiated_contract_address);
-			move |ctx, _| {
-				// Instantiate a contract and save it's address in `instantiated_contract_address`.
-				let (address, output) = ctx
-					.ext
-					.instantiate(
-						Weight::MAX,
-						U256::MAX,
-						dummy_ch,
-						<Test as Config>::Currency::minimum_balance().into(),
-						vec![],
-						Some(&[48; 32]),
-					)
-					.map(|address| (address, ctx.ext.last_frame_output().clone()))
-					.unwrap();
-
-				*instantiated_contract_address.borrow_mut() = Some(address);
-				Ok(output)
-			}
-		});
-
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.existential_deposit(15)
-			.build()
-			.execute_with(|| {
-				let min_balance = <Test as Config>::Currency::minimum_balance();
-				set_balance(&ALICE, min_balance * 100);
-				place_contract(&BOB, instantiator_ch);
-				let origin = Origin::from_account_id(ALICE);
-				let mut storage_meter =
-					storage::meter::Meter::new(&origin, min_balance * 10, min_balance * 10)
-						.unwrap();
-
-				assert_matches!(
-					MockStack::run_call(
-						origin,
-						BOB_ADDR,
-						&mut GasMeter::<Test>::new(GAS_LIMIT),
-						&mut storage_meter,
-						(min_balance * 10).into(),
-						vec![],
-						false,
-					),
-					Ok(_)
-				);
-
-				let instantiated_contract_address =
-					*instantiated_contract_address.borrow().as_ref().unwrap();
-
-				let instantiated_contract_id = <<Test as Config>::AddressMapper as AddressMapper<
-					Test,
-				>>::to_fallback_account_id(
-					&instantiated_contract_address
-				);
-
-				// Check that the newly created account has the expected code hash and
-				// there are instantiation event.
-				assert_eq!(
-					ContractInfo::<Test>::load_code_hash(&instantiated_contract_id).unwrap(),
-					dummy_ch
-				);
-			});
-	}
-
-	#[test]
-	fn instantiation_traps() {
-		let dummy_ch = MockLoader::insert(Constructor, |_, _| Err("It's a trap!".into()));
-		let instantiator_ch = MockLoader::insert(Call, {
-			move |ctx, _| {
-				// Instantiate a contract and save it's address in `instantiated_contract_address`.
-				assert_matches!(
-					ctx.ext.instantiate(
-						Weight::zero(),
-						U256::zero(),
-						dummy_ch,
-						<Test as Config>::Currency::minimum_balance().into(),
-						vec![],
-						Some(&[0; 32]),
-					),
-					Err(ExecError {
-						error: DispatchError::Other("It's a trap!"),
-						origin: ErrorOrigin::Callee,
-					})
-				);
-
-				exec_success()
-			}
-		});
-
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.existential_deposit(15)
-			.build()
-			.execute_with(|| {
-				set_balance(&ALICE, 1000);
-				set_balance(&BOB_FALLBACK, 100);
-				place_contract(&BOB, instantiator_ch);
-				let origin = Origin::from_account_id(ALICE);
-				let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap();
-
-				assert_matches!(
-					MockStack::run_call(
-						origin,
-						BOB_ADDR,
-						&mut GasMeter::<Test>::new(GAS_LIMIT),
-						&mut storage_meter,
-						U256::zero(),
-						vec![],
-						false,
-					),
-					Ok(_)
-				);
-			});
-	}
-
-	#[test]
-	fn termination_from_instantiate_fails() {
-		let terminate_ch = MockLoader::insert(Constructor, |ctx, _| {
-			ctx.ext.terminate(&ALICE_ADDR)?;
-			exec_success()
-		});
-
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.existential_deposit(15)
-			.build()
-			.execute_with(|| {
-				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-				let executable =
-					MockExecutable::from_storage(terminate_ch, &mut gas_meter).unwrap();
-				set_balance(&ALICE, 10_000);
-				let origin = Origin::from_account_id(ALICE);
-				let mut storage_meter =
-					storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 100).unwrap();
-
-				assert_eq!(
-					MockStack::run_instantiate(
-						ALICE,
-						executable,
-						&mut gas_meter,
-						&mut storage_meter,
-						100u64.into(),
-						vec![],
-						Some(&[0; 32]),
-						false,
-					),
-					Err(ExecError {
-						error: Error::<Test>::TerminatedInConstructor.into(),
-						origin: ErrorOrigin::Callee
-					})
-				);
-
-				assert_eq!(&events(), &[]);
-			});
-	}
-
-	#[test]
-	fn in_memory_changes_not_discarded() {
-		// Call stack: BOB -> CHARLIE (trap) -> BOB' (success)
-		// This tests verifies some edge case of the contract info cache:
-		// We change some value in our contract info before calling into a contract
-		// that calls into ourself. This triggers a case where BOBs contract info
-		// is written to storage and invalidated by the successful execution of BOB'.
-		// The trap of CHARLIE reverts the storage changes to BOB. When the root BOB regains
-		// control it reloads its contract info from storage. We check that changes that
-		// are made before calling into CHARLIE are not discarded.
-		let code_bob = MockLoader::insert(Call, |ctx, _| {
-			if ctx.input_data[0] == 0 {
-				let info = ctx.ext.contract_info();
-				assert_eq!(info.storage_byte_deposit, 0);
-				info.storage_byte_deposit = 42;
-				assert_eq!(
-					ctx.ext
-						.call(
-							Weight::zero(),
-							U256::zero(),
-							&CHARLIE_ADDR,
-							U256::zero(),
-							vec![],
-							true,
-							false
-						)
-						.map(|_| ctx.ext.last_frame_output().clone()),
-					exec_trapped()
-				);
-				assert_eq!(ctx.ext.contract_info().storage_byte_deposit, 42);
-			}
-			exec_success()
-		});
-		let code_charlie = MockLoader::insert(Call, |ctx, _| {
-			assert!(ctx
-				.ext
-				.call(Weight::zero(), U256::zero(), &BOB_ADDR, U256::zero(), vec![99], true, false)
-				.is_ok());
-			exec_trapped()
-		});
-
-		// This one tests passing the input data into a contract via call.
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, code_bob);
-			place_contract(&CHARLIE, code_charlie);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![0],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn recursive_call_during_constructor_is_balance_transfer() {
-		let code = MockLoader::insert(Constructor, |ctx, _| {
-			let account_id = ctx.ext.account_id().clone();
-			let addr =
-				<<Test as Config>::AddressMapper as AddressMapper<Test>>::to_address(&account_id);
-			let balance = ctx.ext.balance();
-
-			// Calling ourselves during the constructor will trigger a balance
-			// transfer since no contract exist yet.
-			assert_ok!(ctx.ext.call(
-				Weight::zero(),
-				U256::zero(),
-				&addr,
-				(balance - 1).into(),
-				vec![],
-				true,
-				false
-			));
-
-			// Should also work with call data set as it is ignored when no
-			// contract is deployed.
-			assert_ok!(ctx.ext.call(
-				Weight::zero(),
-				U256::zero(),
-				&addr,
-				1u32.into(),
-				vec![1, 2, 3, 4],
-				true,
-				false
-			));
-			exec_success()
-		});
-
-		// This one tests passing the input data into a contract via instantiate.
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.build()
-			.execute_with(|| {
-				let min_balance = <Test as Config>::Currency::minimum_balance();
-				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-				let executable = MockExecutable::from_storage(code, &mut gas_meter).unwrap();
-				set_balance(&ALICE, min_balance * 10_000);
-				let origin = Origin::from_account_id(ALICE);
-				let mut storage_meter =
-					storage::meter::Meter::new(&origin, deposit_limit::<Test>(), min_balance)
-						.unwrap();
-
-				let result = MockStack::run_instantiate(
-					ALICE,
-					executable,
-					&mut gas_meter,
-					&mut storage_meter,
-					10u64.into(),
-					vec![],
-					Some(&[0; 32]),
-					false,
-				);
-				assert_matches!(result, Ok(_));
-			});
-	}
-
-	#[test]
-	fn cannot_send_more_balance_than_available_to_self() {
-		let code_hash = MockLoader::insert(Call, |ctx, _| {
-			let account_id = ctx.ext.account_id().clone();
-			let addr =
-				<<Test as Config>::AddressMapper as AddressMapper<Test>>::to_address(&account_id);
-			let balance = ctx.ext.balance();
-
-			assert_err!(
-				ctx.ext.call(
-					Weight::zero(),
-					U256::zero(),
-					&addr,
-					(balance + 1).into(),
-					vec![],
-					true,
-					false
-				),
-				<Error<Test>>::TransferFailed,
-			);
-			exec_success()
-		});
-
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.build()
-			.execute_with(|| {
-				let min_balance = <Test as Config>::Currency::minimum_balance();
-				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-				set_balance(&ALICE, min_balance * 10);
-				place_contract(&BOB, code_hash);
-				let origin = Origin::from_account_id(ALICE);
-				let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-				MockStack::run_call(
-					origin,
-					BOB_ADDR,
-					&mut gas_meter,
-					&mut storage_meter,
-					U256::zero(),
-					vec![],
-					false,
-				)
-				.unwrap();
-			});
-	}
-
-	#[test]
-	fn call_reentry_direct_recursion() {
-		// call the contract passed as input with disabled reentry
-		let code_bob = MockLoader::insert(Call, |ctx, _| {
-			let dest = H160::from_slice(ctx.input_data.as_ref());
-			ctx.ext
-				.call(Weight::zero(), U256::zero(), &dest, U256::zero(), vec![], false, false)
-				.map(|_| ctx.ext.last_frame_output().clone())
-		});
-
-		let code_charlie = MockLoader::insert(Call, |_, _| exec_success());
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, code_bob);
-			place_contract(&CHARLIE, code_charlie);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-
-			// Calling another contract should succeed
-			assert_ok!(MockStack::run_call(
-				origin.clone(),
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				CHARLIE_ADDR.as_bytes().to_vec(),
-				false,
-			));
-
-			// Calling into oneself fails
-			assert_err!(
-				MockStack::run_call(
-					origin,
-					BOB_ADDR,
-					&mut GasMeter::<Test>::new(GAS_LIMIT),
-					&mut storage_meter,
-					U256::zero(),
-					BOB_ADDR.as_bytes().to_vec(),
-					false,
-				)
-				.map_err(|e| e.error),
-				<Error<Test>>::ReentranceDenied,
-			);
-		});
-	}
-
-	#[test]
-	fn call_deny_reentry() {
-		let code_bob = MockLoader::insert(Call, |ctx, _| {
-			if ctx.input_data[0] == 0 {
-				ctx.ext
-					.call(
-						Weight::zero(),
-						U256::zero(),
-						&CHARLIE_ADDR,
-						U256::zero(),
-						vec![],
-						false,
-						false,
-					)
-					.map(|_| ctx.ext.last_frame_output().clone())
-			} else {
-				exec_success()
-			}
-		});
-
-		// call BOB with input set to '1'
-		let code_charlie = MockLoader::insert(Call, |ctx, _| {
-			ctx.ext
-				.call(Weight::zero(), U256::zero(), &BOB_ADDR, U256::zero(), vec![1], true, false)
-				.map(|_| ctx.ext.last_frame_output().clone())
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, code_bob);
-			place_contract(&CHARLIE, code_charlie);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-
-			// BOB -> CHARLIE -> BOB fails as BOB denies reentry.
-			assert_err!(
-				MockStack::run_call(
-					origin,
-					BOB_ADDR,
-					&mut GasMeter::<Test>::new(GAS_LIMIT),
-					&mut storage_meter,
-					U256::zero(),
-					vec![0],
-					false,
-				)
-				.map_err(|e| e.error),
-				<Error<Test>>::ReentranceDenied,
-			);
-		});
-	}
-
-	#[test]
-	fn call_runtime_works() {
-		let code_hash = MockLoader::insert(Call, |ctx, _| {
-			let call = RuntimeCall::System(frame_system::Call::remark_with_event {
-				remark: b"Hello World".to_vec(),
-			});
-			ctx.ext.call_runtime(call).unwrap();
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			let min_balance = <Test as Config>::Currency::minimum_balance();
-
-			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-			set_balance(&ALICE, min_balance * 10);
-			place_contract(&BOB, code_hash);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			System::reset_events();
-			MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut gas_meter,
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			)
-			.unwrap();
-
-			let remark_hash = <Test as frame_system::Config>::Hashing::hash(b"Hello World");
-			assert_eq!(
-				System::events(),
-				vec![EventRecord {
-					phase: Phase::Initialization,
-					event: MetaEvent::System(frame_system::Event::Remarked {
-						sender: BOB_FALLBACK,
-						hash: remark_hash
-					}),
-					topics: vec![],
-				},]
-			);
-		});
-	}
-
-	#[test]
-	fn call_runtime_filter() {
-		let code_hash = MockLoader::insert(Call, |ctx, _| {
-			use frame_system::Call as SysCall;
-			use pallet_balances::Call as BalanceCall;
-			use pallet_utility::Call as UtilCall;
-
-			// remark should still be allowed
-			let allowed_call =
-				RuntimeCall::System(SysCall::remark_with_event { remark: b"Hello".to_vec() });
-
-			// transfers are disallowed by the `TestFiler` (see below)
-			let forbidden_call = RuntimeCall::Balances(BalanceCall::transfer_allow_death {
-				dest: CHARLIE,
-				value: 22,
-			});
-
-			// simple cases: direct call
-			assert_err!(
-				ctx.ext.call_runtime(forbidden_call.clone()),
-				frame_system::Error::<Test>::CallFiltered
-			);
-
-			// as part of a patch: return is OK (but it interrupted the batch)
-			assert_ok!(ctx.ext.call_runtime(RuntimeCall::Utility(UtilCall::batch {
-				calls: vec![allowed_call.clone(), forbidden_call, allowed_call]
-			})),);
-
-			// the transfer wasn't performed
-			assert_eq!(get_balance(&CHARLIE), 0);
-
-			exec_success()
-		});
-
-		TestFilter::set_filter(|call| match call {
-			RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { .. }) => false,
-			_ => true,
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			let min_balance = <Test as Config>::Currency::minimum_balance();
-
-			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-			set_balance(&ALICE, min_balance * 10);
-			place_contract(&BOB, code_hash);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			System::reset_events();
-			MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut gas_meter,
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			)
-			.unwrap();
-
-			let remark_hash = <Test as frame_system::Config>::Hashing::hash(b"Hello");
-			assert_eq!(
-				System::events(),
-				vec![
-					EventRecord {
-						phase: Phase::Initialization,
-						event: MetaEvent::System(frame_system::Event::Remarked {
-							sender: BOB_FALLBACK,
-							hash: remark_hash
-						}),
-						topics: vec![],
-					},
-					EventRecord {
-						phase: Phase::Initialization,
-						event: MetaEvent::Utility(pallet_utility::Event::ItemCompleted),
-						topics: vec![],
-					},
-					EventRecord {
-						phase: Phase::Initialization,
-						event: MetaEvent::Utility(pallet_utility::Event::BatchInterrupted {
-							index: 1,
-							error: frame_system::Error::<Test>::CallFiltered.into()
-						},),
-						topics: vec![],
-					},
-				]
-			);
-		});
-	}
-
-	#[test]
-	fn nonce() {
-		let fail_code = MockLoader::insert(Constructor, |_, _| exec_trapped());
-		let success_code = MockLoader::insert(Constructor, |_, _| exec_success());
-		let succ_fail_code = MockLoader::insert(Constructor, move |ctx, _| {
-			ctx.ext
-				.instantiate(
-					Weight::MAX,
-					U256::MAX,
-					fail_code,
-					ctx.ext.minimum_balance() * 100,
-					vec![],
-					Some(&[0; 32]),
-				)
-				.ok();
-			exec_success()
-		});
-		let succ_succ_code = MockLoader::insert(Constructor, move |ctx, _| {
-			let alice_nonce = System::account_nonce(&ALICE);
-			assert_eq!(System::account_nonce(ctx.ext.account_id()), 0);
-			assert_eq!(ctx.ext.caller().account_id().unwrap(), &ALICE);
-			let addr = ctx
-				.ext
-				.instantiate(
-					Weight::MAX,
-					U256::MAX,
-					success_code,
-					ctx.ext.minimum_balance() * 100,
-					vec![],
-					Some(&[0; 32]),
-				)
-				.unwrap();
-
-			let account_id =
-				<<Test as Config>::AddressMapper as AddressMapper<Test>>::to_fallback_account_id(
-					&addr,
-				);
-
-			assert_eq!(System::account_nonce(&ALICE), alice_nonce);
-			assert_eq!(System::account_nonce(ctx.ext.account_id()), 1);
-			assert_eq!(System::account_nonce(&account_id), 0);
-
-			// a plain call should not influence the account counter
-			ctx.ext
-				.call(Weight::zero(), U256::zero(), &addr, U256::zero(), vec![], false, false)
-				.unwrap();
-
-			assert_eq!(System::account_nonce(ALICE), alice_nonce);
-			assert_eq!(System::account_nonce(ctx.ext.account_id()), 1);
-			assert_eq!(System::account_nonce(&account_id), 0);
-
-			exec_success()
-		});
-
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.build()
-			.execute_with(|| {
-				let min_balance = <Test as Config>::Currency::minimum_balance();
-				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-				let fail_executable =
-					MockExecutable::from_storage(fail_code, &mut gas_meter).unwrap();
-				let success_executable =
-					MockExecutable::from_storage(success_code, &mut gas_meter).unwrap();
-				let succ_fail_executable =
-					MockExecutable::from_storage(succ_fail_code, &mut gas_meter).unwrap();
-				let succ_succ_executable =
-					MockExecutable::from_storage(succ_succ_code, &mut gas_meter).unwrap();
-				set_balance(&ALICE, min_balance * 10_000);
-				set_balance(&BOB, min_balance * 10_000);
-				let origin = Origin::from_account_id(BOB);
-				let mut storage_meter =
-					storage::meter::Meter::new(&origin, deposit_limit::<Test>(), min_balance * 100)
-						.unwrap();
-
-				// fail should not increment
-				MockStack::run_instantiate(
-					ALICE,
-					fail_executable,
-					&mut gas_meter,
-					&mut storage_meter,
-					(min_balance * 100).into(),
-					vec![],
-					Some(&[0; 32]),
-					false,
-				)
-				.ok();
-				assert_eq!(System::account_nonce(&ALICE), 0);
-
-				assert_ok!(MockStack::run_instantiate(
-					ALICE,
-					success_executable,
-					&mut gas_meter,
-					&mut storage_meter,
-					(min_balance * 100).into(),
-					vec![],
-					Some(&[0; 32]),
-					false,
-				));
-				assert_eq!(System::account_nonce(&ALICE), 1);
-
-				assert_ok!(MockStack::run_instantiate(
-					ALICE,
-					succ_fail_executable,
-					&mut gas_meter,
-					&mut storage_meter,
-					(min_balance * 200).into(),
-					vec![],
-					Some(&[0; 32]),
-					false,
-				));
-				assert_eq!(System::account_nonce(&ALICE), 2);
-
-				assert_ok!(MockStack::run_instantiate(
-					ALICE,
-					succ_succ_executable,
-					&mut gas_meter,
-					&mut storage_meter,
-					(min_balance * 200).into(),
-					vec![],
-					Some(&[0; 32]),
-					false,
-				));
-				assert_eq!(System::account_nonce(&ALICE), 3);
-			});
-	}
-
-	#[test]
-	fn set_storage_works() {
-		let code_hash = MockLoader::insert(Call, |ctx, _| {
-			// Write
-			assert_eq!(
-				ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![4, 5, 6]), true),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(ctx.ext.set_storage(&Key::Fix([3; 32]), None, false), Ok(WriteOutcome::New));
-			assert_eq!(ctx.ext.set_storage(&Key::Fix([4; 32]), None, true), Ok(WriteOutcome::New));
-			assert_eq!(
-				ctx.ext.set_storage(&Key::Fix([5; 32]), Some(vec![]), false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_storage(&Key::Fix([6; 32]), Some(vec![]), true),
-				Ok(WriteOutcome::New)
-			);
-
-			// Overwrite
-			assert_eq!(
-				ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![42]), false),
-				Ok(WriteOutcome::Overwritten(3))
-			);
-			assert_eq!(
-				ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![48]), true),
-				Ok(WriteOutcome::Taken(vec![4, 5, 6]))
-			);
-			assert_eq!(ctx.ext.set_storage(&Key::Fix([3; 32]), None, false), Ok(WriteOutcome::New));
-			assert_eq!(ctx.ext.set_storage(&Key::Fix([4; 32]), None, true), Ok(WriteOutcome::New));
-			assert_eq!(
-				ctx.ext.set_storage(&Key::Fix([5; 32]), Some(vec![]), false),
-				Ok(WriteOutcome::Overwritten(0))
-			);
-			assert_eq!(
-				ctx.ext.set_storage(&Key::Fix([6; 32]), Some(vec![]), true),
-				Ok(WriteOutcome::Taken(vec![]))
-			);
-
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			let min_balance = <Test as Config>::Currency::minimum_balance();
-
-			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-			set_balance(&ALICE, min_balance * 1000);
-			place_contract(&BOB, code_hash);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter =
-				storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
-			assert_ok!(MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut gas_meter,
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			));
-		});
-	}
-
-	#[test]
-	fn set_storage_varsized_key_works() {
-		let code_hash = MockLoader::insert(Call, |ctx, _| {
-			// Write
-			assert_eq!(
-				ctx.ext.set_storage(
-					&Key::try_from_var([1; 64].to_vec()).unwrap(),
-					Some(vec![1, 2, 3]),
-					false
-				),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_storage(
-					&Key::try_from_var([2; 19].to_vec()).unwrap(),
-					Some(vec![4, 5, 6]),
-					true
-				),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_storage(&Key::try_from_var([3; 19].to_vec()).unwrap(), None, false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_storage(&Key::try_from_var([4; 64].to_vec()).unwrap(), None, true),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_storage(
-					&Key::try_from_var([5; 30].to_vec()).unwrap(),
-					Some(vec![]),
-					false
-				),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_storage(
-					&Key::try_from_var([6; 128].to_vec()).unwrap(),
-					Some(vec![]),
-					true
-				),
-				Ok(WriteOutcome::New)
-			);
-
-			// Overwrite
-			assert_eq!(
-				ctx.ext.set_storage(
-					&Key::try_from_var([1; 64].to_vec()).unwrap(),
-					Some(vec![42, 43, 44]),
-					false
-				),
-				Ok(WriteOutcome::Overwritten(3))
-			);
-			assert_eq!(
-				ctx.ext.set_storage(
-					&Key::try_from_var([2; 19].to_vec()).unwrap(),
-					Some(vec![48]),
-					true
-				),
-				Ok(WriteOutcome::Taken(vec![4, 5, 6]))
-			);
-			assert_eq!(
-				ctx.ext.set_storage(&Key::try_from_var([3; 19].to_vec()).unwrap(), None, false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_storage(&Key::try_from_var([4; 64].to_vec()).unwrap(), None, true),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_storage(
-					&Key::try_from_var([5; 30].to_vec()).unwrap(),
-					Some(vec![]),
-					false
-				),
-				Ok(WriteOutcome::Overwritten(0))
-			);
-			assert_eq!(
-				ctx.ext.set_storage(
-					&Key::try_from_var([6; 128].to_vec()).unwrap(),
-					Some(vec![]),
-					true
-				),
-				Ok(WriteOutcome::Taken(vec![]))
-			);
-
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			let min_balance = <Test as Config>::Currency::minimum_balance();
-
-			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-			set_balance(&ALICE, min_balance * 1000);
-			place_contract(&BOB, code_hash);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter =
-				storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
-			assert_ok!(MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut gas_meter,
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			));
-		});
-	}
-
-	#[test]
-	fn get_storage_works() {
-		let code_hash = MockLoader::insert(Call, |ctx, _| {
-			assert_eq!(
-				ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![]), false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(ctx.ext.get_storage(&Key::Fix([1; 32])), Some(vec![1, 2, 3]));
-			assert_eq!(ctx.ext.get_storage(&Key::Fix([2; 32])), Some(vec![]));
-			assert_eq!(ctx.ext.get_storage(&Key::Fix([3; 32])), None);
-
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			let min_balance = <Test as Config>::Currency::minimum_balance();
-
-			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-			set_balance(&ALICE, min_balance * 1000);
-			place_contract(&BOB, code_hash);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter =
-				storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
-			assert_ok!(MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut gas_meter,
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			));
-		});
-	}
-
-	#[test]
-	fn get_storage_size_works() {
-		let code_hash = MockLoader::insert(Call, |ctx, _| {
-			assert_eq!(
-				ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![]), false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(ctx.ext.get_storage_size(&Key::Fix([1; 32])), Some(3));
-			assert_eq!(ctx.ext.get_storage_size(&Key::Fix([2; 32])), Some(0));
-			assert_eq!(ctx.ext.get_storage_size(&Key::Fix([3; 32])), None);
-
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			let min_balance = <Test as Config>::Currency::minimum_balance();
-
-			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-			set_balance(&ALICE, min_balance * 1000);
-			place_contract(&BOB, code_hash);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter =
-				storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
-			assert_ok!(MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut gas_meter,
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			));
-		});
-	}
-
-	#[test]
-	fn get_storage_varsized_key_works() {
-		let code_hash = MockLoader::insert(Call, |ctx, _| {
-			assert_eq!(
-				ctx.ext.set_storage(
-					&Key::try_from_var([1; 19].to_vec()).unwrap(),
-					Some(vec![1, 2, 3]),
-					false
-				),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_storage(
-					&Key::try_from_var([2; 16].to_vec()).unwrap(),
-					Some(vec![]),
-					false
-				),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.get_storage(&Key::try_from_var([1; 19].to_vec()).unwrap()),
-				Some(vec![1, 2, 3])
-			);
-			assert_eq!(
-				ctx.ext.get_storage(&Key::try_from_var([2; 16].to_vec()).unwrap()),
-				Some(vec![])
-			);
-			assert_eq!(ctx.ext.get_storage(&Key::try_from_var([3; 8].to_vec()).unwrap()), None);
-
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			let min_balance = <Test as Config>::Currency::minimum_balance();
-
-			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-			set_balance(&ALICE, min_balance * 1000);
-			place_contract(&BOB, code_hash);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter =
-				storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
-			assert_ok!(MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut gas_meter,
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			));
-		});
-	}
-
-	#[test]
-	fn get_storage_size_varsized_key_works() {
-		let code_hash = MockLoader::insert(Call, |ctx, _| {
-			assert_eq!(
-				ctx.ext.set_storage(
-					&Key::try_from_var([1; 19].to_vec()).unwrap(),
-					Some(vec![1, 2, 3]),
-					false
-				),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_storage(
-					&Key::try_from_var([2; 16].to_vec()).unwrap(),
-					Some(vec![]),
-					false
-				),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.get_storage_size(&Key::try_from_var([1; 19].to_vec()).unwrap()),
-				Some(3)
-			);
-			assert_eq!(
-				ctx.ext.get_storage_size(&Key::try_from_var([2; 16].to_vec()).unwrap()),
-				Some(0)
-			);
-			assert_eq!(
-				ctx.ext.get_storage_size(&Key::try_from_var([3; 8].to_vec()).unwrap()),
-				None
-			);
-
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			let min_balance = <Test as Config>::Currency::minimum_balance();
-
-			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-			set_balance(&ALICE, min_balance * 1000);
-			place_contract(&BOB, code_hash);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter =
-				storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
-			assert_ok!(MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut gas_meter,
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			));
-		});
-	}
-
-	#[test]
-	fn set_transient_storage_works() {
-		let code_hash = MockLoader::insert(Call, |ctx, _| {
-			// Write
-			assert_eq!(
-				ctx.ext.set_transient_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_transient_storage(&Key::Fix([2; 32]), Some(vec![4, 5, 6]), true),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_transient_storage(&Key::Fix([3; 32]), None, false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_transient_storage(&Key::Fix([4; 32]), None, true),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_transient_storage(&Key::Fix([5; 32]), Some(vec![]), false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_transient_storage(&Key::Fix([6; 32]), Some(vec![]), true),
-				Ok(WriteOutcome::New)
-			);
-
-			// Overwrite
-			assert_eq!(
-				ctx.ext.set_transient_storage(&Key::Fix([1; 32]), Some(vec![42]), false),
-				Ok(WriteOutcome::Overwritten(3))
-			);
-			assert_eq!(
-				ctx.ext.set_transient_storage(&Key::Fix([2; 32]), Some(vec![48]), true),
-				Ok(WriteOutcome::Taken(vec![4, 5, 6]))
-			);
-			assert_eq!(
-				ctx.ext.set_transient_storage(&Key::Fix([3; 32]), None, false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_transient_storage(&Key::Fix([4; 32]), None, true),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_transient_storage(&Key::Fix([5; 32]), Some(vec![]), false),
-				Ok(WriteOutcome::Overwritten(0))
-			);
-			assert_eq!(
-				ctx.ext.set_transient_storage(&Key::Fix([6; 32]), Some(vec![]), true),
-				Ok(WriteOutcome::Taken(vec![]))
-			);
-
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, code_hash);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter =
-				storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
-			assert_ok!(MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			));
-		});
-	}
-
-	#[test]
-	fn get_transient_storage_works() {
-		// Call stack: BOB -> CHARLIE(success) -> BOB' (success)
-		let storage_key_1 = &Key::Fix([1; 32]);
-		let storage_key_2 = &Key::Fix([2; 32]);
-		let storage_key_3 = &Key::Fix([3; 32]);
-		let code_bob = MockLoader::insert(Call, |ctx, _| {
-			if ctx.input_data[0] == 0 {
-				assert_eq!(
-					ctx.ext.set_transient_storage(storage_key_1, Some(vec![1, 2]), false),
-					Ok(WriteOutcome::New)
-				);
-				assert_eq!(
-					ctx.ext
-						.call(
-							Weight::zero(),
-							U256::zero(),
-							&CHARLIE_ADDR,
-							U256::zero(),
-							vec![],
-							true,
-							false,
-						)
-						.map(|_| ctx.ext.last_frame_output().clone()),
-					exec_success()
-				);
-				assert_eq!(ctx.ext.get_transient_storage(storage_key_1), Some(vec![3]));
-				assert_eq!(ctx.ext.get_transient_storage(storage_key_2), Some(vec![]));
-				assert_eq!(ctx.ext.get_transient_storage(storage_key_3), None);
-			} else {
-				assert_eq!(
-					ctx.ext.set_transient_storage(storage_key_1, Some(vec![3]), true),
-					Ok(WriteOutcome::Taken(vec![1, 2]))
-				);
-				assert_eq!(
-					ctx.ext.set_transient_storage(storage_key_2, Some(vec![]), false),
-					Ok(WriteOutcome::New)
-				);
-			}
-			exec_success()
-		});
-		let code_charlie = MockLoader::insert(Call, |ctx, _| {
-			assert!(ctx
-				.ext
-				.call(Weight::zero(), U256::zero(), &BOB_ADDR, U256::zero(), vec![99], true, false)
-				.is_ok());
-			// CHARLIE can not read BOB`s storage.
-			assert_eq!(ctx.ext.get_transient_storage(storage_key_1), None);
-			exec_success()
-		});
-
-		// This one tests passing the input data into a contract via call.
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, code_bob);
-			place_contract(&CHARLIE, code_charlie);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![0],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn get_transient_storage_size_works() {
-		let storage_key_1 = &Key::Fix([1; 32]);
-		let storage_key_2 = &Key::Fix([2; 32]);
-		let storage_key_3 = &Key::Fix([3; 32]);
-		let code_hash = MockLoader::insert(Call, |ctx, _| {
-			assert_eq!(
-				ctx.ext.set_transient_storage(storage_key_1, Some(vec![1, 2, 3]), false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(
-				ctx.ext.set_transient_storage(storage_key_2, Some(vec![]), false),
-				Ok(WriteOutcome::New)
-			);
-			assert_eq!(ctx.ext.get_transient_storage_size(storage_key_1), Some(3));
-			assert_eq!(ctx.ext.get_transient_storage_size(storage_key_2), Some(0));
-			assert_eq!(ctx.ext.get_transient_storage_size(storage_key_3), None);
-
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, code_hash);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			assert_ok!(MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			));
-		});
-	}
-
-	#[test]
-	fn rollback_transient_storage_works() {
-		// Call stack: BOB -> CHARLIE (trap) -> BOB' (success)
-		let storage_key = &Key::Fix([1; 32]);
-		let code_bob = MockLoader::insert(Call, |ctx, _| {
-			if ctx.input_data[0] == 0 {
-				assert_eq!(
-					ctx.ext.set_transient_storage(storage_key, Some(vec![1, 2]), false),
-					Ok(WriteOutcome::New)
-				);
-				assert_eq!(
-					ctx.ext
-						.call(
-							Weight::zero(),
-							U256::zero(),
-							&CHARLIE_ADDR,
-							U256::zero(),
-							vec![],
-							true,
-							false
-						)
-						.map(|_| ctx.ext.last_frame_output().clone()),
-					exec_trapped()
-				);
-				assert_eq!(ctx.ext.get_transient_storage(storage_key), Some(vec![1, 2]));
-			} else {
-				let overwritten_length = ctx.ext.get_transient_storage_size(storage_key).unwrap();
-				assert_eq!(
-					ctx.ext.set_transient_storage(storage_key, Some(vec![3]), false),
-					Ok(WriteOutcome::Overwritten(overwritten_length))
-				);
-				assert_eq!(ctx.ext.get_transient_storage(storage_key), Some(vec![3]));
-			}
-			exec_success()
-		});
-		let code_charlie = MockLoader::insert(Call, |ctx, _| {
-			assert!(ctx
-				.ext
-				.call(Weight::zero(), U256::zero(), &BOB_ADDR, U256::zero(), vec![99], true, false)
-				.is_ok());
-			exec_trapped()
-		});
-
-		// This one tests passing the input data into a contract via call.
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, code_bob);
-			place_contract(&CHARLIE, code_charlie);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![0],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn ecdsa_to_eth_address_returns_proper_value() {
-		let bob_ch = MockLoader::insert(Call, |ctx, _| {
-			let pubkey_compressed = array_bytes::hex2array_unchecked(
-				"028db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd91",
-			);
-			assert_eq!(
-				ctx.ext.ecdsa_to_eth_address(&pubkey_compressed).unwrap(),
-				array_bytes::hex2array_unchecked::<_, 20>(
-					"09231da7b19A016f9e576d23B16277062F4d46A8"
-				)
-			);
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, bob_ch);
-
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn last_frame_output_works_on_instantiate() {
-		let ok_ch = MockLoader::insert(Constructor, move |_, _| {
-			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![127] })
-		});
-		let revert_ch = MockLoader::insert(Constructor, move |_, _| {
-			Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70] })
-		});
-		let trap_ch = MockLoader::insert(Constructor, |_, _| Err("It's a trap!".into()));
-		let instantiator_ch = MockLoader::insert(Call, {
-			move |ctx, _| {
-				let value = <Test as Config>::Currency::minimum_balance().into();
-
-				// Successful instantiation should set the output
-				let address = ctx
-					.ext
-					.instantiate(Weight::MAX, U256::MAX, ok_ch, value, vec![], None)
-					.unwrap();
-				assert_eq!(
-					ctx.ext.last_frame_output(),
-					&ExecReturnValue { flags: ReturnFlags::empty(), data: vec![127] }
-				);
-
-				// Balance transfers should reset the output
-				ctx.ext
-					.call(Weight::MAX, U256::MAX, &address, U256::from(1), vec![], true, false)
-					.unwrap();
-				assert_eq!(ctx.ext.last_frame_output(), &Default::default());
-
-				// Reverted instantiation should set the output
-				ctx.ext
-					.instantiate(Weight::zero(), U256::zero(), revert_ch, value, vec![], None)
-					.unwrap();
-				assert_eq!(
-					ctx.ext.last_frame_output(),
-					&ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70] }
-				);
-
-				// Trapped instantiation should clear the output
-				ctx.ext
-					.instantiate(Weight::zero(), U256::zero(), trap_ch, value, vec![], None)
-					.unwrap_err();
-				assert_eq!(
-					ctx.ext.last_frame_output(),
-					&ExecReturnValue { flags: ReturnFlags::empty(), data: vec![] }
-				);
-
-				exec_success()
-			}
-		});
-
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.existential_deposit(15)
-			.build()
-			.execute_with(|| {
-				set_balance(&ALICE, 1000);
-				set_balance(&BOB, 100);
-				place_contract(&BOB, instantiator_ch);
-				let origin = Origin::from_account_id(ALICE);
-				let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap();
-
-				MockStack::run_call(
-					origin,
-					BOB_ADDR,
-					&mut GasMeter::<Test>::new(GAS_LIMIT),
-					&mut storage_meter,
-					U256::zero(),
-					vec![],
-					false,
-				)
-				.unwrap()
-			});
-	}
-
-	#[test]
-	fn last_frame_output_works_on_nested_call() {
-		// Call stack: BOB -> CHARLIE(revert) -> BOB' (success)
-		let code_bob = MockLoader::insert(Call, |ctx, _| {
-			if ctx.input_data.is_empty() {
-				// We didn't do anything yet
-				assert_eq!(
-					ctx.ext.last_frame_output(),
-					&ExecReturnValue { flags: ReturnFlags::empty(), data: vec![] }
-				);
-
-				ctx.ext
-					.call(
-						Weight::zero(),
-						U256::zero(),
-						&CHARLIE_ADDR,
-						U256::zero(),
-						vec![],
-						true,
-						false,
-					)
-					.unwrap();
-				assert_eq!(
-					ctx.ext.last_frame_output(),
-					&ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70] }
-				);
-			}
-
-			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![127] })
-		});
-		let code_charlie = MockLoader::insert(Call, |ctx, _| {
-			// We didn't do anything yet
-			assert_eq!(
-				ctx.ext.last_frame_output(),
-				&ExecReturnValue { flags: ReturnFlags::empty(), data: vec![] }
-			);
-
-			assert!(ctx
-				.ext
-				.call(Weight::zero(), U256::zero(), &BOB_ADDR, U256::zero(), vec![99], true, false)
-				.is_ok());
-			assert_eq!(
-				ctx.ext.last_frame_output(),
-				&ExecReturnValue { flags: ReturnFlags::empty(), data: vec![127] }
-			);
-
-			Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70] })
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, code_bob);
-			place_contract(&CHARLIE, code_charlie);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![0],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn last_frame_output_is_always_reset() {
-		let code_bob = MockLoader::insert(Call, |ctx, _| {
-			let invalid_code_hash = H256::from_low_u64_le(u64::MAX);
-			let output_revert = || ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![1] };
-
-			// A value of u256::MAX to fail the call on the first condition.
-			*ctx.ext.last_frame_output_mut() = output_revert();
-			assert_eq!(
-				ctx.ext.call(
-					Weight::zero(),
-					U256::zero(),
-					&H160::zero(),
-					U256::max_value(),
-					vec![],
-					true,
-					false,
-				),
-				Err(Error::<Test>::BalanceConversionFailed.into())
-			);
-			assert_eq!(ctx.ext.last_frame_output(), &Default::default());
-
-			// An unknown code hash to fail the delegate_call on the first condition.
-			*ctx.ext.last_frame_output_mut() = output_revert();
-			assert_eq!(
-				ctx.ext.delegate_call(
-					Weight::zero(),
-					U256::zero(),
-					H160([0xff; 20]),
-					Default::default()
-				),
-				Err(Error::<Test>::CodeNotFound.into())
-			);
-			assert_eq!(ctx.ext.last_frame_output(), &Default::default());
-
-			// An unknown code hash to fail instantiation on the first condition.
-			*ctx.ext.last_frame_output_mut() = output_revert();
-			assert_eq!(
-				ctx.ext.instantiate(
-					Weight::zero(),
-					U256::zero(),
-					invalid_code_hash,
-					U256::zero(),
-					vec![],
-					None,
-				),
-				Err(Error::<Test>::CodeNotFound.into())
-			);
-			assert_eq!(ctx.ext.last_frame_output(), &Default::default());
-
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			place_contract(&BOB, code_bob);
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-
-			let result = MockStack::run_call(
-				origin,
-				BOB_ADDR,
-				&mut GasMeter::<Test>::new(GAS_LIMIT),
-				&mut storage_meter,
-				U256::zero(),
-				vec![],
-				false,
-			);
-			assert_matches!(result, Ok(_));
-		});
-	}
-
-	#[test]
-	fn immutable_data_access_checks_work() {
-		let dummy_ch = MockLoader::insert(Constructor, move |ctx, _| {
-			// Calls can not store immutable data
-			assert_eq!(
-				ctx.ext.get_immutable_data(),
-				Err(Error::<Test>::InvalidImmutableAccess.into())
-			);
-			exec_success()
-		});
-		let instantiator_ch = MockLoader::insert(Call, {
-			move |ctx, _| {
-				let value = <Test as Config>::Currency::minimum_balance().into();
-
-				assert_eq!(
-					ctx.ext.set_immutable_data(vec![0, 1, 2, 3].try_into().unwrap()),
-					Err(Error::<Test>::InvalidImmutableAccess.into())
-				);
-
-				// Constructors can not access the immutable data
-				ctx.ext
-					.instantiate(Weight::MAX, U256::MAX, dummy_ch, value, vec![], None)
-					.unwrap();
-
-				exec_success()
-			}
-		});
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.existential_deposit(15)
-			.build()
-			.execute_with(|| {
-				set_balance(&ALICE, 1000);
-				set_balance(&BOB, 100);
-				place_contract(&BOB, instantiator_ch);
-				let origin = Origin::from_account_id(ALICE);
-				let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap();
-
-				MockStack::run_call(
-					origin,
-					BOB_ADDR,
-					&mut GasMeter::<Test>::new(GAS_LIMIT),
-					&mut storage_meter,
-					U256::zero(),
-					vec![],
-					false,
-				)
-				.unwrap()
-			});
-	}
-
-	#[test]
-	fn correct_immutable_data_in_delegate_call() {
-		let charlie_ch = MockLoader::insert(Call, |ctx, _| {
-			Ok(ExecReturnValue {
-				flags: ReturnFlags::empty(),
-				data: ctx.ext.get_immutable_data()?.to_vec(),
-			})
-		});
-		let bob_ch = MockLoader::insert(Call, move |ctx, _| {
-			// In a regular call, we should witness the callee immutable data
-			assert_eq!(
-				ctx.ext
-					.call(
-						Weight::zero(),
-						U256::zero(),
-						&CHARLIE_ADDR,
-						U256::zero(),
-						vec![],
-						true,
-						false,
-					)
-					.map(|_| ctx.ext.last_frame_output().data.clone()),
-				Ok(vec![2]),
-			);
-
-			// Also in a delegate call, we should witness the callee immutable data
-			assert_eq!(
-				ctx.ext
-					.delegate_call(Weight::zero(), U256::zero(), CHARLIE_ADDR, Vec::new())
-					.map(|_| ctx.ext.last_frame_output().data.clone()),
-				Ok(vec![2])
-			);
-
-			exec_success()
-		});
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.existential_deposit(15)
-			.build()
-			.execute_with(|| {
-				place_contract(&BOB, bob_ch);
-				place_contract(&CHARLIE, charlie_ch);
-
-				let origin = Origin::from_account_id(ALICE);
-				let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap();
-
-				// Place unique immutable data for each contract
-				<ImmutableDataOf<Test>>::insert::<_, ImmutableData>(
-					BOB_ADDR,
-					vec![1].try_into().unwrap(),
-				);
-				<ImmutableDataOf<Test>>::insert::<_, ImmutableData>(
-					CHARLIE_ADDR,
-					vec![2].try_into().unwrap(),
-				);
-
-				MockStack::run_call(
-					origin,
-					BOB_ADDR,
-					&mut GasMeter::<Test>::new(GAS_LIMIT),
-					&mut storage_meter,
-					U256::zero(),
-					vec![],
-					false,
-				)
-				.unwrap()
-			});
-	}
-
-	#[test]
-	fn immutable_data_set_overrides() {
-		let hash = MockLoader::insert_both(
-			move |ctx, _| {
-				// Calling `set_immutable_data` the first time should work
-				assert_ok!(ctx.ext.set_immutable_data(vec![0, 1, 2, 3].try_into().unwrap()));
-				// Calling `set_immutable_data` the second time overrides the original one
-				assert_ok!(ctx.ext.set_immutable_data(vec![7, 5].try_into().unwrap()));
-				exec_success()
-			},
-			move |ctx, _| {
-				assert_eq!(ctx.ext.get_immutable_data().unwrap().into_inner(), vec![7, 5]);
-				exec_success()
-			},
-		);
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.existential_deposit(15)
-			.build()
-			.execute_with(|| {
-				set_balance(&ALICE, 1000);
-				let origin = Origin::from_account_id(ALICE);
-				let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap();
-				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
-
-				let addr = MockStack::run_instantiate(
-					ALICE,
-					MockExecutable::from_storage(hash, &mut gas_meter).unwrap(),
-					&mut gas_meter,
-					&mut storage_meter,
-					U256::zero(),
-					vec![],
-					None,
-					false,
-				)
-				.unwrap()
-				.0;
-
-				MockStack::run_call(
-					origin,
-					addr,
-					&mut GasMeter::<Test>::new(GAS_LIMIT),
-					&mut storage_meter,
-					U256::zero(),
-					vec![],
-					false,
-				)
-				.unwrap()
-			});
-	}
-
-	#[test]
-	fn immutable_data_set_errors_with_empty_data() {
-		let dummy_ch = MockLoader::insert(Constructor, move |ctx, _| {
-			// Calling `set_immutable_data` with empty data should error out
-			assert_eq!(
-				ctx.ext.set_immutable_data(Default::default()),
-				Err(Error::<Test>::InvalidImmutableAccess.into())
-			);
-			exec_success()
-		});
-		let instantiator_ch = MockLoader::insert(Call, {
-			move |ctx, _| {
-				let value = <Test as Config>::Currency::minimum_balance().into();
-				ctx.ext
-					.instantiate(Weight::MAX, U256::MAX, dummy_ch, value, vec![], None)
-					.unwrap();
-
-				exec_success()
-			}
-		});
-		ExtBuilder::default()
-			.with_code_hashes(MockLoader::code_hashes())
-			.existential_deposit(15)
-			.build()
-			.execute_with(|| {
-				set_balance(&ALICE, 1000);
-				set_balance(&BOB, 100);
-				place_contract(&BOB, instantiator_ch);
-				let origin = Origin::from_account_id(ALICE);
-				let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap();
-
-				MockStack::run_call(
-					origin,
-					BOB_ADDR,
-					&mut GasMeter::<Test>::new(GAS_LIMIT),
-					&mut storage_meter,
-					U256::zero(),
-					vec![],
-					false,
-				)
-				.unwrap()
-			});
-	}
-
-	#[test]
-	fn block_hash_returns_proper_values() {
-		let bob_code_hash = MockLoader::insert(Call, |ctx, _| {
-			ctx.ext.block_number = 1u32.into();
-			assert_eq!(ctx.ext.block_hash(U256::from(1)), None);
-			assert_eq!(ctx.ext.block_hash(U256::from(0)), Some(H256::from([1; 32])));
-
-			ctx.ext.block_number = 300u32.into();
-			assert_eq!(ctx.ext.block_hash(U256::from(300)), None);
-			assert_eq!(ctx.ext.block_hash(U256::from(43)), None);
-			assert_eq!(ctx.ext.block_hash(U256::from(44)), Some(H256::from([2; 32])));
-
-			exec_success()
-		});
-
-		ExtBuilder::default().build().execute_with(|| {
-			frame_system::BlockHash::<Test>::insert(
-				&BlockNumberFor::<Test>::from(0u32),
-				<tests::Test as frame_system::Config>::Hash::from([1; 32]),
-			);
-			frame_system::BlockHash::<Test>::insert(
-				&BlockNumberFor::<Test>::from(1u32),
-				<tests::Test as frame_system::Config>::Hash::default(),
-			);
-			frame_system::BlockHash::<Test>::insert(
-				&BlockNumberFor::<Test>::from(43u32),
-				<tests::Test as frame_system::Config>::Hash::default(),
-			);
-			frame_system::BlockHash::<Test>::insert(
-				&BlockNumberFor::<Test>::from(44u32),
-				<tests::Test as frame_system::Config>::Hash::from([2; 32]),
-			);
-			frame_system::BlockHash::<Test>::insert(
-				&BlockNumberFor::<Test>::from(300u32),
-				<tests::Test as frame_system::Config>::Hash::default(),
-			);
-
-			place_contract(&BOB, bob_code_hash);
-
-			let origin = Origin::from_account_id(ALICE);
-			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
-			assert_matches!(
-				MockStack::run_call(
-					origin,
-					BOB_ADDR,
-					&mut GasMeter::<Test>::new(GAS_LIMIT),
-					&mut storage_meter,
-					U256::zero(),
-					vec![0],
-					false,
-				),
-				Ok(_)
-			);
-		});
-	}
-}
diff --git a/substrate/frame/revive/src/exec/tests.rs b/substrate/frame/revive/src/exec/tests.rs
new file mode 100644
index 0000000000000000000000000000000000000000..2511715654c171ea5de097571ba581fb409b5068
--- /dev/null
+++ b/substrate/frame/revive/src/exec/tests.rs
@@ -0,0 +1,2949 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/// These tests exercise the executive layer.
+///
+/// In these tests the VM/loader are mocked. Instead of dealing with wasm bytecode they use
+/// simple closures. This allows you to tackle executive logic more thoroughly without writing
+/// a wasm VM code.
+#[cfg(test)]
+use super::*;
+use crate::{
+	exec::ExportedFunction::*,
+	gas::GasMeter,
+	test_utils::*,
+	tests::{
+		test_utils::{get_balance, place_contract, set_balance},
+		ExtBuilder, RuntimeCall, RuntimeEvent as MetaEvent, Test, TestFilter,
+	},
+	AddressMapper, Error,
+};
+use assert_matches::assert_matches;
+use frame_support::{assert_err, assert_noop, assert_ok, parameter_types};
+use frame_system::{AccountInfo, EventRecord, Phase};
+use pallet_revive_uapi::ReturnFlags;
+use pretty_assertions::assert_eq;
+use sp_io::hashing::keccak_256;
+use sp_runtime::{traits::Hash, DispatchError};
+use std::{cell::RefCell, collections::hash_map::HashMap, rc::Rc};
+
+type System = frame_system::Pallet<Test>;
+
+type MockStack<'a> = Stack<'a, Test, MockExecutable>;
+
+parameter_types! {
+	static Loader: MockLoader = MockLoader::default();
+}
+
+fn events() -> Vec<Event<Test>> {
+	System::events()
+		.into_iter()
+		.filter_map(|meta| match meta.event {
+			MetaEvent::Contracts(contract_event) => Some(contract_event),
+			_ => None,
+		})
+		.collect()
+}
+
+struct MockCtx<'a> {
+	ext: &'a mut MockStack<'a>,
+	input_data: Vec<u8>,
+}
+
+#[derive(Clone)]
+struct MockExecutable {
+	func: Rc<dyn for<'a> Fn(MockCtx<'a>, &Self) -> ExecResult + 'static>,
+	constructor: Rc<dyn for<'a> Fn(MockCtx<'a>, &Self) -> ExecResult + 'static>,
+	code_hash: H256,
+	code_info: CodeInfo<Test>,
+}
+
+#[derive(Default, Clone)]
+pub struct MockLoader {
+	map: HashMap<H256, MockExecutable>,
+	counter: u64,
+}
+
+impl MockLoader {
+	fn code_hashes() -> Vec<H256> {
+		Loader::get().map.keys().copied().collect()
+	}
+
+	fn insert(
+		func_type: ExportedFunction,
+		f: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static,
+	) -> H256 {
+		Loader::mutate(|loader| {
+			// Generate code hashes from contract index value.
+			let hash = H256(keccak_256(&loader.counter.to_le_bytes()));
+			loader.counter += 1;
+			if func_type == ExportedFunction::Constructor {
+				loader.map.insert(
+					hash,
+					MockExecutable {
+						func: Rc::new(|_, _| exec_success()),
+						constructor: Rc::new(f),
+						code_hash: hash,
+						code_info: CodeInfo::<Test>::new(ALICE),
+					},
+				);
+			} else {
+				loader.map.insert(
+					hash,
+					MockExecutable {
+						func: Rc::new(f),
+						constructor: Rc::new(|_, _| exec_success()),
+						code_hash: hash,
+						code_info: CodeInfo::<Test>::new(ALICE),
+					},
+				);
+			}
+			hash
+		})
+	}
+
+	fn insert_both(
+		constructor: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static,
+		call: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static,
+	) -> H256 {
+		Loader::mutate(|loader| {
+			// Generate code hashes from contract index value.
+			let hash = H256(keccak_256(&loader.counter.to_le_bytes()));
+			loader.counter += 1;
+			loader.map.insert(
+				hash,
+				MockExecutable {
+					func: Rc::new(call),
+					constructor: Rc::new(constructor),
+					code_hash: hash,
+					code_info: CodeInfo::<Test>::new(ALICE),
+				},
+			);
+			hash
+		})
+	}
+}
+
+impl Executable<Test> for MockExecutable {
+	fn from_storage(
+		code_hash: H256,
+		_gas_meter: &mut GasMeter<Test>,
+	) -> Result<Self, DispatchError> {
+		Loader::mutate(|loader| {
+			loader.map.get(&code_hash).cloned().ok_or(Error::<Test>::CodeNotFound.into())
+		})
+	}
+
+	fn execute<E: Ext<T = Test>>(
+		self,
+		ext: &mut E,
+		function: ExportedFunction,
+		input_data: Vec<u8>,
+	) -> ExecResult {
+		// # Safety
+		//
+		// We know that we **always** call execute with a `MockStack` in this test.
+		//
+		// # Note
+		//
+		// The transmute is necessary because `execute` has to be generic over all
+		// `E: Ext`. However, `MockExecutable` can't be generic over `E` as it would
+		// constitute a cycle.
+		let ext = unsafe { mem::transmute(ext) };
+		if function == ExportedFunction::Constructor {
+			(self.constructor)(MockCtx { ext, input_data }, &self)
+		} else {
+			(self.func)(MockCtx { ext, input_data }, &self)
+		}
+	}
+
+	fn code(&self) -> &[u8] {
+		// The mock executable doesn't have code", so we return the code hash.
+		self.code_hash.as_ref()
+	}
+
+	fn code_hash(&self) -> &H256 {
+		&self.code_hash
+	}
+
+	fn code_info(&self) -> &CodeInfo<Test> {
+		&self.code_info
+	}
+}
+
+fn exec_success() -> ExecResult {
+	Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
+}
+
+fn exec_trapped() -> ExecResult {
+	Err(ExecError { error: <Error<Test>>::ContractTrapped.into(), origin: ErrorOrigin::Callee })
+}
+
+#[test]
+fn it_works() {
+	parameter_types! {
+		static TestData: Vec<usize> = vec![0];
+	}
+
+	let value = Default::default();
+	let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+	let exec_ch = MockLoader::insert(Call, |_ctx, _executable| {
+		TestData::mutate(|data| data.push(1));
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, exec_ch);
+		let mut storage_meter =
+			storage::meter::Meter::new(&Origin::from_account_id(ALICE), 0, value).unwrap();
+
+		assert_matches!(
+			MockStack::run_call(
+				Origin::from_account_id(ALICE),
+				BOB_ADDR,
+				&mut gas_meter,
+				&mut storage_meter,
+				value.into(),
+				vec![],
+				false,
+			),
+			Ok(_)
+		);
+	});
+
+	assert_eq!(TestData::get(), vec![0, 1]);
+}
+
+#[test]
+fn transfer_works() {
+	// This test verifies that a contract is able to transfer
+	// some funds to another account.
+	ExtBuilder::default().build().execute_with(|| {
+		set_balance(&ALICE, 100);
+		set_balance(&BOB, 0);
+
+		let origin = Origin::from_account_id(ALICE);
+		MockStack::transfer(&origin, &ALICE, &BOB, 55u64.into()).unwrap();
+
+		let min_balance = <Test as Config>::Currency::minimum_balance();
+		assert_eq!(get_balance(&ALICE), 45 - min_balance);
+		assert_eq!(get_balance(&BOB), 55 + min_balance);
+	});
+}
+
+#[test]
+fn transfer_to_nonexistent_account_works() {
+	// This test verifies that a contract is able to transfer
+	// some funds to a nonexistant account and that those transfers
+	// are not able to reap accounts.
+	ExtBuilder::default().build().execute_with(|| {
+		let ed = <Test as Config>::Currency::minimum_balance();
+		let value = 1024;
+
+		// Transfers to nonexistant accounts should work
+		set_balance(&ALICE, ed * 2);
+		set_balance(&BOB, ed + value);
+
+		assert_ok!(MockStack::transfer(
+			&Origin::from_account_id(ALICE),
+			&BOB,
+			&CHARLIE,
+			value.into()
+		));
+		assert_eq!(get_balance(&ALICE), ed);
+		assert_eq!(get_balance(&BOB), ed);
+		assert_eq!(get_balance(&CHARLIE), ed + value);
+
+		// Do not reap the origin account
+		set_balance(&ALICE, ed);
+		set_balance(&BOB, ed + value);
+		assert_err!(
+			MockStack::transfer(&Origin::from_account_id(ALICE), &BOB, &DJANGO, value.into()),
+			<Error<Test>>::TransferFailed
+		);
+
+		// Do not reap the sender account
+		set_balance(&ALICE, ed * 2);
+		set_balance(&BOB, value);
+		assert_err!(
+			MockStack::transfer(&Origin::from_account_id(ALICE), &BOB, &EVE, value.into()),
+			<Error<Test>>::TransferFailed
+		);
+		// The ED transfer would work. But it should only be executed with the actual transfer
+		assert!(!System::account_exists(&EVE));
+	});
+}
+
+#[test]
+fn correct_transfer_on_call() {
+	let value = 55;
+
+	let success_ch = MockLoader::insert(Call, move |ctx, _| {
+		assert_eq!(ctx.ext.value_transferred(), U256::from(value));
+		Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, success_ch);
+		set_balance(&ALICE, 100);
+		let balance = get_balance(&BOB_FALLBACK);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, value).unwrap();
+
+		let _ = MockStack::run_call(
+			origin.clone(),
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			value.into(),
+			vec![],
+			false,
+		)
+		.unwrap();
+
+		assert_eq!(get_balance(&ALICE), 100 - value);
+		assert_eq!(get_balance(&BOB_FALLBACK), balance + value);
+	});
+}
+
+#[test]
+fn correct_transfer_on_delegate_call() {
+	let value = 35;
+
+	let success_ch = MockLoader::insert(Call, move |ctx, _| {
+		assert_eq!(ctx.ext.value_transferred(), U256::from(value));
+		Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
+	});
+
+	let delegate_ch = MockLoader::insert(Call, move |ctx, _| {
+		assert_eq!(ctx.ext.value_transferred(), U256::from(value));
+		let _ = ctx.ext.delegate_call(Weight::zero(), U256::zero(), CHARLIE_ADDR, Vec::new())?;
+		Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, delegate_ch);
+		place_contract(&CHARLIE, success_ch);
+		set_balance(&ALICE, 100);
+		let balance = get_balance(&BOB_FALLBACK);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 55).unwrap();
+
+		assert_ok!(MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			value.into(),
+			vec![],
+			false,
+		));
+
+		assert_eq!(get_balance(&ALICE), 100 - value);
+		assert_eq!(get_balance(&BOB_FALLBACK), balance + value);
+	});
+}
+
+#[test]
+fn delegate_call_missing_contract() {
+	let missing_ch = MockLoader::insert(Call, move |_ctx, _| {
+		Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
+	});
+
+	let delegate_ch = MockLoader::insert(Call, move |ctx, _| {
+		let _ = ctx.ext.delegate_call(Weight::zero(), U256::zero(), CHARLIE_ADDR, Vec::new())?;
+		Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, delegate_ch);
+		set_balance(&ALICE, 100);
+
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 55).unwrap();
+
+		// contract code missing
+		assert_noop!(
+			MockStack::run_call(
+				origin.clone(),
+				BOB_ADDR,
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
+				&mut storage_meter,
+				U256::zero(),
+				vec![],
+				false,
+			),
+			ExecError { error: Error::<Test>::CodeNotFound.into(), origin: ErrorOrigin::Callee }
+		);
+
+		// add missing contract code
+		place_contract(&CHARLIE, missing_ch);
+		assert_ok!(MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		));
+	});
+}
+
+#[test]
+fn changes_are_reverted_on_failing_call() {
+	// This test verifies that changes are reverted on a call which fails (or equally, returns
+	// a non-zero status code).
+
+	let return_ch = MockLoader::insert(Call, |_, _| {
+		Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: Vec::new() })
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, return_ch);
+		set_balance(&ALICE, 100);
+		let balance = get_balance(&BOB);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 55).unwrap();
+
+		let output = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			55u64.into(),
+			vec![],
+			false,
+		)
+		.unwrap();
+
+		assert!(output.did_revert());
+		assert_eq!(get_balance(&ALICE), 100);
+		assert_eq!(get_balance(&BOB), balance);
+	});
+}
+
+#[test]
+fn balance_too_low() {
+	// This test verifies that a contract can't send value if it's
+	// balance is too low.
+	let from = ALICE;
+	let origin = Origin::from_account_id(ALICE);
+	let dest = BOB;
+
+	ExtBuilder::default().build().execute_with(|| {
+		set_balance(&from, 0);
+
+		let result = MockStack::transfer(&origin, &from, &dest, 100u64.into());
+
+		assert_eq!(result, Err(Error::<Test>::TransferFailed.into()));
+		assert_eq!(get_balance(&from), 0);
+		assert_eq!(get_balance(&dest), 0);
+	});
+}
+
+#[test]
+fn output_is_returned_on_success() {
+	// Verifies that if a contract returns data with a successful exit status, this data
+	// is returned from the execution context.
+	let return_ch = MockLoader::insert(Call, |_, _| {
+		Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![1, 2, 3, 4] })
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		place_contract(&BOB, return_ch);
+
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		);
+
+		let output = result.unwrap();
+		assert!(!output.did_revert());
+		assert_eq!(output.data, vec![1, 2, 3, 4]);
+	});
+}
+
+#[test]
+fn output_is_returned_on_failure() {
+	// Verifies that if a contract returns data with a failing exit status, this data
+	// is returned from the execution context.
+	let return_ch = MockLoader::insert(Call, |_, _| {
+		Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![1, 2, 3, 4] })
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, return_ch);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		);
+
+		let output = result.unwrap();
+		assert!(output.did_revert());
+		assert_eq!(output.data, vec![1, 2, 3, 4]);
+	});
+}
+
+#[test]
+fn input_data_to_call() {
+	let input_data_ch = MockLoader::insert(Call, |ctx, _| {
+		assert_eq!(ctx.input_data, &[1, 2, 3, 4]);
+		exec_success()
+	});
+
+	// This one tests passing the input data into a contract via call.
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, input_data_ch);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![1, 2, 3, 4],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn input_data_to_instantiate() {
+	let input_data_ch = MockLoader::insert(Constructor, |ctx, _| {
+		assert_eq!(ctx.input_data, &[1, 2, 3, 4]);
+		exec_success()
+	});
+
+	// This one tests passing the input data into a contract via instantiate.
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.build()
+		.execute_with(|| {
+			let min_balance = <Test as Config>::Currency::minimum_balance();
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+			let executable = MockExecutable::from_storage(input_data_ch, &mut gas_meter).unwrap();
+			set_balance(&ALICE, min_balance * 10_000);
+			let origin = Origin::from_account_id(ALICE);
+			let mut storage_meter =
+				storage::meter::Meter::new(&origin, deposit_limit::<Test>(), min_balance).unwrap();
+
+			let result = MockStack::run_instantiate(
+				ALICE,
+				executable,
+				&mut gas_meter,
+				&mut storage_meter,
+				min_balance.into(),
+				vec![1, 2, 3, 4],
+				Some(&[0; 32]),
+				false,
+			);
+			assert_matches!(result, Ok(_));
+		});
+}
+
+#[test]
+fn max_depth() {
+	// This test verifies that when we reach the maximal depth creation of an
+	// yet another context fails.
+	parameter_types! {
+		static ReachedBottom: bool = false;
+	}
+	let value = Default::default();
+	let recurse_ch = MockLoader::insert(Call, |ctx, _| {
+		// Try to call into yourself.
+		let r = ctx.ext.call(
+			Weight::zero(),
+			U256::zero(),
+			&BOB_ADDR,
+			U256::zero(),
+			vec![],
+			true,
+			false,
+		);
+
+		ReachedBottom::mutate(|reached_bottom| {
+			if !*reached_bottom {
+				// We are first time here, it means we just reached bottom.
+				// Verify that we've got proper error and set `reached_bottom`.
+				assert_eq!(r, Err(Error::<Test>::MaxCallDepthReached.into()));
+				*reached_bottom = true;
+			} else {
+				// We just unwinding stack here.
+				assert_matches!(r, Ok(_));
+			}
+		});
+
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		set_balance(&BOB, 1);
+		place_contract(&BOB, recurse_ch);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, value).unwrap();
+
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			value.into(),
+			vec![],
+			false,
+		);
+
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn caller_returns_proper_values() {
+	parameter_types! {
+		static WitnessedCallerBob: Option<H160> = None;
+		static WitnessedCallerCharlie: Option<H160> = None;
+	}
+
+	let bob_ch = MockLoader::insert(Call, |ctx, _| {
+		// Record the caller for bob.
+		WitnessedCallerBob::mutate(|caller| {
+			let origin = ctx.ext.caller();
+			*caller = Some(<<Test as Config>::AddressMapper as AddressMapper<Test>>::to_address(
+				&origin.account_id().unwrap(),
+			));
+		});
+
+		// Call into CHARLIE contract.
+		assert_matches!(
+			ctx.ext.call(
+				Weight::zero(),
+				U256::zero(),
+				&CHARLIE_ADDR,
+				U256::zero(),
+				vec![],
+				true,
+				false
+			),
+			Ok(_)
+		);
+		exec_success()
+	});
+	let charlie_ch = MockLoader::insert(Call, |ctx, _| {
+		// Record the caller for charlie.
+		WitnessedCallerCharlie::mutate(|caller| {
+			let origin = ctx.ext.caller();
+			*caller = Some(<<Test as Config>::AddressMapper as AddressMapper<Test>>::to_address(
+				&origin.account_id().unwrap(),
+			));
+		});
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, bob_ch);
+		place_contract(&CHARLIE, charlie_ch);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		);
+
+		assert_matches!(result, Ok(_));
+	});
+
+	assert_eq!(WitnessedCallerBob::get(), Some(ALICE_ADDR));
+	assert_eq!(WitnessedCallerCharlie::get(), Some(BOB_ADDR));
+}
+
+#[test]
+fn origin_returns_proper_values() {
+	parameter_types! {
+		static WitnessedCallerBob: Option<H160> = None;
+		static WitnessedCallerCharlie: Option<H160> = None;
+	}
+
+	let bob_ch = MockLoader::insert(Call, |ctx, _| {
+		// Record the origin for bob.
+		WitnessedCallerBob::mutate(|witness| {
+			let origin = ctx.ext.origin();
+			*witness =
+				Some(<Test as Config>::AddressMapper::to_address(&origin.account_id().unwrap()));
+		});
+
+		// Call into CHARLIE contract.
+		assert_matches!(
+			ctx.ext.call(
+				Weight::zero(),
+				U256::zero(),
+				&CHARLIE_ADDR,
+				U256::zero(),
+				vec![],
+				true,
+				false
+			),
+			Ok(_)
+		);
+		exec_success()
+	});
+	let charlie_ch = MockLoader::insert(Call, |ctx, _| {
+		// Record the origin for charlie.
+		WitnessedCallerCharlie::mutate(|witness| {
+			let origin = ctx.ext.origin();
+			*witness =
+				Some(<Test as Config>::AddressMapper::to_address(&origin.account_id().unwrap()));
+		});
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, bob_ch);
+		place_contract(&CHARLIE, charlie_ch);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		);
+
+		assert_matches!(result, Ok(_));
+	});
+
+	assert_eq!(WitnessedCallerBob::get(), Some(ALICE_ADDR));
+	assert_eq!(WitnessedCallerCharlie::get(), Some(ALICE_ADDR));
+}
+
+#[test]
+fn is_contract_returns_proper_values() {
+	let bob_ch = MockLoader::insert(Call, |ctx, _| {
+		// Verify that BOB is a contract
+		assert!(ctx.ext.is_contract(&BOB_ADDR));
+		// Verify that ALICE is not a contract
+		assert!(!ctx.ext.is_contract(&ALICE_ADDR));
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, bob_ch);
+
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn to_account_id_returns_proper_values() {
+	let bob_code_hash = MockLoader::insert(Call, |ctx, _| {
+		let alice_account_id = <Test as Config>::AddressMapper::to_account_id(&ALICE_ADDR);
+		assert_eq!(ctx.ext.to_account_id(&ALICE_ADDR), alice_account_id);
+
+		const UNMAPPED_ADDR: H160 = H160([99u8; 20]);
+		let mut unmapped_fallback_account_id = [0xEE; 32];
+		unmapped_fallback_account_id[..20].copy_from_slice(UNMAPPED_ADDR.as_bytes());
+		assert_eq!(
+			ctx.ext.to_account_id(&UNMAPPED_ADDR),
+			AccountId32::new(unmapped_fallback_account_id)
+		);
+
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, bob_code_hash);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![0],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn code_hash_returns_proper_values() {
+	let bob_code_hash = MockLoader::insert(Call, |ctx, _| {
+		// ALICE is not a contract but account exists so it returns hash of empty data
+		assert_eq!(ctx.ext.code_hash(&ALICE_ADDR), EMPTY_CODE_HASH);
+		// BOB is a contract (this function) and hence it has a code_hash.
+		// `MockLoader` uses contract index to generate the code hash.
+		assert_eq!(ctx.ext.code_hash(&BOB_ADDR), H256(keccak_256(&0u64.to_le_bytes())));
+		// [0xff;20] doesn't exist and returns hash zero
+		assert!(ctx.ext.code_hash(&H160([0xff; 20])).is_zero());
+
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		// add alice account info to test case EOA code hash
+		frame_system::Account::<Test>::insert(
+			<Test as Config>::AddressMapper::to_account_id(&ALICE_ADDR),
+			AccountInfo { consumers: 1, providers: 1, ..Default::default() },
+		);
+		place_contract(&BOB, bob_code_hash);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		// ALICE (not contract) -> BOB (contract)
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![0],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn own_code_hash_returns_proper_values() {
+	let bob_ch = MockLoader::insert(Call, |ctx, _| {
+		let code_hash = ctx.ext.code_hash(&BOB_ADDR);
+		assert_eq!(*ctx.ext.own_code_hash(), code_hash);
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, bob_ch);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		// ALICE (not contract) -> BOB (contract)
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![0],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn caller_is_origin_returns_proper_values() {
+	let code_charlie = MockLoader::insert(Call, |ctx, _| {
+		// BOB is not the origin of the stack call
+		assert!(!ctx.ext.caller_is_origin());
+		exec_success()
+	});
+
+	let code_bob = MockLoader::insert(Call, |ctx, _| {
+		// ALICE is the origin of the call stack
+		assert!(ctx.ext.caller_is_origin());
+		// BOB calls CHARLIE
+		ctx.ext
+			.call(Weight::zero(), U256::zero(), &CHARLIE_ADDR, U256::zero(), vec![], true, false)
+			.map(|_| ctx.ext.last_frame_output().clone())
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, code_bob);
+		place_contract(&CHARLIE, code_charlie);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		// ALICE -> BOB (caller is origin) -> CHARLIE (caller is not origin)
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![0],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn root_caller_succeeds() {
+	let code_bob = MockLoader::insert(Call, |ctx, _| {
+		// root is the origin of the call stack.
+		assert!(ctx.ext.caller_is_root());
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, code_bob);
+		let origin = Origin::Root;
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		// root -> BOB (caller is root)
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![0],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn root_caller_does_not_succeed_when_value_not_zero() {
+	let code_bob = MockLoader::insert(Call, |ctx, _| {
+		// root is the origin of the call stack.
+		assert!(ctx.ext.caller_is_root());
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, code_bob);
+		let origin = Origin::Root;
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		// root -> BOB (caller is root)
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			1u64.into(),
+			vec![0],
+			false,
+		);
+		assert_matches!(result, Err(_));
+	});
+}
+
+#[test]
+fn root_caller_succeeds_with_consecutive_calls() {
+	let code_charlie = MockLoader::insert(Call, |ctx, _| {
+		// BOB is not root, even though the origin is root.
+		assert!(!ctx.ext.caller_is_root());
+		exec_success()
+	});
+
+	let code_bob = MockLoader::insert(Call, |ctx, _| {
+		// root is the origin of the call stack.
+		assert!(ctx.ext.caller_is_root());
+		// BOB calls CHARLIE.
+		ctx.ext
+			.call(Weight::zero(), U256::zero(), &CHARLIE_ADDR, U256::zero(), vec![], true, false)
+			.map(|_| ctx.ext.last_frame_output().clone())
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, code_bob);
+		place_contract(&CHARLIE, code_charlie);
+		let origin = Origin::Root;
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		// root -> BOB (caller is root) -> CHARLIE (caller is not root)
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![0],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn address_returns_proper_values() {
+	let bob_ch = MockLoader::insert(Call, |ctx, _| {
+		// Verify that address matches BOB.
+		assert_eq!(ctx.ext.address(), BOB_ADDR);
+
+		// Call into charlie contract.
+		assert_matches!(
+			ctx.ext.call(
+				Weight::zero(),
+				U256::zero(),
+				&CHARLIE_ADDR,
+				U256::zero(),
+				vec![],
+				true,
+				false
+			),
+			Ok(_)
+		);
+		exec_success()
+	});
+	let charlie_ch = MockLoader::insert(Call, |ctx, _| {
+		assert_eq!(ctx.ext.address(), CHARLIE_ADDR);
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, bob_ch);
+		place_contract(&CHARLIE, charlie_ch);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		);
+
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn refuse_instantiate_with_value_below_existential_deposit() {
+	let dummy_ch = MockLoader::insert(Constructor, |_, _| exec_success());
+
+	ExtBuilder::default().existential_deposit(15).build().execute_with(|| {
+		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+		let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+
+		assert_matches!(
+			MockStack::run_instantiate(
+				ALICE,
+				executable,
+				&mut gas_meter,
+				&mut storage_meter,
+				U256::zero(), // <- zero value
+				vec![],
+				Some(&[0; 32]),
+				false,
+			),
+			Err(_)
+		);
+	});
+}
+
+#[test]
+fn instantiation_work_with_success_output() {
+	let dummy_ch = MockLoader::insert(Constructor, |_, _| {
+		Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![80, 65, 83, 83] })
+	});
+
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.existential_deposit(15)
+		.build()
+		.execute_with(|| {
+			let min_balance = <Test as Config>::Currency::minimum_balance();
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+			let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
+			set_balance(&ALICE, min_balance * 1000);
+			let origin = Origin::from_account_id(ALICE);
+			let mut storage_meter =
+				storage::meter::Meter::new(&origin, min_balance * 100, min_balance).unwrap();
+
+			let instantiated_contract_address = assert_matches!(
+				MockStack::run_instantiate(
+					ALICE,
+					executable,
+					&mut gas_meter,
+					&mut storage_meter,
+					min_balance.into(),
+					vec![],
+					Some(&[0 ;32]),
+					false,
+				),
+				Ok((address, ref output)) if output.data == vec![80, 65, 83, 83] => address
+			);
+			let instantiated_contract_id =
+				<<Test as Config>::AddressMapper as AddressMapper<Test>>::to_fallback_account_id(
+					&instantiated_contract_address,
+				);
+
+			// Check that the newly created account has the expected code hash and
+			// there are instantiation event.
+			assert_eq!(
+				ContractInfo::<Test>::load_code_hash(&instantiated_contract_id).unwrap(),
+				dummy_ch
+			);
+		});
+}
+
+#[test]
+fn instantiation_fails_with_failing_output() {
+	let dummy_ch = MockLoader::insert(Constructor, |_, _| {
+		Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70, 65, 73, 76] })
+	});
+
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.existential_deposit(15)
+		.build()
+		.execute_with(|| {
+			let min_balance = <Test as Config>::Currency::minimum_balance();
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+			let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
+			set_balance(&ALICE, min_balance * 1000);
+			let origin = Origin::from_account_id(ALICE);
+			let mut storage_meter =
+				storage::meter::Meter::new(&origin, min_balance * 100, min_balance).unwrap();
+
+			let instantiated_contract_address = assert_matches!(
+				MockStack::run_instantiate(
+					ALICE,
+					executable,
+					&mut gas_meter,
+					&mut storage_meter,
+					min_balance.into(),
+					vec![],
+					Some(&[0; 32]),
+					false,
+				),
+				Ok((address, ref output)) if output.data == vec![70, 65, 73, 76] => address
+			);
+
+			let instantiated_contract_id =
+				<<Test as Config>::AddressMapper as AddressMapper<Test>>::to_fallback_account_id(
+					&instantiated_contract_address,
+				);
+
+			// Check that the account has not been created.
+			assert!(ContractInfo::<Test>::load_code_hash(&instantiated_contract_id).is_none());
+			assert!(events().is_empty());
+		});
+}
+
+#[test]
+fn instantiation_from_contract() {
+	let dummy_ch = MockLoader::insert(Call, |_, _| exec_success());
+	let instantiated_contract_address = Rc::new(RefCell::new(None::<H160>));
+	let instantiator_ch = MockLoader::insert(Call, {
+		let instantiated_contract_address = Rc::clone(&instantiated_contract_address);
+		move |ctx, _| {
+			// Instantiate a contract and save it's address in `instantiated_contract_address`.
+			let (address, output) = ctx
+				.ext
+				.instantiate(
+					Weight::MAX,
+					U256::MAX,
+					dummy_ch,
+					<Test as Config>::Currency::minimum_balance().into(),
+					vec![],
+					Some(&[48; 32]),
+				)
+				.map(|address| (address, ctx.ext.last_frame_output().clone()))
+				.unwrap();
+
+			*instantiated_contract_address.borrow_mut() = Some(address);
+			Ok(output)
+		}
+	});
+
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.existential_deposit(15)
+		.build()
+		.execute_with(|| {
+			let min_balance = <Test as Config>::Currency::minimum_balance();
+			set_balance(&ALICE, min_balance * 100);
+			place_contract(&BOB, instantiator_ch);
+			let origin = Origin::from_account_id(ALICE);
+			let mut storage_meter =
+				storage::meter::Meter::new(&origin, min_balance * 10, min_balance * 10).unwrap();
+
+			assert_matches!(
+				MockStack::run_call(
+					origin,
+					BOB_ADDR,
+					&mut GasMeter::<Test>::new(GAS_LIMIT),
+					&mut storage_meter,
+					(min_balance * 10).into(),
+					vec![],
+					false,
+				),
+				Ok(_)
+			);
+
+			let instantiated_contract_address =
+				*instantiated_contract_address.borrow().as_ref().unwrap();
+
+			let instantiated_contract_id =
+				<<Test as Config>::AddressMapper as AddressMapper<Test>>::to_fallback_account_id(
+					&instantiated_contract_address,
+				);
+
+			// Check that the newly created account has the expected code hash and
+			// there are instantiation event.
+			assert_eq!(
+				ContractInfo::<Test>::load_code_hash(&instantiated_contract_id).unwrap(),
+				dummy_ch
+			);
+		});
+}
+
+#[test]
+fn instantiation_traps() {
+	let dummy_ch = MockLoader::insert(Constructor, |_, _| Err("It's a trap!".into()));
+	let instantiator_ch = MockLoader::insert(Call, {
+		move |ctx, _| {
+			// Instantiate a contract and save it's address in `instantiated_contract_address`.
+			assert_matches!(
+				ctx.ext.instantiate(
+					Weight::zero(),
+					U256::zero(),
+					dummy_ch,
+					<Test as Config>::Currency::minimum_balance().into(),
+					vec![],
+					Some(&[0; 32]),
+				),
+				Err(ExecError {
+					error: DispatchError::Other("It's a trap!"),
+					origin: ErrorOrigin::Callee,
+				})
+			);
+
+			exec_success()
+		}
+	});
+
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.existential_deposit(15)
+		.build()
+		.execute_with(|| {
+			set_balance(&ALICE, 1000);
+			set_balance(&BOB_FALLBACK, 100);
+			place_contract(&BOB, instantiator_ch);
+			let origin = Origin::from_account_id(ALICE);
+			let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap();
+
+			assert_matches!(
+				MockStack::run_call(
+					origin,
+					BOB_ADDR,
+					&mut GasMeter::<Test>::new(GAS_LIMIT),
+					&mut storage_meter,
+					U256::zero(),
+					vec![],
+					false,
+				),
+				Ok(_)
+			);
+		});
+}
+
+#[test]
+fn termination_from_instantiate_fails() {
+	let terminate_ch = MockLoader::insert(Constructor, |ctx, _| {
+		ctx.ext.terminate(&ALICE_ADDR)?;
+		exec_success()
+	});
+
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.existential_deposit(15)
+		.build()
+		.execute_with(|| {
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+			let executable = MockExecutable::from_storage(terminate_ch, &mut gas_meter).unwrap();
+			set_balance(&ALICE, 10_000);
+			let origin = Origin::from_account_id(ALICE);
+			let mut storage_meter =
+				storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 100).unwrap();
+
+			assert_eq!(
+				MockStack::run_instantiate(
+					ALICE,
+					executable,
+					&mut gas_meter,
+					&mut storage_meter,
+					100u64.into(),
+					vec![],
+					Some(&[0; 32]),
+					false,
+				),
+				Err(ExecError {
+					error: Error::<Test>::TerminatedInConstructor.into(),
+					origin: ErrorOrigin::Callee
+				})
+			);
+
+			assert_eq!(&events(), &[]);
+		});
+}
+
+#[test]
+fn in_memory_changes_not_discarded() {
+	// Call stack: BOB -> CHARLIE (trap) -> BOB' (success)
+	// This tests verifies some edge case of the contract info cache:
+	// We change some value in our contract info before calling into a contract
+	// that calls into ourself. This triggers a case where BOBs contract info
+	// is written to storage and invalidated by the successful execution of BOB'.
+	// The trap of CHARLIE reverts the storage changes to BOB. When the root BOB regains
+	// control it reloads its contract info from storage. We check that changes that
+	// are made before calling into CHARLIE are not discarded.
+	let code_bob = MockLoader::insert(Call, |ctx, _| {
+		if ctx.input_data[0] == 0 {
+			let info = ctx.ext.contract_info();
+			assert_eq!(info.storage_byte_deposit, 0);
+			info.storage_byte_deposit = 42;
+			assert_eq!(
+				ctx.ext
+					.call(
+						Weight::zero(),
+						U256::zero(),
+						&CHARLIE_ADDR,
+						U256::zero(),
+						vec![],
+						true,
+						false
+					)
+					.map(|_| ctx.ext.last_frame_output().clone()),
+				exec_trapped()
+			);
+			assert_eq!(ctx.ext.contract_info().storage_byte_deposit, 42);
+		}
+		exec_success()
+	});
+	let code_charlie = MockLoader::insert(Call, |ctx, _| {
+		assert!(ctx
+			.ext
+			.call(Weight::zero(), U256::zero(), &BOB_ADDR, U256::zero(), vec![99], true, false)
+			.is_ok());
+		exec_trapped()
+	});
+
+	// This one tests passing the input data into a contract via call.
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, code_bob);
+		place_contract(&CHARLIE, code_charlie);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![0],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn recursive_call_during_constructor_is_balance_transfer() {
+	let code = MockLoader::insert(Constructor, |ctx, _| {
+		let account_id = ctx.ext.account_id().clone();
+		let addr =
+			<<Test as Config>::AddressMapper as AddressMapper<Test>>::to_address(&account_id);
+		let balance = ctx.ext.balance();
+
+		// Calling ourselves during the constructor will trigger a balance
+		// transfer since no contract exist yet.
+		assert_ok!(ctx.ext.call(
+			Weight::zero(),
+			U256::zero(),
+			&addr,
+			(balance - 1).into(),
+			vec![],
+			true,
+			false
+		));
+
+		// Should also work with call data set as it is ignored when no
+		// contract is deployed.
+		assert_ok!(ctx.ext.call(
+			Weight::zero(),
+			U256::zero(),
+			&addr,
+			1u32.into(),
+			vec![1, 2, 3, 4],
+			true,
+			false
+		));
+		exec_success()
+	});
+
+	// This one tests passing the input data into a contract via instantiate.
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.build()
+		.execute_with(|| {
+			let min_balance = <Test as Config>::Currency::minimum_balance();
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+			let executable = MockExecutable::from_storage(code, &mut gas_meter).unwrap();
+			set_balance(&ALICE, min_balance * 10_000);
+			let origin = Origin::from_account_id(ALICE);
+			let mut storage_meter =
+				storage::meter::Meter::new(&origin, deposit_limit::<Test>(), min_balance).unwrap();
+
+			let result = MockStack::run_instantiate(
+				ALICE,
+				executable,
+				&mut gas_meter,
+				&mut storage_meter,
+				10u64.into(),
+				vec![],
+				Some(&[0; 32]),
+				false,
+			);
+			assert_matches!(result, Ok(_));
+		});
+}
+
+#[test]
+fn cannot_send_more_balance_than_available_to_self() {
+	let code_hash = MockLoader::insert(Call, |ctx, _| {
+		let account_id = ctx.ext.account_id().clone();
+		let addr =
+			<<Test as Config>::AddressMapper as AddressMapper<Test>>::to_address(&account_id);
+		let balance = ctx.ext.balance();
+
+		assert_err!(
+			ctx.ext.call(
+				Weight::zero(),
+				U256::zero(),
+				&addr,
+				(balance + 1).into(),
+				vec![],
+				true,
+				false
+			),
+			<Error<Test>>::TransferFailed,
+		);
+		exec_success()
+	});
+
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.build()
+		.execute_with(|| {
+			let min_balance = <Test as Config>::Currency::minimum_balance();
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+			set_balance(&ALICE, min_balance * 10);
+			place_contract(&BOB, code_hash);
+			let origin = Origin::from_account_id(ALICE);
+			let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+			MockStack::run_call(
+				origin,
+				BOB_ADDR,
+				&mut gas_meter,
+				&mut storage_meter,
+				U256::zero(),
+				vec![],
+				false,
+			)
+			.unwrap();
+		});
+}
+
+#[test]
+fn call_reentry_direct_recursion() {
+	// call the contract passed as input with disabled reentry
+	let code_bob = MockLoader::insert(Call, |ctx, _| {
+		let dest = H160::from_slice(ctx.input_data.as_ref());
+		ctx.ext
+			.call(Weight::zero(), U256::zero(), &dest, U256::zero(), vec![], false, false)
+			.map(|_| ctx.ext.last_frame_output().clone())
+	});
+
+	let code_charlie = MockLoader::insert(Call, |_, _| exec_success());
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, code_bob);
+		place_contract(&CHARLIE, code_charlie);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+
+		// Calling another contract should succeed
+		assert_ok!(MockStack::run_call(
+			origin.clone(),
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			CHARLIE_ADDR.as_bytes().to_vec(),
+			false,
+		));
+
+		// Calling into oneself fails
+		assert_err!(
+			MockStack::run_call(
+				origin,
+				BOB_ADDR,
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
+				&mut storage_meter,
+				U256::zero(),
+				BOB_ADDR.as_bytes().to_vec(),
+				false,
+			)
+			.map_err(|e| e.error),
+			<Error<Test>>::ReentranceDenied,
+		);
+	});
+}
+
+#[test]
+fn call_deny_reentry() {
+	let code_bob = MockLoader::insert(Call, |ctx, _| {
+		if ctx.input_data[0] == 0 {
+			ctx.ext
+				.call(
+					Weight::zero(),
+					U256::zero(),
+					&CHARLIE_ADDR,
+					U256::zero(),
+					vec![],
+					false,
+					false,
+				)
+				.map(|_| ctx.ext.last_frame_output().clone())
+		} else {
+			exec_success()
+		}
+	});
+
+	// call BOB with input set to '1'
+	let code_charlie = MockLoader::insert(Call, |ctx, _| {
+		ctx.ext
+			.call(Weight::zero(), U256::zero(), &BOB_ADDR, U256::zero(), vec![1], true, false)
+			.map(|_| ctx.ext.last_frame_output().clone())
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, code_bob);
+		place_contract(&CHARLIE, code_charlie);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+
+		// BOB -> CHARLIE -> BOB fails as BOB denies reentry.
+		assert_err!(
+			MockStack::run_call(
+				origin,
+				BOB_ADDR,
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
+				&mut storage_meter,
+				U256::zero(),
+				vec![0],
+				false,
+			)
+			.map_err(|e| e.error),
+			<Error<Test>>::ReentranceDenied,
+		);
+	});
+}
+
+#[test]
+fn call_runtime_works() {
+	let code_hash = MockLoader::insert(Call, |ctx, _| {
+		let call = RuntimeCall::System(frame_system::Call::remark_with_event {
+			remark: b"Hello World".to_vec(),
+		});
+		ctx.ext.call_runtime(call).unwrap();
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		let min_balance = <Test as Config>::Currency::minimum_balance();
+
+		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+		set_balance(&ALICE, min_balance * 10);
+		place_contract(&BOB, code_hash);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		System::reset_events();
+		MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut gas_meter,
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		)
+		.unwrap();
+
+		let remark_hash = <Test as frame_system::Config>::Hashing::hash(b"Hello World");
+		assert_eq!(
+			System::events(),
+			vec![EventRecord {
+				phase: Phase::Initialization,
+				event: MetaEvent::System(frame_system::Event::Remarked {
+					sender: BOB_FALLBACK,
+					hash: remark_hash
+				}),
+				topics: vec![],
+			},]
+		);
+	});
+}
+
+#[test]
+fn call_runtime_filter() {
+	let code_hash = MockLoader::insert(Call, |ctx, _| {
+		use frame_system::Call as SysCall;
+		use pallet_balances::Call as BalanceCall;
+		use pallet_utility::Call as UtilCall;
+
+		// remark should still be allowed
+		let allowed_call =
+			RuntimeCall::System(SysCall::remark_with_event { remark: b"Hello".to_vec() });
+
+		// transfers are disallowed by the `TestFiler` (see below)
+		let forbidden_call =
+			RuntimeCall::Balances(BalanceCall::transfer_allow_death { dest: CHARLIE, value: 22 });
+
+		// simple cases: direct call
+		assert_err!(
+			ctx.ext.call_runtime(forbidden_call.clone()),
+			frame_system::Error::<Test>::CallFiltered
+		);
+
+		// as part of a patch: return is OK (but it interrupted the batch)
+		assert_ok!(ctx.ext.call_runtime(RuntimeCall::Utility(UtilCall::batch {
+			calls: vec![allowed_call.clone(), forbidden_call, allowed_call]
+		})),);
+
+		// the transfer wasn't performed
+		assert_eq!(get_balance(&CHARLIE), 0);
+
+		exec_success()
+	});
+
+	TestFilter::set_filter(|call| match call {
+		RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { .. }) => false,
+		_ => true,
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		let min_balance = <Test as Config>::Currency::minimum_balance();
+
+		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+		set_balance(&ALICE, min_balance * 10);
+		place_contract(&BOB, code_hash);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		System::reset_events();
+		MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut gas_meter,
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		)
+		.unwrap();
+
+		let remark_hash = <Test as frame_system::Config>::Hashing::hash(b"Hello");
+		assert_eq!(
+			System::events(),
+			vec![
+				EventRecord {
+					phase: Phase::Initialization,
+					event: MetaEvent::System(frame_system::Event::Remarked {
+						sender: BOB_FALLBACK,
+						hash: remark_hash
+					}),
+					topics: vec![],
+				},
+				EventRecord {
+					phase: Phase::Initialization,
+					event: MetaEvent::Utility(pallet_utility::Event::ItemCompleted),
+					topics: vec![],
+				},
+				EventRecord {
+					phase: Phase::Initialization,
+					event: MetaEvent::Utility(pallet_utility::Event::BatchInterrupted {
+						index: 1,
+						error: frame_system::Error::<Test>::CallFiltered.into()
+					},),
+					topics: vec![],
+				},
+			]
+		);
+	});
+}
+
+#[test]
+fn nonce() {
+	let fail_code = MockLoader::insert(Constructor, |_, _| exec_trapped());
+	let success_code = MockLoader::insert(Constructor, |_, _| exec_success());
+	let succ_fail_code = MockLoader::insert(Constructor, move |ctx, _| {
+		ctx.ext
+			.instantiate(
+				Weight::MAX,
+				U256::MAX,
+				fail_code,
+				ctx.ext.minimum_balance() * 100,
+				vec![],
+				Some(&[0; 32]),
+			)
+			.ok();
+		exec_success()
+	});
+	let succ_succ_code = MockLoader::insert(Constructor, move |ctx, _| {
+		let alice_nonce = System::account_nonce(&ALICE);
+		assert_eq!(System::account_nonce(ctx.ext.account_id()), 0);
+		assert_eq!(ctx.ext.caller().account_id().unwrap(), &ALICE);
+		let addr = ctx
+			.ext
+			.instantiate(
+				Weight::MAX,
+				U256::MAX,
+				success_code,
+				ctx.ext.minimum_balance() * 100,
+				vec![],
+				Some(&[0; 32]),
+			)
+			.unwrap();
+
+		let account_id =
+			<<Test as Config>::AddressMapper as AddressMapper<Test>>::to_fallback_account_id(&addr);
+
+		assert_eq!(System::account_nonce(&ALICE), alice_nonce);
+		assert_eq!(System::account_nonce(ctx.ext.account_id()), 1);
+		assert_eq!(System::account_nonce(&account_id), 0);
+
+		// a plain call should not influence the account counter
+		ctx.ext
+			.call(Weight::zero(), U256::zero(), &addr, U256::zero(), vec![], false, false)
+			.unwrap();
+
+		assert_eq!(System::account_nonce(ALICE), alice_nonce);
+		assert_eq!(System::account_nonce(ctx.ext.account_id()), 1);
+		assert_eq!(System::account_nonce(&account_id), 0);
+
+		exec_success()
+	});
+
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.build()
+		.execute_with(|| {
+			let min_balance = <Test as Config>::Currency::minimum_balance();
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+			let fail_executable = MockExecutable::from_storage(fail_code, &mut gas_meter).unwrap();
+			let success_executable =
+				MockExecutable::from_storage(success_code, &mut gas_meter).unwrap();
+			let succ_fail_executable =
+				MockExecutable::from_storage(succ_fail_code, &mut gas_meter).unwrap();
+			let succ_succ_executable =
+				MockExecutable::from_storage(succ_succ_code, &mut gas_meter).unwrap();
+			set_balance(&ALICE, min_balance * 10_000);
+			set_balance(&BOB, min_balance * 10_000);
+			let origin = Origin::from_account_id(BOB);
+			let mut storage_meter =
+				storage::meter::Meter::new(&origin, deposit_limit::<Test>(), min_balance * 100)
+					.unwrap();
+
+			// fail should not increment
+			MockStack::run_instantiate(
+				ALICE,
+				fail_executable,
+				&mut gas_meter,
+				&mut storage_meter,
+				(min_balance * 100).into(),
+				vec![],
+				Some(&[0; 32]),
+				false,
+			)
+			.ok();
+			assert_eq!(System::account_nonce(&ALICE), 0);
+
+			assert_ok!(MockStack::run_instantiate(
+				ALICE,
+				success_executable,
+				&mut gas_meter,
+				&mut storage_meter,
+				(min_balance * 100).into(),
+				vec![],
+				Some(&[0; 32]),
+				false,
+			));
+			assert_eq!(System::account_nonce(&ALICE), 1);
+
+			assert_ok!(MockStack::run_instantiate(
+				ALICE,
+				succ_fail_executable,
+				&mut gas_meter,
+				&mut storage_meter,
+				(min_balance * 200).into(),
+				vec![],
+				Some(&[0; 32]),
+				false,
+			));
+			assert_eq!(System::account_nonce(&ALICE), 2);
+
+			assert_ok!(MockStack::run_instantiate(
+				ALICE,
+				succ_succ_executable,
+				&mut gas_meter,
+				&mut storage_meter,
+				(min_balance * 200).into(),
+				vec![],
+				Some(&[0; 32]),
+				false,
+			));
+			assert_eq!(System::account_nonce(&ALICE), 3);
+		});
+}
+
+#[test]
+fn set_storage_works() {
+	let code_hash = MockLoader::insert(Call, |ctx, _| {
+		// Write
+		assert_eq!(
+			ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![4, 5, 6]), true),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(ctx.ext.set_storage(&Key::Fix([3; 32]), None, false), Ok(WriteOutcome::New));
+		assert_eq!(ctx.ext.set_storage(&Key::Fix([4; 32]), None, true), Ok(WriteOutcome::New));
+		assert_eq!(
+			ctx.ext.set_storage(&Key::Fix([5; 32]), Some(vec![]), false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_storage(&Key::Fix([6; 32]), Some(vec![]), true),
+			Ok(WriteOutcome::New)
+		);
+
+		// Overwrite
+		assert_eq!(
+			ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![42]), false),
+			Ok(WriteOutcome::Overwritten(3))
+		);
+		assert_eq!(
+			ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![48]), true),
+			Ok(WriteOutcome::Taken(vec![4, 5, 6]))
+		);
+		assert_eq!(ctx.ext.set_storage(&Key::Fix([3; 32]), None, false), Ok(WriteOutcome::New));
+		assert_eq!(ctx.ext.set_storage(&Key::Fix([4; 32]), None, true), Ok(WriteOutcome::New));
+		assert_eq!(
+			ctx.ext.set_storage(&Key::Fix([5; 32]), Some(vec![]), false),
+			Ok(WriteOutcome::Overwritten(0))
+		);
+		assert_eq!(
+			ctx.ext.set_storage(&Key::Fix([6; 32]), Some(vec![]), true),
+			Ok(WriteOutcome::Taken(vec![]))
+		);
+
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		let min_balance = <Test as Config>::Currency::minimum_balance();
+
+		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+		set_balance(&ALICE, min_balance * 1000);
+		place_contract(&BOB, code_hash);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter =
+			storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
+		assert_ok!(MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut gas_meter,
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		));
+	});
+}
+
+#[test]
+fn set_storage_varsized_key_works() {
+	let code_hash = MockLoader::insert(Call, |ctx, _| {
+		// Write
+		assert_eq!(
+			ctx.ext.set_storage(
+				&Key::try_from_var([1; 64].to_vec()).unwrap(),
+				Some(vec![1, 2, 3]),
+				false
+			),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_storage(
+				&Key::try_from_var([2; 19].to_vec()).unwrap(),
+				Some(vec![4, 5, 6]),
+				true
+			),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_storage(&Key::try_from_var([3; 19].to_vec()).unwrap(), None, false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_storage(&Key::try_from_var([4; 64].to_vec()).unwrap(), None, true),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext
+				.set_storage(&Key::try_from_var([5; 30].to_vec()).unwrap(), Some(vec![]), false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext
+				.set_storage(&Key::try_from_var([6; 128].to_vec()).unwrap(), Some(vec![]), true),
+			Ok(WriteOutcome::New)
+		);
+
+		// Overwrite
+		assert_eq!(
+			ctx.ext.set_storage(
+				&Key::try_from_var([1; 64].to_vec()).unwrap(),
+				Some(vec![42, 43, 44]),
+				false
+			),
+			Ok(WriteOutcome::Overwritten(3))
+		);
+		assert_eq!(
+			ctx.ext.set_storage(
+				&Key::try_from_var([2; 19].to_vec()).unwrap(),
+				Some(vec![48]),
+				true
+			),
+			Ok(WriteOutcome::Taken(vec![4, 5, 6]))
+		);
+		assert_eq!(
+			ctx.ext.set_storage(&Key::try_from_var([3; 19].to_vec()).unwrap(), None, false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_storage(&Key::try_from_var([4; 64].to_vec()).unwrap(), None, true),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext
+				.set_storage(&Key::try_from_var([5; 30].to_vec()).unwrap(), Some(vec![]), false),
+			Ok(WriteOutcome::Overwritten(0))
+		);
+		assert_eq!(
+			ctx.ext
+				.set_storage(&Key::try_from_var([6; 128].to_vec()).unwrap(), Some(vec![]), true),
+			Ok(WriteOutcome::Taken(vec![]))
+		);
+
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		let min_balance = <Test as Config>::Currency::minimum_balance();
+
+		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+		set_balance(&ALICE, min_balance * 1000);
+		place_contract(&BOB, code_hash);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter =
+			storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
+		assert_ok!(MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut gas_meter,
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		));
+	});
+}
+
+#[test]
+fn get_storage_works() {
+	let code_hash = MockLoader::insert(Call, |ctx, _| {
+		assert_eq!(
+			ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![]), false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(ctx.ext.get_storage(&Key::Fix([1; 32])), Some(vec![1, 2, 3]));
+		assert_eq!(ctx.ext.get_storage(&Key::Fix([2; 32])), Some(vec![]));
+		assert_eq!(ctx.ext.get_storage(&Key::Fix([3; 32])), None);
+
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		let min_balance = <Test as Config>::Currency::minimum_balance();
+
+		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+		set_balance(&ALICE, min_balance * 1000);
+		place_contract(&BOB, code_hash);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter =
+			storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
+		assert_ok!(MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut gas_meter,
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		));
+	});
+}
+
+#[test]
+fn get_storage_size_works() {
+	let code_hash = MockLoader::insert(Call, |ctx, _| {
+		assert_eq!(
+			ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![]), false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(ctx.ext.get_storage_size(&Key::Fix([1; 32])), Some(3));
+		assert_eq!(ctx.ext.get_storage_size(&Key::Fix([2; 32])), Some(0));
+		assert_eq!(ctx.ext.get_storage_size(&Key::Fix([3; 32])), None);
+
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		let min_balance = <Test as Config>::Currency::minimum_balance();
+
+		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+		set_balance(&ALICE, min_balance * 1000);
+		place_contract(&BOB, code_hash);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter =
+			storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
+		assert_ok!(MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut gas_meter,
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		));
+	});
+}
+
+#[test]
+fn get_storage_varsized_key_works() {
+	let code_hash = MockLoader::insert(Call, |ctx, _| {
+		assert_eq!(
+			ctx.ext.set_storage(
+				&Key::try_from_var([1; 19].to_vec()).unwrap(),
+				Some(vec![1, 2, 3]),
+				false
+			),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext
+				.set_storage(&Key::try_from_var([2; 16].to_vec()).unwrap(), Some(vec![]), false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.get_storage(&Key::try_from_var([1; 19].to_vec()).unwrap()),
+			Some(vec![1, 2, 3])
+		);
+		assert_eq!(
+			ctx.ext.get_storage(&Key::try_from_var([2; 16].to_vec()).unwrap()),
+			Some(vec![])
+		);
+		assert_eq!(ctx.ext.get_storage(&Key::try_from_var([3; 8].to_vec()).unwrap()), None);
+
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		let min_balance = <Test as Config>::Currency::minimum_balance();
+
+		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+		set_balance(&ALICE, min_balance * 1000);
+		place_contract(&BOB, code_hash);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter =
+			storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
+		assert_ok!(MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut gas_meter,
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		));
+	});
+}
+
+#[test]
+fn get_storage_size_varsized_key_works() {
+	let code_hash = MockLoader::insert(Call, |ctx, _| {
+		assert_eq!(
+			ctx.ext.set_storage(
+				&Key::try_from_var([1; 19].to_vec()).unwrap(),
+				Some(vec![1, 2, 3]),
+				false
+			),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext
+				.set_storage(&Key::try_from_var([2; 16].to_vec()).unwrap(), Some(vec![]), false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.get_storage_size(&Key::try_from_var([1; 19].to_vec()).unwrap()),
+			Some(3)
+		);
+		assert_eq!(
+			ctx.ext.get_storage_size(&Key::try_from_var([2; 16].to_vec()).unwrap()),
+			Some(0)
+		);
+		assert_eq!(ctx.ext.get_storage_size(&Key::try_from_var([3; 8].to_vec()).unwrap()), None);
+
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		let min_balance = <Test as Config>::Currency::minimum_balance();
+
+		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+		set_balance(&ALICE, min_balance * 1000);
+		place_contract(&BOB, code_hash);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter =
+			storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
+		assert_ok!(MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut gas_meter,
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		));
+	});
+}
+
+#[test]
+fn set_transient_storage_works() {
+	let code_hash = MockLoader::insert(Call, |ctx, _| {
+		// Write
+		assert_eq!(
+			ctx.ext.set_transient_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_transient_storage(&Key::Fix([2; 32]), Some(vec![4, 5, 6]), true),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_transient_storage(&Key::Fix([3; 32]), None, false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_transient_storage(&Key::Fix([4; 32]), None, true),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_transient_storage(&Key::Fix([5; 32]), Some(vec![]), false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_transient_storage(&Key::Fix([6; 32]), Some(vec![]), true),
+			Ok(WriteOutcome::New)
+		);
+
+		// Overwrite
+		assert_eq!(
+			ctx.ext.set_transient_storage(&Key::Fix([1; 32]), Some(vec![42]), false),
+			Ok(WriteOutcome::Overwritten(3))
+		);
+		assert_eq!(
+			ctx.ext.set_transient_storage(&Key::Fix([2; 32]), Some(vec![48]), true),
+			Ok(WriteOutcome::Taken(vec![4, 5, 6]))
+		);
+		assert_eq!(
+			ctx.ext.set_transient_storage(&Key::Fix([3; 32]), None, false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_transient_storage(&Key::Fix([4; 32]), None, true),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_transient_storage(&Key::Fix([5; 32]), Some(vec![]), false),
+			Ok(WriteOutcome::Overwritten(0))
+		);
+		assert_eq!(
+			ctx.ext.set_transient_storage(&Key::Fix([6; 32]), Some(vec![]), true),
+			Ok(WriteOutcome::Taken(vec![]))
+		);
+
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, code_hash);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter =
+			storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap();
+		assert_ok!(MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		));
+	});
+}
+
+#[test]
+fn get_transient_storage_works() {
+	// Call stack: BOB -> CHARLIE(success) -> BOB' (success)
+	let storage_key_1 = &Key::Fix([1; 32]);
+	let storage_key_2 = &Key::Fix([2; 32]);
+	let storage_key_3 = &Key::Fix([3; 32]);
+	let code_bob = MockLoader::insert(Call, |ctx, _| {
+		if ctx.input_data[0] == 0 {
+			assert_eq!(
+				ctx.ext.set_transient_storage(storage_key_1, Some(vec![1, 2]), false),
+				Ok(WriteOutcome::New)
+			);
+			assert_eq!(
+				ctx.ext
+					.call(
+						Weight::zero(),
+						U256::zero(),
+						&CHARLIE_ADDR,
+						U256::zero(),
+						vec![],
+						true,
+						false,
+					)
+					.map(|_| ctx.ext.last_frame_output().clone()),
+				exec_success()
+			);
+			assert_eq!(ctx.ext.get_transient_storage(storage_key_1), Some(vec![3]));
+			assert_eq!(ctx.ext.get_transient_storage(storage_key_2), Some(vec![]));
+			assert_eq!(ctx.ext.get_transient_storage(storage_key_3), None);
+		} else {
+			assert_eq!(
+				ctx.ext.set_transient_storage(storage_key_1, Some(vec![3]), true),
+				Ok(WriteOutcome::Taken(vec![1, 2]))
+			);
+			assert_eq!(
+				ctx.ext.set_transient_storage(storage_key_2, Some(vec![]), false),
+				Ok(WriteOutcome::New)
+			);
+		}
+		exec_success()
+	});
+	let code_charlie = MockLoader::insert(Call, |ctx, _| {
+		assert!(ctx
+			.ext
+			.call(Weight::zero(), U256::zero(), &BOB_ADDR, U256::zero(), vec![99], true, false)
+			.is_ok());
+		// CHARLIE can not read BOB`s storage.
+		assert_eq!(ctx.ext.get_transient_storage(storage_key_1), None);
+		exec_success()
+	});
+
+	// This one tests passing the input data into a contract via call.
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, code_bob);
+		place_contract(&CHARLIE, code_charlie);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![0],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn get_transient_storage_size_works() {
+	let storage_key_1 = &Key::Fix([1; 32]);
+	let storage_key_2 = &Key::Fix([2; 32]);
+	let storage_key_3 = &Key::Fix([3; 32]);
+	let code_hash = MockLoader::insert(Call, |ctx, _| {
+		assert_eq!(
+			ctx.ext.set_transient_storage(storage_key_1, Some(vec![1, 2, 3]), false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(
+			ctx.ext.set_transient_storage(storage_key_2, Some(vec![]), false),
+			Ok(WriteOutcome::New)
+		);
+		assert_eq!(ctx.ext.get_transient_storage_size(storage_key_1), Some(3));
+		assert_eq!(ctx.ext.get_transient_storage_size(storage_key_2), Some(0));
+		assert_eq!(ctx.ext.get_transient_storage_size(storage_key_3), None);
+
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, code_hash);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		assert_ok!(MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		));
+	});
+}
+
+#[test]
+fn rollback_transient_storage_works() {
+	// Call stack: BOB -> CHARLIE (trap) -> BOB' (success)
+	let storage_key = &Key::Fix([1; 32]);
+	let code_bob = MockLoader::insert(Call, |ctx, _| {
+		if ctx.input_data[0] == 0 {
+			assert_eq!(
+				ctx.ext.set_transient_storage(storage_key, Some(vec![1, 2]), false),
+				Ok(WriteOutcome::New)
+			);
+			assert_eq!(
+				ctx.ext
+					.call(
+						Weight::zero(),
+						U256::zero(),
+						&CHARLIE_ADDR,
+						U256::zero(),
+						vec![],
+						true,
+						false
+					)
+					.map(|_| ctx.ext.last_frame_output().clone()),
+				exec_trapped()
+			);
+			assert_eq!(ctx.ext.get_transient_storage(storage_key), Some(vec![1, 2]));
+		} else {
+			let overwritten_length = ctx.ext.get_transient_storage_size(storage_key).unwrap();
+			assert_eq!(
+				ctx.ext.set_transient_storage(storage_key, Some(vec![3]), false),
+				Ok(WriteOutcome::Overwritten(overwritten_length))
+			);
+			assert_eq!(ctx.ext.get_transient_storage(storage_key), Some(vec![3]));
+		}
+		exec_success()
+	});
+	let code_charlie = MockLoader::insert(Call, |ctx, _| {
+		assert!(ctx
+			.ext
+			.call(Weight::zero(), U256::zero(), &BOB_ADDR, U256::zero(), vec![99], true, false)
+			.is_ok());
+		exec_trapped()
+	});
+
+	// This one tests passing the input data into a contract via call.
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, code_bob);
+		place_contract(&CHARLIE, code_charlie);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![0],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn ecdsa_to_eth_address_returns_proper_value() {
+	let bob_ch = MockLoader::insert(Call, |ctx, _| {
+		let pubkey_compressed = array_bytes::hex2array_unchecked(
+			"028db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd91",
+		);
+		assert_eq!(
+			ctx.ext.ecdsa_to_eth_address(&pubkey_compressed).unwrap(),
+			array_bytes::hex2array_unchecked::<_, 20>("09231da7b19A016f9e576d23B16277062F4d46A8")
+		);
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, bob_ch);
+
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn last_frame_output_works_on_instantiate() {
+	let ok_ch = MockLoader::insert(Constructor, move |_, _| {
+		Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![127] })
+	});
+	let revert_ch = MockLoader::insert(Constructor, move |_, _| {
+		Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70] })
+	});
+	let trap_ch = MockLoader::insert(Constructor, |_, _| Err("It's a trap!".into()));
+	let instantiator_ch = MockLoader::insert(Call, {
+		move |ctx, _| {
+			let value = <Test as Config>::Currency::minimum_balance().into();
+
+			// Successful instantiation should set the output
+			let address =
+				ctx.ext.instantiate(Weight::MAX, U256::MAX, ok_ch, value, vec![], None).unwrap();
+			assert_eq!(
+				ctx.ext.last_frame_output(),
+				&ExecReturnValue { flags: ReturnFlags::empty(), data: vec![127] }
+			);
+
+			// Balance transfers should reset the output
+			ctx.ext
+				.call(Weight::MAX, U256::MAX, &address, U256::from(1), vec![], true, false)
+				.unwrap();
+			assert_eq!(ctx.ext.last_frame_output(), &Default::default());
+
+			// Reverted instantiation should set the output
+			ctx.ext
+				.instantiate(Weight::zero(), U256::zero(), revert_ch, value, vec![], None)
+				.unwrap();
+			assert_eq!(
+				ctx.ext.last_frame_output(),
+				&ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70] }
+			);
+
+			// Trapped instantiation should clear the output
+			ctx.ext
+				.instantiate(Weight::zero(), U256::zero(), trap_ch, value, vec![], None)
+				.unwrap_err();
+			assert_eq!(
+				ctx.ext.last_frame_output(),
+				&ExecReturnValue { flags: ReturnFlags::empty(), data: vec![] }
+			);
+
+			exec_success()
+		}
+	});
+
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.existential_deposit(15)
+		.build()
+		.execute_with(|| {
+			set_balance(&ALICE, 1000);
+			set_balance(&BOB, 100);
+			place_contract(&BOB, instantiator_ch);
+			let origin = Origin::from_account_id(ALICE);
+			let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap();
+
+			MockStack::run_call(
+				origin,
+				BOB_ADDR,
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
+				&mut storage_meter,
+				U256::zero(),
+				vec![],
+				false,
+			)
+			.unwrap()
+		});
+}
+
+#[test]
+fn last_frame_output_works_on_nested_call() {
+	// Call stack: BOB -> CHARLIE(revert) -> BOB' (success)
+	let code_bob = MockLoader::insert(Call, |ctx, _| {
+		if ctx.input_data.is_empty() {
+			// We didn't do anything yet
+			assert_eq!(
+				ctx.ext.last_frame_output(),
+				&ExecReturnValue { flags: ReturnFlags::empty(), data: vec![] }
+			);
+
+			ctx.ext
+				.call(
+					Weight::zero(),
+					U256::zero(),
+					&CHARLIE_ADDR,
+					U256::zero(),
+					vec![],
+					true,
+					false,
+				)
+				.unwrap();
+			assert_eq!(
+				ctx.ext.last_frame_output(),
+				&ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70] }
+			);
+		}
+
+		Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![127] })
+	});
+	let code_charlie = MockLoader::insert(Call, |ctx, _| {
+		// We didn't do anything yet
+		assert_eq!(
+			ctx.ext.last_frame_output(),
+			&ExecReturnValue { flags: ReturnFlags::empty(), data: vec![] }
+		);
+
+		assert!(ctx
+			.ext
+			.call(Weight::zero(), U256::zero(), &BOB_ADDR, U256::zero(), vec![99], true, false)
+			.is_ok());
+		assert_eq!(
+			ctx.ext.last_frame_output(),
+			&ExecReturnValue { flags: ReturnFlags::empty(), data: vec![127] }
+		);
+
+		Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70] })
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, code_bob);
+		place_contract(&CHARLIE, code_charlie);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![0],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn last_frame_output_is_always_reset() {
+	let code_bob = MockLoader::insert(Call, |ctx, _| {
+		let invalid_code_hash = H256::from_low_u64_le(u64::MAX);
+		let output_revert = || ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![1] };
+
+		// A value of u256::MAX to fail the call on the first condition.
+		*ctx.ext.last_frame_output_mut() = output_revert();
+		assert_eq!(
+			ctx.ext.call(
+				Weight::zero(),
+				U256::zero(),
+				&H160::zero(),
+				U256::max_value(),
+				vec![],
+				true,
+				false,
+			),
+			Err(Error::<Test>::BalanceConversionFailed.into())
+		);
+		assert_eq!(ctx.ext.last_frame_output(), &Default::default());
+
+		// An unknown code hash to fail the delegate_call on the first condition.
+		*ctx.ext.last_frame_output_mut() = output_revert();
+		assert_eq!(
+			ctx.ext.delegate_call(
+				Weight::zero(),
+				U256::zero(),
+				H160([0xff; 20]),
+				Default::default()
+			),
+			Err(Error::<Test>::CodeNotFound.into())
+		);
+		assert_eq!(ctx.ext.last_frame_output(), &Default::default());
+
+		// An unknown code hash to fail instantiation on the first condition.
+		*ctx.ext.last_frame_output_mut() = output_revert();
+		assert_eq!(
+			ctx.ext.instantiate(
+				Weight::zero(),
+				U256::zero(),
+				invalid_code_hash,
+				U256::zero(),
+				vec![],
+				None,
+			),
+			Err(Error::<Test>::CodeNotFound.into())
+		);
+		assert_eq!(ctx.ext.last_frame_output(), &Default::default());
+
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		place_contract(&BOB, code_bob);
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+
+		let result = MockStack::run_call(
+			origin,
+			BOB_ADDR,
+			&mut GasMeter::<Test>::new(GAS_LIMIT),
+			&mut storage_meter,
+			U256::zero(),
+			vec![],
+			false,
+		);
+		assert_matches!(result, Ok(_));
+	});
+}
+
+#[test]
+fn immutable_data_access_checks_work() {
+	let dummy_ch = MockLoader::insert(Constructor, move |ctx, _| {
+		// Calls can not store immutable data
+		assert_eq!(ctx.ext.get_immutable_data(), Err(Error::<Test>::InvalidImmutableAccess.into()));
+		exec_success()
+	});
+	let instantiator_ch = MockLoader::insert(Call, {
+		move |ctx, _| {
+			let value = <Test as Config>::Currency::minimum_balance().into();
+
+			assert_eq!(
+				ctx.ext.set_immutable_data(vec![0, 1, 2, 3].try_into().unwrap()),
+				Err(Error::<Test>::InvalidImmutableAccess.into())
+			);
+
+			// Constructors can not access the immutable data
+			ctx.ext
+				.instantiate(Weight::MAX, U256::MAX, dummy_ch, value, vec![], None)
+				.unwrap();
+
+			exec_success()
+		}
+	});
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.existential_deposit(15)
+		.build()
+		.execute_with(|| {
+			set_balance(&ALICE, 1000);
+			set_balance(&BOB, 100);
+			place_contract(&BOB, instantiator_ch);
+			let origin = Origin::from_account_id(ALICE);
+			let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap();
+
+			MockStack::run_call(
+				origin,
+				BOB_ADDR,
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
+				&mut storage_meter,
+				U256::zero(),
+				vec![],
+				false,
+			)
+			.unwrap()
+		});
+}
+
+#[test]
+fn correct_immutable_data_in_delegate_call() {
+	let charlie_ch = MockLoader::insert(Call, |ctx, _| {
+		Ok(ExecReturnValue {
+			flags: ReturnFlags::empty(),
+			data: ctx.ext.get_immutable_data()?.to_vec(),
+		})
+	});
+	let bob_ch = MockLoader::insert(Call, move |ctx, _| {
+		// In a regular call, we should witness the callee immutable data
+		assert_eq!(
+			ctx.ext
+				.call(
+					Weight::zero(),
+					U256::zero(),
+					&CHARLIE_ADDR,
+					U256::zero(),
+					vec![],
+					true,
+					false,
+				)
+				.map(|_| ctx.ext.last_frame_output().data.clone()),
+			Ok(vec![2]),
+		);
+
+		// Also in a delegate call, we should witness the callee immutable data
+		assert_eq!(
+			ctx.ext
+				.delegate_call(Weight::zero(), U256::zero(), CHARLIE_ADDR, Vec::new())
+				.map(|_| ctx.ext.last_frame_output().data.clone()),
+			Ok(vec![2])
+		);
+
+		exec_success()
+	});
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.existential_deposit(15)
+		.build()
+		.execute_with(|| {
+			place_contract(&BOB, bob_ch);
+			place_contract(&CHARLIE, charlie_ch);
+
+			let origin = Origin::from_account_id(ALICE);
+			let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap();
+
+			// Place unique immutable data for each contract
+			<ImmutableDataOf<Test>>::insert::<_, ImmutableData>(
+				BOB_ADDR,
+				vec![1].try_into().unwrap(),
+			);
+			<ImmutableDataOf<Test>>::insert::<_, ImmutableData>(
+				CHARLIE_ADDR,
+				vec![2].try_into().unwrap(),
+			);
+
+			MockStack::run_call(
+				origin,
+				BOB_ADDR,
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
+				&mut storage_meter,
+				U256::zero(),
+				vec![],
+				false,
+			)
+			.unwrap()
+		});
+}
+
+#[test]
+fn immutable_data_set_overrides() {
+	let hash = MockLoader::insert_both(
+		move |ctx, _| {
+			// Calling `set_immutable_data` the first time should work
+			assert_ok!(ctx.ext.set_immutable_data(vec![0, 1, 2, 3].try_into().unwrap()));
+			// Calling `set_immutable_data` the second time overrides the original one
+			assert_ok!(ctx.ext.set_immutable_data(vec![7, 5].try_into().unwrap()));
+			exec_success()
+		},
+		move |ctx, _| {
+			assert_eq!(ctx.ext.get_immutable_data().unwrap().into_inner(), vec![7, 5]);
+			exec_success()
+		},
+	);
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.existential_deposit(15)
+		.build()
+		.execute_with(|| {
+			set_balance(&ALICE, 1000);
+			let origin = Origin::from_account_id(ALICE);
+			let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap();
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+
+			let addr = MockStack::run_instantiate(
+				ALICE,
+				MockExecutable::from_storage(hash, &mut gas_meter).unwrap(),
+				&mut gas_meter,
+				&mut storage_meter,
+				U256::zero(),
+				vec![],
+				None,
+				false,
+			)
+			.unwrap()
+			.0;
+
+			MockStack::run_call(
+				origin,
+				addr,
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
+				&mut storage_meter,
+				U256::zero(),
+				vec![],
+				false,
+			)
+			.unwrap()
+		});
+}
+
+#[test]
+fn immutable_data_set_errors_with_empty_data() {
+	let dummy_ch = MockLoader::insert(Constructor, move |ctx, _| {
+		// Calling `set_immutable_data` with empty data should error out
+		assert_eq!(
+			ctx.ext.set_immutable_data(Default::default()),
+			Err(Error::<Test>::InvalidImmutableAccess.into())
+		);
+		exec_success()
+	});
+	let instantiator_ch = MockLoader::insert(Call, {
+		move |ctx, _| {
+			let value = <Test as Config>::Currency::minimum_balance().into();
+			ctx.ext
+				.instantiate(Weight::MAX, U256::MAX, dummy_ch, value, vec![], None)
+				.unwrap();
+
+			exec_success()
+		}
+	});
+	ExtBuilder::default()
+		.with_code_hashes(MockLoader::code_hashes())
+		.existential_deposit(15)
+		.build()
+		.execute_with(|| {
+			set_balance(&ALICE, 1000);
+			set_balance(&BOB, 100);
+			place_contract(&BOB, instantiator_ch);
+			let origin = Origin::from_account_id(ALICE);
+			let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap();
+
+			MockStack::run_call(
+				origin,
+				BOB_ADDR,
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
+				&mut storage_meter,
+				U256::zero(),
+				vec![],
+				false,
+			)
+			.unwrap()
+		});
+}
+
+#[test]
+fn block_hash_returns_proper_values() {
+	let bob_code_hash = MockLoader::insert(Call, |ctx, _| {
+		ctx.ext.block_number = 1u32.into();
+		assert_eq!(ctx.ext.block_hash(U256::from(1)), None);
+		assert_eq!(ctx.ext.block_hash(U256::from(0)), Some(H256::from([1; 32])));
+
+		ctx.ext.block_number = 300u32.into();
+		assert_eq!(ctx.ext.block_hash(U256::from(300)), None);
+		assert_eq!(ctx.ext.block_hash(U256::from(43)), None);
+		assert_eq!(ctx.ext.block_hash(U256::from(44)), Some(H256::from([2; 32])));
+
+		exec_success()
+	});
+
+	ExtBuilder::default().build().execute_with(|| {
+		frame_system::BlockHash::<Test>::insert(
+			&BlockNumberFor::<Test>::from(0u32),
+			<tests::Test as frame_system::Config>::Hash::from([1; 32]),
+		);
+		frame_system::BlockHash::<Test>::insert(
+			&BlockNumberFor::<Test>::from(1u32),
+			<tests::Test as frame_system::Config>::Hash::default(),
+		);
+		frame_system::BlockHash::<Test>::insert(
+			&BlockNumberFor::<Test>::from(43u32),
+			<tests::Test as frame_system::Config>::Hash::default(),
+		);
+		frame_system::BlockHash::<Test>::insert(
+			&BlockNumberFor::<Test>::from(44u32),
+			<tests::Test as frame_system::Config>::Hash::from([2; 32]),
+		);
+		frame_system::BlockHash::<Test>::insert(
+			&BlockNumberFor::<Test>::from(300u32),
+			<tests::Test as frame_system::Config>::Hash::default(),
+		);
+
+		place_contract(&BOB, bob_code_hash);
+
+		let origin = Origin::from_account_id(ALICE);
+		let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap();
+		assert_matches!(
+			MockStack::run_call(
+				origin,
+				BOB_ADDR,
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
+				&mut storage_meter,
+				U256::zero(),
+				vec![0],
+				false,
+			),
+			Ok(_)
+		);
+	});
+}
diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs
index 5487a8eb069b5d3e71025b25cac1f9b6e34e2cc9..b1851ebe41f097803262d998875f26cc6a83f368 100644
--- a/substrate/frame/revive/src/lib.rs
+++ b/substrate/frame/revive/src/lib.rs
@@ -492,6 +492,8 @@ pub mod pallet {
 		InvalidGenericTransaction,
 		/// The refcount of a code either over or underflowed.
 		RefcountOverOrUnderflow,
+		/// Unsupported precompile address
+		UnsupportedPrecompileAddress,
 	}
 
 	/// A reason for the pallet contracts placing a hold on funds.
diff --git a/substrate/frame/revive/src/test_utils/builder.rs b/substrate/frame/revive/src/test_utils/builder.rs
index 7fbb5b676439e6c378e3b51683bac449513faca5..c9c2a3240bc473bc82f0f7f7df69e0849c7bc353 100644
--- a/substrate/frame/revive/src/test_utils/builder.rs
+++ b/substrate/frame/revive/src/test_utils/builder.rs
@@ -146,7 +146,10 @@ builder!(
 
 	/// Build the instantiate call and unwrap the account id.
 	pub fn build_and_unwrap_contract(self) -> Contract<T> {
-		let addr = self.build().result.unwrap().addr;
+		let result = self.build().result.unwrap();
+		assert!(!result.result.did_revert(), "instantiation did revert");
+
+		let addr = result.addr;
 		let account_id = T::AddressMapper::to_account_id(&addr);
 		Contract{ account_id,  addr }
 	}
diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs
index 44f2afc8b0e8a0ce2b5f312a65293a0347392cf7..bda47030b23bb038b5ccd12a854026badb93c49f 100644
--- a/substrate/frame/revive/src/tests.rs
+++ b/substrate/frame/revive/src/tests.rs
@@ -4441,7 +4441,7 @@ fn tracing_works_for_transfers() {
 			vec![CallTrace {
 				from: ALICE_ADDR,
 				to: BOB_ADDR,
-				value: U256::from(10_000_000),
+				value: Some(U256::from(10_000_000)),
 				call_type: CallType::Call,
 				..Default::default()
 			},]
@@ -4509,6 +4509,7 @@ fn tracing_works() {
 					input: (3u32, addr_callee).encode().into(),
 					call_type: Call,
 					logs: logs.clone(),
+					value: Some(U256::from(0)),
 					calls: vec![
 						CallTrace {
 							from: addr,
@@ -4520,6 +4521,7 @@ fn tracing_works() {
 							revert_reason: Some("revert: This function always fails".to_string()),
 							error: Some("execution reverted".to_string()),
 							call_type: Call,
+							value: Some(U256::from(0)),
 							..Default::default()
 						},
 						CallTrace {
@@ -4528,6 +4530,7 @@ fn tracing_works() {
 							input: (2u32, addr_callee).encode().into(),
 							call_type: Call,
 							logs: logs.clone(),
+							value: Some(U256::from(0)),
 							calls: vec![
 								CallTrace {
 									from: addr,
@@ -4536,6 +4539,7 @@ fn tracing_works() {
 									output: Default::default(),
 									error: Some("ContractTrapped".to_string()),
 									call_type: Call,
+									value: Some(U256::from(0)),
 									..Default::default()
 								},
 								CallTrace {
@@ -4544,6 +4548,7 @@ fn tracing_works() {
 									input: (1u32, addr_callee).encode().into(),
 									call_type: Call,
 									logs: logs.clone(),
+									value: Some(U256::from(0)),
 									calls: vec![
 										CallTrace {
 											from: addr,
@@ -4551,6 +4556,7 @@ fn tracing_works() {
 											input: 0u32.encode().into(),
 											output: 0u32.to_le_bytes().to_vec().into(),
 											call_type: Call,
+											value: Some(U256::from(0)),
 											..Default::default()
 										},
 										CallTrace {
@@ -4558,11 +4564,12 @@ fn tracing_works() {
 											to: addr,
 											input: (0u32, addr_callee).encode().into(),
 											call_type: Call,
+											value: Some(U256::from(0)),
 											calls: vec![
 												CallTrace {
 													from: addr,
 													to: BOB_ADDR,
-													value: U256::from(100),
+													value: Some(U256::from(100)),
 													call_type: CallType::Call,
 													..Default::default()
 												}
@@ -4582,3 +4589,41 @@ fn tracing_works() {
 		}
 	});
 }
+
+#[test]
+fn unknown_precompiles_revert() {
+	let (code, _code_hash) = compile_module("read_only_call").unwrap();
+
+	ExtBuilder::default().build().execute_with(|| {
+		let _ = <Test as Config>::Currency::set_balance(&ALICE, 100_000_000_000);
+		let Contract { addr, .. } =
+			builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_contract();
+
+		let cases: Vec<(H160, Box<dyn FnOnce(_)>)> = vec![
+			(
+				H160::from_low_u64_be(0x1),
+				Box::new(|result| {
+					assert_err!(result, <Error<Test>>::UnsupportedPrecompileAddress);
+				}),
+			),
+			(
+				H160::from_low_u64_be(0xff),
+				Box::new(|result| {
+					assert_err!(result, <Error<Test>>::UnsupportedPrecompileAddress);
+				}),
+			),
+			(
+				H160::from_low_u64_be(0x1ff),
+				Box::new(|result| {
+					assert_ok!(result);
+				}),
+			),
+		];
+
+		for (callee_addr, assert_result) in cases {
+			let result =
+				builder::bare_call(addr).data((callee_addr, [0u8; 0]).encode()).build().result;
+			assert_result(result);
+		}
+	});
+}
diff --git a/substrate/frame/safe-mode/src/lib.rs b/substrate/frame/safe-mode/src/lib.rs
index cfa9097b54121badf81bf6efa52afedbe96f6a06..110f46b0322045ffb8d183c1994612a4a6163754 100644
--- a/substrate/frame/safe-mode/src/lib.rs
+++ b/substrate/frame/safe-mode/src/lib.rs
@@ -238,7 +238,18 @@ pub mod pallet {
 	}
 
 	/// The reason why the safe-mode was deactivated.
-	#[derive(Copy, Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]
+	#[derive(
+		Copy,
+		Clone,
+		PartialEq,
+		Eq,
+		RuntimeDebug,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		TypeInfo,
+		MaxEncodedLen,
+	)]
 	pub enum ExitReason {
 		/// The safe-mode was automatically deactivated after it's duration ran out.
 		Timeout,
diff --git a/substrate/frame/safe-mode/src/mock.rs b/substrate/frame/safe-mode/src/mock.rs
index 2980f86abc2811143b137ce669c856c257d6760c..277fe20ec4122059297008bdc27d3f7fb5be7b34 100644
--- a/substrate/frame/safe-mode/src/mock.rs
+++ b/substrate/frame/safe-mode/src/mock.rs
@@ -91,6 +91,7 @@ impl pallet_utility::Config for Test {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	MaxEncodedLen,
 	scale_info::TypeInfo,
diff --git a/substrate/frame/scored-pool/src/lib.rs b/substrate/frame/scored-pool/src/lib.rs
index c4464bbbfac0448bf449c02e2d9966895942d2da..fcaa6950110a8473cc006cbfdd4043d01d223f87 100644
--- a/substrate/frame/scored-pool/src/lib.rs
+++ b/substrate/frame/scored-pool/src/lib.rs
@@ -93,6 +93,8 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 
 #[cfg(test)]
+// We do not declare all features used by `construct_runtime`
+#[allow(unexpected_cfgs)]
 mod mock;
 
 #[cfg(test)]
diff --git a/substrate/frame/society/Cargo.toml b/substrate/frame/society/Cargo.toml
index d5860518fdda84c7ea6bd602ddead60f80bb20e9..e507538640f5ead84084c1c3a1238f087ad409a5 100644
--- a/substrate/frame/society/Cargo.toml
+++ b/substrate/frame/society/Cargo.toml
@@ -55,6 +55,7 @@ std = [
 runtime-benchmarks = [
 	"frame-benchmarking",
 	"frame-benchmarking/runtime-benchmarks",
+	"frame-support-test/runtime-benchmarks",
 	"frame-support/runtime-benchmarks",
 	"frame-system/runtime-benchmarks",
 	"pallet-balances/runtime-benchmarks",
diff --git a/substrate/frame/society/src/lib.rs b/substrate/frame/society/src/lib.rs
index 03726e6215ca1d0a71fc703e27f49ed3a0fdf85d..577c1a71f89d7c80cec732ccae7553b77667c238 100644
--- a/substrate/frame/society/src/lib.rs
+++ b/substrate/frame/society/src/lib.rs
@@ -463,7 +463,18 @@ pub struct IntakeRecord<AccountId, Balance> {
 pub type IntakeRecordFor<T, I> =
 	IntakeRecord<<T as frame_system::Config>::AccountId, BalanceOf<T, I>>;
 
-#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Copy,
+	Clone,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct GroupParams<Balance> {
 	max_members: u32,
 	max_intake: u32,
diff --git a/substrate/frame/staking/rc-client/src/lib.rs b/substrate/frame/staking/rc-client/src/lib.rs
index dc6c0b7e5c6fc4d8fc9c9e7196cf9b76890451d9..ab94df9c910ff35ab966c009022deca53a36554c 100644
--- a/substrate/frame/staking/rc-client/src/lib.rs
+++ b/substrate/frame/staking/rc-client/src/lib.rs
@@ -66,7 +66,7 @@ enum SessionCalls {
 }
 
 // An offence on the relay chain. Based on [`sp_staking::offence::OffenceDetails`].
-#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Debug, Clone, PartialEq, TypeInfo)]
 pub struct Offence {
 	offender: AccountId32,
 	reporters: Vec<AccountId32>,
diff --git a/substrate/frame/staking/src/lib.rs b/substrate/frame/staking/src/lib.rs
index 9105a3e7ec13a5202efdbf7ddb988995759adef8..a5fe16e500b8f29bbba27eb5667cde1b73a1793b 100644
--- a/substrate/frame/staking/src/lib.rs
+++ b/substrate/frame/staking/src/lib.rs
@@ -344,7 +344,7 @@ mod pallet;
 extern crate alloc;
 
 use alloc::{collections::btree_map::BTreeMap, vec, vec::Vec};
-use codec::{Decode, Encode, HasCompact, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, HasCompact, MaxEncodedLen};
 use frame_election_provider_support::ElectionProvider;
 use frame_support::{
 	defensive, defensive_assert,
@@ -448,7 +448,18 @@ impl<AccountId: Ord> Default for EraRewardPoints<AccountId> {
 }
 
 /// A destination account for payment.
-#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	PartialEq,
+	Eq,
+	Copy,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum RewardDestination<AccountId> {
 	/// Pay into the stash account, increasing the amount at stake accordingly.
 	Staked,
@@ -465,7 +476,18 @@ pub enum RewardDestination<AccountId> {
 }
 
 /// Preference of what happens regarding validation.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, Default, MaxEncodedLen)]
+#[derive(
+	PartialEq,
+	Eq,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	TypeInfo,
+	Default,
+	MaxEncodedLen,
+)]
 pub struct ValidatorPrefs {
 	/// Reward that validator takes up-front; only the rest is split between themselves and
 	/// nominators.
@@ -478,7 +500,17 @@ pub struct ValidatorPrefs {
 }
 
 /// Just a Balance/BlockNumber tuple to encode when a chunk of funds will be unlocked.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	PartialEq,
+	Eq,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct UnlockChunk<Balance: HasCompact + MaxEncodedLen> {
 	/// Amount of funds to be unlocked.
 	#[codec(compact)]
@@ -997,6 +1029,7 @@ where
 	Eq,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	TypeInfo,
 	MaxEncodedLen,
diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs
index 4184ac3bdde81d8e77036f5c53bc9c405d64ca36..6bd52e2bce166befd6fd20340a06a83b36342a56 100644
--- a/substrate/frame/staking/src/pallet/mod.rs
+++ b/substrate/frame/staking/src/pallet/mod.rs
@@ -83,7 +83,7 @@ pub mod pallet {
 	pub struct Pallet<T>(_);
 
 	/// Possible operations on the configuration values of this pallet.
-	#[derive(TypeInfo, Debug, Clone, Encode, Decode, PartialEq)]
+	#[derive(TypeInfo, Debug, Clone, Encode, Decode, DecodeWithMemTracking, PartialEq)]
 	pub enum ConfigOp<T: Default + Codec> {
 		/// Don't change.
 		Noop,
diff --git a/substrate/frame/state-trie-migration/src/lib.rs b/substrate/frame/state-trie-migration/src/lib.rs
index 6e475b7067e16e8d22eddc1861db63aac470d0ce..1418ea0b6f0a404b28c0ddb17eedcff92c0415c1 100644
--- a/substrate/frame/state-trie-migration/src/lib.rs
+++ b/substrate/frame/state-trie-migration/src/lib.rs
@@ -106,6 +106,7 @@ pub mod pallet {
 		CloneNoBound,
 		Encode,
 		Decode,
+		DecodeWithMemTracking,
 		scale_info::TypeInfo,
 		PartialEqNoBound,
 		EqNoBound,
@@ -127,7 +128,16 @@ pub mod pallet {
 	/// A migration task stored in state.
 	///
 	/// It tracks the last top and child keys read.
-	#[derive(Clone, Encode, Decode, scale_info::TypeInfo, PartialEq, Eq, MaxEncodedLen)]
+	#[derive(
+		Clone,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		scale_info::TypeInfo,
+		PartialEq,
+		Eq,
+		MaxEncodedLen,
+	)]
 	#[scale_info(skip_type_params(T))]
 	pub struct MigrationTask<T: Config> {
 		/// The current top trie migration progress.
@@ -404,6 +414,7 @@ pub mod pallet {
 		Copy,
 		Encode,
 		Decode,
+		DecodeWithMemTracking,
 		scale_info::TypeInfo,
 		Default,
 		Debug,
@@ -419,7 +430,17 @@ pub mod pallet {
 	}
 
 	/// How a migration was computed.
-	#[derive(Clone, Copy, Encode, Decode, scale_info::TypeInfo, Debug, PartialEq, Eq)]
+	#[derive(
+		Clone,
+		Copy,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		scale_info::TypeInfo,
+		Debug,
+		PartialEq,
+		Eq,
+	)]
 	pub enum MigrationCompute {
 		/// A signed origin triggered the migration.
 		Signed,
diff --git a/substrate/frame/statement/src/lib.rs b/substrate/frame/statement/src/lib.rs
index 6a7f577ab0869cbf5762ad2d8edd4e015a9b8242..02eef2ca1b2c6f663c910e11d6f5fa7c97c7525a 100644
--- a/substrate/frame/statement/src/lib.rs
+++ b/substrate/frame/statement/src/lib.rs
@@ -45,6 +45,8 @@ use sp_statement_store::{
 };
 
 #[cfg(test)]
+// We do not declare all features used by `construct_runtime`
+#[allow(unexpected_cfgs)]
 mod mock;
 #[cfg(test)]
 mod tests;
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs
index 411d74ecbb3d23c84e5b62c14e10a1b047e49248..43648118cab6872d7bb69366aa9aafa32bd5f385 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs
@@ -62,6 +62,7 @@ pub fn expand_outer_dispatch(
 			Clone, PartialEq, Eq,
 			#scrate::__private::codec::Encode,
 			#scrate::__private::codec::Decode,
+			#scrate::__private::codec::DecodeWithMemTracking,
 			#scrate::__private::scale_info::TypeInfo,
 			#scrate::__private::RuntimeDebug,
 		)]
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/freeze_reason.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/freeze_reason.rs
index f12f995266422e2a6337114d09e193d267885b24..b36d54fb79e60e47e748e7486cc31f2cc1662665 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/freeze_reason.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/freeze_reason.rs
@@ -58,7 +58,10 @@ pub fn expand_outer_freeze_reason(pallet_decls: &[Pallet], scrate: &TokenStream)
 		/// A reason for placing a freeze on funds.
 		#[derive(
 			Copy, Clone, Eq, PartialEq,
-			#scrate::__private::codec::Encode, #scrate::__private::codec::Decode, #scrate::__private::codec::MaxEncodedLen,
+			#scrate::__private::codec::Encode,
+			#scrate::__private::codec::Decode,
+			#scrate::__private::codec::DecodeWithMemTracking,
+			#scrate::__private::codec::MaxEncodedLen,
 			#scrate::__private::scale_info::TypeInfo,
 			#scrate::__private::RuntimeDebug,
 		)]
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/hold_reason.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/hold_reason.rs
index cdab92712fddcadbaee67c48119c7bf8c527e6cc..b729c3d0a19c4490384fde8f684a2e6108f686d0 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/hold_reason.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/hold_reason.rs
@@ -58,7 +58,10 @@ pub fn expand_outer_hold_reason(pallet_decls: &[Pallet], scrate: &TokenStream) -
 		/// A reason for placing a hold on funds.
 		#[derive(
 			Copy, Clone, Eq, PartialEq,
-			#scrate::__private::codec::Encode, #scrate::__private::codec::Decode, #scrate::__private::codec::MaxEncodedLen,
+			#scrate::__private::codec::Encode,
+			#scrate::__private::codec::Decode,
+			#scrate::__private::codec::DecodeWithMemTracking,
+			#scrate::__private::codec::MaxEncodedLen,
 			#scrate::__private::scale_info::TypeInfo,
 			#scrate::__private::RuntimeDebug,
 		)]
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/lock_id.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/lock_id.rs
index e67c0da00ea15e42efd0bcdddab98be5844b3e3f..902acc58d5ab246c5781436e2e7f350f7189ca43 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/lock_id.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/lock_id.rs
@@ -51,7 +51,10 @@ pub fn expand_outer_lock_id(pallet_decls: &[Pallet], scrate: &TokenStream) -> To
 		/// An identifier for each lock placed on funds.
 		#[derive(
 			Copy, Clone, Eq, PartialEq,
-			#scrate::__private::codec::Encode, #scrate::__private::codec::Decode, #scrate::__private::codec::MaxEncodedLen,
+			#scrate::__private::codec::Encode,
+			#scrate::__private::codec::Decode,
+			#scrate::__private::codec::DecodeWithMemTracking,
+			#scrate::__private::codec::MaxEncodedLen,
 			#scrate::__private::scale_info::TypeInfo,
 			#scrate::__private::RuntimeDebug,
 		)]
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs
index aada9f7af75b73a0d4b8166e0cbb47f899f8045e..7883541b90191c7eabe88a0d967bf231a3e3ea20 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs
@@ -200,8 +200,13 @@ pub fn expand_outer_origin(
 		}
 
 		#[derive(
-			Clone, PartialEq, Eq, #scrate::__private::RuntimeDebug, #scrate::__private::codec::Encode,
-			#scrate::__private::codec::Decode, #scrate::__private::scale_info::TypeInfo, #scrate::__private::codec::MaxEncodedLen,
+			Clone, PartialEq, Eq,
+			#scrate::__private::RuntimeDebug,
+			#scrate::__private::codec::Encode,
+			#scrate::__private::codec::Decode,
+			#scrate::__private::codec::DecodeWithMemTracking,
+			#scrate::__private::scale_info::TypeInfo,
+			#scrate::__private::codec::MaxEncodedLen,
 		)]
 		#[allow(non_camel_case_types)]
 		pub enum OriginCaller {
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs
index 1f19687c36f5531d5f201177e5d61811f2578223..1495bd210127ba5fdc155669bf9d439968422c8e 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs
@@ -159,6 +159,7 @@ pub fn expand_outer_enum(
 			#event_custom_derives
 			#scrate::__private::codec::Encode,
 			#scrate::__private::codec::Decode,
+			#scrate::__private::codec::DecodeWithMemTracking,
 			#scrate::__private::scale_info::TypeInfo,
 			#scrate::__private::Debug,
 		)]
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/slash_reason.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/slash_reason.rs
index 892b842b174872c1d15ab39bcf0c7cc5b509c961..a0e441dec26a3ef3e02aefba9d6c476a0931d823 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/slash_reason.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/slash_reason.rs
@@ -51,7 +51,10 @@ pub fn expand_outer_slash_reason(pallet_decls: &[Pallet], scrate: &TokenStream)
 		/// A reason for slashing funds.
 		#[derive(
 			Copy, Clone, Eq, PartialEq,
-			#scrate::__private::codec::Encode, #scrate::__private::codec::Decode, #scrate::__private::codec::MaxEncodedLen,
+			#scrate::__private::codec::Encode,
+			#scrate::__private::codec::Decode,
+			#scrate::__private::codec::DecodeWithMemTracking,
+			#scrate::__private::codec::MaxEncodedLen,
 			#scrate::__private::scale_info::TypeInfo,
 			#scrate::__private::RuntimeDebug,
 		)]
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs
index b9b8efb8c006364dc48e25926c158664066a9d65..b1cf4f858de11ff4a3b5f7bca2e5289f976ab1f9 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs
@@ -88,6 +88,7 @@ pub fn expand_outer_task(
 			Clone, Eq, PartialEq,
 			#scrate::__private::codec::Encode,
 			#scrate::__private::codec::Decode,
+			#scrate::__private::codec::DecodeWithMemTracking,
 			#scrate::__private::scale_info::TypeInfo,
 			#scrate::__private::RuntimeDebug,
 		)]
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/view_function.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/view_function.rs
index df6b4c42a9b053018cfa90c4de5ec9a6eed5d25f..082a2e6ea3076b9d66677d25d0d568143567e568 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/view_function.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/view_function.rs
@@ -43,6 +43,7 @@ pub fn expand_outer_query(
 			Clone, PartialEq, Eq,
 			#scrate::__private::codec::Encode,
 			#scrate::__private::codec::Decode,
+			#scrate::__private::codec::DecodeWithMemTracking,
 			#scrate::__private::scale_info::TypeInfo,
 			#scrate::__private::RuntimeDebug,
 		)]
diff --git a/substrate/frame/support/procedural/src/dynamic_params.rs b/substrate/frame/support/procedural/src/dynamic_params.rs
index ad62f59e6b0a04ea50c02375d6e1f421fc5689aa..9cc04e8a1647a132c1c21a35761a62f4911626d0 100644
--- a/substrate/frame/support/procedural/src/dynamic_params.rs
+++ b/substrate/frame/support/procedural/src/dynamic_params.rs
@@ -266,6 +266,7 @@ impl ToTokens for DynamicPalletParamAttr {
 					Eq,
 					#scrate::__private::codec::Encode,
 					#scrate::__private::codec::Decode,
+					#scrate::__private::codec::DecodeWithMemTracking,
 					#scrate::__private::codec::MaxEncodedLen,
 					#scrate::__private::RuntimeDebug,
 					#scrate::__private::scale_info::TypeInfo
@@ -284,6 +285,7 @@ impl ToTokens for DynamicPalletParamAttr {
 					Eq,
 					#scrate::__private::codec::Encode,
 					#scrate::__private::codec::Decode,
+					#scrate::__private::codec::DecodeWithMemTracking,
 					#scrate::__private::codec::MaxEncodedLen,
 					#scrate::__private::RuntimeDebug,
 					#scrate::__private::scale_info::TypeInfo
@@ -302,6 +304,7 @@ impl ToTokens for DynamicPalletParamAttr {
 					Eq,
 					#scrate::__private::codec::Encode,
 					#scrate::__private::codec::Decode,
+					#scrate::__private::codec::DecodeWithMemTracking,
 					#scrate::__private::codec::MaxEncodedLen,
 					#scrate::__private::RuntimeDebug,
 					#scrate::__private::scale_info::TypeInfo
@@ -336,6 +339,7 @@ impl ToTokens for DynamicPalletParamAttr {
 						Eq,
 						#scrate::__private::codec::Encode,
 						#scrate::__private::codec::Decode,
+						#scrate::__private::codec::DecodeWithMemTracking,
 						#scrate::__private::codec::MaxEncodedLen,
 						#scrate::__private::RuntimeDebug,
 						#scrate::__private::scale_info::TypeInfo
@@ -473,6 +477,7 @@ impl ToTokens for DynamicParamAggregatedEnum {
 				Eq,
 				#scrate::__private::codec::Encode,
 				#scrate::__private::codec::Decode,
+				#scrate::__private::codec::DecodeWithMemTracking,
 				#scrate::__private::codec::MaxEncodedLen,
 				#scrate::sp_runtime::RuntimeDebug,
 				#scrate::__private::scale_info::TypeInfo
@@ -492,6 +497,7 @@ impl ToTokens for DynamicParamAggregatedEnum {
 				Eq,
 				#scrate::__private::codec::Encode,
 				#scrate::__private::codec::Decode,
+				#scrate::__private::codec::DecodeWithMemTracking,
 				#scrate::__private::codec::MaxEncodedLen,
 				#scrate::sp_runtime::RuntimeDebug,
 				#scrate::__private::scale_info::TypeInfo
@@ -510,6 +516,7 @@ impl ToTokens for DynamicParamAggregatedEnum {
 				Eq,
 				#scrate::__private::codec::Encode,
 				#scrate::__private::codec::Decode,
+				#scrate::__private::codec::DecodeWithMemTracking,
 				#scrate::__private::codec::MaxEncodedLen,
 				#scrate::sp_runtime::RuntimeDebug,
 				#scrate::__private::scale_info::TypeInfo
diff --git a/substrate/frame/support/procedural/src/pallet/expand/call.rs b/substrate/frame/support/procedural/src/pallet/expand/call.rs
index 87fb4b8967e6e03f95b26675fc2bbb2c0636d05e..a968b5f9df80061251bde558036b6293010a8bb0 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/call.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/call.rs
@@ -306,6 +306,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
 			#frame_support::PartialEqNoBound,
 			#frame_support::__private::codec::Encode,
 			#frame_support::__private::codec::Decode,
+			#frame_support::__private::codec::DecodeWithMemTracking,
 			#frame_support::__private::scale_info::TypeInfo,
 		)]
 		#[codec(encode_bound())]
diff --git a/substrate/frame/support/procedural/src/pallet/expand/error.rs b/substrate/frame/support/procedural/src/pallet/expand/error.rs
index 646655cfe14eb20f78b3e5f296c51aa7d1247d6e..5df82d453e0a02d8716dba53ae55a69c7218db6d 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/error.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/error.rs
@@ -122,6 +122,7 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream {
 		#[derive(
 			#frame_support::__private::codec::Encode,
 			#frame_support::__private::codec::Decode,
+			#frame_support::__private::codec::DecodeWithMemTracking,
 			#frame_support::__private::scale_info::TypeInfo,
 			#frame_support::PalletError,
 		)]
diff --git a/substrate/frame/support/procedural/src/pallet/expand/event.rs b/substrate/frame/support/procedural/src/pallet/expand/event.rs
index 45ca4b7df948a2c00ce6546b66b040bddec0c706..8ebf077d0925db1be4f3b3a814a574b88adf771d 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/event.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/event.rs
@@ -123,6 +123,7 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream {
 			#frame_support::DebugNoBound,
 			#frame_support::__private::codec::Encode,
 			#frame_support::__private::codec::Decode,
+			#frame_support::__private::codec::DecodeWithMemTracking,
 			#frame_support::__private::scale_info::TypeInfo,
 		)]
 	));
diff --git a/substrate/frame/support/procedural/src/pallet/expand/tasks.rs b/substrate/frame/support/procedural/src/pallet/expand/tasks.rs
index b6346ca8ff34265844d14ca19c9dd8e6514bae2b..6cd2436c4646a36f4471befa48681796247def68 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/tasks.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/tasks.rs
@@ -99,6 +99,7 @@ impl TaskEnumDef {
 					#frame_support::PartialEqNoBound,
 					#frame_support::pallet_prelude::Encode,
 					#frame_support::pallet_prelude::Decode,
+					#frame_support::pallet_prelude::DecodeWithMemTracking,
 					#frame_support::pallet_prelude::TypeInfo,
 				)]
 				#[codec(encode_bound())]
diff --git a/substrate/frame/support/procedural/src/pallet/expand/view_functions.rs b/substrate/frame/support/procedural/src/pallet/expand/view_functions.rs
index 5838db9d89ddcf5dbae38fa9fcd2d42ad54df99f..0222301852c9bdeb143fe78943b7575aae607b15 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/view_functions.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/view_functions.rs
@@ -108,6 +108,7 @@ fn expand_view_function(
 			#frame_support::PartialEqNoBound,
 			#frame_support::__private::codec::Encode,
 			#frame_support::__private::codec::Decode,
+			#frame_support::__private::codec::DecodeWithMemTracking,
 			#frame_support::__private::scale_info::TypeInfo,
 		)]
 		#[codec(encode_bound())]
diff --git a/substrate/frame/support/procedural/src/pallet/parse/composite.rs b/substrate/frame/support/procedural/src/pallet/parse/composite.rs
index 20fc30cd26b1f5eca394a319e31fee1280978b69..b3131d29f338b66e23efeb3a7b8857d5c638f1c0 100644
--- a/substrate/frame/support/procedural/src/pallet/parse/composite.rs
+++ b/substrate/frame/support/procedural/src/pallet/parse/composite.rs
@@ -151,7 +151,10 @@ impl CompositeDef {
 			let derive_attr: syn::Attribute = syn::parse_quote! {
 				#[derive(
 					Copy, Clone, Eq, PartialEq,
-					#scrate::__private::codec::Encode, #scrate::__private::codec::Decode, #scrate::__private::codec::MaxEncodedLen,
+					#scrate::__private::codec::Encode,
+					#scrate::__private::codec::Decode,
+					#scrate::__private::codec::DecodeWithMemTracking,
+					#scrate::__private::codec::MaxEncodedLen,
 					#scrate::__private::scale_info::TypeInfo,
 					#scrate::__private::RuntimeDebug,
 				)]
diff --git a/substrate/frame/support/src/dispatch.rs b/substrate/frame/support/src/dispatch.rs
index 14bc2667def179cc0d403287acca811939824bbe..92284f370a5f33f8449996e2d10db4d471f24c0e 100644
--- a/substrate/frame/support/src/dispatch.rs
+++ b/substrate/frame/support/src/dispatch.rs
@@ -19,7 +19,7 @@
 //! generating values representing lazy module function calls.
 
 use crate::traits::UnfilteredDispatchable;
-use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen};
+use codec::{Codec, Decode, DecodeWithMemTracking, Encode, EncodeLike, MaxEncodedLen};
 use core::fmt;
 use scale_info::TypeInfo;
 #[cfg(feature = "std")]
@@ -72,7 +72,17 @@ pub trait CheckIfFeeless {
 }
 
 /// Origin for the System pallet.
-#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]
+#[derive(
+	PartialEq,
+	Eq,
+	Clone,
+	RuntimeDebug,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum RawOrigin<AccountId> {
 	/// The system itself ordained this dispatch to happen: this is the highest privilege level.
 	Root,
@@ -135,7 +145,9 @@ pub trait PaysFee<T> {
 }
 
 /// Explicit enum to denote if a transaction pays fee or not.
-#[derive(Clone, Copy, Eq, PartialEq, RuntimeDebug, Encode, Decode, TypeInfo)]
+#[derive(
+	Clone, Copy, Eq, PartialEq, RuntimeDebug, Encode, Decode, DecodeWithMemTracking, TypeInfo,
+)]
 pub enum Pays {
 	/// Transactor will pay related fees.
 	Yes,
@@ -170,7 +182,9 @@ impl From<bool> for Pays {
 /// [DispatchClass::all] and [DispatchClass::non_mandatory] helper functions.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
-#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)]
+#[derive(
+	PartialEq, Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, TypeInfo,
+)]
 pub enum DispatchClass {
 	/// A normal dispatch.
 	Normal,
@@ -291,7 +305,18 @@ pub fn extract_actual_pays_fee(result: &DispatchResultWithPostInfo, info: &Dispa
 
 /// Weight information that is only available post dispatch.
 /// NOTE: This can only be used to reduce the weight or fee, not increase it.
-#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)]
+#[derive(
+	Clone,
+	Copy,
+	Eq,
+	PartialEq,
+	Default,
+	RuntimeDebug,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+)]
 pub struct PostDispatchInfo {
 	/// Actual weight consumed by a call or `None` which stands for the worst case static weight.
 	pub actual_weight: Option<Weight>,
diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs
index 825628fb01edb1600efbd379faac4f0665621f93..86c7330d275de3cfa722fd9ba789a42a1a730dec 100644
--- a/substrate/frame/support/src/lib.rs
+++ b/substrate/frame/support/src/lib.rs
@@ -914,7 +914,7 @@ pub mod pallet_prelude {
 		Blake2_128, Blake2_128Concat, Blake2_256, CloneNoBound, DebugNoBound, EqNoBound, Identity,
 		PartialEqNoBound, RuntimeDebugNoBound, Twox128, Twox256, Twox64Concat,
 	};
-	pub use codec::{Decode, Encode, MaxEncodedLen};
+	pub use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 	pub use core::marker::PhantomData;
 	pub use frame_support::pallet_macros::*;
 	pub use frame_support_procedural::{inject_runtime_type, register_default_impl};
diff --git a/substrate/frame/support/src/traits/hooks.rs b/substrate/frame/support/src/traits/hooks.rs
index 51209cb542467822c51465b6fe4c779aedaf4246..bf54f237eb707cb27181e07ba5f7fae578d273e8 100644
--- a/substrate/frame/support/src/traits/hooks.rs
+++ b/substrate/frame/support/src/traits/hooks.rs
@@ -628,6 +628,8 @@ pub trait OnTimestampSet<Moment> {
 #[cfg(test)]
 mod tests {
 	use super::*;
+	use crate::parameter_types;
+	use alloc::vec::Vec;
 	use sp_io::TestExternalities;
 
 	#[cfg(feature = "try-runtime")]
@@ -712,7 +714,9 @@ mod tests {
 
 	#[test]
 	fn on_idle_round_robin_works() {
-		static mut ON_IDLE_INVOCATION_ORDER: alloc::vec::Vec<&str> = alloc::vec::Vec::new();
+		parameter_types! {
+			static OnIdleInvocationOrder: Vec<&'static str> = Vec::new();
+		}
 
 		struct Test1;
 		struct Test2;
@@ -720,49 +724,41 @@ mod tests {
 		type TestTuple = (Test1, Test2, Test3);
 		impl OnIdle<u32> for Test1 {
 			fn on_idle(_n: u32, _weight: Weight) -> Weight {
-				unsafe {
-					ON_IDLE_INVOCATION_ORDER.push("Test1");
-				}
+				OnIdleInvocationOrder::mutate(|o| o.push("Test1"));
 				Weight::zero()
 			}
 		}
 		impl OnIdle<u32> for Test2 {
 			fn on_idle(_n: u32, _weight: Weight) -> Weight {
-				unsafe {
-					ON_IDLE_INVOCATION_ORDER.push("Test2");
-				}
+				OnIdleInvocationOrder::mutate(|o| o.push("Test2"));
 				Weight::zero()
 			}
 		}
 		impl OnIdle<u32> for Test3 {
 			fn on_idle(_n: u32, _weight: Weight) -> Weight {
-				unsafe {
-					ON_IDLE_INVOCATION_ORDER.push("Test3");
-				}
+				OnIdleInvocationOrder::mutate(|o| o.push("Test3"));
 				Weight::zero()
 			}
 		}
 
-		unsafe {
-			TestTuple::on_idle(0, Weight::zero());
-			assert_eq!(ON_IDLE_INVOCATION_ORDER, ["Test1", "Test2", "Test3"].to_vec());
-			ON_IDLE_INVOCATION_ORDER.clear();
+		TestTuple::on_idle(0, Weight::zero());
+		assert_eq!(OnIdleInvocationOrder::get(), ["Test1", "Test2", "Test3"].to_vec());
+		OnIdleInvocationOrder::mutate(|o| o.clear());
 
-			TestTuple::on_idle(1, Weight::zero());
-			assert_eq!(ON_IDLE_INVOCATION_ORDER, ["Test2", "Test3", "Test1"].to_vec());
-			ON_IDLE_INVOCATION_ORDER.clear();
+		TestTuple::on_idle(1, Weight::zero());
+		assert_eq!(OnIdleInvocationOrder::get(), ["Test2", "Test3", "Test1"].to_vec());
+		OnIdleInvocationOrder::mutate(|o| o.clear());
 
-			TestTuple::on_idle(2, Weight::zero());
-			assert_eq!(ON_IDLE_INVOCATION_ORDER, ["Test3", "Test1", "Test2"].to_vec());
-			ON_IDLE_INVOCATION_ORDER.clear();
+		TestTuple::on_idle(2, Weight::zero());
+		assert_eq!(OnIdleInvocationOrder::get(), ["Test3", "Test1", "Test2"].to_vec());
+		OnIdleInvocationOrder::mutate(|o| o.clear());
 
-			TestTuple::on_idle(3, Weight::zero());
-			assert_eq!(ON_IDLE_INVOCATION_ORDER, ["Test1", "Test2", "Test3"].to_vec());
-			ON_IDLE_INVOCATION_ORDER.clear();
+		TestTuple::on_idle(3, Weight::zero());
+		assert_eq!(OnIdleInvocationOrder::get(), ["Test1", "Test2", "Test3"].to_vec());
+		OnIdleInvocationOrder::mutate(|o| o.clear());
 
-			TestTuple::on_idle(4, Weight::zero());
-			assert_eq!(ON_IDLE_INVOCATION_ORDER, ["Test2", "Test3", "Test1"].to_vec());
-			ON_IDLE_INVOCATION_ORDER.clear();
-		}
+		TestTuple::on_idle(4, Weight::zero());
+		assert_eq!(OnIdleInvocationOrder::get(), ["Test2", "Test3", "Test1"].to_vec());
+		OnIdleInvocationOrder::mutate(|o| o.clear());
 	}
 }
diff --git a/substrate/frame/support/src/traits/messages.rs b/substrate/frame/support/src/traits/messages.rs
index d28716237119e8972b7069a806a82cbca0c26169..f2bbb2fdadabe25e4d647c0344d81b4a9ceb11dc 100644
--- a/substrate/frame/support/src/traits/messages.rs
+++ b/substrate/frame/support/src/traits/messages.rs
@@ -18,7 +18,7 @@
 //! Traits for managing message queuing and handling.
 
 use super::storage::Footprint;
-use codec::{Decode, Encode, FullCodec, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, FullCodec, MaxEncodedLen};
 use core::{fmt::Debug, marker::PhantomData};
 use scale_info::TypeInfo;
 use sp_core::{ConstU32, Get, TypedGet};
@@ -27,7 +27,7 @@ use sp_weights::{Weight, WeightMeter};
 
 /// Errors that can happen when attempting to process a message with
 /// [`ProcessMessage::process_message()`].
-#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, TypeInfo, Debug)]
+#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, TypeInfo, Debug)]
 pub enum ProcessMessageError {
 	/// The message data format is unknown (e.g. unrecognised header)
 	BadFormat,
diff --git a/substrate/frame/support/src/traits/preimages.rs b/substrate/frame/support/src/traits/preimages.rs
index 6e46a7489654ee61b76bf3da219fcafec4333acd..e0c76b8bdff817245214bcf0024989615a5de280 100644
--- a/substrate/frame/support/src/traits/preimages.rs
+++ b/substrate/frame/support/src/traits/preimages.rs
@@ -18,7 +18,7 @@
 //! Stuff for dealing with hashed preimages.
 
 use alloc::borrow::Cow;
-use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, EncodeLike, MaxEncodedLen};
 use scale_info::TypeInfo;
 use sp_core::RuntimeDebug;
 use sp_runtime::{
@@ -31,7 +31,17 @@ pub type BoundedInline = crate::BoundedVec<u8, ConstU32<128>>;
 /// The maximum we expect a single legacy hash lookup to be.
 const MAX_LEGACY_LEN: u32 = 1_000_000;
 
-#[derive(Encode, Decode, MaxEncodedLen, Clone, Eq, PartialEq, TypeInfo, RuntimeDebug)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	Clone,
+	Eq,
+	PartialEq,
+	TypeInfo,
+	RuntimeDebug,
+)]
 #[codec(mel_bound())]
 pub enum Bounded<T, H: Hash> {
 	/// A hash with no preimage length. We do not support creation of this except
diff --git a/substrate/frame/support/src/traits/schedule.rs b/substrate/frame/support/src/traits/schedule.rs
index a302e28d4ce24fe4c6c1b7cc7a4fcb79d0e107c2..2bf53d5f45a98e0984df51fd8a6a7084f03bad9e 100644
--- a/substrate/frame/support/src/traits/schedule.rs
+++ b/substrate/frame/support/src/traits/schedule.rs
@@ -20,7 +20,7 @@
 #[allow(deprecated)]
 use super::PreimageProvider;
 use alloc::vec::Vec;
-use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen};
+use codec::{Codec, Decode, DecodeWithMemTracking, Encode, EncodeLike, MaxEncodedLen};
 use core::{fmt::Debug, result::Result};
 use scale_info::TypeInfo;
 use sp_runtime::{traits::Saturating, DispatchError, RuntimeDebug};
@@ -35,7 +35,18 @@ pub type Period<BlockNumber> = (BlockNumber, u32);
 pub type Priority = u8;
 
 /// The dispatch time of a scheduled task.
-#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Copy,
+	Clone,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum DispatchTime<BlockNumber> {
 	/// At specified block.
 	At(BlockNumber),
diff --git a/substrate/frame/support/src/traits/tokens/fungible/union_of.rs b/substrate/frame/support/src/traits/tokens/fungible/union_of.rs
index 5cb1d0a9e7b0758504ad92a0a6698ad1f652e078..f8d476d517fe4d36427a579841b285cb89ed61ad 100644
--- a/substrate/frame/support/src/traits/tokens/fungible/union_of.rs
+++ b/substrate/frame/support/src/traits/tokens/fungible/union_of.rs
@@ -20,7 +20,7 @@
 //!
 //! See the [`crate::traits::fungible`] doc for more information about fungible traits.
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::cmp::Ordering;
 use frame_support::traits::{
 	fungible::imbalance,
@@ -40,7 +40,9 @@ use sp_runtime::{
 
 /// The `NativeOrWithId` enum classifies an asset as either `Native` to the current chain or as an
 /// asset with a specific ID.
-#[derive(Decode, Encode, Default, MaxEncodedLen, TypeInfo, Clone, RuntimeDebug, Eq)]
+#[derive(
+	Decode, DecodeWithMemTracking, Encode, Default, MaxEncodedLen, TypeInfo, Clone, RuntimeDebug, Eq,
+)]
 pub enum NativeOrWithId<AssetId>
 where
 	AssetId: Ord,
diff --git a/substrate/frame/support/src/traits/tokens/misc.rs b/substrate/frame/support/src/traits/tokens/misc.rs
index 52d3e8c014b317261746371d8ff99acc66f2a517..4978016603dcbdc2b58e4489404023356aaa2952 100644
--- a/substrate/frame/support/src/traits/tokens/misc.rs
+++ b/substrate/frame/support/src/traits/tokens/misc.rs
@@ -18,7 +18,7 @@
 //! Miscellaneous types.
 
 use crate::{traits::Contains, TypeInfo};
-use codec::{Decode, Encode, FullCodec, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, FullCodec, MaxEncodedLen};
 use core::fmt::Debug;
 use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero};
 use sp_core::RuntimeDebug;
@@ -178,7 +178,16 @@ pub enum ExistenceRequirement {
 
 /// Status of funds.
 #[derive(
-	PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug, scale_info::TypeInfo, MaxEncodedLen,
+	PartialEq,
+	Eq,
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	scale_info::TypeInfo,
+	MaxEncodedLen,
 )]
 pub enum BalanceStatus {
 	/// Funds are free, as corresponding to `free` item in Balances.
diff --git a/substrate/frame/support/test/Cargo.toml b/substrate/frame/support/test/Cargo.toml
index ca122e6bd5446bc0d45e526fd7ba588a9ceda9be..37287452f319dc38e39369d882c08f7d9ccbd2c9 100644
--- a/substrate/frame/support/test/Cargo.toml
+++ b/substrate/frame/support/test/Cargo.toml
@@ -60,6 +60,12 @@ std = [
 	"test-pallet/std",
 ]
 experimental = ["frame-support/experimental", "frame-system/experimental"]
+runtime-benchmarks = [
+	"frame-benchmarking/runtime-benchmarks",
+	"frame-support/runtime-benchmarks",
+	"frame-system/runtime-benchmarks",
+	"sp-runtime/runtime-benchmarks",
+]
 try-runtime = [
 	"frame-executive/try-runtime",
 	"frame-support/try-runtime",
diff --git a/substrate/frame/support/test/tests/benchmark_ui.rs b/substrate/frame/support/test/tests/benchmark_ui.rs
index aa5fadd0e27bf591e1a1e5552dcfed0c0b4e316d..410f9e09a43a16ea6501dbc1085d39292960c219 100644
--- a/substrate/frame/support/test/tests/benchmark_ui.rs
+++ b/substrate/frame/support/test/tests/benchmark_ui.rs
@@ -28,7 +28,7 @@ fn benchmark_ui() {
 	std::env::set_var("SKIP_WASM_BUILD", "1");
 
 	// Deny all warnings since we emit warnings as part of a Pallet's UI.
-	std::env::set_var("RUSTFLAGS", "--deny warnings");
+	std::env::set_var("CARGO_ENCODED_RUSTFLAGS", "--deny=warnings");
 
 	let t = trybuild::TestCases::new();
 	t.compile_fail("tests/benchmark_ui/*.rs");
diff --git a/substrate/frame/support/test/tests/benchmark_ui/invalid_origin.stderr b/substrate/frame/support/test/tests/benchmark_ui/invalid_origin.stderr
index 30f1289767fc54ca55c5d64125eea402e84344c3..87d4f476a60d1be358a31f965d9d01772082e450 100644
--- a/substrate/frame/support/test/tests/benchmark_ui/invalid_origin.stderr
+++ b/substrate/frame/support/test/tests/benchmark_ui/invalid_origin.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `<T as frame_support_test::Config>::RuntimeOrigin:
   --> tests/benchmark_ui/invalid_origin.rs:23:1
    |
 23 | #[benchmarks]
-   | ^^^^^^^^^^^^^ the trait `From<{integer}>` is not implemented for `<T as frame_support_test::Config>::RuntimeOrigin`, which is required by `{integer}: Into<_>`
+   | ^^^^^^^^^^^^^ the trait `From<{integer}>` is not implemented for `<T as frame_support_test::Config>::RuntimeOrigin`
    |
    = note: required for `{integer}` to implement `Into<<T as frame_support_test::Config>::RuntimeOrigin>`
    = note: this error originates in the attribute macro `benchmarks` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/substrate/frame/support/test/tests/benchmark_ui/pass/valid_const_expr.rs b/substrate/frame/support/test/tests/benchmark_ui/pass/valid_const_expr.rs
index b1ef44be8b09dcb5e55a998b49cf38ffde7e91b3..e6ba5873e899daa4fe3d72742a3639a83de2d730 100644
--- a/substrate/frame/support/test/tests/benchmark_ui/pass/valid_const_expr.rs
+++ b/substrate/frame/support/test/tests/benchmark_ui/pass/valid_const_expr.rs
@@ -25,6 +25,7 @@ mod benches {
 
 	const MY_CONST: u32 = 100;
 
+	#[allow(dead_code)]
 	const fn my_fn() -> u32 {
 		200
 	}
diff --git a/substrate/frame/support/test/tests/construct_runtime_ui.rs b/substrate/frame/support/test/tests/construct_runtime_ui.rs
index 0cf857e2d73c025392c96e02c3d7439690ea8c88..3ff60a60c611c941a8d69c3817df1cb8a586b0c9 100644
--- a/substrate/frame/support/test/tests/construct_runtime_ui.rs
+++ b/substrate/frame/support/test/tests/construct_runtime_ui.rs
@@ -28,7 +28,7 @@ fn ui() {
 	std::env::set_var("SKIP_WASM_BUILD", "1");
 
 	// Deny all warnings since we emit warnings as part of a Runtime's UI.
-	std::env::set_var("RUSTFLAGS", "--deny warnings");
+	std::env::set_var("CARGO_ENCODED_RUSTFLAGS", "--deny=warnings");
 
 	let t = trybuild::TestCases::new();
 	t.compile_fail("tests/construct_runtime_ui/*.rs");
diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr
index 3b0bf05bd4e721ae334f51961a92da8abb3110a4..b468b8647ca19c83fca9da4eb448715312a54e5b 100644
--- a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr
+++ b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr
@@ -86,7 +86,7 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied
 ...  |
 27 | |     }
 28 | | }
-   | |_^ the trait `Config` is not implemented for `Runtime`, which is required by `Pallet<Runtime>: Callable<Runtime>`
+   | |_^ the trait `Config` is not implemented for `Runtime`
    |
    = help: the trait `Callable<T>` is implemented for `Pallet<T>`
    = note: required for `Pallet<Runtime>` to implement `Callable<Runtime>`
@@ -237,7 +237,7 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied
 ...  |
 27 | |     }
 28 | | }
-   | |_^ the trait `Config` is not implemented for `Runtime`, which is required by `&frame_system::Event<Runtime>: std::fmt::Debug`
+   | |_^ the trait `Config` is not implemented for `Runtime`
    |
    = help: the trait `std::fmt::Debug` is implemented for `frame_system::Event<T>`
    = note: required for `frame_system::Event<Runtime>` to implement `std::fmt::Debug`
@@ -256,7 +256,7 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied
 ...  |
 27 | |     }
 28 | | }
-   | |_^ the trait `Config` is not implemented for `Runtime`, which is required by `&frame_system::Error<Runtime>: std::fmt::Debug`
+   | |_^ the trait `Config` is not implemented for `Runtime`
    |
    = help: the trait `std::fmt::Debug` is implemented for `frame_system::Error<T>`
    = note: required for `frame_system::Error<Runtime>` to implement `std::fmt::Debug`
@@ -295,7 +295,7 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied
 ...  |
 27 | |     }
 28 | | }
-   | |_^ the trait `Config` is not implemented for `Runtime`, which is required by `RawOrigin<_>: Into<_>`
+   | |_^ the trait `Config` is not implemented for `Runtime`
    |
    = note: required for `RawOrigin<_>` to implement `Into<RuntimeOrigin>`
    = note: this error originates in the macro `frame_support::construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -344,7 +344,7 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied
 ...  |
 27 | |     }
 28 | | }
-   | |_^ the trait `Config` is not implemented for `Runtime`, which is required by `Pallet<Runtime>: PalletInfoAccess`
+   | |_^ the trait `Config` is not implemented for `Runtime`
    |
    = help: the trait `PalletInfoAccess` is implemented for `Pallet<T>`
    = note: required for `Pallet<Runtime>` to implement `PalletInfoAccess`
@@ -360,7 +360,7 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied
 ...  |
 27 | |     }
 28 | | }
-   | |_^ the trait `Config` is not implemented for `Runtime`, which is required by `Pallet<Runtime>: Callable<Runtime>`
+   | |_^ the trait `Config` is not implemented for `Runtime`
    |
    = help: the trait `Callable<T>` is implemented for `Pallet<T>`
    = note: required for `Pallet<Runtime>` to implement `Callable<Runtime>`
@@ -376,7 +376,7 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied
 ...  |
 27 | |     }
 28 | | }
-   | |_^ the trait `Config` is not implemented for `Runtime`, which is required by `Pallet<Runtime>: Callable<Runtime>`
+   | |_^ the trait `Config` is not implemented for `Runtime`
    |
    = help: the trait `Callable<T>` is implemented for `Pallet<T>`
    = note: required for `Pallet<Runtime>` to implement `Callable<Runtime>`
@@ -466,7 +466,7 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied
 ...  |
 27 | |     }
 28 | | }
-   | |_^ the trait `Config` is not implemented for `Runtime`, which is required by `Pallet<Runtime>: Callable<Runtime>`
+   | |_^ the trait `Config` is not implemented for `Runtime`
    |
    = help: the trait `Callable<T>` is implemented for `Pallet<T>`
    = note: required for `Pallet<Runtime>` to implement `Callable<Runtime>`
@@ -569,7 +569,7 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied
   --> tests/construct_runtime_ui/deprecated_where_block.rs:26:3
    |
 26 |         System: frame_system::{Pallet, Call, Storage, Config<T>, Event<T>},
-   |         ^^^^^^ the trait `Config` is not implemented for `Runtime`, which is required by `Pallet<Runtime>: ViewFunctionIdPrefix`
+   |         ^^^^^^ the trait `Config` is not implemented for `Runtime`
    |
    = help: the trait `ViewFunctionIdPrefix` is implemented for `Pallet<T>`
    = note: required for `Pallet<Runtime>` to implement `ViewFunctionIdPrefix`
@@ -784,7 +784,7 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied
 ...  |
 27 | |     }
 28 | | }
-   | |_^ the trait `Config` is not implemented for `Runtime`, which is required by `GenesisConfig<Runtime>: Serialize`
+   | |_^ the trait `Config` is not implemented for `Runtime`
    |
    = help: the trait `Serialize` is implemented for `GenesisConfig<T>`
    = note: required for `GenesisConfig<Runtime>` to implement `Serialize`
@@ -846,10 +846,13 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied
 ...  |
 27 | |     }
 28 | | }
-   | |_^ the trait `Config` is not implemented for `Runtime`, which is required by `GenesisConfig<Runtime>: std::default::Default`
+   | |_^ the trait `Config` is not implemented for `Runtime`
+   |
+note: required by a bound in `GenesisConfig`
+  --> $WORKSPACE/substrate/frame/system/src/lib.rs
    |
-   = help: the trait `std::default::Default` is implemented for `GenesisConfig<T>`
-   = note: required for `GenesisConfig<Runtime>` to implement `std::default::Default`
+   |     pub struct GenesisConfig<T: Config> {
+   |                                 ^^^^^^ required by this bound in `GenesisConfig`
    = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `Runtime: Config` is not satisfied
@@ -862,7 +865,7 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied
 ...  |
 27 | |     }
 28 | | }
-   | |_^ the trait `Config` is not implemented for `Runtime`, which is required by `(Pallet<Runtime>,): OnGenesis`
+   | |_^ the trait `Config` is not implemented for `Runtime`
    |
    = help: the following other types implement trait `OnGenesis`:
              ()
diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.rs b/substrate/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.rs
index 3ec1d5669618fc1a76afe195dbce9cac135e1035..fe1478a6369898ad5a64035c242f8a63f9c989e8 100644
--- a/substrate/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.rs
+++ b/substrate/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.rs
@@ -33,22 +33,46 @@ mod pallet {
 	}
 }
 
-#[derive(scale_info::TypeInfo, frame_support::PalletError, codec::Encode, codec::Decode)]
+#[derive(
+	scale_info::TypeInfo,
+	frame_support::PalletError,
+	codec::Encode,
+	codec::Decode,
+	codec::DecodeWithMemTracking,
+)]
 pub enum Nested1 {
 	Nested2(Nested2),
 }
 
-#[derive(scale_info::TypeInfo, frame_support::PalletError, codec::Encode, codec::Decode)]
+#[derive(
+	scale_info::TypeInfo,
+	frame_support::PalletError,
+	codec::Encode,
+	codec::Decode,
+	codec::DecodeWithMemTracking,
+)]
 pub enum Nested2 {
 	Nested3(Nested3),
 }
 
-#[derive(scale_info::TypeInfo, frame_support::PalletError, codec::Encode, codec::Decode)]
+#[derive(
+	scale_info::TypeInfo,
+	frame_support::PalletError,
+	codec::Encode,
+	codec::Decode,
+	codec::DecodeWithMemTracking,
+)]
 pub enum Nested3 {
 	Nested4(Nested4),
 }
 
-#[derive(scale_info::TypeInfo, frame_support::PalletError, codec::Encode, codec::Decode)]
+#[derive(
+	scale_info::TypeInfo,
+	frame_support::PalletError,
+	codec::Encode,
+	codec::Decode,
+	codec::DecodeWithMemTracking,
+)]
 pub enum Nested4 {
 	Num(u8),
 }
diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.stderr
index 75116f71919500736a084cf8e0c854bcd2ac6f50..349fbab002cdaa0fa32882b42c13abf68054bf10 100644
--- a/substrate/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.stderr
+++ b/substrate/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.stderr
@@ -1,13 +1,13 @@
 error[E0080]: evaluation of constant value failed
-  --> tests/construct_runtime_ui/pallet_error_too_large.rs:91:1
-   |
-91 | / construct_runtime! {
-92 | |     pub struct Runtime
-93 | |     {
-94 | |         System: frame_system::{Pallet, Call, Storage, Config<T>, Event<T>},
-95 | |         Pallet: pallet::{Pallet},
-96 | |     }
-97 | | }
-   | |_^ the evaluated program panicked at 'The maximum encoded size of the error type in the `Pallet` pallet exceeds `MAX_MODULE_ERROR_ENCODED_SIZE`', $DIR/tests/construct_runtime_ui/pallet_error_too_large.rs:91:1
-   |
-   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `frame_support::construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info)
+   --> tests/construct_runtime_ui/pallet_error_too_large.rs:115:1
+    |
+115 | / construct_runtime! {
+116 | |     pub struct Runtime
+117 | |     {
+118 | |         System: frame_system::{Pallet, Call, Storage, Config<T>, Event<T>},
+119 | |         Pallet: pallet::{Pallet},
+120 | |     }
+121 | | }
+    | |_^ the evaluated program panicked at 'The maximum encoded size of the error type in the `Pallet` pallet exceeds `MAX_MODULE_ERROR_ENCODED_SIZE`', $DIR/tests/construct_runtime_ui/pallet_error_too_large.rs:115:1
+    |
+    = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `frame_support::construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/substrate/frame/support/test/tests/derive_impl_ui.rs b/substrate/frame/support/test/tests/derive_impl_ui.rs
index ee219d0670aaff7986338c26d7e80a9ef0b13395..84c010187b82e877c48cdba7c5a81c36e9979e05 100644
--- a/substrate/frame/support/test/tests/derive_impl_ui.rs
+++ b/substrate/frame/support/test/tests/derive_impl_ui.rs
@@ -30,7 +30,7 @@ fn derive_impl_ui() {
 	std::env::set_var("SKIP_WASM_BUILD", "1");
 
 	// Deny all warnings since we emit warnings as part of a Pallet's UI.
-	std::env::set_var("RUSTFLAGS", "--deny warnings");
+	std::env::set_var("CARGO_ENCODED_RUSTFLAGS", "--deny=warnings");
 
 	let t = trybuild::TestCases::new();
 	t.compile_fail("tests/derive_impl_ui/*.rs");
diff --git a/substrate/frame/support/test/tests/derive_no_bound_ui.rs b/substrate/frame/support/test/tests/derive_no_bound_ui.rs
index b1c9283c0925a7b661f680811f612e5598f35f29..11f61f6329b3c312248889541d05f332ef3e5162 100644
--- a/substrate/frame/support/test/tests/derive_no_bound_ui.rs
+++ b/substrate/frame/support/test/tests/derive_no_bound_ui.rs
@@ -27,6 +27,9 @@ fn derive_no_bound_ui() {
 	// As trybuild is using `cargo check`, we don't need the real WASM binaries.
 	std::env::set_var("SKIP_WASM_BUILD", "1");
 
+	// Deny all warnings since we emit warnings as part of a Pallet's UI.
+	std::env::set_var("CARGO_ENCODED_RUSTFLAGS", "--deny=warnings");
+
 	let t = trybuild::TestCases::new();
 	t.compile_fail("tests/derive_no_bound_ui/*.rs");
 }
diff --git a/substrate/frame/support/test/tests/enum_deprecation.rs b/substrate/frame/support/test/tests/enum_deprecation.rs
index 72b14dad962917ce0ea0fe21530aaa66cf769bb7..c8f133b06b97e82b2769bea6719c27badfa30b51 100644
--- a/substrate/frame/support/test/tests/enum_deprecation.rs
+++ b/substrate/frame/support/test/tests/enum_deprecation.rs
@@ -102,6 +102,7 @@ pub mod pallet {
 		OrdNoBound,
 		Encode,
 		Decode,
+		DecodeWithMemTracking,
 		TypeInfo,
 		MaxEncodedLen,
 	)]
diff --git a/substrate/frame/support/test/tests/instance.rs b/substrate/frame/support/test/tests/instance.rs
index 7f8423a0127e40b2b22b3eafeb4565cd8bd05c79..1325e112de16f93cf719a84f32e7cfbc7e81eefc 100644
--- a/substrate/frame/support/test/tests/instance.rs
+++ b/substrate/frame/support/test/tests/instance.rs
@@ -112,7 +112,17 @@ mod module1 {
 	}
 
 	#[pallet::origin]
-	#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
+	#[derive(
+		Clone,
+		PartialEq,
+		Eq,
+		RuntimeDebug,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		MaxEncodedLen,
+		TypeInfo,
+	)]
 	#[scale_info(skip_type_params(I))]
 	pub enum Origin<T, I = ()> {
 		Members(u32),
@@ -217,7 +227,17 @@ mod module2 {
 	}
 
 	#[pallet::origin]
-	#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
+	#[derive(
+		Clone,
+		PartialEq,
+		Eq,
+		RuntimeDebug,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		MaxEncodedLen,
+		TypeInfo,
+	)]
 	#[scale_info(skip_type_params(I))]
 	pub enum Origin<T, I = ()> {
 		Members(u32),
diff --git a/substrate/frame/support/test/tests/origin.rs b/substrate/frame/support/test/tests/origin.rs
index e6dd0cfc0e31596a868b5e0958b98af8a59e7b52..c507da320ac9738d5020390e000d866c8f7792b5 100644
--- a/substrate/frame/support/test/tests/origin.rs
+++ b/substrate/frame/support/test/tests/origin.rs
@@ -48,7 +48,17 @@ mod nested {
 		}
 
 		#[pallet::origin]
-		#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
+		#[derive(
+			Clone,
+			PartialEq,
+			Eq,
+			RuntimeDebug,
+			Encode,
+			Decode,
+			DecodeWithMemTracking,
+			MaxEncodedLen,
+			TypeInfo,
+		)]
 		pub struct Origin;
 
 		#[pallet::event]
@@ -118,7 +128,17 @@ pub mod module {
 	}
 
 	#[pallet::origin]
-	#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
+	#[derive(
+		Clone,
+		PartialEq,
+		Eq,
+		RuntimeDebug,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		MaxEncodedLen,
+		TypeInfo,
+	)]
 	pub struct Origin<T>(pub PhantomData<T>);
 
 	#[pallet::event]
diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs
index e45ff64e4c26eda45147fb9d65b688914735bfca..dc09f1d35f9893a7e1bd6ba6835eb29c09098efb 100644
--- a/substrate/frame/support/test/tests/pallet.rs
+++ b/substrate/frame/support/test/tests/pallet.rs
@@ -498,6 +498,7 @@ pub mod pallet {
 		OrdNoBound,
 		Encode,
 		Decode,
+		DecodeWithMemTracking,
 		TypeInfo,
 		MaxEncodedLen,
 	)]
diff --git a/substrate/frame/support/test/tests/pallet_instance.rs b/substrate/frame/support/test/tests/pallet_instance.rs
index 2e4baae1db7cf0dc7876d896e0b71b25959fed76..75e0c09e0b719ec2892709c8c390c0898947153d 100644
--- a/substrate/frame/support/test/tests/pallet_instance.rs
+++ b/substrate/frame/support/test/tests/pallet_instance.rs
@@ -213,6 +213,7 @@ pub mod pallet {
 		OrdNoBound,
 		Encode,
 		Decode,
+		DecodeWithMemTracking,
 		scale_info::TypeInfo,
 		MaxEncodedLen,
 	)]
diff --git a/substrate/frame/support/test/tests/pallet_ui.rs b/substrate/frame/support/test/tests/pallet_ui.rs
index 466957c9faa636c2a2d7f2b2bb1f5b58f208d1a2..c92b07b829d5d6dd8b3915344aef63e6fca89b85 100644
--- a/substrate/frame/support/test/tests/pallet_ui.rs
+++ b/substrate/frame/support/test/tests/pallet_ui.rs
@@ -28,7 +28,7 @@ fn pallet_ui() {
 	std::env::set_var("SKIP_WASM_BUILD", "1");
 
 	// Deny all warnings since we emit warnings as part of a Pallet's UI.
-	std::env::set_var("RUSTFLAGS", "--deny warnings");
+	std::env::set_var("CARGO_ENCODED_RUSTFLAGS", "--deny=warnings");
 
 	let t = trybuild::TestCases::new();
 	t.compile_fail("tests/pallet_ui/*.rs");
diff --git a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr
index 1f91f7740238622275f09f803ccea748d260b966..883740ea9245738a94cdc292e636637a30de6917 100644
--- a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr
@@ -18,7 +18,7 @@ error[E0277]: `<T as pallet::Config>::Bar` doesn't implement `std::fmt::Debug`
 38 |         pub fn foo(origin: OriginFor<T>, _bar: T::Bar) -> DispatchResultWithPostInfo {
    |                                          ^^^^ `<T as pallet::Config>::Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
    |
-   = help: the trait `std::fmt::Debug` is not implemented for `<T as pallet::Config>::Bar`, which is required by `&<T as pallet::Config>::Bar: std::fmt::Debug`
+   = help: the trait `std::fmt::Debug` is not implemented for `<T as pallet::Config>::Bar`
    = note: required for `&<T as pallet::Config>::Bar` to implement `std::fmt::Debug`
    = note: required for the cast from `&&<T as pallet::Config>::Bar` to `&dyn std::fmt::Debug`
 
diff --git a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr
index 4657c0a0c601f96709cee2ace0c45c7cdf436bef..999f9fea87251a1c6ac73b885a6518f8e2c51082 100644
--- a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr
@@ -18,7 +18,7 @@ error[E0277]: `<T as pallet::Config>::Bar` doesn't implement `std::fmt::Debug`
 38 |         pub fn foo(origin: OriginFor<T>, _bar: T::Bar) -> DispatchResultWithPostInfo {
    |                                          ^^^^ `<T as pallet::Config>::Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
    |
-   = help: the trait `std::fmt::Debug` is not implemented for `<T as pallet::Config>::Bar`, which is required by `&<T as pallet::Config>::Bar: std::fmt::Debug`
+   = help: the trait `std::fmt::Debug` is not implemented for `<T as pallet::Config>::Bar`
    = note: required for `&<T as pallet::Config>::Bar` to implement `std::fmt::Debug`
    = note: required for the cast from `&&<T as pallet::Config>::Bar` to `&dyn std::fmt::Debug`
 
@@ -41,7 +41,7 @@ error[E0277]: the trait bound `<T as pallet::Config>::Bar: Encode` is not satisf
    | ------------------------ required by a bound introduced by this call
 ...
 38 |         pub fn foo(origin: OriginFor<T>, _bar: T::Bar) -> DispatchResultWithPostInfo {
-   |                                          ^^^^ the trait `WrapperTypeEncode` is not implemented for `<T as pallet::Config>::Bar`, which is required by `<T as pallet::Config>::Bar: Encode`
+   |                                          ^^^^ the trait `WrapperTypeEncode` is not implemented for `<T as pallet::Config>::Bar`
    |
    = note: required for `<T as pallet::Config>::Bar` to implement `Encode`
 
@@ -49,7 +49,7 @@ error[E0277]: the trait bound `<T as pallet::Config>::Bar: Decode` is not satisf
   --> tests/pallet_ui/call_argument_invalid_bound_2.rs:38:42
    |
 38 |         pub fn foo(origin: OriginFor<T>, _bar: T::Bar) -> DispatchResultWithPostInfo {
-   |                                                ^^^^^^ the trait `WrapperTypeDecode` is not implemented for `<T as pallet::Config>::Bar`, which is required by `<T as pallet::Config>::Bar: Decode`
+   |                                                ^^^^^^ the trait `WrapperTypeDecode` is not implemented for `<T as pallet::Config>::Bar`
    |
    = note: required for `<T as pallet::Config>::Bar` to implement `Decode`
 
diff --git a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.rs b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.rs
index 22507b196e46b9df824b2347ccefe14907b2c07a..f4f13c8ef64db373951e2066cfe0a9c538e5febe 100644
--- a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.rs
@@ -17,7 +17,7 @@
 
 #[frame_support::pallet]
 mod pallet {
-	use codec::{Decode, Encode};
+	use codec::{Decode, DecodeWithMemTracking, Encode};
 	use frame_support::pallet_prelude::{DispatchResultWithPostInfo, Hooks};
 	use frame_system::pallet_prelude::{BlockNumberFor, OriginFor};
 
@@ -30,7 +30,7 @@ mod pallet {
 	#[pallet::hooks]
 	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
 
-	#[derive(Encode, Decode, scale_info::TypeInfo, PartialEq, Clone)]
+	#[derive(Encode, Decode, DecodeWithMemTracking, scale_info::TypeInfo, PartialEq, Clone)]
 	struct Bar;
 
 	#[pallet::call]
diff --git a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr
index f829baeb4c112727b6eccc845494831833983b92..f3424331498379e8a687c20c96a509dfeedce7dd 100644
--- a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr
@@ -18,7 +18,7 @@ error[E0277]: `Bar` doesn't implement `std::fmt::Debug`
 40 |         pub fn foo(origin: OriginFor<T>, _bar: Bar) -> DispatchResultWithPostInfo {
    |                                          ^^^^ `Bar` cannot be formatted using `{:?}`
    |
-   = help: the trait `std::fmt::Debug` is not implemented for `Bar`, which is required by `&Bar: std::fmt::Debug`
+   = help: the trait `std::fmt::Debug` is not implemented for `Bar`
    = note: add `#[derive(Debug)]` to `Bar` or manually `impl std::fmt::Debug for Bar`
    = note: required for `&Bar` to implement `std::fmt::Debug`
    = note: required for the cast from `&&Bar` to `&dyn std::fmt::Debug`
diff --git a/substrate/frame/support/test/tests/pallet_ui/call_missing_index.stderr b/substrate/frame/support/test/tests/pallet_ui/call_missing_index.stderr
index ba06285bdeeabbd6d6b45f18e75c3c622fbffe7b..cace73a333c5a35bcdb1eca7b74527427c5990e0 100644
--- a/substrate/frame/support/test/tests/pallet_ui/call_missing_index.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/call_missing_index.stderr
@@ -46,3 +46,24 @@ error: use of deprecated constant `pallet::warnings::ConstantWeight_1::_w`:
    |
 36 |         #[pallet::weight(0)]
    |                          ^
+
+error: associated function `error_metadata` is never used
+  --> tests/pallet_ui/call_missing_index.rs:26:12
+   |
+26 |     #[pallet::pallet]
+   |               ^^^^^^ associated function in this implementation
+   |
+   = note: `-D dead-code` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(dead_code)]`
+
+error: associated functions `new_call_variant_foo` and `new_call_variant_bar` are never used
+  --> tests/pallet_ui/call_missing_index.rs:32:10
+   |
+29 |     #[pallet::call]
+   |               ---- associated functions in this implementation
+...
+32 |         pub fn foo(_: OriginFor<T>) -> DispatchResult {
+   |                ^^^
+...
+37 |         pub fn bar(_: OriginFor<T>) -> DispatchResult {
+   |                ^^^
diff --git a/substrate/frame/support/test/tests/pallet_ui/call_weight_const_warning.stderr b/substrate/frame/support/test/tests/pallet_ui/call_weight_const_warning.stderr
index d399df4d85bd41f8b7d4f2eeeeb8f1be3e9ff506..553ae08cefdd12a26df90cec9a1048172b613747 100644
--- a/substrate/frame/support/test/tests/pallet_ui/call_weight_const_warning.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/call_weight_const_warning.stderr
@@ -11,3 +11,21 @@ error: use of deprecated constant `pallet::warnings::ConstantWeight_0::_w`:
    |
    = note: `-D deprecated` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(deprecated)]`
+
+error: associated function `error_metadata` is never used
+  --> tests/pallet_ui/call_weight_const_warning.rs:26:12
+   |
+26 |     #[pallet::pallet]
+   |               ^^^^^^ associated function in this implementation
+   |
+   = note: `-D dead-code` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(dead_code)]`
+
+error: associated function `new_call_variant_foo` is never used
+  --> tests/pallet_ui/call_weight_const_warning.rs:33:10
+   |
+29 |     #[pallet::call]
+   |               ---- associated function in this implementation
+...
+33 |         pub fn foo(_: OriginFor<T>) -> DispatchResult { Ok(()) }
+   |                ^^^
diff --git a/substrate/frame/support/test/tests/pallet_ui/call_weight_unchecked_warning.stderr b/substrate/frame/support/test/tests/pallet_ui/call_weight_unchecked_warning.stderr
index 33302a2a0278a12c4037e4eb194bf7032f311f08..fca5f657c67b7ee03ace2804de91aee55a60efe0 100644
--- a/substrate/frame/support/test/tests/pallet_ui/call_weight_unchecked_warning.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/call_weight_unchecked_warning.stderr
@@ -11,3 +11,21 @@ error: use of deprecated constant `pallet::warnings::UncheckedWeightWitness_0::_
    |
    = note: `-D deprecated` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(deprecated)]`
+
+error: associated function `error_metadata` is never used
+  --> tests/pallet_ui/call_weight_unchecked_warning.rs:26:12
+   |
+26 |     #[pallet::pallet]
+   |               ^^^^^^ associated function in this implementation
+   |
+   = note: `-D dead-code` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(dead_code)]`
+
+error: associated function `new_call_variant_foo` is never used
+  --> tests/pallet_ui/call_weight_unchecked_warning.rs:33:10
+   |
+29 |     #[pallet::call]
+   |               ---- associated function in this implementation
+...
+33 |         pub fn foo(_: OriginFor<T>, _unused: u64) -> DispatchResult { Ok(()) }
+   |                ^^^
diff --git a/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg_max_encoded_len.stderr b/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg_max_encoded_len.stderr
index 2fcc3328214082b97bfdda3e3acabf73ddd9b9be..d36a9a453c57c3385283d115a74c9cd5a07f693c 100644
--- a/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg_max_encoded_len.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg_max_encoded_len.stderr
@@ -35,7 +35,7 @@ error[E0277]: the trait bound `Vec<u8>: MaxEncodedLen` is not satisfied
 ...  |
 35 | |     #[pallet::storage]
 36 | |     type MyStorage<T: Config> = StorageValue<_, Vec<u8>>;
-   | |__________________^ the trait `MaxEncodedLen` is not implemented for `Vec<u8>`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageMyStorage<T>, Vec<u8>>: StorageInfoTrait`
+   | |__________________^ the trait `MaxEncodedLen` is not implemented for `Vec<u8>`
    |
    = help: the following other types implement trait `MaxEncodedLen`:
              ()
diff --git a/substrate/frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.rs b/substrate/frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.rs
index 3c6730471cb51aa2c6acc3fbb6b2c6035ce790cc..ae7d4a3d48eadc5ff2f26c827a9e4f101718e6e4 100644
--- a/substrate/frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.rs
@@ -30,7 +30,7 @@ mod pallet {
 	}
 }
 
-#[derive(scale_info::TypeInfo, codec::Encode, codec::Decode)]
+#[derive(scale_info::TypeInfo, codec::Encode, codec::Decode, codec::DecodeWithMemTracking)]
 enum MyError {}
 
 fn main() {}
diff --git a/substrate/frame/support/test/tests/pallet_ui/event_field_not_member.stderr b/substrate/frame/support/test/tests/pallet_ui/event_field_not_member.stderr
index e9c2eae686baf43af57d5b54074869de57298723..44660d269060386ab10d749e4a16cd4e65b97950 100644
--- a/substrate/frame/support/test/tests/pallet_ui/event_field_not_member.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/event_field_not_member.stderr
@@ -16,6 +16,6 @@ error[E0277]: `<T as pallet::Config>::Bar` doesn't implement `std::fmt::Debug`
 41 |         B { b: T::Bar },
    |             ^ `<T as pallet::Config>::Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
    |
-   = help: the trait `std::fmt::Debug` is not implemented for `<T as pallet::Config>::Bar`, which is required by `&<T as pallet::Config>::Bar: std::fmt::Debug`
+   = help: the trait `std::fmt::Debug` is not implemented for `<T as pallet::Config>::Bar`
    = note: required for `&<T as pallet::Config>::Bar` to implement `std::fmt::Debug`
    = note: required for the cast from `&&<T as pallet::Config>::Bar` to `&dyn std::fmt::Debug`
diff --git a/substrate/frame/support/test/tests/pallet_ui/hooks_invalid_item.stderr b/substrate/frame/support/test/tests/pallet_ui/hooks_invalid_item.stderr
index c04499dbbd144d2c85a84c908544041dd8603387..5c37e99fac22025bf44dcfaef76d8ef06648a414 100644
--- a/substrate/frame/support/test/tests/pallet_ui/hooks_invalid_item.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/hooks_invalid_item.stderr
@@ -18,4 +18,6 @@ error[E0277]: the trait bound `pallet::Pallet<T>: Hooks<<<<T as frame_system::Co
   --> tests/pallet_ui/hooks_invalid_item.rs:28:12
    |
 28 |     #[pallet::hooks]
-   |               ^^^^^ the trait `Hooks<<<<T as frame_system::Config>::Block as frame_support::sp_runtime::traits::Block>::Header as frame_support::sp_runtime::traits::Header>::Number>` is not implemented for `pallet::Pallet<T>`
+   |               ^^^^^ unsatisfied trait bound
+   |
+   = help: the trait `Hooks<<<<T as frame_system::Config>::Block as frame_support::sp_runtime::traits::Block>::Header as frame_support::sp_runtime::traits::Header>::Number>` is not implemented for `pallet::Pallet<T>`
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/config_multiple_attr.rs b/substrate/frame/support/test/tests/pallet_ui/pass/config_multiple_attr.rs
index c016c52181cf9140e1c51136bb4b2a0d913735ad..e7af18be00e084f40adb29cd73768d358f522d21 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/config_multiple_attr.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/config_multiple_attr.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 #[frame_support::pallet]
-mod pallet {
+pub mod pallet {
 	use frame_support::pallet_prelude::*;
 
 	#[pallet::config(with_default, without_automatic_metadata)]
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/config_without_metadata.rs b/substrate/frame/support/test/tests/pallet_ui/pass/config_without_metadata.rs
index c9f5244d734528347e487a5177a5bb678b32a35b..734c31431efb8f524bbcdadeaaf7645e20ee3ffe 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/config_without_metadata.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/config_without_metadata.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 #[frame_support::pallet]
-mod pallet {
+pub mod pallet {
 	use frame_support::pallet_prelude::*;
 
 	#[pallet::config(without_automatic_metadata)]
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/default_config.rs b/substrate/frame/support/test/tests/pallet_ui/pass/default_config.rs
index f169ee34c9ab5542071b11c48fa101e1c16e2e95..0d1e92e4be986d14ca35bbc6beec33e0b8f7e54d 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/default_config.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/default_config.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 #[frame_support::pallet]
-mod pallet {
+pub mod pallet {
 	use frame_support::pallet_prelude::*;
 
 	#[pallet::config(with_default)]
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/error_nested_types.rs b/substrate/frame/support/test/tests/pallet_ui/pass/error_nested_types.rs
index 0e0dc5890519fa65cbbc1b7c0d845646a2f6bb9e..9fe5f21722ab18913f2ababd80787b2202609032 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/error_nested_types.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/error_nested_types.rs
@@ -15,12 +15,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use frame_support::PalletError;
 
 #[frame_support::pallet]
 #[allow(unused_imports)]
-mod pallet {
+pub mod pallet {
 	#[pallet::config]
 	pub trait Config: frame_system::Config {}
 
@@ -33,7 +33,7 @@ mod pallet {
 	}
 }
 
-#[derive(Encode, Decode, PalletError, scale_info::TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, PalletError, scale_info::TypeInfo)]
 pub enum MyError {
 	Foo,
 	Bar,
@@ -42,17 +42,17 @@ pub enum MyError {
 	Wrapper(Wrapper),
 }
 
-#[derive(Encode, Decode, PalletError, scale_info::TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, PalletError, scale_info::TypeInfo)]
 pub enum NestedError {
 	Quux,
 }
 
-#[derive(Encode, Decode, PalletError, scale_info::TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, PalletError, scale_info::TypeInfo)]
 pub struct MyStruct {
 	field: u8,
 }
 
-#[derive(Encode, Decode, PalletError, scale_info::TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, PalletError, scale_info::TypeInfo)]
 pub struct Wrapper(bool);
 
 fn main() {}
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/event_type_bound_system_config_assoc_type.rs b/substrate/frame/support/test/tests/pallet_ui/pass/event_type_bound_system_config_assoc_type.rs
index d84d320b0b24a0d4fc7f6725678db6d1f578bdee..f028dd20de869dee47399ae3c4b57042bdfc456c 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/event_type_bound_system_config_assoc_type.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/event_type_bound_system_config_assoc_type.rs
@@ -17,7 +17,7 @@
 
 #[frame_support::pallet]
 #[allow(unused_imports)]
-mod pallet {
+pub mod pallet {
 	use frame_support::pallet_prelude::{Hooks, IsType};
 	use frame_system::pallet_prelude::BlockNumberFor;
 
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/feeless_call.rs b/substrate/frame/support/test/tests/pallet_ui/pass/feeless_call.rs
index 566b7c65cc71005a75b07f2cb9a79bf24f087e19..9028d46c9ef9b9ef47f7802b77872f34d7d96e0d 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/feeless_call.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/feeless_call.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 #[frame_support::pallet(dev_mode)]
-mod pallet {
+pub mod pallet {
 	use frame_support::pallet_prelude::DispatchResult;
 	use frame_system::pallet_prelude::OriginFor;
 
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight.rs b/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight.rs
index fdb9d8c401d1d3ffec38c1393b147b88b4acf2ac..d37a6da12bd1fb1d9a1cc7c3241ea94b2b77b489 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight.rs
@@ -23,7 +23,7 @@ pub trait WeightInfo {
 }
 
 #[frame_support::pallet]
-mod parentheses {
+pub mod parentheses {
 	use super::*;
 
 	#[pallet::config]
@@ -44,7 +44,7 @@ mod parentheses {
 }
 
 #[frame_support::pallet]
-mod assign {
+pub mod assign {
 	use super::*;
 
 	#[pallet::config]
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight2.rs b/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight2.rs
index 208c719cdfc81d90c9fa7f56626e7f96adff0f79..8a569bc96e2fee053ed2e99d58c78867fd6d9fa5 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight2.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight2.rs
@@ -29,7 +29,7 @@ impl WeightInfo for () {
 }
 
 #[frame_support::pallet]
-mod parentheses {
+pub mod parentheses {
 	use super::*;
 
 	#[pallet::config]
@@ -50,7 +50,7 @@ mod parentheses {
 }
 
 #[frame_support::pallet]
-mod assign {
+pub mod assign {
 	use super::*;
 
 	#[pallet::config]
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight3.rs b/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight3.rs
index ddccd0b3e192c4d89bc841bfbb2bf2412d82631d..574b7cceb43f73d8b42d9a304fc3bc8a82f6d439 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight3.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight3.rs
@@ -19,16 +19,16 @@ use frame_support::pallet_prelude::*;
 use frame_system::pallet_prelude::*;
 
 // If, for whatever reason, you don't to not use a `WeightInfo` trait - it will still work.
-struct Impl;
+pub struct Impl;
 
 impl Impl {
-	fn foo() -> Weight {
+	pub fn foo() -> Weight {
 		Weight::zero()
 	}
 }
 
 #[frame_support::pallet]
-mod parentheses {
+pub mod parentheses {
 	use super::*;
 
 	#[pallet::config]
@@ -48,7 +48,7 @@ mod parentheses {
 }
 
 #[frame_support::pallet]
-mod assign {
+pub mod assign {
 	use super::*;
 
 	#[pallet::config]
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight_dev_mode.rs b/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight_dev_mode.rs
index a78c9d8f36ebf4a506e2d45404adf7a81c340a23..6512a3c684815a33a0ad9061cf7142e4a8862d05 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight_dev_mode.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight_dev_mode.rs
@@ -23,7 +23,7 @@ pub trait WeightInfo {
 }
 
 #[frame_support::pallet(dev_mode)]
-mod pallet {
+pub mod pallet {
 	use super::*;
 
 	#[pallet::config]
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/simple_storage.rs b/substrate/frame/support/test/tests/pallet_ui/pass/simple_storage.rs
index 13ed3b2306fa0aef1da99853cd048e87769c750a..00f26e64b1c7298105f3f8abb2594e6525b44132 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/simple_storage.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/simple_storage.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 #[frame_support::pallet]
-mod pallet {
+pub mod pallet {
 	use frame_support::pallet_prelude::*;
 
 	#[pallet::config(with_default)]
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/task_valid.rs b/substrate/frame/support/test/tests/pallet_ui/pass/task_valid.rs
index bc66c09de7e80dddf4e710161b569e81f9b8909a..4cc2cfe700bea8a74a72614e9b0e2a90d7f9904c 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/task_valid.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/task_valid.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 #[frame_support::pallet(dev_mode)]
-mod pallet {
+pub mod pallet {
 	use frame_support::{ensure, pallet_prelude::DispatchResult};
 
 	#[pallet::config]
@@ -40,7 +40,7 @@ mod pallet {
 }
 
 #[frame_support::pallet(dev_mode)]
-mod pallet_with_instance {
+pub mod pallet_with_instance {
 	use frame_support::pallet_prelude::{ValueQuery, StorageValue};
 
 	#[pallet::config]
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/trait_constant_valid_bounds.rs b/substrate/frame/support/test/tests/pallet_ui/pass/trait_constant_valid_bounds.rs
index 83b323e3abafdaac013b232deb75e60834570abb..9fbce7fcafc0c447e68f7c9e428b3f391a1c7ba2 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/trait_constant_valid_bounds.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/trait_constant_valid_bounds.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 #[frame_support::pallet]
-mod pallet {
+pub mod pallet {
 	use frame_support::pallet_prelude::*;
 	use frame_system::pallet_prelude::BlockNumberFor;
 
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/view_function_valid.rs b/substrate/frame/support/test/tests/pallet_ui/pass/view_function_valid.rs
index a4c3a6eb9baf563994c49046c0c3cbd79f429f51..18392d4c316a5761832ba66f3e372f3e16524316 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/view_function_valid.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/view_function_valid.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 #[frame_support::pallet]
-mod pallet {
+pub mod pallet {
 	use frame_support::pallet_prelude::*;
 
 	#[pallet::config(with_default)]
diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/where_clause_missing_hooks.rs b/substrate/frame/support/test/tests/pallet_ui/pass/where_clause_missing_hooks.rs
index 560ebbb8687081bec65b52473a6508fa210dfb58..688fcef3c93fa7dea4abd6383f2624752f2d95b7 100644
--- a/substrate/frame/support/test/tests/pallet_ui/pass/where_clause_missing_hooks.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/pass/where_clause_missing_hooks.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 #[frame_support::pallet]
-mod pallet {
+pub mod pallet {
 	#[pallet::config]
 	pub trait Config: frame_system::Config
 	where
@@ -34,7 +34,7 @@ mod pallet {
 	where
 		<T as frame_system::Config>::Nonce: From<u128>,
 	{
-		fn foo(x: u128) {
+		pub fn foo(x: u128) {
 			let _index = <T as frame_system::Config>::Nonce::from(x);
 		}
 	}
diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr
index 641cdef1cc0871e5b46439f977048dac8754eff5..fee09c8011ba2feabc5c90dd4c420756044e43f8 100644
--- a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr
@@ -9,7 +9,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
 ...  |
 38 | |     #[pallet::storage]
 39 | |     type Foo<T> = StorageValue<Value = Bar>;
-   | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: PartialStorageInfoTrait`
+   | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar`
    |
    = help: the following other types implement trait `WrapperTypeDecode`:
              Arc<T>
@@ -31,7 +31,7 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
 ...  |
 38 | |     #[pallet::storage]
 39 | |     type Foo<T> = StorageValue<Value = Bar>;
-   | |____________^ the trait `EncodeLike` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: PartialStorageInfoTrait`
+   | |____________^ the trait `EncodeLike` is not implemented for `Bar`
    |
    = help: the following other types implement trait `EncodeLike<T>`:
              `&&T` implements `EncodeLike<T>`
@@ -58,7 +58,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied
 ...  |
 38 | |     #[pallet::storage]
 39 | |     type Foo<T> = StorageValue<Value = Bar>;
-   | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: PartialStorageInfoTrait`
+   | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar`
    |
    = help: the following other types implement trait `WrapperTypeEncode`:
              &T
@@ -81,7 +81,7 @@ error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<Value = Bar>;
-   | |____________^ the trait `TypeInfo` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: StorageEntryMetadataBuilder`
+   | |____________^ the trait `TypeInfo` is not implemented for `Bar`
    |
    = help: the following other types implement trait `TypeInfo`:
              &T
@@ -102,7 +102,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<Value = Bar>;
-   | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: StorageEntryMetadataBuilder`
+   | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar`
    |
    = help: the following other types implement trait `WrapperTypeDecode`:
              Arc<T>
@@ -119,7 +119,7 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<Value = Bar>;
-   | |____________^ the trait `EncodeLike` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: StorageEntryMetadataBuilder`
+   | |____________^ the trait `EncodeLike` is not implemented for `Bar`
    |
    = help: the following other types implement trait `EncodeLike<T>`:
              `&&T` implements `EncodeLike<T>`
@@ -141,7 +141,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<Value = Bar>;
-   | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: StorageEntryMetadataBuilder`
+   | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar`
    |
    = help: the following other types implement trait `WrapperTypeEncode`:
              &T
@@ -164,7 +164,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<Value = Bar>;
-   | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: TryDecodeEntireStorage`
+   | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar`
    |
    = help: the following other types implement trait `WrapperTypeDecode`:
              Arc<T>
@@ -181,7 +181,7 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<Value = Bar>;
-   | |____________^ the trait `EncodeLike` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: TryDecodeEntireStorage`
+   | |____________^ the trait `EncodeLike` is not implemented for `Bar`
    |
    = help: the following other types implement trait `EncodeLike<T>`:
              `&&T` implements `EncodeLike<T>`
@@ -203,7 +203,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<Value = Bar>;
-   | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: TryDecodeEntireStorage`
+   | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar`
    |
    = help: the following other types implement trait `WrapperTypeEncode`:
              &T
diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr
index a79a3509e69c8113390245bb91293ce61828dda1..be362137e8e17a4ee64447216dccdaff9b916789 100644
--- a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr
@@ -9,7 +9,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
 ...  |
 38 | |     #[pallet::storage]
 39 | |     type Foo<T> = StorageValue<_, Bar>;
-   | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: PartialStorageInfoTrait`
+   | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar`
    |
    = help: the following other types implement trait `WrapperTypeDecode`:
              Arc<T>
@@ -31,7 +31,7 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
 ...  |
 38 | |     #[pallet::storage]
 39 | |     type Foo<T> = StorageValue<_, Bar>;
-   | |____________^ the trait `EncodeLike` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: PartialStorageInfoTrait`
+   | |____________^ the trait `EncodeLike` is not implemented for `Bar`
    |
    = help: the following other types implement trait `EncodeLike<T>`:
              `&&T` implements `EncodeLike<T>`
@@ -58,7 +58,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied
 ...  |
 38 | |     #[pallet::storage]
 39 | |     type Foo<T> = StorageValue<_, Bar>;
-   | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: PartialStorageInfoTrait`
+   | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar`
    |
    = help: the following other types implement trait `WrapperTypeEncode`:
              &T
@@ -81,7 +81,7 @@ error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<_, Bar>;
-   | |____________^ the trait `TypeInfo` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: StorageEntryMetadataBuilder`
+   | |____________^ the trait `TypeInfo` is not implemented for `Bar`
    |
    = help: the following other types implement trait `TypeInfo`:
              &T
@@ -102,7 +102,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<_, Bar>;
-   | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: StorageEntryMetadataBuilder`
+   | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar`
    |
    = help: the following other types implement trait `WrapperTypeDecode`:
              Arc<T>
@@ -119,7 +119,7 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<_, Bar>;
-   | |____________^ the trait `EncodeLike` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: StorageEntryMetadataBuilder`
+   | |____________^ the trait `EncodeLike` is not implemented for `Bar`
    |
    = help: the following other types implement trait `EncodeLike<T>`:
              `&&T` implements `EncodeLike<T>`
@@ -141,7 +141,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<_, Bar>;
-   | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: StorageEntryMetadataBuilder`
+   | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar`
    |
    = help: the following other types implement trait `WrapperTypeEncode`:
              &T
@@ -164,7 +164,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<_, Bar>;
-   | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: TryDecodeEntireStorage`
+   | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar`
    |
    = help: the following other types implement trait `WrapperTypeDecode`:
              Arc<T>
@@ -181,7 +181,7 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<_, Bar>;
-   | |____________^ the trait `EncodeLike` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: TryDecodeEntireStorage`
+   | |____________^ the trait `EncodeLike` is not implemented for `Bar`
    |
    = help: the following other types implement trait `EncodeLike<T>`:
              `&&T` implements `EncodeLike<T>`
@@ -203,7 +203,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied
 38 |       #[pallet::storage]
    |  _______________^
 39 | |     type Foo<T> = StorageValue<_, Bar>;
-   | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: TryDecodeEntireStorage`
+   | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar`
    |
    = help: the following other types implement trait `WrapperTypeEncode`:
              &T
diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr
index 95ec76e29c0be79585d5902b87694804be88c148..637f9fc1268568ffe054feae18d5d181eda7768d 100644
--- a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr
@@ -9,7 +9,7 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied
 ...  |
 38 | |     #[pallet::storage]
 39 | |     type Foo<T> = StorageValue<_, Bar>;
-   | |____________^ the trait `MaxEncodedLen` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>: StorageInfoTrait`
+   | |____________^ the trait `MaxEncodedLen` is not implemented for `Bar`
    |
    = help: the following other types implement trait `MaxEncodedLen`:
              ()
diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr
index 8351dd92d5944c14ebd1ccd1b6d17c3eaf017f4d..a601c9f33f665353b2e75e5b3e0a18ab82222729 100644
--- a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr
@@ -9,7 +9,7 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied
 ...  |
 41 | |     #[pallet::storage]
 42 | |     type Foo<T> = StorageNMap<_, Key<Twox64Concat, Bar>, u32>;
-   | |____________^ the trait `MaxEncodedLen` is not implemented for `Bar`, which is required by `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo<T>, NMapKey<frame_support::Twox64Concat, Bar>, u32>: StorageInfoTrait`
+   | |____________^ the trait `MaxEncodedLen` is not implemented for `Bar`
    |
    = help: the following other types implement trait `MaxEncodedLen`:
              ()
@@ -22,4 +22,5 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied
              (TupleElement0, TupleElement1, TupleElement2, TupleElement3, TupleElement4, TupleElement5, TupleElement6, TupleElement7)
            and $N others
    = note: required for `NMapKey<frame_support::Twox64Concat, Bar>` to implement `KeyGeneratorMaxEncodedLen`
-   = note: required for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo<T>, NMapKey<frame_support::Twox64Concat, Bar>, u32>` to implement `StorageInfoTrait`
+   = note: required for `StorageNMap<_GeneratedPrefixForStorageFoo<T>, Key<..., ...>, ...>` to implement `StorageInfoTrait`
+   = note: consider using `--verbose` to print the full type name to the console
diff --git a/substrate/frame/support/test/tests/runtime.rs b/substrate/frame/support/test/tests/runtime.rs
index cbcdf8d27b39a6e3f48f7cbef5e02c350d56a943..a7a2f6ca37860d7ae4cb4286d04c0755c34ff8a0 100644
--- a/substrate/frame/support/test/tests/runtime.rs
+++ b/substrate/frame/support/test/tests/runtime.rs
@@ -64,7 +64,17 @@ mod module1 {
 	}
 
 	#[pallet::origin]
-	#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
+	#[derive(
+		Clone,
+		PartialEq,
+		Eq,
+		RuntimeDebug,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		MaxEncodedLen,
+		TypeInfo,
+	)]
 	#[scale_info(skip_type_params(I))]
 	pub struct Origin<T, I = ()>(pub PhantomData<(T, I)>);
 
@@ -108,7 +118,17 @@ mod module2 {
 	}
 
 	#[pallet::origin]
-	#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
+	#[derive(
+		Clone,
+		PartialEq,
+		Eq,
+		RuntimeDebug,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		MaxEncodedLen,
+		TypeInfo,
+	)]
 	pub struct Origin;
 
 	#[pallet::event]
@@ -155,7 +175,17 @@ mod nested {
 		}
 
 		#[pallet::origin]
-		#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
+		#[derive(
+			Clone,
+			PartialEq,
+			Eq,
+			RuntimeDebug,
+			Encode,
+			Decode,
+			DecodeWithMemTracking,
+			MaxEncodedLen,
+			TypeInfo,
+		)]
 		pub struct Origin;
 
 		#[pallet::event]
@@ -237,7 +267,17 @@ pub mod module3 {
 	}
 
 	#[pallet::origin]
-	#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
+	#[derive(
+		Clone,
+		PartialEq,
+		Eq,
+		RuntimeDebug,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		MaxEncodedLen,
+		TypeInfo,
+	)]
 	pub struct Origin<T>(pub PhantomData<T>);
 
 	#[pallet::event]
diff --git a/substrate/frame/support/test/tests/runtime_legacy_ordering.rs b/substrate/frame/support/test/tests/runtime_legacy_ordering.rs
index 1594356ad8fe846b329818634c2a235fd2cae77e..cbe5276d0b726239e82e0ad634918e898b8145df 100644
--- a/substrate/frame/support/test/tests/runtime_legacy_ordering.rs
+++ b/substrate/frame/support/test/tests/runtime_legacy_ordering.rs
@@ -64,7 +64,17 @@ mod module1 {
 	}
 
 	#[pallet::origin]
-	#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
+	#[derive(
+		Clone,
+		PartialEq,
+		Eq,
+		RuntimeDebug,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		MaxEncodedLen,
+		TypeInfo,
+	)]
 	#[scale_info(skip_type_params(I))]
 	pub struct Origin<T, I = ()>(pub PhantomData<(T, I)>);
 
@@ -108,7 +118,17 @@ mod module2 {
 	}
 
 	#[pallet::origin]
-	#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
+	#[derive(
+		Clone,
+		PartialEq,
+		Eq,
+		RuntimeDebug,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		MaxEncodedLen,
+		TypeInfo,
+	)]
 	pub struct Origin;
 
 	#[pallet::event]
@@ -155,7 +175,17 @@ mod nested {
 		}
 
 		#[pallet::origin]
-		#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
+		#[derive(
+			Clone,
+			PartialEq,
+			Eq,
+			RuntimeDebug,
+			Encode,
+			Decode,
+			DecodeWithMemTracking,
+			MaxEncodedLen,
+			TypeInfo,
+		)]
 		pub struct Origin;
 
 		#[pallet::event]
@@ -237,7 +267,17 @@ pub mod module3 {
 	}
 
 	#[pallet::origin]
-	#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)]
+	#[derive(
+		Clone,
+		PartialEq,
+		Eq,
+		RuntimeDebug,
+		Encode,
+		Decode,
+		DecodeWithMemTracking,
+		MaxEncodedLen,
+		TypeInfo,
+	)]
 	pub struct Origin<T>(pub PhantomData<T>);
 
 	#[pallet::event]
diff --git a/substrate/frame/support/test/tests/runtime_ui.rs b/substrate/frame/support/test/tests/runtime_ui.rs
index dbe150f38ed6a3b6a45ac58e288b65c397c671f9..83847f71cfe90086392a3af17ff31ab09fbcc524 100644
--- a/substrate/frame/support/test/tests/runtime_ui.rs
+++ b/substrate/frame/support/test/tests/runtime_ui.rs
@@ -28,7 +28,7 @@ fn ui() {
 	std::env::set_var("SKIP_WASM_BUILD", "1");
 
 	// Deny all warnings since we emit warnings as part of a Runtime's UI.
-	std::env::set_var("RUSTFLAGS", "--deny warnings");
+	std::env::set_var("CARGO_ENCODED_RUSTFLAGS", "--deny=warnings");
 
 	let t = trybuild::TestCases::new();
 	t.compile_fail("tests/runtime_ui/*.rs");
diff --git a/substrate/frame/support/test/tests/split_ui.rs b/substrate/frame/support/test/tests/split_ui.rs
index 14f99b8ecdab1f88778d379e657c3bf7f1f66a70..50a3f812145fe826115a54ad1a0d85d737119aae 100644
--- a/substrate/frame/support/test/tests/split_ui.rs
+++ b/substrate/frame/support/test/tests/split_ui.rs
@@ -28,7 +28,7 @@ fn split_ui() {
 	std::env::set_var("SKIP_WASM_BUILD", "1");
 
 	// Deny all warnings since we emit warnings as part of a Pallet's UI.
-	std::env::set_var("RUSTFLAGS", "--deny warnings");
+	std::env::set_var("CARGO_ENCODED_RUSTFLAGS", "--deny=warnings");
 
 	let t = trybuild::TestCases::new();
 	t.compile_fail("tests/split_ui/*.rs");
diff --git a/substrate/frame/support/test/tests/storage_alias_ui.rs b/substrate/frame/support/test/tests/storage_alias_ui.rs
index b82acd8f3be43aca96aec941b263fbf715212d54..ab25808e9718a36872954e338f313bb29e77c951 100644
--- a/substrate/frame/support/test/tests/storage_alias_ui.rs
+++ b/substrate/frame/support/test/tests/storage_alias_ui.rs
@@ -27,6 +27,9 @@ fn storage_alias_ui() {
 	// As trybuild is using `cargo check`, we don't need the real WASM binaries.
 	std::env::set_var("SKIP_WASM_BUILD", "1");
 
+	// Deny all warnings since we emit warnings as part of a Runtime's UI.
+	std::env::set_var("CARGO_ENCODED_RUSTFLAGS", "--deny=warnings");
+
 	let t = trybuild::TestCases::new();
 	t.compile_fail("tests/storage_alias_ui/*.rs");
 }
diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs
index 8980c6d6c8f427eedd924a8d2cfb555635b18cf7..9a21c65902983d446e20a42049da8c3cc8632954 100644
--- a/substrate/frame/system/src/lib.rs
+++ b/substrate/frame/system/src/lib.rs
@@ -122,7 +122,7 @@ use sp_runtime::{
 };
 use sp_version::RuntimeVersion;
 
-use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, EncodeLike, FullCodec, MaxEncodedLen};
 #[cfg(feature = "std")]
 use frame_support::traits::BuildGenesisConfig;
 use frame_support::{
@@ -267,7 +267,18 @@ where
 /// Information about the dispatch of a call, to be displayed in the
 /// [`ExtrinsicSuccess`](Event::ExtrinsicSuccess) and [`ExtrinsicFailed`](Event::ExtrinsicFailed)
 /// events.
-#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)]
+#[derive(
+	Clone,
+	Copy,
+	Eq,
+	PartialEq,
+	Default,
+	RuntimeDebug,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+)]
 pub struct DispatchEventInfo {
 	/// Weight of this transaction.
 	pub weight: Weight,
diff --git a/substrate/frame/transaction-storage/src/lib.rs b/substrate/frame/transaction-storage/src/lib.rs
index 68f24526300d8539bb1865520dbc6d7b06dc2cf0..1fa5109ad6178e150a60569723c78059c557359c 100644
--- a/substrate/frame/transaction-storage/src/lib.rs
+++ b/substrate/frame/transaction-storage/src/lib.rs
@@ -85,7 +85,7 @@ pub struct TransactionInfo {
 }
 
 fn num_chunks(bytes: u32) -> u32 {
-	((bytes as u64 + CHUNK_SIZE as u64 - 1) / CHUNK_SIZE as u64) as u32
+	(bytes as u64).div_ceil(CHUNK_SIZE as u64) as u32
 }
 
 #[frame_support::pallet]
diff --git a/substrate/frame/tx-pause/src/mock.rs b/substrate/frame/tx-pause/src/mock.rs
index d543f447ca7a541c579ad8c4e01e2c07eac5099a..a34095a2ffdd2463f1a40c030645ee33a17806e2 100644
--- a/substrate/frame/tx-pause/src/mock.rs
+++ b/substrate/frame/tx-pause/src/mock.rs
@@ -58,6 +58,7 @@ impl pallet_utility::Config for Test {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	MaxEncodedLen,
 	scale_info::TypeInfo,
diff --git a/substrate/frame/uniques/src/lib.rs b/substrate/frame/uniques/src/lib.rs
index 01548418a04993b5667210f4d76566e1a4e3aee2..d2fa0adb11704bdd423155951fabb1de38851d04 100644
--- a/substrate/frame/uniques/src/lib.rs
+++ b/substrate/frame/uniques/src/lib.rs
@@ -45,7 +45,7 @@ pub mod weights;
 extern crate alloc;
 
 use alloc::vec::Vec;
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use frame_support::traits::{
 	tokens::Locker, BalanceStatus::Reserved, Currency, EnsureOriginWithArg, ReservableCurrency,
 };
diff --git a/substrate/frame/uniques/src/types.rs b/substrate/frame/uniques/src/types.rs
index 6451e3800da8d8866a01c970aa4f7ec1d733f745..b17703223ca6ff9e1bf1431f58cefb59b38dcb80 100644
--- a/substrate/frame/uniques/src/types.rs
+++ b/substrate/frame/uniques/src/types.rs
@@ -62,7 +62,18 @@ pub struct CollectionDetails<AccountId, DepositBalance> {
 }
 
 /// Witness data for the destroy transactions.
-#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Copy,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub struct DestroyWitness {
 	/// The total number of outstanding items of this collection.
 	#[codec(compact)]
diff --git a/substrate/frame/utility/src/benchmarking.rs b/substrate/frame/utility/src/benchmarking.rs
index 261d52436889a1033dd4f576c25c070a8944112c..a329815836ba696957c0f0bf9c8b5ab972c3d9f0 100644
--- a/substrate/frame/utility/src/benchmarking.rs
+++ b/substrate/frame/utility/src/benchmarking.rs
@@ -92,6 +92,18 @@ mod benchmark {
 		assert_last_event::<T>(Event::BatchCompleted.into());
 	}
 
+	#[benchmark]
+	fn dispatch_as_fallible() {
+		let caller = account("caller", SEED, SEED);
+		let call = Box::new(frame_system::Call::remark { remark: vec![] }.into());
+		let origin: T::RuntimeOrigin = RawOrigin::Signed(caller).into();
+		let pallets_origin = origin.caller().clone();
+		let pallets_origin = T::PalletsOrigin::from(pallets_origin);
+
+		#[extrinsic_call]
+		_(RawOrigin::Root, Box::new(pallets_origin), call);
+	}
+
 	#[benchmark]
 	fn if_else() {
 		// Failing main call.
diff --git a/substrate/frame/utility/src/lib.rs b/substrate/frame/utility/src/lib.rs
index 63a02febb94c51b6c7f2fe1eff07ae0f6f1f767f..518e75453501cd29d587eb0a3edda4c19a9a5d0e 100644
--- a/substrate/frame/utility/src/lib.rs
+++ b/substrate/frame/utility/src/lib.rs
@@ -141,9 +141,9 @@ pub mod pallet {
 		/// The limit on the number of batched calls.
 		fn batched_calls_limit() -> u32 {
 			let allocator_limit = sp_core::MAX_POSSIBLE_ALLOCATION;
-			let call_size = ((core::mem::size_of::<<T as Config>::RuntimeCall>() as u32 +
-				CALL_ALIGN - 1) /
-				CALL_ALIGN) * CALL_ALIGN;
+			let call_size = (core::mem::size_of::<<T as Config>::RuntimeCall>() as u32)
+				.div_ceil(CALL_ALIGN) *
+				CALL_ALIGN;
 			// The margin to take into account vec doubling capacity.
 			let margin_factor = 3;
 
@@ -554,6 +554,34 @@ pub mod pallet {
 				post_info: Some(weight).into(),
 			})
 		}
+
+		/// Dispatches a function call with a provided origin.
+		///
+		/// Almost the same as [`Pallet::dispatch_as`] but forwards any error of the inner call.
+		///
+		/// The dispatch origin for this call must be _Root_.
+		#[pallet::call_index(7)]
+		#[pallet::weight({
+			let dispatch_info = call.get_dispatch_info();
+			(
+				T::WeightInfo::dispatch_as_fallible()
+					.saturating_add(dispatch_info.call_weight),
+				dispatch_info.class,
+			)
+		})]
+		pub fn dispatch_as_fallible(
+			origin: OriginFor<T>,
+			as_origin: Box<T::PalletsOrigin>,
+			call: Box<<T as Config>::RuntimeCall>,
+		) -> DispatchResult {
+			ensure_root(origin)?;
+
+			call.dispatch_bypass_filter((*as_origin).into()).map_err(|e| e.error)?;
+
+			Self::deposit_event(Event::DispatchedAs { result: Ok(()) });
+
+			Ok(())
+		}
 	}
 
 	impl<T: Config> Pallet<T> {
diff --git a/substrate/frame/utility/src/tests.rs b/substrate/frame/utility/src/tests.rs
index 759621907dfeda5028298cc2dadee190212dcda5..56e7e3c21ea24853313ab38e3c3a2ff1a3f578bc 100644
--- a/substrate/frame/utility/src/tests.rs
+++ b/substrate/frame/utility/src/tests.rs
@@ -262,6 +262,14 @@ fn call_foobar(err: bool, start_weight: Weight, end_weight: Option<Weight>) -> R
 	RuntimeCall::Example(ExampleCall::foobar { err, start_weight, end_weight })
 }
 
+fn utility_events() -> Vec<Event> {
+	System::events()
+		.into_iter()
+		.map(|r| r.event)
+		.filter_map(|e| if let RuntimeEvent::Utility(inner) = e { Some(inner) } else { None })
+		.collect()
+}
+
 #[test]
 fn as_derivative_works() {
 	new_test_ext().execute_with(|| {
@@ -916,6 +924,33 @@ fn with_weight_works() {
 	})
 }
 
+#[test]
+fn dispatch_as_works() {
+	new_test_ext().execute_with(|| {
+		Balances::force_set_balance(RuntimeOrigin::root(), 666, 100).unwrap();
+		assert_eq!(Balances::free_balance(666), 100);
+		assert_eq!(Balances::free_balance(777), 0);
+		assert_ok!(Utility::dispatch_as(
+			RuntimeOrigin::root(),
+			Box::new(OriginCaller::system(frame_system::RawOrigin::Signed(666))),
+			Box::new(call_transfer(777, 100))
+		));
+		assert_eq!(Balances::free_balance(666), 0);
+		assert_eq!(Balances::free_balance(777), 100);
+
+		System::reset_events();
+		assert_ok!(Utility::dispatch_as(
+			RuntimeOrigin::root(),
+			Box::new(OriginCaller::system(frame_system::RawOrigin::Signed(777))),
+			Box::new(RuntimeCall::Timestamp(TimestampCall::set { now: 0 }))
+		));
+		assert_eq!(
+			utility_events(),
+			vec![Event::DispatchedAs { result: Err(DispatchError::BadOrigin) }]
+		);
+	})
+}
+
 #[test]
 fn if_else_with_root_works() {
 	new_test_ext().execute_with(|| {
@@ -983,6 +1018,31 @@ fn if_else_successful_main_call() {
 	})
 }
 
+#[test]
+fn dispatch_as_fallible_works() {
+	new_test_ext().execute_with(|| {
+		Balances::force_set_balance(RuntimeOrigin::root(), 666, 100).unwrap();
+		assert_eq!(Balances::free_balance(666), 100);
+		assert_eq!(Balances::free_balance(777), 0);
+		assert_ok!(Utility::dispatch_as_fallible(
+			RuntimeOrigin::root(),
+			Box::new(OriginCaller::system(frame_system::RawOrigin::Signed(666))),
+			Box::new(call_transfer(777, 100))
+		));
+		assert_eq!(Balances::free_balance(666), 0);
+		assert_eq!(Balances::free_balance(777), 100);
+
+		assert_noop!(
+			Utility::dispatch_as_fallible(
+				RuntimeOrigin::root(),
+				Box::new(OriginCaller::system(frame_system::RawOrigin::Signed(777))),
+				Box::new(RuntimeCall::Timestamp(TimestampCall::set { now: 0 }))
+			),
+			DispatchError::BadOrigin,
+		);
+	})
+}
+
 #[test]
 fn if_else_failing_fallback_call() {
 	new_test_ext().execute_with(|| {
diff --git a/substrate/frame/utility/src/weights.rs b/substrate/frame/utility/src/weights.rs
index 30922bbb22d5b30cd2f48c2eec667b51c2f8ce15..ce57af72f91424ffe6c1d2ca74700c45b3617664 100644
--- a/substrate/frame/utility/src/weights.rs
+++ b/substrate/frame/utility/src/weights.rs
@@ -56,6 +56,7 @@ pub trait WeightInfo {
 	fn batch_all(c: u32, ) -> Weight;
 	fn dispatch_as() -> Weight;
 	fn force_batch(c: u32, ) -> Weight;
+	fn dispatch_as_fallible() -> Weight;
 	fn if_else() -> Weight;
 }
 
@@ -126,6 +127,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 			.saturating_add(Weight::from_parts(4_570_923, 0).saturating_mul(c.into()))
 			.saturating_add(T::DbWeight::get().reads(2_u64))
 	}
+	fn dispatch_as_fallible() -> Weight {
+		Weight::MAX
+	}
+
 	fn if_else() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
@@ -202,6 +207,11 @@ impl WeightInfo for () {
 			.saturating_add(Weight::from_parts(4_570_923, 0).saturating_mul(c.into()))
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 	}
+
+	fn dispatch_as_fallible() -> Weight {
+		Weight::MAX
+	}
+
 	fn if_else() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `0`
diff --git a/substrate/frame/vesting/src/lib.rs b/substrate/frame/vesting/src/lib.rs
index 9e3e30106f34126f0a61df7854f5358732ff49cf..357f454519dd9b4ac28407445c48429f7d344c5c 100644
--- a/substrate/frame/vesting/src/lib.rs
+++ b/substrate/frame/vesting/src/lib.rs
@@ -59,7 +59,7 @@ pub mod weights;
 extern crate alloc;
 
 use alloc::vec::Vec;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::{fmt::Debug, marker::PhantomData};
 use frame_support::{
 	dispatch::DispatchResult,
diff --git a/substrate/frame/vesting/src/vesting_info.rs b/substrate/frame/vesting/src/vesting_info.rs
index 5d5ae31fc324743eeb71ed0d898d91885d3cf73c..fd26ff3e6b77ea87fd40c40ddf489e6978af81b8 100644
--- a/substrate/frame/vesting/src/vesting_info.rs
+++ b/substrate/frame/vesting/src/vesting_info.rs
@@ -20,7 +20,18 @@
 use super::*;
 
 /// Struct to encode the vesting schedule of an individual account.
-#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Copy,
+	Clone,
+	PartialEq,
+	Eq,
+	RuntimeDebug,
+	MaxEncodedLen,
+	TypeInfo,
+)]
 pub struct VestingInfo<Balance, BlockNumber> {
 	/// Locked amount at genesis.
 	locked: Balance,
diff --git a/substrate/primitives/api/test/tests/trybuild.rs b/substrate/primitives/api/test/tests/trybuild.rs
index b13e5df9d6f858db1d92b360efb27fbd6db8e56f..da6a339578e164d972c2d0c6cac63465db0e3dea 100644
--- a/substrate/primitives/api/test/tests/trybuild.rs
+++ b/substrate/primitives/api/test/tests/trybuild.rs
@@ -28,7 +28,7 @@ fn ui() {
 	std::env::set_var("SKIP_WASM_BUILD", "1");
 
 	// Warnings are part of our UI.
-	std::env::set_var("RUSTFLAGS", "--deny warnings");
+	std::env::set_var("CARGO_ENCODED_RUSTFLAGS", "--deny=warnings");
 
 	let t = trybuild::TestCases::new();
 	t.compile_fail("tests/ui/*.rs");
diff --git a/substrate/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr b/substrate/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr
index 26be311c02fa4297c153cded586a3180fa23a589..7383fd4f2b29aa121bdd408970f45347d42547b3 100644
--- a/substrate/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr
+++ b/substrate/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr
@@ -54,10 +54,6 @@ note: associated function defined here
    |
 27 |         fn test(data: u64);
    |            ^^^^
-help: consider removing the borrow
-   |
-33 |         fn test(data: &u64) {
-   |
 
 error: unused variable: `data`
   --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:33:11
diff --git a/substrate/primitives/application-crypto/src/lib.rs b/substrate/primitives/application-crypto/src/lib.rs
index a8eb6b786a31779a55690117818bb137cd9b192d..818062717cfceda4577fe385cf77497c261f81a8 100644
--- a/substrate/primitives/application-crypto/src/lib.rs
+++ b/substrate/primitives/application-crypto/src/lib.rs
@@ -251,6 +251,7 @@ macro_rules! app_crypto_public_full_crypto {
 				Clone, Eq, Hash, PartialEq, PartialOrd, Ord,
 				$crate::codec::Encode,
 				$crate::codec::Decode,
+				$crate::codec::DecodeWithMemTracking,
 				$crate::RuntimeDebug,
 				$crate::codec::MaxEncodedLen,
 				$crate::scale_info::TypeInfo,
@@ -287,6 +288,7 @@ macro_rules! app_crypto_public_not_full_crypto {
 				Clone, Eq, Hash, PartialEq, Ord, PartialOrd,
 				$crate::codec::Encode,
 				$crate::codec::Decode,
+				$crate::codec::DecodeWithMemTracking,
 				$crate::RuntimeDebug,
 				$crate::codec::MaxEncodedLen,
 				$crate::scale_info::TypeInfo,
@@ -432,6 +434,7 @@ macro_rules! app_crypto_signature_full_crypto {
 			#[derive(Clone, Eq, PartialEq,
 				$crate::codec::Encode,
 				$crate::codec::Decode,
+				$crate::codec::DecodeWithMemTracking,
 				$crate::RuntimeDebug,
 				$crate::scale_info::TypeInfo,
 			)]
@@ -466,6 +469,7 @@ macro_rules! app_crypto_signature_not_full_crypto {
 			#[derive(Clone, Eq, PartialEq,
 				$crate::codec::Encode,
 				$crate::codec::Decode,
+				$crate::codec::DecodeWithMemTracking,
 				$crate::RuntimeDebug,
 				$crate::scale_info::TypeInfo,
 			)]
diff --git a/substrate/primitives/arithmetic/src/fixed_point.rs b/substrate/primitives/arithmetic/src/fixed_point.rs
index c4e9259c5fc94e3494a4df2bacc36fcdb562e006..9b5ef81917ca2ee208038dbda00ca8e8f0b5e330 100644
--- a/substrate/primitives/arithmetic/src/fixed_point.rs
+++ b/substrate/primitives/arithmetic/src/fixed_point.rs
@@ -52,7 +52,7 @@ use crate::{
 	},
 	PerThing, Perbill, Rounding, SignedRounding,
 };
-use codec::{CompactAs, Decode, Encode};
+use codec::{CompactAs, Decode, DecodeWithMemTracking, Encode};
 use core::{
 	fmt::Debug,
 	ops::{self, Add, Div, Mul, Sub},
@@ -404,6 +404,7 @@ macro_rules! implement_fixed {
 		#[derive(
 			Encode,
 			Decode,
+			DecodeWithMemTracking,
 			CompactAs,
 			Default,
 			Copy,
diff --git a/substrate/primitives/arithmetic/src/lib.rs b/substrate/primitives/arithmetic/src/lib.rs
index 01c403a7c4af284a2e6eaec65a5e5e820be9163e..7ac51543ba333d2971d9a87995b049c216050856 100644
--- a/substrate/primitives/arithmetic/src/lib.rs
+++ b/substrate/primitives/arithmetic/src/lib.rs
@@ -55,14 +55,25 @@ use alloc::vec::Vec;
 use core::{cmp::Ordering, fmt::Debug};
 use traits::{BaseArithmetic, One, SaturatedConversion, Unsigned, Zero};
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Serialize};
 
 /// Arithmetic errors.
-#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Eq,
+	PartialEq,
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Debug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub enum ArithmeticError {
 	/// Underflow.
diff --git a/substrate/primitives/arithmetic/src/per_things.rs b/substrate/primitives/arithmetic/src/per_things.rs
index f73dbe30cec17ea56b2c349d057df92b76edf724..6d0394cd1da54ddc063330b2000d8ef561400b22 100644
--- a/substrate/primitives/arithmetic/src/per_things.rs
+++ b/substrate/primitives/arithmetic/src/per_things.rs
@@ -58,7 +58,7 @@ use crate::traits::{
 	BaseArithmetic, Bounded, CheckedAdd, CheckedMul, CheckedSub, One, SaturatedConversion,
 	Saturating, UniqueSaturatedInto, Unsigned, Zero,
 };
-use codec::{CompactAs, Encode};
+use codec::{CompactAs, DecodeWithMemTracking, Encode};
 use core::{
 	fmt, ops,
 	ops::{Add, Sub},
@@ -592,7 +592,7 @@ macro_rules! implement_per_thing {
 		///
 		#[doc = $title]
 		#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-		#[derive(Encode, Copy, Clone, PartialEq, Eq, codec::MaxEncodedLen, PartialOrd, Ord, scale_info::TypeInfo)]
+		#[derive(Encode, DecodeWithMemTracking, Copy, Clone, PartialEq, Eq, codec::MaxEncodedLen, PartialOrd, Ord, scale_info::TypeInfo)]
 		pub struct $name($type);
 
 		/// Implementation makes any compact encoding of `PerThing::Inner` valid,
diff --git a/substrate/primitives/blockchain/src/header_metadata.rs b/substrate/primitives/blockchain/src/header_metadata.rs
index b2910a32e99546f9cb74803f124ba963ed21700f..c6782a721ec1ad0a508398e68307c1f41619bb5a 100644
--- a/substrate/primitives/blockchain/src/header_metadata.rs
+++ b/substrate/primitives/blockchain/src/header_metadata.rs
@@ -153,6 +153,29 @@ pub struct HashAndNumber<Block: BlockT> {
 	pub hash: Block::Hash,
 }
 
+impl<Block: BlockT> Eq for HashAndNumber<Block> {}
+
+impl<Block: BlockT> PartialEq for HashAndNumber<Block> {
+	fn eq(&self, other: &Self) -> bool {
+		self.number.eq(&other.number) && self.hash.eq(&other.hash)
+	}
+}
+
+impl<Block: BlockT> Ord for HashAndNumber<Block> {
+	fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+		match self.number.cmp(&other.number) {
+			std::cmp::Ordering::Equal => self.hash.cmp(&other.hash),
+			result => result,
+		}
+	}
+}
+
+impl<Block: BlockT> PartialOrd for HashAndNumber<Block> {
+	fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+		Some(self.cmp(&other))
+	}
+}
+
 /// A tree-route from one block to another in the chain.
 ///
 /// All blocks prior to the pivot in the vector is the reverse-order unique ancestry
diff --git a/substrate/primitives/consensus/babe/src/digests.rs b/substrate/primitives/consensus/babe/src/digests.rs
index e7af8c5763a0f93223c749cea6b21313f46ba430..6516a3c0fd8eb3b67947f0ac0ac042d70cb5582c 100644
--- a/substrate/primitives/consensus/babe/src/digests.rs
+++ b/substrate/primitives/consensus/babe/src/digests.rs
@@ -27,7 +27,7 @@ use alloc::vec::Vec;
 use sp_core::sr25519::vrf::VrfSignature;
 use sp_runtime::{DigestItem, RuntimeDebug};
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 
 /// Raw BABE primary slot assignment pre-digest.
@@ -139,7 +139,15 @@ pub struct NextEpochDescriptor {
 /// Information about the next epoch config, if changed. This is broadcast in the first
 /// block of the epoch, and applies using the same rules as `NextEpochDescriptor`.
 #[derive(
-	Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug, MaxEncodedLen, scale_info::TypeInfo,
+	Decode,
+	DecodeWithMemTracking,
+	Encode,
+	PartialEq,
+	Eq,
+	Clone,
+	RuntimeDebug,
+	MaxEncodedLen,
+	scale_info::TypeInfo,
 )]
 pub enum NextConfigDescriptor {
 	/// Version 1.
diff --git a/substrate/primitives/consensus/babe/src/lib.rs b/substrate/primitives/consensus/babe/src/lib.rs
index 163fbafa8dd4c6c80a37fe2b6bf820c24c9a6065..b29785b1c4463c39e2a93f51773bf5b422e798fd 100644
--- a/substrate/primitives/consensus/babe/src/lib.rs
+++ b/substrate/primitives/consensus/babe/src/lib.rs
@@ -27,7 +27,7 @@ pub mod inherents;
 
 #[cfg(not(feature = "std"))]
 use alloc::vec::Vec;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Serialize};
@@ -219,7 +219,18 @@ impl BabeConfiguration {
 }
 
 /// Types of allowed slots.
-#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo)]
+#[derive(
+	Clone,
+	Copy,
+	PartialEq,
+	Eq,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	MaxEncodedLen,
+	TypeInfo,
+)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub enum AllowedSlots {
 	/// Only allow primary slots.
diff --git a/substrate/primitives/consensus/beefy/src/commitment.rs b/substrate/primitives/consensus/beefy/src/commitment.rs
index 5d4338aca10f9cee1cf13548d9904f326cb728bc..49547ed877ecc3c5579b28646008c0eea45d844f 100644
--- a/substrate/primitives/consensus/beefy/src/commitment.rs
+++ b/substrate/primitives/consensus/beefy/src/commitment.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 use alloc::{vec, vec::Vec};
-use codec::{Decode, Encode, Error, Input};
+use codec::{Decode, DecodeWithMemTracking, Encode, Error, Input};
 use core::cmp;
 use scale_info::TypeInfo;
 use sp_application_crypto::RuntimeAppPublic;
@@ -50,7 +50,7 @@ impl<TAuthorityId: Clone, TSignature: Clone> KnownSignature<&TAuthorityId, &TSig
 /// height [block_number](Commitment::block_number).
 /// GRANDPA validators collect signatures on commitments and a stream of such signed commitments
 /// (see [SignedCommitment]) forms the BEEFY protocol.
-#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode, TypeInfo)]
+#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
 pub struct Commitment<TBlockNumber> {
 	///  A collection of payloads to be signed, see [`Payload`] for details.
 	///
diff --git a/substrate/primitives/consensus/beefy/src/lib.rs b/substrate/primitives/consensus/beefy/src/lib.rs
index 0f57cdfc810420176c9354fd2bb29662f2a198cc..40bf158df87463dfd273c7e6f10c4f7b9a1b5de6 100644
--- a/substrate/primitives/consensus/beefy/src/lib.rs
+++ b/substrate/primitives/consensus/beefy/src/lib.rs
@@ -47,7 +47,7 @@ pub use commitment::{Commitment, KnownSignature, SignedCommitment, VersionedFina
 pub use payload::{known_payloads, BeefyPayloadId, Payload, PayloadProvider};
 
 use alloc::vec::Vec;
-use codec::{Codec, Decode, Encode};
+use codec::{Codec, Decode, DecodeWithMemTracking, Encode};
 use core::fmt::{Debug, Display};
 use scale_info::TypeInfo;
 use sp_application_crypto::{AppPublic, RuntimeAppPublic};
@@ -298,7 +298,7 @@ pub enum ConsensusLog<AuthorityId: Codec> {
 /// A vote message is a direct vote created by a BEEFY node on every voting round
 /// and is gossiped to its peers.
 // TODO: Remove `Signature` generic type, instead get it from `Id::Signature`.
-#[derive(Clone, Debug, Decode, Encode, PartialEq, TypeInfo)]
+#[derive(Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, TypeInfo)]
 pub struct VoteMessage<Number, Id, Signature> {
 	/// Commit to information extracted from a finalized block
 	pub commitment: Commitment<Number>,
@@ -313,7 +313,7 @@ pub struct VoteMessage<Number, Id, Signature> {
 /// One type of misbehavior in BEEFY happens when an authority votes in the same round/block
 /// for different payloads.
 /// Proving is achieved by collecting the signed commitments of conflicting votes.
-#[derive(Clone, Debug, Decode, Encode, PartialEq, TypeInfo)]
+#[derive(Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, TypeInfo)]
 pub struct DoubleVotingProof<Number, Id, Signature> {
 	/// The first vote in the equivocation.
 	pub first: VoteMessage<Number, Id, Signature>,
@@ -340,7 +340,7 @@ impl<Number, Id, Signature> DoubleVotingProof<Number, Id, Signature> {
 ///
 /// Proving is achieved by providing a proof that contains relevant info about the canonical chain
 /// at `commitment.block_number`. The `commitment` can be checked against this info.
-#[derive(Clone, Debug, Decode, Encode, PartialEq, TypeInfo)]
+#[derive(Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, TypeInfo)]
 pub struct ForkVotingProof<Header: HeaderT, Id: RuntimeAppPublic, AncestryProof> {
 	/// The equivocated vote.
 	pub vote: VoteMessage<Header::Number, Id, Id::Signature>,
@@ -364,7 +364,7 @@ impl<Header: HeaderT, Id: RuntimeAppPublic> ForkVotingProof<Header, Id, OpaqueVa
 }
 
 /// Proof showing that an authority voted for a future block.
-#[derive(Clone, Debug, Decode, Encode, PartialEq, TypeInfo)]
+#[derive(Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, TypeInfo)]
 pub struct FutureBlockVotingProof<Number, Id: RuntimeAppPublic> {
 	/// The equivocated vote.
 	pub vote: VoteMessage<Number, Id, Id::Signature>,
diff --git a/substrate/primitives/consensus/beefy/src/payload.rs b/substrate/primitives/consensus/beefy/src/payload.rs
index 2bc96548bdfff345292e8b9e12f735581a965828..82ca1ad21f024f362ecd783aa58b932fcff82329 100644
--- a/substrate/primitives/consensus/beefy/src/payload.rs
+++ b/substrate/primitives/consensus/beefy/src/payload.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 use alloc::{vec, vec::Vec};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use scale_info::TypeInfo;
 use sp_runtime::traits::Block;
 
@@ -39,7 +39,19 @@ pub mod known_payloads {
 /// Identifiers MUST be sorted by the [`BeefyPayloadId`] to allow efficient lookup of expected
 /// value. Duplicated identifiers are disallowed. It's okay for different implementations to only
 /// support a subset of possible values.
-#[derive(Decode, Encode, Debug, PartialEq, Eq, Clone, Ord, PartialOrd, Hash, TypeInfo)]
+#[derive(
+	Decode,
+	DecodeWithMemTracking,
+	Encode,
+	Debug,
+	PartialEq,
+	Eq,
+	Clone,
+	Ord,
+	PartialOrd,
+	Hash,
+	TypeInfo,
+)]
 pub struct Payload(Vec<(BeefyPayloadId, Vec<u8>)>);
 
 impl Payload {
diff --git a/substrate/primitives/consensus/grandpa/src/lib.rs b/substrate/primitives/consensus/grandpa/src/lib.rs
index d86ea0992c2e1c1beb134dddd057b45484d9891c..3aa4dc2b4cfb32a084a6b15c3ab385b21468a526 100644
--- a/substrate/primitives/consensus/grandpa/src/lib.rs
+++ b/substrate/primitives/consensus/grandpa/src/lib.rs
@@ -25,7 +25,7 @@ extern crate alloc;
 use serde::Serialize;
 
 use alloc::vec::Vec;
-use codec::{Codec, Decode, Encode};
+use codec::{Codec, Decode, DecodeWithMemTracking, Encode};
 use scale_info::TypeInfo;
 #[cfg(feature = "std")]
 use sp_keystore::KeystorePtr;
@@ -231,7 +231,7 @@ impl<N: Codec> ConsensusLog<N> {
 /// GRANDPA happens when a voter votes on the same round (either at prevote or
 /// precommit stage) for different blocks. Proving is achieved by collecting the
 /// signed messages of conflicting votes.
-#[derive(Clone, Debug, Decode, Encode, PartialEq, Eq, TypeInfo)]
+#[derive(Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, Eq, TypeInfo)]
 pub struct EquivocationProof<H, N> {
 	set_id: SetId,
 	equivocation: Equivocation<H, N>,
@@ -265,7 +265,7 @@ impl<H, N> EquivocationProof<H, N> {
 
 /// Wrapper object for GRANDPA equivocation proofs, useful for unifying prevote
 /// and precommit equivocations under a common type.
-#[derive(Clone, Debug, Decode, Encode, PartialEq, Eq, TypeInfo)]
+#[derive(Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, Eq, TypeInfo)]
 pub enum Equivocation<H, N> {
 	/// Proof of equivocation at prevote stage.
 	Prevote(
diff --git a/substrate/primitives/consensus/sassafras/src/lib.rs b/substrate/primitives/consensus/sassafras/src/lib.rs
index d7880c4de9e8fec6d5feb4345af90214f3ac76bc..09baf678f16de43c09d7dd8bf70b5f2fd53cd6ef 100644
--- a/substrate/primitives/consensus/sassafras/src/lib.rs
+++ b/substrate/primitives/consensus/sassafras/src/lib.rs
@@ -24,7 +24,7 @@
 extern crate alloc;
 
 use alloc::vec::Vec;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 use sp_core::crypto::KeyTypeId;
 use sp_runtime::{ConsensusEngineId, RuntimeDebug};
@@ -86,7 +86,17 @@ pub type Randomness = [u8; RANDOMNESS_LENGTH];
 ///
 /// Mostly tweaks to the ticketing system parameters.
 #[derive(
-	Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo, Default,
+	Copy,
+	Clone,
+	PartialEq,
+	Eq,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	MaxEncodedLen,
+	TypeInfo,
+	Default,
 )]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub struct EpochConfiguration {
diff --git a/substrate/primitives/consensus/sassafras/src/ticket.rs b/substrate/primitives/consensus/sassafras/src/ticket.rs
index fd025f1d53eaffc01c615233d8000da220d6ea7c..1083530117cfe094ef0e6ee4dfc48a323a891181 100644
--- a/substrate/primitives/consensus/sassafras/src/ticket.rs
+++ b/substrate/primitives/consensus/sassafras/src/ticket.rs
@@ -18,7 +18,7 @@
 //! Primitives related to tickets.
 
 use crate::vrf::RingVrfSignature;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 
 pub use sp_core::ed25519::{Public as EphemeralPublic, Signature as EphemeralSignature};
@@ -33,7 +33,9 @@ pub use sp_core::ed25519::{Public as EphemeralPublic, Signature as EphemeralSign
 pub type TicketId = u128;
 
 /// Ticket data persisted on-chain.
-#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo)]
+#[derive(
+	Debug, Clone, PartialEq, Eq, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, TypeInfo,
+)]
 pub struct TicketBody {
 	/// Attempt index.
 	pub attempt_idx: u32,
@@ -47,7 +49,9 @@ pub struct TicketBody {
 pub type TicketSignature = RingVrfSignature;
 
 /// Ticket envelope used on during submission.
-#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo)]
+#[derive(
+	Debug, Clone, PartialEq, Eq, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, TypeInfo,
+)]
 pub struct TicketEnvelope {
 	/// Ticket body.
 	pub body: TicketBody,
diff --git a/substrate/primitives/consensus/slots/src/lib.rs b/substrate/primitives/consensus/slots/src/lib.rs
index dfa46fcf2571f3681e7de48995bef035daba0ba2..21f6f2e95b1bd057707ec360b43f485e16dc4ec8 100644
--- a/substrate/primitives/consensus/slots/src/lib.rs
+++ b/substrate/primitives/consensus/slots/src/lib.rs
@@ -19,12 +19,25 @@
 
 #![cfg_attr(not(feature = "std"), no_std)]
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 use sp_timestamp::Timestamp;
 
 /// Unit type wrapper that represents a slot.
-#[derive(Debug, Encode, MaxEncodedLen, Decode, Eq, Clone, Copy, Default, Ord, Hash, TypeInfo)]
+#[derive(
+	Debug,
+	Encode,
+	MaxEncodedLen,
+	Decode,
+	DecodeWithMemTracking,
+	Eq,
+	Clone,
+	Copy,
+	Default,
+	Ord,
+	Hash,
+	TypeInfo,
+)]
 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
 #[repr(transparent)]
 pub struct Slot(u64);
@@ -172,7 +185,7 @@ impl SlotDuration {
 /// produces more than one block on the same slot. The proof of equivocation
 /// are the given distinct headers that were signed by the validator and which
 /// include the slot number.
-#[derive(Clone, Debug, Decode, Encode, PartialEq, TypeInfo, Eq)]
+#[derive(Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, TypeInfo, Eq)]
 pub struct EquivocationProof<Header, Id> {
 	/// Returns the authority id of the equivocator.
 	pub offender: Id,
diff --git a/substrate/primitives/core/src/bandersnatch.rs b/substrate/primitives/core/src/bandersnatch.rs
index 25bf4657030fbcddcc75a419941a247759e0f9d5..0ede8119ce3d9ea65b9b4cceb919dc946fbf5567 100644
--- a/substrate/primitives/core/src/bandersnatch.rs
+++ b/substrate/primitives/core/src/bandersnatch.rs
@@ -28,7 +28,7 @@ use crate::crypto::{
 };
 
 use bandersnatch_vrfs::{CanonicalSerialize, SecretKey};
-use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, EncodeLike, MaxEncodedLen};
 use scale_info::TypeInfo;
 
 use alloc::{vec, vec::Vec};
@@ -227,6 +227,22 @@ pub mod vrf {
 		}
 	}
 
+	// `VrfPreOutput` resolves to:
+	// ```
+	// pub struct Affine<P: SWCurveConfig> {
+	//     #[doc(hidden)]
+	//     pub x: P::BaseField,
+	//     #[doc(hidden)]
+	//     pub y: P::BaseField,
+	//     #[doc(hidden)]
+	//     pub infinity: bool,
+	// }
+	// ```
+	// where each `P::BaseField` contains a `pub struct BigInt<const N: usize>(pub [u64; N]);`
+	// Since none of these structures is allocated on the heap, we don't need any special
+	// memory tracking logic. We can simply implement `DecodeWithMemTracking`.
+	impl DecodeWithMemTracking for VrfPreOutput {}
+
 	impl EncodeLike for VrfPreOutput {}
 
 	impl MaxEncodedLen for VrfPreOutput {
@@ -657,7 +673,9 @@ pub mod ring_vrf {
 	}
 
 	/// Ring VRF signature.
-	#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo)]
+	#[derive(
+		Clone, Debug, PartialEq, Eq, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, TypeInfo,
+	)]
 	pub struct RingVrfSignature {
 		/// Ring signature.
 		pub signature: [u8; RING_SIGNATURE_SERIALIZED_SIZE],
diff --git a/substrate/primitives/core/src/crypto.rs b/substrate/primitives/core/src/crypto.rs
index cf24861e233c1c855fd36d9a752699cdac5a42b1..4838b48c0cd28b410a34e5ed38fb6e61e9c2723e 100644
--- a/substrate/primitives/core/src/crypto.rs
+++ b/substrate/primitives/core/src/crypto.rs
@@ -22,7 +22,7 @@ use alloc::{format, str, vec::Vec};
 #[cfg(all(not(feature = "std"), feature = "serde"))]
 use alloc::{string::String, vec};
 use bip39::{Language, Mnemonic};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::hash::Hash;
 #[doc(hidden)]
 pub use core::ops::Deref;
@@ -501,7 +501,18 @@ pub trait Public: CryptoType + ByteArray + PartialEq + Eq + Clone + Send + Sync
 pub trait Signature: CryptoType + ByteArray + PartialEq + Eq + Clone + Send + Sync {}
 
 /// An opaque 32-byte cryptographic identifier.
-#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, MaxEncodedLen, TypeInfo)]
+#[derive(
+	Clone,
+	Eq,
+	PartialEq,
+	Ord,
+	PartialOrd,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	TypeInfo,
+)]
 #[cfg_attr(feature = "std", derive(Hash))]
 pub struct AccountId32([u8; 32]);
 
diff --git a/substrate/primitives/core/src/crypto_bytes.rs b/substrate/primitives/core/src/crypto_bytes.rs
index e5130e6d50079f3b9c8e8797f89e1c04e636679b..1964109cfac82eccaee1811ec35feac2eaad1c0e 100644
--- a/substrate/primitives/core/src/crypto_bytes.rs
+++ b/substrate/primitives/core/src/crypto_bytes.rs
@@ -22,7 +22,7 @@ use crate::{
 	hash::{H256, H512},
 };
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::marker::PhantomData;
 use scale_info::TypeInfo;
 
@@ -47,7 +47,7 @@ pub use signature_bytes::*;
 /// The tag `T` is held in a `PhantomData<fn() ->T>`, a trick allowing
 /// `CryptoBytes` to be `Send` and `Sync` regardless of `T` properties
 /// ([ref](https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns)).
-#[derive(Encode, Decode, MaxEncodedLen)]
+#[derive(Encode, Decode, DecodeWithMemTracking, MaxEncodedLen)]
 #[repr(transparent)]
 pub struct CryptoBytes<const N: usize, T = ()>(pub [u8; N], PhantomData<fn() -> T>);
 
diff --git a/substrate/primitives/core/src/lib.rs b/substrate/primitives/core/src/lib.rs
index 454f61df79419b76960ae6d1e3419fb0a919320a..b24eb400e64594ce27c639a8bce55da490f71063 100644
--- a/substrate/primitives/core/src/lib.rs
+++ b/substrate/primitives/core/src/lib.rs
@@ -35,7 +35,7 @@ extern crate alloc;
 
 use alloc::vec::Vec;
 #[doc(hidden)]
-pub use codec::{Decode, Encode, MaxEncodedLen};
+pub use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::ops::Deref;
 use scale_info::TypeInfo;
 #[cfg(feature = "serde")]
@@ -178,6 +178,7 @@ impl Deref for OpaqueMetadata {
 	PartialOrd,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	RuntimeDebug,
 	PassByInner,
 	TypeInfo,
@@ -324,7 +325,17 @@ pub fn to_substrate_wasm_fn_return_value(value: &impl Encode) -> u64 {
 
 /// The void type - it cannot exist.
 // Oh rust, you crack me up...
-#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Clone,
+	Decode,
+	DecodeWithMemTracking,
+	Encode,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 pub enum Void {}
 
 /// Macro for creating `Maybe*` marker traits.
@@ -470,16 +481,17 @@ macro_rules! generate_feature_enabled_macro {
 mod tests {
 	use super::*;
 
+	generate_feature_enabled_macro!(if_test, test, $);
+	generate_feature_enabled_macro!(if_not_test, not(test), $);
+
 	#[test]
 	#[should_panic]
 	fn generate_feature_enabled_macro_panics() {
-		generate_feature_enabled_macro!(if_test, test, $);
 		if_test!(panic!("This should panic"));
 	}
 
 	#[test]
 	fn generate_feature_enabled_macro_works() {
-		generate_feature_enabled_macro!(if_not_test, not(test), $);
 		if_not_test!(panic!("This should not panic"));
 	}
 }
diff --git a/substrate/primitives/merkle-mountain-range/src/lib.rs b/substrate/primitives/merkle-mountain-range/src/lib.rs
index 061e5dbb6c7d896ea2e18e1cb1b07beaff7c670d..53158476cf1074c1f01d4706341eef8ae0d396fb 100644
--- a/substrate/primitives/merkle-mountain-range/src/lib.rs
+++ b/substrate/primitives/merkle-mountain-range/src/lib.rs
@@ -26,6 +26,7 @@ pub use mmr_lib;
 
 #[cfg(not(feature = "std"))]
 use alloc::vec::Vec;
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use core::fmt;
 use scale_info::TypeInfo;
 use sp_debug_derive::RuntimeDebug;
@@ -362,7 +363,7 @@ pub struct LeafProof<Hash> {
 }
 
 /// An MMR ancestry proof for a prior mmr root.
-#[derive(codec::Encode, codec::Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)]
 pub struct AncestryProof<Hash> {
 	/// Peaks of the ancestor's mmr
 	pub prev_peaks: Vec<Hash>,
diff --git a/substrate/primitives/npos-elections/src/lib.rs b/substrate/primitives/npos-elections/src/lib.rs
index 12d4c5948ed9c1c56bf36c05823fcd7e1736d406..6fcdd38d4010789faac961e2568d72ee4cc45ec1 100644
--- a/substrate/primitives/npos-elections/src/lib.rs
+++ b/substrate/primitives/npos-elections/src/lib.rs
@@ -77,7 +77,7 @@
 extern crate alloc;
 
 use alloc::{collections::btree_map::BTreeMap, rc::Rc, vec, vec::Vec};
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::{cell::RefCell, cmp::Ordering};
 use scale_info::TypeInfo;
 #[cfg(feature = "serde")]
@@ -111,7 +111,14 @@ pub use traits::{IdentifierT, PerThing128};
 
 /// The errors that might occur in this crate and `frame-election-provider-solution-type`.
 #[derive(
-	Eq, PartialEq, RuntimeDebug, Clone, codec::Encode, codec::Decode, scale_info::TypeInfo,
+	Eq,
+	PartialEq,
+	RuntimeDebug,
+	Clone,
+	codec::Encode,
+	codec::Decode,
+	codec::DecodeWithMemTracking,
+	scale_info::TypeInfo,
 )]
 pub enum Error {
 	/// While going from solution indices to ratio, the weight of all the edges has gone above the
@@ -147,7 +154,19 @@ pub type ExtendedBalance = u128;
 /// 1. `minimal_stake`.
 /// 2. `sum_stake`.
 /// 3. `sum_stake_squared`.
-#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo, Debug, Default)]
+#[derive(
+	Clone,
+	Copy,
+	PartialEq,
+	Eq,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	TypeInfo,
+	Debug,
+	Default,
+)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub struct ElectionScore {
 	/// The minimal winner, in terms of total backing stake.
@@ -433,7 +452,7 @@ pub struct ElectionResult<AccountId, P: PerThing> {
 ///
 /// This, at the current version, resembles the `Exposure` defined in the Staking pallet, yet they
 /// do not necessarily have to be the same.
-#[derive(RuntimeDebug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
+#[derive(RuntimeDebug, Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, TypeInfo)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub struct Support<AccountId> {
 	/// Total support.
diff --git a/substrate/primitives/runtime-interface/test-wasm/src/lib.rs b/substrate/primitives/runtime-interface/test-wasm/src/lib.rs
index 545f1ff4a115e1b3a381e5b3c85d74f19f41fbd0..f0b9d6839d41219e8b5802b08208a63ca92f9249 100644
--- a/substrate/primitives/runtime-interface/test-wasm/src/lib.rs
+++ b/substrate/primitives/runtime-interface/test-wasm/src/lib.rs
@@ -83,7 +83,7 @@ pub trait TestApi {
 	/// Copy `hello` into the given mutable reference
 	fn return_value_into_mutable_reference(&self, data: &mut [u8]) {
 		let res = "hello";
-		data[..res.as_bytes().len()].copy_from_slice(res.as_bytes());
+		data[..res.len()].copy_from_slice(res.as_bytes());
 	}
 
 	/// Returns the input data wrapped in an `Option` as result.
diff --git a/substrate/primitives/runtime-interface/tests/ui/no_feature_gated_method.stderr b/substrate/primitives/runtime-interface/tests/ui/no_feature_gated_method.stderr
index 1c1649d011e686d9d30166cf0461add1bbb94006..35be091749e6bfa381b3145ec372b6dfce9ccf5a 100644
--- a/substrate/primitives/runtime-interface/tests/ui/no_feature_gated_method.stderr
+++ b/substrate/primitives/runtime-interface/tests/ui/no_feature_gated_method.stderr
@@ -26,7 +26,7 @@ note: the item is gated here
    | ^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the attribute macro `runtime_interface` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: unexpected `cfg` condition value: `bar-feature`
+warning: unexpected `cfg` condition value: `bar-feature`
   --> tests/ui/no_feature_gated_method.rs:24:8
    |
 24 |     #[cfg(feature = "bar-feature")]
@@ -35,10 +35,9 @@ error: unexpected `cfg` condition value: `bar-feature`
    = note: expected values for `feature` are: `default`, `disable_target_static_assertions`, and `std`
    = help: consider adding `bar-feature` as a feature in `Cargo.toml`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
-   = note: `-D unexpected-cfgs` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(unexpected_cfgs)]`
+   = note: `#[warn(unexpected_cfgs)]` on by default
 
-error: unexpected `cfg` condition value: `bar-feature`
+warning: unexpected `cfg` condition value: `bar-feature`
   --> tests/ui/no_feature_gated_method.rs:27:12
    |
 27 |     #[cfg(not(feature = "bar-feature"))]
diff --git a/substrate/primitives/runtime/src/generic/digest.rs b/substrate/primitives/runtime/src/generic/digest.rs
index 5ed0c7075cae653839961ab8b910fdcd8b88e0ae..593fbdd66c4775b5c28155912eb77f3a12431ca4 100644
--- a/substrate/primitives/runtime/src/generic/digest.rs
+++ b/substrate/primitives/runtime/src/generic/digest.rs
@@ -25,7 +25,7 @@ use codec::DecodeAll;
 use serde::{Deserialize, Serialize};
 
 use crate::{
-	codec::{Decode, Encode, Error, Input},
+	codec::{Decode, DecodeWithMemTracking, Encode, Error, Input},
 	scale_info::{
 		build::{Fields, Variants},
 		Path, Type, TypeInfo,
@@ -35,7 +35,9 @@ use crate::{
 use sp_core::RuntimeDebug;
 
 /// Generic header digest.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, Default)]
+#[derive(
+	PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, TypeInfo, Default,
+)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub struct Digest {
 	/// A list of logs in the digest.
@@ -71,7 +73,7 @@ impl Digest {
 
 /// Digest item that is able to encode/decode 'system' digest items and
 /// provide opaque access to other items.
-#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, DecodeWithMemTracking, RuntimeDebug)]
 pub enum DigestItem {
 	/// A pre-runtime digest.
 	///
diff --git a/substrate/primitives/runtime/src/generic/header.rs b/substrate/primitives/runtime/src/generic/header.rs
index d78aa5c8d3c29ea35eacecdbd0c40ebe0bfec926..cde8098404b4479b2c9c0ac401b89eb7e95e8cc7 100644
--- a/substrate/primitives/runtime/src/generic/header.rs
+++ b/substrate/primitives/runtime/src/generic/header.rs
@@ -18,7 +18,7 @@
 //! Generic implementation of a block header.
 
 use crate::{
-	codec::{Codec, Decode, Encode},
+	codec::{Codec, Decode, DecodeWithMemTracking, Encode},
 	generic::Digest,
 	scale_info::TypeInfo,
 	traits::{self, AtLeast32BitUnsigned, BlockNumber, Hash as HashT, MaybeDisplay, Member},
@@ -28,7 +28,9 @@ use serde::{Deserialize, Serialize};
 use sp_core::U256;
 
 /// Abstraction over a block header for a substrate chain.
-#[derive(Encode, Decode, PartialEq, Eq, Clone, sp_core::RuntimeDebug, TypeInfo)]
+#[derive(
+	Encode, Decode, DecodeWithMemTracking, PartialEq, Eq, Clone, sp_core::RuntimeDebug, TypeInfo,
+)]
 #[scale_info(skip_type_params(Hash))]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
diff --git a/substrate/primitives/runtime/src/lib.rs b/substrate/primitives/runtime/src/lib.rs
index f0c8e50f1ba1e66993b98badf980d1f385f8591c..f0813dd33779ee7f9b9c524bb55df83bb0f84da5 100644
--- a/substrate/primitives/runtime/src/lib.rs
+++ b/substrate/primitives/runtime/src/lib.rs
@@ -80,7 +80,7 @@ use sp_core::{
 };
 
 use alloc::vec;
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 
 pub mod curve;
@@ -272,7 +272,17 @@ pub type ConsensusEngineId = [u8; 4];
 
 /// Signature verify that can work with any known signature types.
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[derive(Eq, PartialEq, Clone, Encode, Decode, MaxEncodedLen, RuntimeDebug, TypeInfo)]
+#[derive(
+	Eq,
+	PartialEq,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	RuntimeDebug,
+	TypeInfo,
+)]
 pub enum MultiSignature {
 	/// An Ed25519 signature.
 	Ed25519(ed25519::Signature),
@@ -334,7 +344,18 @@ impl TryFrom<MultiSignature> for ecdsa::Signature {
 }
 
 /// Public key for any known crypto algorithm.
-#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
+#[derive(
+	Eq,
+	PartialEq,
+	Ord,
+	PartialOrd,
+	Clone,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	RuntimeDebug,
+	TypeInfo,
+)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub enum MultiSigner {
 	/// An Ed25519 identity.
@@ -511,7 +532,9 @@ pub type DispatchResult = core::result::Result<(), DispatchError>;
 pub type DispatchResultWithInfo<T> = core::result::Result<T, DispatchErrorWithPostInfo<T>>;
 
 /// Reason why a pallet call failed.
-#[derive(Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo, MaxEncodedLen,
+)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub struct ModuleError {
 	/// Module index, matching the metadata module index.
@@ -531,7 +554,18 @@ impl PartialEq for ModuleError {
 }
 
 /// Errors related to transactional storage layers.
-#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Eq,
+	PartialEq,
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Debug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub enum TransactionalError {
 	/// Too many transactional layers have been spawned.
@@ -556,7 +590,18 @@ impl From<TransactionalError> for DispatchError {
 }
 
 /// Reason why a dispatch call failed.
-#[derive(Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo, PartialEq, MaxEncodedLen)]
+#[derive(
+	Eq,
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Debug,
+	TypeInfo,
+	PartialEq,
+	MaxEncodedLen,
+)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub enum DispatchError {
 	/// Some error occurred.
@@ -598,7 +643,9 @@ pub enum DispatchError {
 
 /// Result of a `Dispatchable` which contains the `DispatchResult` and additional information about
 /// the `Dispatchable` that is only known post dispatch.
-#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)]
+#[derive(
+	Eq, PartialEq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, TypeInfo,
+)]
 pub struct DispatchErrorWithPostInfo<Info>
 where
 	Info: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable,
@@ -643,7 +690,18 @@ impl From<crate::traits::BadOrigin> for DispatchError {
 }
 
 /// Description of what went wrong when trying to complete an operation on a token.
-#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Eq,
+	PartialEq,
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Debug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub enum TokenError {
 	/// Funds are unavailable.
@@ -1190,16 +1248,17 @@ mod tests {
 mod sp_core_tests {
 	use super::*;
 
+	sp_core::generate_feature_enabled_macro!(if_test, test, $);
+	sp_core::generate_feature_enabled_macro!(if_not_test, not(test), $);
+
 	#[test]
 	#[should_panic]
 	fn generate_feature_enabled_macro_panics() {
-		sp_core::generate_feature_enabled_macro!(if_test, test, $);
 		if_test!(panic!("This should panic"));
 	}
 
 	#[test]
 	fn generate_feature_enabled_macro_works() {
-		sp_core::generate_feature_enabled_macro!(if_not_test, not(test), $);
 		if_not_test!(panic!("This should not panic"));
 	}
 }
diff --git a/substrate/primitives/runtime/src/multiaddress.rs b/substrate/primitives/runtime/src/multiaddress.rs
index 4382405a8ebc67bf8975cb35b99d18b7b213dd2b..5a309af704206e4ea34781073f4ac6c5022059c0 100644
--- a/substrate/primitives/runtime/src/multiaddress.rs
+++ b/substrate/primitives/runtime/src/multiaddress.rs
@@ -18,10 +18,19 @@
 //! MultiAddress type is a wrapper for multiple downstream account formats.
 
 use alloc::vec::Vec;
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 
 /// A multi-format address wrapper for on-chain accounts.
-#[derive(Encode, Decode, PartialEq, Eq, Clone, crate::RuntimeDebug, scale_info::TypeInfo)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	PartialEq,
+	Eq,
+	Clone,
+	crate::RuntimeDebug,
+	scale_info::TypeInfo,
+)]
 #[cfg_attr(feature = "std", derive(Hash))]
 pub enum MultiAddress<AccountId, AccountIndex> {
 	/// It's an account ID (pubkey).
diff --git a/substrate/primitives/runtime/src/proving_trie/mod.rs b/substrate/primitives/runtime/src/proving_trie/mod.rs
index 32b2284b4d79d9e7481e8231cda3dfa454c84ffc..bd5ddbe9742923f739e50d161cf2da88e9e44f6a 100644
--- a/substrate/primitives/runtime/src/proving_trie/mod.rs
+++ b/substrate/primitives/runtime/src/proving_trie/mod.rs
@@ -20,14 +20,25 @@
 pub mod base16;
 pub mod base2;
 
-use crate::{Decode, DispatchError, Encode, MaxEncodedLen, TypeInfo};
+use crate::{Decode, DecodeWithMemTracking, DispatchError, Encode, MaxEncodedLen, TypeInfo};
 #[cfg(feature = "serde")]
 use crate::{Deserialize, Serialize};
 use alloc::vec::Vec;
 use sp_trie::{trie_types::TrieError as SpTrieError, VerifyError};
 
 /// A runtime friendly error type for tries.
-#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(
+	Eq,
+	PartialEq,
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Debug,
+	TypeInfo,
+	MaxEncodedLen,
+)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub enum TrieError {
 	/* From TrieError */
diff --git a/substrate/primitives/runtime/src/testing.rs b/substrate/primitives/runtime/src/testing.rs
index 1fc78cce6707c1c16f7cab2ef0e73265d8777ef1..3f037eb153b9fb2bf7c64f9b419c3b16654d21b3 100644
--- a/substrate/primitives/runtime/src/testing.rs
+++ b/substrate/primitives/runtime/src/testing.rs
@@ -18,7 +18,7 @@
 //! Testing utilities.
 
 use crate::{
-	codec::{Codec, Decode, Encode, MaxEncodedLen},
+	codec::{Codec, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen},
 	generic::{self, UncheckedExtrinsic},
 	scale_info::TypeInfo,
 	traits::{self, BlakeTwo256, Dispatchable, OpaqueKeys},
@@ -42,6 +42,7 @@ use std::{cell::RefCell, fmt::Debug};
 	Clone,
 	Encode,
 	Decode,
+	DecodeWithMemTracking,
 	Debug,
 	Hash,
 	Serialize,
@@ -165,7 +166,19 @@ impl traits::Verify for UintAuthorityId {
 }
 
 /// A dummy signature type, to match `UintAuthorityId`.
-#[derive(Eq, PartialEq, Clone, Debug, Hash, Serialize, Deserialize, Encode, Decode, TypeInfo)]
+#[derive(
+	Eq,
+	PartialEq,
+	Clone,
+	Debug,
+	Hash,
+	Serialize,
+	Deserialize,
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	TypeInfo,
+)]
 pub struct TestSignature(pub u64, pub Vec<u8>);
 
 impl traits::Verify for TestSignature {
diff --git a/substrate/primitives/runtime/src/traits/mod.rs b/substrate/primitives/runtime/src/traits/mod.rs
index 46f17a0fcc6337a9973b13ca03604c9c115f441e..3781120fa4488c07735d7eb39f9063f9e1613ee9 100644
--- a/substrate/primitives/runtime/src/traits/mod.rs
+++ b/substrate/primitives/runtime/src/traits/mod.rs
@@ -2066,6 +2066,7 @@ macro_rules! impl_opaque_keys_inner {
 			Clone, PartialEq, Eq,
 			$crate::codec::Encode,
 			$crate::codec::Decode,
+			$crate::codec::DecodeWithMemTracking,
 			$crate::scale_info::TypeInfo,
 			$crate::RuntimeDebug,
 		)]
diff --git a/substrate/primitives/session/src/lib.rs b/substrate/primitives/session/src/lib.rs
index fe7a38047338d92d18e5427587c7e46bdee11829..3225097b665e6ca5a642b5ee130674f64f9b7134 100644
--- a/substrate/primitives/session/src/lib.rs
+++ b/substrate/primitives/session/src/lib.rs
@@ -21,7 +21,7 @@
 
 extern crate alloc;
 
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 
 #[cfg(feature = "std")]
 use sp_api::ProvideRuntimeApi;
@@ -39,7 +39,17 @@ pub use runtime_api::*;
 pub type ValidatorCount = u32;
 
 /// Proof of membership of a specific key in a given session.
-#[derive(Encode, Decode, Clone, Eq, PartialEq, Default, RuntimeDebug, scale_info::TypeInfo)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	Clone,
+	Eq,
+	PartialEq,
+	Default,
+	RuntimeDebug,
+	scale_info::TypeInfo,
+)]
 pub struct MembershipProof {
 	/// The session index on which the specific key is a member.
 	pub session: SessionIndex,
diff --git a/substrate/primitives/state-machine/src/ext.rs b/substrate/primitives/state-machine/src/ext.rs
index baad7e621bedcc28923bb668b1f49357afa2291e..afd0eeb1a55cde0f51d4a97e6cf7e3b69362e684 100644
--- a/substrate/primitives/state-machine/src/ext.rs
+++ b/substrate/primitives/state-machine/src/ext.rs
@@ -139,6 +139,7 @@ where
 	H::Out: Ord + 'static,
 	B: 'a + Backend<H>,
 {
+	/// Return all storage pairs from the backend and overlay combined.
 	pub fn storage_pairs(&mut self) -> Vec<(StorageKey, StorageValue)> {
 		use std::collections::HashMap;
 
diff --git a/substrate/primitives/statement-store/src/lib.rs b/substrate/primitives/statement-store/src/lib.rs
index dbac017ff6493e1da04251b33da9510d12eed078..d765ddad3ed8ce1c2591608fe73c5d3d5bfde3e5 100644
--- a/substrate/primitives/statement-store/src/lib.rs
+++ b/substrate/primitives/statement-store/src/lib.rs
@@ -23,7 +23,7 @@
 extern crate alloc;
 
 use alloc::vec::Vec;
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use scale_info::TypeInfo;
 use sp_application_crypto::RuntimeAppPublic;
 #[cfg(feature = "std")]
@@ -93,7 +93,9 @@ pub fn hash_encoded(data: &[u8]) -> [u8; 32] {
 }
 
 /// Statement proof.
-#[derive(Encode, Decode, TypeInfo, sp_core::RuntimeDebug, Clone, PartialEq, Eq)]
+#[derive(
+	Encode, Decode, DecodeWithMemTracking, TypeInfo, sp_core::RuntimeDebug, Clone, PartialEq, Eq,
+)]
 pub enum Proof {
 	/// Sr25519 Signature.
 	Sr25519 {
@@ -174,7 +176,16 @@ impl Field {
 }
 
 /// Statement structure.
-#[derive(TypeInfo, sp_core::RuntimeDebug, PassByCodec, Clone, PartialEq, Eq, Default)]
+#[derive(
+	DecodeWithMemTracking,
+	TypeInfo,
+	sp_core::RuntimeDebug,
+	PassByCodec,
+	Clone,
+	PartialEq,
+	Eq,
+	Default,
+)]
 pub struct Statement {
 	proof: Option<Proof>,
 	decryption_key: Option<DecryptionKey>,
diff --git a/substrate/primitives/transaction-storage-proof/src/lib.rs b/substrate/primitives/transaction-storage-proof/src/lib.rs
index 893b2e33bee6ca21bd900e485d482cb0acba3cc7..7d8e95dbb0df37b37dfc7bd74aaaf34f1190c559 100644
--- a/substrate/primitives/transaction-storage-proof/src/lib.rs
+++ b/substrate/primitives/transaction-storage-proof/src/lib.rs
@@ -25,7 +25,7 @@ extern crate alloc;
 use core::result::Result;
 
 use alloc::vec::Vec;
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use sp_inherents::{InherentData, InherentIdentifier, IsFatalError};
 use sp_runtime::traits::{Block as BlockT, NumberFor};
 
@@ -54,7 +54,7 @@ impl IsFatalError for InherentError {
 
 /// Holds a chunk of data retrieved from storage along with
 /// a proof that the data was stored at that location in the trie.
-#[derive(Encode, Decode, Clone, PartialEq, Debug, scale_info::TypeInfo)]
+#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Debug, scale_info::TypeInfo)]
 pub struct TransactionStorageProof {
 	/// Data chunk that is proved to exist.
 	pub chunk: Vec<u8>,
@@ -189,10 +189,8 @@ pub mod registration {
 		let mut target_chunk_key = Default::default();
 		let mut chunk_proof = Default::default();
 
-		let total_chunks: u64 = transactions
-			.iter()
-			.map(|t| ((t.len() + CHUNK_SIZE - 1) / CHUNK_SIZE) as u64)
-			.sum();
+		let total_chunks: u64 =
+			transactions.iter().map(|t| t.len().div_ceil(CHUNK_SIZE) as u64).sum();
 		let mut buf = [0u8; 8];
 		buf.copy_from_slice(&random_hash[0..8]);
 		let random_u64 = u64::from_be_bytes(buf);
diff --git a/substrate/primitives/trie/src/node_codec.rs b/substrate/primitives/trie/src/node_codec.rs
index 400f57f3b1bfebe7104679f20b356940f0242b6a..1b6a816589177201ef27636e525ec91c69237b2b 100644
--- a/substrate/primitives/trie/src/node_codec.rs
+++ b/substrate/primitives/trie/src/node_codec.rs
@@ -118,10 +118,7 @@ where
 				if padding && nibble_ops::pad_left(data[input.offset]) != 0 {
 					return Err(Error::BadFormat)
 				}
-				let partial = input.take(
-					(nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) /
-						nibble_ops::NIBBLE_PER_BYTE,
-				)?;
+				let partial = input.take(nibble_count.div_ceil(nibble_ops::NIBBLE_PER_BYTE))?;
 				let partial_padding = nibble_ops::number_padding(nibble_count);
 				let bitmap_range = input.take(BITMAP_LENGTH)?;
 				let bitmap = Bitmap::decode(&data[bitmap_range])?;
@@ -166,10 +163,7 @@ where
 				if padding && nibble_ops::pad_left(data[input.offset]) != 0 {
 					return Err(Error::BadFormat)
 				}
-				let partial = input.take(
-					(nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) /
-						nibble_ops::NIBBLE_PER_BYTE,
-				)?;
+				let partial = input.take(nibble_count.div_ceil(nibble_ops::NIBBLE_PER_BYTE))?;
 				let partial_padding = nibble_ops::number_padding(nibble_count);
 				let value = if contains_hash {
 					ValuePlan::Node(input.take(H::LENGTH)?)
diff --git a/substrate/primitives/trie/src/storage_proof.rs b/substrate/primitives/trie/src/storage_proof.rs
index bf0dc72e650b18a6be4c1bd5f5447cdebc77b06d..28ebb394d638164992b9d563c832336365ee866f 100644
--- a/substrate/primitives/trie/src/storage_proof.rs
+++ b/substrate/primitives/trie/src/storage_proof.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 use alloc::{collections::btree_set::BTreeSet, vec::Vec};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use core::iter::{DoubleEndedIterator, IntoIterator};
 use hash_db::{HashDB, Hasher};
 use scale_info::TypeInfo;
@@ -39,7 +39,7 @@ pub enum StorageProofError {
 /// The proof consists of the set of serialized nodes in the storage trie accessed when looking up
 /// the keys covered by the proof. Verifying the proof requires constructing the partial trie from
 /// the serialized nodes and performing the key lookups.
-#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)]
+#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
 pub struct StorageProof {
 	trie_nodes: BTreeSet<Vec<u8>>,
 }
diff --git a/substrate/primitives/weights/src/weight_v2.rs b/substrate/primitives/weights/src/weight_v2.rs
index 0f92e6448ca94485cfc56206d2b0068100c8e049..87e6e69c49f63a53d0e655d32457e49e777fdc3d 100644
--- a/substrate/primitives/weights/src/weight_v2.rs
+++ b/substrate/primitives/weights/src/weight_v2.rs
@@ -15,13 +15,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use codec::{Decode, Encode, MaxEncodedLen};
+use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
 use core::ops::{Add, AddAssign, Div, Mul, Sub, SubAssign};
 use sp_arithmetic::traits::{Bounded, CheckedAdd, CheckedSub, Zero};
 
 use super::*;
 
-#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Eq, PartialEq, Copy, Clone, Debug, Default)]
+#[derive(
+	Encode,
+	Decode,
+	DecodeWithMemTracking,
+	MaxEncodedLen,
+	TypeInfo,
+	Eq,
+	PartialEq,
+	Copy,
+	Clone,
+	Debug,
+	Default,
+)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
 pub struct Weight {
diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs
index 7c092f2851663d2a2807807e5d812a3c0071a71e..b5d3bf2dbbea79dfb4a67d03bc0f7420d5de49b5 100644
--- a/substrate/test-utils/runtime/src/lib.rs
+++ b/substrate/test-utils/runtime/src/lib.rs
@@ -29,7 +29,7 @@ pub mod substrate_test_pallet;
 
 #[cfg(not(feature = "std"))]
 use alloc::{vec, vec::Vec};
-use codec::{Decode, Encode};
+use codec::{Decode, DecodeWithMemTracking, Encode};
 use frame_support::{
 	construct_runtime, derive_impl,
 	dispatch::DispatchClass,
@@ -135,7 +135,7 @@ pub fn native_version() -> NativeVersion {
 }
 
 /// Transfer data extracted from Extrinsic containing `Balances::transfer_allow_death`.
-#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
+#[derive(Clone, PartialEq, Eq, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, TypeInfo)]
 pub struct TransferData {
 	pub from: AccountId,
 	pub to: AccountId,
diff --git a/templates/parachain/runtime/src/apis.rs b/templates/parachain/runtime/src/apis.rs
index 53fa753946d845e98b05029b2f9ec8e5bfec25d3..19a88dd6869dcf262f3ef7d440dc492f56d82b05 100644
--- a/templates/parachain/runtime/src/apis.rs
+++ b/templates/parachain/runtime/src/apis.rs
@@ -265,6 +265,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
diff --git a/templates/parachain/runtime/src/configs/xcm_config.rs b/templates/parachain/runtime/src/configs/xcm_config.rs
index 3da3b711f4ff3ccec15bd94947e0eb4c9f5e110f..ab1ce0d41d66681e020b59a5c19b5f06c47cc2a6 100644
--- a/templates/parachain/runtime/src/configs/xcm_config.rs
+++ b/templates/parachain/runtime/src/configs/xcm_config.rs
@@ -16,10 +16,11 @@ use frame_system::EnsureRoot;
 use pallet_xcm::XcmPassthrough;
 use polkadot_parachain_primitives::primitives::Sibling;
 use polkadot_runtime_common::impls::ToAuthor;
+use polkadot_sdk::staging_xcm_builder::{DenyRecursively, DenyThenTry};
 use xcm::latest::prelude::*;
 use xcm_builder::{
 	AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom,
-	DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FixedWeightBounds,
+	DenyReserveTransferToRelayChain, EnsureXcmOrigin, FixedWeightBounds,
 	FrameTransactionalProcessor, FungibleAdapter, IsConcrete, NativeAsset, ParentIsPreset,
 	RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
 	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
@@ -99,7 +100,7 @@ impl Contains<Location> for ParentOrParentsExecutivePlurality {
 
 pub type Barrier = TrailingSetTopicAsId<
 	DenyThenTry<
-		DenyReserveTransferToRelayChain,
+		DenyRecursively<DenyReserveTransferToRelayChain>,
 		(
 			TakeWeightCredit,
 			WithComputedOrigin<
diff --git a/templates/solochain/runtime/src/apis.rs b/templates/solochain/runtime/src/apis.rs
index 536e8250056d3d2379ac28de8340142195f46292..02880708f92281eb2e914e2360b4a0d03c1eac0a 100644
--- a/templates/solochain/runtime/src/apis.rs
+++ b/templates/solochain/runtime/src/apis.rs
@@ -241,6 +241,7 @@ impl_runtime_apis! {
 			(list, storage_info)
 		}
 
+		#[allow(non_local_definitions)]
 		fn dispatch_benchmark(
 			config: frame_benchmarking::BenchmarkConfig
 		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {