From a4791617241732f4fecafe21e12c16b7fe42f73e Mon Sep 17 00:00:00 2001
From: davidk-pt <david.kazlauskas@parity.io>
Date: Wed, 6 Nov 2024 03:27:48 +0200
Subject: [PATCH] pallet-child-bounties index child bounty by parent bounty
 (#6255)

Resolves https://github.com/paritytech/polkadot-sdk/issues/5929

Migrates `ChildBountyDescriptions` to be indexed instead of unique child
bounty id unique per all child bounties in the pallet to be unique per
every parent bounty.

Migrates `(ParentBounty, ChildBounty)` keys inside `ChildBounties`
storage item to use new `ChildBounty` ids starting from `0`.

@paritytech/frame-coders

---------

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: DavidK <davidk@parity.io>
Co-authored-by: muharem <ismailov.m.h@gmail.com>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
---
 polkadot/runtime/rococo/src/lib.rs            |   2 +
 prdoc/pr_6255.prdoc                           |  34 +
 substrate/frame/bounties/src/lib.rs           |  10 +-
 .../frame/child-bounties/src/benchmarking.rs  |   8 +-
 substrate/frame/child-bounties/src/lib.rs     | 105 +++-
 .../frame/child-bounties/src/migration.rs     | 229 +++++++
 substrate/frame/child-bounties/src/tests.rs   | 592 ++++++++++++------
 substrate/primitives/core/src/crypto.rs       |   4 +-
 8 files changed, 759 insertions(+), 225 deletions(-)
 create mode 100644 prdoc/pr_6255.prdoc
 create mode 100644 substrate/frame/child-bounties/src/migration.rs

diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs
index 88e738cc980..f8f8573bc90 100644
--- a/polkadot/runtime/rococo/src/lib.rs
+++ b/polkadot/runtime/rococo/src/lib.rs
@@ -1661,6 +1661,7 @@ pub mod migrations {
 		pub const PhragmenElectionPalletId: LockIdentifier = *b"phrelect";
 		/// Weight for balance unreservations
 		pub BalanceUnreserveWeight: Weight = weights::pallet_balances_balances::WeightInfo::<Runtime>::force_unreserve();
+		pub BalanceTransferAllowDeath: Weight = weights::pallet_balances_balances::WeightInfo::<Runtime>::transfer_allow_death();
 	}
 
 	// Special Config for Gov V1 pallets, allowing us to run migrations for them without
@@ -1710,6 +1711,7 @@ pub mod migrations {
         paras_registrar::migration::MigrateToV1<Runtime, ()>,
         pallet_referenda::migration::v1::MigrateV0ToV1<Runtime, ()>,
         pallet_referenda::migration::v1::MigrateV0ToV1<Runtime, pallet_referenda::Instance2>,
+        pallet_child_bounties::migration::MigrateV0ToV1<Runtime, BalanceTransferAllowDeath>,
 
         // Unlock & unreserve Gov1 funds
 
diff --git a/prdoc/pr_6255.prdoc b/prdoc/pr_6255.prdoc
new file mode 100644
index 00000000000..7b69717b5c2
--- /dev/null
+++ b/prdoc/pr_6255.prdoc
@@ -0,0 +1,34 @@
+title: '[pallet-child-bounties] Index child bounties by parent bounty'
+doc:
+- audience: Runtime Dev
+  description: |
+    Index child bounties by their parent bounty, ensuring that their indexes are independent of
+    child bounties from other parent bounties. This will allow for predictable indexes and the
+    ability to batch creation and approval calls together.
+
+    ### Migration for Runtime Pallet Instance
+    Use `migration::v1::MigrateToV1Impl` storage migration type to translate ids for the active
+    child bounties and migrate the state to the new schema.
+
+    ### Migration for Clients
+    - Use new `ParentTotalChildBounties` storage item to iterate over child bounties for a certain
+    parent bounty;
+    - Use new `ChildBountyDescriptionsV1` storage item to get the bounty description instead of
+    removed `ChildBountyDescriptions`;
+    - Use `V0ToV1ChildBountyIds` storage item to look up the new child bounty id for a given 
+    old child bounty id;
+    - Update the child bounty account id derivation from `PalletId + "cb" + child_id` to
+    `PalletId + "cb" + bounty_id + child_id`.
+
+    ### Additional Notes
+    - The `ChildBountyCount` storage item is deprecated and will be remove in May 2025.
+
+crates:
+- name: pallet-child-bounties
+  bump: major
+- name: pallet-bounties
+  bump: major
+- name: rococo-runtime
+  bump: major
+- name: sp-core
+  bump: minor
diff --git a/substrate/frame/bounties/src/lib.rs b/substrate/frame/bounties/src/lib.rs
index 06b0e76cfc7..3ed408a1912 100644
--- a/substrate/frame/bounties/src/lib.rs
+++ b/substrate/frame/bounties/src/lib.rs
@@ -188,8 +188,11 @@ pub trait ChildBountyManager<Balance> {
 	/// Get the active child bounties for a parent bounty.
 	fn child_bounties_count(bounty_id: BountyIndex) -> BountyIndex;
 
-	/// Get total curator fees of children-bounty curators.
+	/// Take total curator fees of children-bounty curators.
 	fn children_curator_fees(bounty_id: BountyIndex) -> Balance;
+
+	/// Hook called when a parent bounty is removed.
+	fn bounty_removed(bounty_id: BountyIndex);
 }
 
 #[frame_support::pallet]
@@ -679,6 +682,7 @@ pub mod pallet {
 					*maybe_bounty = None;
 
 					BountyDescriptions::<T, I>::remove(bounty_id);
+					T::ChildBountyManager::bounty_removed(bounty_id);
 
 					Self::deposit_event(Event::<T, I>::BountyClaimed {
 						index: bounty_id,
@@ -776,7 +780,9 @@ pub mod pallet {
 						AllowDeath,
 					); // should not fail
 					debug_assert!(res.is_ok());
+
 					*maybe_bounty = None;
+					T::ChildBountyManager::bounty_removed(bounty_id);
 
 					Self::deposit_event(Event::<T, I>::BountyCanceled { index: bounty_id });
 					Ok(Some(<T as Config<I>>::WeightInfo::close_bounty_active()).into())
@@ -1054,4 +1060,6 @@ impl<Balance: Zero> ChildBountyManager<Balance> for () {
 	fn children_curator_fees(_bounty_id: BountyIndex) -> Balance {
 		Zero::zero()
 	}
+
+	fn bounty_removed(_bounty_id: BountyIndex) {}
 }
diff --git a/substrate/frame/child-bounties/src/benchmarking.rs b/substrate/frame/child-bounties/src/benchmarking.rs
index 68e99e21a45..67074f90cbf 100644
--- a/substrate/frame/child-bounties/src/benchmarking.rs
+++ b/substrate/frame/child-bounties/src/benchmarking.rs
@@ -151,7 +151,7 @@ fn activate_child_bounty<T: Config>(
 		bounty_setup.reason.clone(),
 	)?;
 
-	bounty_setup.child_bounty_id = ChildBountyCount::<T>::get() - 1;
+	bounty_setup.child_bounty_id = ParentTotalChildBounties::<T>::get(bounty_setup.bounty_id) - 1;
 
 	ChildBounties::<T>::propose_curator(
 		RawOrigin::Signed(bounty_setup.curator.clone()).into(),
@@ -205,7 +205,7 @@ benchmarks! {
 			bounty_setup.child_bounty_value,
 			bounty_setup.reason.clone(),
 		)?;
-		let child_bounty_id = ChildBountyCount::<T>::get() - 1;
+		let child_bounty_id = ParentTotalChildBounties::<T>::get(bounty_setup.bounty_id) - 1;
 
 	}: _(RawOrigin::Signed(bounty_setup.curator), bounty_setup.bounty_id,
 			child_bounty_id, child_curator_lookup, bounty_setup.child_bounty_fee)
@@ -221,7 +221,7 @@ benchmarks! {
 			bounty_setup.child_bounty_value,
 			bounty_setup.reason.clone(),
 		)?;
-		bounty_setup.child_bounty_id = ChildBountyCount::<T>::get() - 1;
+		bounty_setup.child_bounty_id = ParentTotalChildBounties::<T>::get(bounty_setup.bounty_id) - 1;
 
 		ChildBounties::<T>::propose_curator(
 			RawOrigin::Signed(bounty_setup.curator.clone()).into(),
@@ -296,7 +296,7 @@ benchmarks! {
 			bounty_setup.child_bounty_value,
 			bounty_setup.reason.clone(),
 		)?;
-		bounty_setup.child_bounty_id = ChildBountyCount::<T>::get() - 1;
+		bounty_setup.child_bounty_id = ParentTotalChildBounties::<T>::get(bounty_setup.bounty_id) - 1;
 
 	}: close_child_bounty(RawOrigin::Root, bounty_setup.bounty_id,
 		bounty_setup.child_bounty_id)
diff --git a/substrate/frame/child-bounties/src/lib.rs b/substrate/frame/child-bounties/src/lib.rs
index 1e970b6ae67..ea1d9547d46 100644
--- a/substrate/frame/child-bounties/src/lib.rs
+++ b/substrate/frame/child-bounties/src/lib.rs
@@ -53,11 +53,15 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 
 mod benchmarking;
+pub mod migration;
 mod tests;
 pub mod weights;
 
 extern crate alloc;
 
+/// The log target for this pallet.
+const LOG_TARGET: &str = "runtime::child-bounties";
+
 use alloc::vec::Vec;
 
 use frame_support::traits::{
@@ -134,7 +138,11 @@ pub mod pallet {
 
 	use super::*;
 
+	/// The in-code storage version.
+	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
+
 	#[pallet::pallet]
+	#[pallet::storage_version(STORAGE_VERSION)]
 	pub struct Pallet<T>(_);
 
 	#[pallet::config]
@@ -184,16 +192,22 @@ pub mod pallet {
 		Canceled { index: BountyIndex, child_index: BountyIndex },
 	}
 
-	/// Number of total child bounties.
+	/// DEPRECATED: Replaced with `ParentTotalChildBounties` storage item keeping dedicated counts
+	/// for each parent bounty. Number of total child bounties. Will be removed in May 2025.
 	#[pallet::storage]
 	pub type ChildBountyCount<T: Config> = StorageValue<_, BountyIndex, ValueQuery>;
 
-	/// Number of child bounties per parent bounty.
+	/// Number of active child bounties per parent bounty.
 	/// Map of parent bounty index to number of child bounties.
 	#[pallet::storage]
 	pub type ParentChildBounties<T: Config> =
 		StorageMap<_, Twox64Concat, BountyIndex, u32, ValueQuery>;
 
+	/// Number of total child bounties per parent bounty, including completed bounties.
+	#[pallet::storage]
+	pub type ParentTotalChildBounties<T: Config> =
+		StorageMap<_, Twox64Concat, BountyIndex, u32, ValueQuery>;
+
 	/// Child bounties that have been added.
 	#[pallet::storage]
 	pub type ChildBounties<T: Config> = StorageDoubleMap<
@@ -205,10 +219,27 @@ pub mod pallet {
 		ChildBounty<T::AccountId, BalanceOf<T>, BlockNumberFor<T>>,
 	>;
 
-	/// The description of each child-bounty.
+	/// The description of each child-bounty. Indexed by `(parent_id, child_id)`.
+	///
+	/// This item replaces the `ChildBountyDescriptions` storage item from the V0 storage version.
+	#[pallet::storage]
+	pub type ChildBountyDescriptionsV1<T: Config> = StorageDoubleMap<
+		_,
+		Twox64Concat,
+		BountyIndex,
+		Twox64Concat,
+		BountyIndex,
+		BoundedVec<u8, T::MaximumReasonLength>,
+	>;
+
+	/// The mapping of the child bounty ids from storage version `V0` to the new `V1` version.
+	///
+	/// The `V0` ids based on total child bounty count [`ChildBountyCount`]`. The `V1` version ids
+	/// based on the child bounty count per parent bounty [`ParentTotalChildBounties`].
+	/// The item intended solely for client convenience and not used in the pallet's core logic.
 	#[pallet::storage]
-	pub type ChildBountyDescriptions<T: Config> =
-		StorageMap<_, Twox64Concat, BountyIndex, BoundedVec<u8, T::MaximumReasonLength>>;
+	pub type V0ToV1ChildBountyIds<T: Config> =
+		StorageMap<_, Twox64Concat, BountyIndex, (BountyIndex, BountyIndex)>;
 
 	/// The cumulative child-bounty curator fee for each parent bounty.
 	#[pallet::storage]
@@ -276,15 +307,19 @@ pub mod pallet {
 			)?;
 
 			// Get child-bounty ID.
-			let child_bounty_id = ChildBountyCount::<T>::get();
-			let child_bounty_account = Self::child_bounty_account_id(child_bounty_id);
+			let child_bounty_id = ParentTotalChildBounties::<T>::get(parent_bounty_id);
+			let child_bounty_account =
+				Self::child_bounty_account_id(parent_bounty_id, child_bounty_id);
 
 			// Transfer funds from parent bounty to child-bounty.
 			T::Currency::transfer(&parent_bounty_account, &child_bounty_account, value, KeepAlive)?;
 
 			// Increment the active child-bounty count.
 			ParentChildBounties::<T>::mutate(parent_bounty_id, |count| count.saturating_inc());
-			ChildBountyCount::<T>::put(child_bounty_id.saturating_add(1));
+			ParentTotalChildBounties::<T>::insert(
+				parent_bounty_id,
+				child_bounty_id.saturating_add(1),
+			);
 
 			// Create child-bounty instance.
 			Self::create_child_bounty(
@@ -672,7 +707,8 @@ pub mod pallet {
 						);
 
 						// Make curator fee payment.
-						let child_bounty_account = Self::child_bounty_account_id(child_bounty_id);
+						let child_bounty_account =
+							Self::child_bounty_account_id(parent_bounty_id, child_bounty_id);
 						let balance = T::Currency::free_balance(&child_bounty_account);
 						let curator_fee = child_bounty.fee.min(balance);
 						let payout = balance.saturating_sub(curator_fee);
@@ -716,7 +752,7 @@ pub mod pallet {
 						});
 
 						// Remove the child-bounty description.
-						ChildBountyDescriptions::<T>::remove(child_bounty_id);
+						ChildBountyDescriptionsV1::<T>::remove(parent_bounty_id, child_bounty_id);
 
 						// Remove the child-bounty instance from the state.
 						*maybe_child_bounty = None;
@@ -772,6 +808,19 @@ pub mod pallet {
 			Ok(())
 		}
 	}
+
+	#[pallet::hooks]
+	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
+		fn integrity_test() {
+			let parent_bounty_id: BountyIndex = 1;
+			let child_bounty_id: BountyIndex = 2;
+			let _: T::AccountId = T::PalletId::get()
+				.try_into_sub_account(("cb", parent_bounty_id, child_bounty_id))
+				.expect(
+					"The `AccountId` type must be large enough to fit the child bounty account ID.",
+				);
+		}
+	}
 }
 
 impl<T: Config> Pallet<T> {
@@ -797,11 +846,14 @@ impl<T: Config> Pallet<T> {
 	}
 
 	/// The account ID of a child-bounty account.
-	pub fn child_bounty_account_id(id: BountyIndex) -> T::AccountId {
+	pub fn child_bounty_account_id(
+		parent_bounty_id: BountyIndex,
+		child_bounty_id: BountyIndex,
+	) -> T::AccountId {
 		// This function is taken from the parent (bounties) pallet, but the
 		// prefix is changed to have different AccountId when the index of
 		// parent and child is same.
-		T::PalletId::get().into_sub_account_truncating(("cb", id))
+		T::PalletId::get().into_sub_account_truncating(("cb", parent_bounty_id, child_bounty_id))
 	}
 
 	fn create_child_bounty(
@@ -818,7 +870,7 @@ impl<T: Config> Pallet<T> {
 			status: ChildBountyStatus::Added,
 		};
 		ChildBounties::<T>::insert(parent_bounty_id, child_bounty_id, &child_bounty);
-		ChildBountyDescriptions::<T>::insert(child_bounty_id, description);
+		ChildBountyDescriptionsV1::<T>::insert(parent_bounty_id, child_bounty_id, description);
 		Self::deposit_event(Event::Added { index: parent_bounty_id, child_index: child_bounty_id });
 	}
 
@@ -877,7 +929,8 @@ impl<T: Config> Pallet<T> {
 				// Transfer fund from child-bounty to parent bounty.
 				let parent_bounty_account =
 					pallet_bounties::Pallet::<T>::bounty_account_id(parent_bounty_id);
-				let child_bounty_account = Self::child_bounty_account_id(child_bounty_id);
+				let child_bounty_account =
+					Self::child_bounty_account_id(parent_bounty_id, child_bounty_id);
 				let balance = T::Currency::free_balance(&child_bounty_account);
 				let transfer_result = T::Currency::transfer(
 					&child_bounty_account,
@@ -888,7 +941,7 @@ impl<T: Config> Pallet<T> {
 				debug_assert!(transfer_result.is_ok());
 
 				// Remove the child-bounty description.
-				ChildBountyDescriptions::<T>::remove(child_bounty_id);
+				ChildBountyDescriptionsV1::<T>::remove(parent_bounty_id, child_bounty_id);
 
 				*maybe_child_bounty = None;
 
@@ -902,16 +955,22 @@ impl<T: Config> Pallet<T> {
 	}
 }
 
-// Implement ChildBountyManager to connect with the bounties pallet. This is
-// where we pass the active child bounties and child curator fees to the parent
-// bounty.
+/// Implement ChildBountyManager to connect with the bounties pallet. This is
+/// where we pass the active child bounties and child curator fees to the parent
+/// bounty.
+///
+/// Function `children_curator_fees` not only returns the fee but also removes cumulative curator
+/// fees during call.
 impl<T: Config> pallet_bounties::ChildBountyManager<BalanceOf<T>> for Pallet<T> {
+	/// Returns number of active child bounties for `bounty_id`
 	fn child_bounties_count(
 		bounty_id: pallet_bounties::BountyIndex,
 	) -> pallet_bounties::BountyIndex {
 		ParentChildBounties::<T>::get(bounty_id)
 	}
 
+	/// Returns cumulative child bounty curator fees for `bounty_id` also removing the associated
+	/// storage item. This function is assumed to be called when parent bounty is claimed.
 	fn children_curator_fees(bounty_id: pallet_bounties::BountyIndex) -> BalanceOf<T> {
 		// This is asked for when the parent bounty is being claimed. No use of
 		// keeping it in state after that. Hence removing.
@@ -919,4 +978,14 @@ impl<T: Config> pallet_bounties::ChildBountyManager<BalanceOf<T>> for Pallet<T>
 		ChildrenCuratorFees::<T>::remove(bounty_id);
 		children_fee_total
 	}
+
+	/// Clean up the storage on a parent bounty removal.
+	fn bounty_removed(bounty_id: BountyIndex) {
+		debug_assert!(ParentChildBounties::<T>::get(bounty_id).is_zero());
+		debug_assert!(ChildrenCuratorFees::<T>::get(bounty_id).is_zero());
+		debug_assert!(ChildBounties::<T>::iter_key_prefix(bounty_id).count().is_zero());
+		debug_assert!(ChildBountyDescriptionsV1::<T>::iter_key_prefix(bounty_id).count().is_zero());
+		ParentChildBounties::<T>::remove(bounty_id);
+		ParentTotalChildBounties::<T>::remove(bounty_id);
+	}
 }
diff --git a/substrate/frame/child-bounties/src/migration.rs b/substrate/frame/child-bounties/src/migration.rs
new file mode 100644
index 00000000000..52232a5a7f2
--- /dev/null
+++ b/substrate/frame/child-bounties/src/migration.rs
@@ -0,0 +1,229 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use super::*;
+use core::marker::PhantomData;
+use frame_support::{
+	storage_alias,
+	traits::{Get, UncheckedOnRuntimeUpgrade},
+};
+
+use alloc::collections::BTreeSet;
+#[cfg(feature = "try-runtime")]
+use alloc::vec::Vec;
+#[cfg(feature = "try-runtime")]
+use frame_support::ensure;
+
+pub mod v1 {
+	use super::*;
+
+	/// Creates a new ids for the child balances based on the child bounty count per parent bounty
+	/// instead of the total child bounty count. Translates the existing child bounties to the new
+	/// ids. Creates the `V0ToV1ChildBountyIds` map from `old_child_id` to new (`parent_id`,
+	/// `new_child_id`).
+	///
+	/// `TransferWeight` returns `Weight` of `T::Currency::transfer` and `T::Currency::free_balance`
+	/// operation which is performed during this migration.
+	pub struct MigrateToV1Impl<T, TransferWeight>(PhantomData<(T, TransferWeight)>);
+
+	#[storage_alias]
+	type ChildBountyDescriptions<T: Config + pallet_bounties::Config> = StorageMap<
+		Pallet<T>,
+		Twox64Concat,
+		BountyIndex,
+		BoundedVec<u8, <T as pallet_bounties::Config>::MaximumReasonLength>,
+	>;
+
+	impl<T: Config, TransferWeight: Get<Weight>> UncheckedOnRuntimeUpgrade
+		for MigrateToV1Impl<T, TransferWeight>
+	{
+		fn on_runtime_upgrade() -> frame_support::weights::Weight {
+			// increment reads/writes after the action
+			let mut reads = 0u64;
+			let mut writes = 0u64;
+			let mut transfer_weights: Weight = Weight::zero();
+
+			// keep ids order roughly the same with the old order
+			let mut old_bounty_ids = BTreeSet::new();
+			// first iteration collect all existing ids not to mutate map as we iterate it
+			for (parent_bounty_id, old_child_bounty_id) in ChildBounties::<T>::iter_keys() {
+				reads += 1;
+				old_bounty_ids.insert((parent_bounty_id, old_child_bounty_id));
+			}
+
+			log::info!(
+				target: LOG_TARGET,
+				"Migrating {} child bounties",
+				old_bounty_ids.len(),
+			);
+
+			for (parent_bounty_id, old_child_bounty_id) in old_bounty_ids {
+				// assign new child bounty id
+				let new_child_bounty_id = ParentTotalChildBounties::<T>::get(parent_bounty_id);
+				reads += 1;
+				ParentTotalChildBounties::<T>::insert(
+					parent_bounty_id,
+					new_child_bounty_id.saturating_add(1),
+				);
+				writes += 1;
+
+				V0ToV1ChildBountyIds::<T>::insert(
+					old_child_bounty_id,
+					(parent_bounty_id, new_child_bounty_id),
+				);
+				writes += 1;
+
+				let old_child_bounty_account =
+					Self::old_child_bounty_account_id(old_child_bounty_id);
+				let new_child_bounty_account =
+					Pallet::<T>::child_bounty_account_id(parent_bounty_id, new_child_bounty_id);
+				let old_balance = T::Currency::free_balance(&old_child_bounty_account);
+				log::info!(
+					"Transferring {:?} funds from old child bounty account {:?} to new child bounty account {:?}",
+					old_balance, old_child_bounty_account, new_child_bounty_account
+				);
+				if let Err(err) = T::Currency::transfer(
+					&old_child_bounty_account,
+					&new_child_bounty_account,
+					old_balance,
+					AllowDeath,
+				) {
+					log::error!(
+						target: LOG_TARGET,
+						"Error transferring funds: {:?}",
+						err
+					);
+				}
+				transfer_weights += TransferWeight::get();
+
+				log::info!(
+					target: LOG_TARGET,
+					"Remapped parent bounty {} child bounty id {}->{}",
+					parent_bounty_id,
+					old_child_bounty_id,
+					new_child_bounty_id,
+				);
+
+				let bounty_description = ChildBountyDescriptions::<T>::take(old_child_bounty_id);
+				writes += 1;
+				let child_bounty = ChildBounties::<T>::take(parent_bounty_id, old_child_bounty_id);
+				writes += 1;
+
+				// should always be some
+				if let Some(taken) = child_bounty {
+					ChildBounties::<T>::insert(parent_bounty_id, new_child_bounty_id, taken);
+					writes += 1;
+				} else {
+					log::error!(
+						"child bounty with old id {} not found, should be impossible",
+						old_child_bounty_id
+					);
+				}
+				if let Some(bounty_description) = bounty_description {
+					super::super::ChildBountyDescriptionsV1::<T>::insert(
+						parent_bounty_id,
+						new_child_bounty_id,
+						bounty_description,
+					);
+					writes += 1;
+				} else {
+					log::error!(
+						"child bounty description with old id {} not found, should be impossible",
+						old_child_bounty_id
+					);
+				}
+			}
+
+			log::info!(
+				target: LOG_TARGET,
+				"Migration done, reads: {}, writes: {}, transfer weights: {}",
+				reads, writes, transfer_weights
+			);
+
+			T::DbWeight::get().reads_writes(reads, writes) + transfer_weights
+		}
+
+		#[cfg(feature = "try-runtime")]
+		fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
+			let old_child_bounty_count = ChildBounties::<T>::iter_keys().count() as u32;
+			let old_child_bounty_descriptions =
+				v1::ChildBountyDescriptions::<T>::iter_keys().count() as u32;
+			let old_child_bounty_ids = ChildBounties::<T>::iter_keys().collect::<Vec<_>>();
+			Ok((old_child_bounty_count, old_child_bounty_descriptions, old_child_bounty_ids)
+				.encode())
+		}
+
+		#[cfg(feature = "try-runtime")]
+		fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
+			type StateType = (u32, u32, Vec<(u32, u32)>);
+			let (old_child_bounty_count, old_child_bounty_descriptions, old_child_bounty_ids) =
+				StateType::decode(&mut &state[..]).expect("Can't decode previous state");
+			let new_child_bounty_count = ChildBounties::<T>::iter_keys().count() as u32;
+			let new_child_bounty_descriptions =
+				super::super::ChildBountyDescriptionsV1::<T>::iter_keys().count() as u32;
+
+			ensure!(
+				old_child_bounty_count == new_child_bounty_count,
+				"child bounty count doesn't match"
+			);
+			ensure!(
+				old_child_bounty_descriptions == new_child_bounty_descriptions,
+				"child bounty descriptions count doesn't match"
+			);
+
+			let old_child_bounty_descriptions_storage =
+				v1::ChildBountyDescriptions::<T>::iter_keys().count();
+			log::info!("old child bounty descriptions: {}", old_child_bounty_descriptions_storage);
+			ensure!(
+				old_child_bounty_descriptions_storage == 0,
+				"Old bounty descriptions should have been drained."
+			);
+
+			for (_, old_child_bounty_id) in old_child_bounty_ids {
+				let old_account_id = Self::old_child_bounty_account_id(old_child_bounty_id);
+				let balance = T::Currency::total_balance(&old_account_id);
+				if !balance.is_zero() {
+					log::error!(
+						"Old child bounty id {} still has balance {:?}",
+						old_child_bounty_id,
+						balance
+					);
+				}
+			}
+
+			Ok(())
+		}
+	}
+
+	impl<T: Config, TransferWeight: Get<Weight>> MigrateToV1Impl<T, TransferWeight> {
+		fn old_child_bounty_account_id(id: BountyIndex) -> T::AccountId {
+			// This function is taken from the parent (bounties) pallet, but the
+			// prefix is changed to have different AccountId when the index of
+			// parent and child is same.
+			T::PalletId::get().into_sub_account_truncating(("cb", id))
+		}
+	}
+}
+
+/// Migrate the pallet storage from `0` to `1`.
+pub type MigrateV0ToV1<T, TransferWeight> = frame_support::migrations::VersionedMigration<
+	0,
+	1,
+	v1::MigrateToV1Impl<T, TransferWeight>,
+	Pallet<T>,
+	<T as frame_system::Config>::DbWeight,
+>;
diff --git a/substrate/frame/child-bounties/src/tests.rs b/substrate/frame/child-bounties/src/tests.rs
index 0e58f7c9178..939983054f6 100644
--- a/substrate/frame/child-bounties/src/tests.rs
+++ b/substrate/frame/child-bounties/src/tests.rs
@@ -66,10 +66,16 @@ parameter_types! {
 }
 
 type Balance = u64;
+// must be at least 20 bytes long because of child-bounty account derivation.
+type AccountId = sp_core::U256;
+
+fn account_id(id: u8) -> AccountId {
+	sp_core::U256::from(id)
+}
 
 #[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
 impl frame_system::Config for Test {
-	type AccountId = u128;
+	type AccountId = AccountId;
 	type Lookup = IdentityLookup<Self::AccountId>;
 	type Block = Block;
 	type AccountData = pallet_balances::AccountData<u64>;
@@ -82,14 +88,14 @@ impl pallet_balances::Config for Test {
 parameter_types! {
 	pub const Burn: Permill = Permill::from_percent(50);
 	pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry");
-	pub TreasuryAccount: u128 = Treasury::account_id();
+	pub TreasuryAccount: AccountId = Treasury::account_id();
 	pub const SpendLimit: Balance = u64::MAX;
 }
 
 impl pallet_treasury::Config for Test {
 	type PalletId = TreasuryPalletId;
 	type Currency = pallet_balances::Pallet<Test>;
-	type RejectOrigin = frame_system::EnsureRoot<u128>;
+	type RejectOrigin = frame_system::EnsureRoot<AccountId>;
 	type RuntimeEvent = RuntimeEvent;
 	type SpendPeriod = ConstU64<2>;
 	type Burn = Burn;
@@ -141,7 +147,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
 	let mut t = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();
 	pallet_balances::GenesisConfig::<Test> {
 		// Total issuance will be 200 with treasury account initialized at ED.
-		balances: vec![(0, 100), (1, 98), (2, 1)],
+		balances: vec![(account_id(0), 100), (account_id(1), 98), (account_id(2), 1)],
 	}
 	.assimilate_storage(&mut t)
 	.unwrap();
@@ -195,52 +201,71 @@ fn add_child_bounty() {
 		go_to_block(1);
 		Balances::make_free_balance_be(&Treasury::account_id(), 101);
 
-		assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec()));
+		assert_ok!(Bounties::propose_bounty(
+			RuntimeOrigin::signed(account_id(0)),
+			50,
+			b"12345".to_vec()
+		));
 
 		assert_ok!(Bounties::approve_bounty(RuntimeOrigin::root(), 0));
 
 		go_to_block(2);
 
 		let fee = 8;
-		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 4, fee));
+		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, account_id(4), fee));
 
-		Balances::make_free_balance_be(&4, 10);
+		Balances::make_free_balance_be(&account_id(4), 10);
 
-		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(4), 0));
+		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(account_id(4)), 0));
 
 		// This verifies that the accept curator logic took a deposit.
 		let expected_deposit = CuratorDepositMultiplier::get() * fee;
-		assert_eq!(Balances::reserved_balance(&4), expected_deposit);
-		assert_eq!(Balances::free_balance(&4), 10 - expected_deposit);
+		assert_eq!(Balances::reserved_balance(&account_id(4)), expected_deposit);
+		assert_eq!(Balances::free_balance(&account_id(4)), 10 - expected_deposit);
 
 		// Add child-bounty.
 		// Acc-4 is the parent curator.
 		// Call from invalid origin & check for error "RequireCurator".
 		assert_noop!(
-			ChildBounties::add_child_bounty(RuntimeOrigin::signed(0), 0, 10, b"12345-p1".to_vec()),
+			ChildBounties::add_child_bounty(
+				RuntimeOrigin::signed(account_id(0)),
+				0,
+				10,
+				b"12345-p1".to_vec()
+			),
 			BountiesError::RequireCurator,
 		);
 
 		// Update the parent curator balance.
-		Balances::make_free_balance_be(&4, 101);
+		Balances::make_free_balance_be(&account_id(4), 101);
 
 		// parent curator fee is reserved on parent bounty account.
 		assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 50);
 		assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0);
 
 		assert_noop!(
-			ChildBounties::add_child_bounty(RuntimeOrigin::signed(4), 0, 50, b"12345-p1".to_vec()),
+			ChildBounties::add_child_bounty(
+				RuntimeOrigin::signed(account_id(4)),
+				0,
+				50,
+				b"12345-p1".to_vec()
+			),
 			TokenError::NotExpendable,
 		);
 
 		assert_noop!(
-			ChildBounties::add_child_bounty(RuntimeOrigin::signed(4), 0, 100, b"12345-p1".to_vec()),
+			ChildBounties::add_child_bounty(
+				RuntimeOrigin::signed(account_id(4)),
+				0,
+				100,
+				b"12345-p1".to_vec()
+			),
 			Error::<Test>::InsufficientBountyBalance,
 		);
 
 		// Add child-bounty with valid value, which can be funded by parent bounty.
 		assert_ok!(ChildBounties::add_child_bounty(
-			RuntimeOrigin::signed(4),
+			RuntimeOrigin::signed(account_id(4)),
 			0,
 			10,
 			b"12345-p1".to_vec()
@@ -249,8 +274,8 @@ fn add_child_bounty() {
 		// Check for the event child-bounty added.
 		assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 });
 
-		assert_eq!(Balances::free_balance(4), 101);
-		assert_eq!(Balances::reserved_balance(4), expected_deposit);
+		assert_eq!(Balances::free_balance(account_id(4)), 101);
+		assert_eq!(Balances::reserved_balance(account_id(4)), expected_deposit);
 
 		// DB check.
 		// Check the child-bounty status.
@@ -270,7 +295,7 @@ fn add_child_bounty() {
 
 		// Check the child-bounty description status.
 		assert_eq!(
-			pallet_child_bounties::ChildBountyDescriptions::<Test>::get(0).unwrap(),
+			pallet_child_bounties::ChildBountyDescriptionsV1::<Test>::get(0, 0).unwrap(),
 			b"12345-p1".to_vec(),
 		);
 	});
@@ -287,18 +312,22 @@ fn child_bounty_assign_curator() {
 		// Make the parent bounty.
 		go_to_block(1);
 		Balances::make_free_balance_be(&Treasury::account_id(), 101);
-		Balances::make_free_balance_be(&4, 101);
-		Balances::make_free_balance_be(&8, 101);
+		Balances::make_free_balance_be(&account_id(4), 101);
+		Balances::make_free_balance_be(&account_id(8), 101);
 
-		assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec()));
+		assert_ok!(Bounties::propose_bounty(
+			RuntimeOrigin::signed(account_id(0)),
+			50,
+			b"12345".to_vec()
+		));
 
 		assert_ok!(Bounties::approve_bounty(RuntimeOrigin::root(), 0));
 
 		go_to_block(2);
 
 		let fee = 4;
-		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 4, fee));
-		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(4), 0));
+		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, account_id(4), fee));
+		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(account_id(4)), 0));
 
 		// Bounty account status before adding child-bounty.
 		assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 50);
@@ -307,13 +336,13 @@ fn child_bounty_assign_curator() {
 		// Check the balance of parent curator.
 		// Curator deposit is reserved for parent curator on parent bounty.
 		let expected_deposit = Bounties::calculate_curator_deposit(&fee);
-		assert_eq!(Balances::free_balance(4), 101 - expected_deposit);
-		assert_eq!(Balances::reserved_balance(4), expected_deposit);
+		assert_eq!(Balances::free_balance(account_id(4)), 101 - expected_deposit);
+		assert_eq!(Balances::reserved_balance(account_id(4)), expected_deposit);
 
 		// Add child-bounty.
 		// Acc-4 is the parent curator & make sure enough deposit.
 		assert_ok!(ChildBounties::add_child_bounty(
-			RuntimeOrigin::signed(4),
+			RuntimeOrigin::signed(account_id(4)),
 			0,
 			10,
 			b"12345-p1".to_vec()
@@ -326,11 +355,17 @@ fn child_bounty_assign_curator() {
 		assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0);
 
 		// Child-bounty account status.
-		assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 10);
-		assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0);
+		assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0, 0)), 10);
+		assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0, 0)), 0);
 
 		let fee = 6u64;
-		assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 8, fee));
+		assert_ok!(ChildBounties::propose_curator(
+			RuntimeOrigin::signed(account_id(4)),
+			0,
+			0,
+			account_id(8),
+			fee
+		));
 
 		assert_eq!(
 			pallet_child_bounties::ChildBounties::<Test>::get(0, 0).unwrap(),
@@ -339,20 +374,20 @@ fn child_bounty_assign_curator() {
 				value: 10,
 				fee,
 				curator_deposit: 0,
-				status: ChildBountyStatus::CuratorProposed { curator: 8 },
+				status: ChildBountyStatus::CuratorProposed { curator: account_id(8) },
 			}
 		);
 
 		// Check the balance of parent curator.
-		assert_eq!(Balances::free_balance(4), 101 - expected_deposit);
-		assert_eq!(Balances::reserved_balance(4), expected_deposit);
+		assert_eq!(Balances::free_balance(account_id(4)), 101 - expected_deposit);
+		assert_eq!(Balances::reserved_balance(account_id(4)), expected_deposit);
 
 		assert_noop!(
-			ChildBounties::accept_curator(RuntimeOrigin::signed(3), 0, 0),
+			ChildBounties::accept_curator(RuntimeOrigin::signed(account_id(3)), 0, 0),
 			BountiesError::RequireCurator,
 		);
 
-		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(8), 0, 0));
+		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(account_id(8)), 0, 0));
 
 		let expected_child_deposit = CuratorDepositMultiplier::get() * fee;
 
@@ -363,21 +398,21 @@ fn child_bounty_assign_curator() {
 				value: 10,
 				fee,
 				curator_deposit: expected_child_deposit,
-				status: ChildBountyStatus::Active { curator: 8 },
+				status: ChildBountyStatus::Active { curator: account_id(8) },
 			}
 		);
 
 		// Deposit for child-bounty curator deposit is reserved.
-		assert_eq!(Balances::free_balance(8), 101 - expected_child_deposit);
-		assert_eq!(Balances::reserved_balance(8), expected_child_deposit);
+		assert_eq!(Balances::free_balance(account_id(8)), 101 - expected_child_deposit);
+		assert_eq!(Balances::reserved_balance(account_id(8)), expected_child_deposit);
 
 		// Bounty account status at exit.
 		assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 40);
 		assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0);
 
 		// Child-bounty account status at exit.
-		assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 10);
-		assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0);
+		assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0, 0)), 10);
+		assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0, 0)), 0);
 
 		// Treasury account status at exit.
 		assert_eq!(Balances::free_balance(Treasury::account_id()), 26);
@@ -395,21 +430,25 @@ fn award_claim_child_bounty() {
 		assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0);
 
 		// Bounty curator initial balance.
-		Balances::make_free_balance_be(&4, 101); // Parent-bounty curator.
-		Balances::make_free_balance_be(&8, 101); // Child-bounty curator.
+		Balances::make_free_balance_be(&account_id(4), 101); // Parent-bounty curator.
+		Balances::make_free_balance_be(&account_id(8), 101); // Child-bounty curator.
 
-		assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec()));
+		assert_ok!(Bounties::propose_bounty(
+			RuntimeOrigin::signed(account_id(0)),
+			50,
+			b"12345".to_vec()
+		));
 
 		assert_ok!(Bounties::approve_bounty(RuntimeOrigin::root(), 0));
 
 		go_to_block(2);
 
-		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 4, 6));
-		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(4), 0));
+		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, account_id(4), 6));
+		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(account_id(4)), 0));
 
 		// Child-bounty.
 		assert_ok!(ChildBounties::add_child_bounty(
-			RuntimeOrigin::signed(4),
+			RuntimeOrigin::signed(account_id(4)),
 			0,
 			10,
 			b"12345-p1".to_vec()
@@ -419,17 +458,33 @@ fn award_claim_child_bounty() {
 
 		// Propose and accept curator for child-bounty.
 		let fee = 8;
-		assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 8, fee));
-		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(8), 0, 0));
+		assert_ok!(ChildBounties::propose_curator(
+			RuntimeOrigin::signed(account_id(4)),
+			0,
+			0,
+			account_id(8),
+			fee
+		));
+		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(account_id(8)), 0, 0));
 
 		// Award child-bounty.
 		// Test for non child-bounty curator.
 		assert_noop!(
-			ChildBounties::award_child_bounty(RuntimeOrigin::signed(3), 0, 0, 7),
+			ChildBounties::award_child_bounty(
+				RuntimeOrigin::signed(account_id(3)),
+				0,
+				0,
+				account_id(7)
+			),
 			BountiesError::RequireCurator,
 		);
 
-		assert_ok!(ChildBounties::award_child_bounty(RuntimeOrigin::signed(8), 0, 0, 7));
+		assert_ok!(ChildBounties::award_child_bounty(
+			RuntimeOrigin::signed(account_id(8)),
+			0,
+			0,
+			account_id(7)
+		));
 
 		let expected_deposit = CuratorDepositMultiplier::get() * fee;
 		assert_eq!(
@@ -440,8 +495,8 @@ fn award_claim_child_bounty() {
 				fee,
 				curator_deposit: expected_deposit,
 				status: ChildBountyStatus::PendingPayout {
-					curator: 8,
-					beneficiary: 7,
+					curator: account_id(8),
+					beneficiary: account_id(7),
 					unlock_at: 5
 				},
 			}
@@ -450,25 +505,25 @@ fn award_claim_child_bounty() {
 		// Claim child-bounty.
 		// Test for Premature condition.
 		assert_noop!(
-			ChildBounties::claim_child_bounty(RuntimeOrigin::signed(7), 0, 0),
+			ChildBounties::claim_child_bounty(RuntimeOrigin::signed(account_id(7)), 0, 0),
 			BountiesError::Premature
 		);
 
 		go_to_block(9);
 
-		assert_ok!(ChildBounties::claim_child_bounty(RuntimeOrigin::signed(7), 0, 0));
+		assert_ok!(ChildBounties::claim_child_bounty(RuntimeOrigin::signed(account_id(7)), 0, 0));
 
 		// Ensure child-bounty curator is paid with curator fee & deposit refund.
-		assert_eq!(Balances::free_balance(8), 101 + fee);
-		assert_eq!(Balances::reserved_balance(8), 0);
+		assert_eq!(Balances::free_balance(account_id(8)), 101 + fee);
+		assert_eq!(Balances::reserved_balance(account_id(8)), 0);
 
 		// Ensure executor is paid with beneficiary amount.
-		assert_eq!(Balances::free_balance(7), 10 - fee);
-		assert_eq!(Balances::reserved_balance(7), 0);
+		assert_eq!(Balances::free_balance(account_id(7)), 10 - fee);
+		assert_eq!(Balances::reserved_balance(account_id(7)), 0);
 
 		// Child-bounty account status.
-		assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 0);
-		assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0);
+		assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0, 0)), 0);
+		assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0, 0)), 0);
 
 		// Check the child-bounty count.
 		assert_eq!(pallet_child_bounties::ParentChildBounties::<Test>::get(0), 0);
@@ -485,22 +540,26 @@ fn close_child_bounty_added() {
 		assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0);
 
 		// Bounty curator initial balance.
-		Balances::make_free_balance_be(&4, 101); // Parent-bounty curator.
-		Balances::make_free_balance_be(&8, 101); // Child-bounty curator.
+		Balances::make_free_balance_be(&account_id(4), 101); // Parent-bounty curator.
+		Balances::make_free_balance_be(&account_id(8), 101); // Child-bounty curator.
 
-		assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec()));
+		assert_ok!(Bounties::propose_bounty(
+			RuntimeOrigin::signed(account_id(0)),
+			50,
+			b"12345".to_vec()
+		));
 
 		assert_ok!(Bounties::approve_bounty(RuntimeOrigin::root(), 0));
 
 		go_to_block(2);
 
-		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 4, 6));
+		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, account_id(4), 6));
 
-		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(4), 0));
+		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(account_id(4)), 0));
 
 		// Child-bounty.
 		assert_ok!(ChildBounties::add_child_bounty(
-			RuntimeOrigin::signed(4),
+			RuntimeOrigin::signed(account_id(4)),
 			0,
 			10,
 			b"12345-p1".to_vec()
@@ -512,11 +571,17 @@ fn close_child_bounty_added() {
 
 		// Close child-bounty.
 		// Wrong origin.
-		assert_noop!(ChildBounties::close_child_bounty(RuntimeOrigin::signed(7), 0, 0), BadOrigin);
-		assert_noop!(ChildBounties::close_child_bounty(RuntimeOrigin::signed(8), 0, 0), BadOrigin);
+		assert_noop!(
+			ChildBounties::close_child_bounty(RuntimeOrigin::signed(account_id(7)), 0, 0),
+			BadOrigin
+		);
+		assert_noop!(
+			ChildBounties::close_child_bounty(RuntimeOrigin::signed(account_id(8)), 0, 0),
+			BadOrigin
+		);
 
 		// Correct origin - parent curator.
-		assert_ok!(ChildBounties::close_child_bounty(RuntimeOrigin::signed(4), 0, 0));
+		assert_ok!(ChildBounties::close_child_bounty(RuntimeOrigin::signed(account_id(4)), 0, 0));
 
 		// Check the child-bounty count.
 		assert_eq!(pallet_child_bounties::ParentChildBounties::<Test>::get(0), 0);
@@ -526,8 +591,8 @@ fn close_child_bounty_added() {
 		assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0);
 
 		// Child-bounty account status.
-		assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 0);
-		assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0);
+		assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0, 0)), 0);
+		assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0, 0)), 0);
 	});
 }
 
@@ -541,22 +606,26 @@ fn close_child_bounty_active() {
 		assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0);
 
 		// Bounty curator initial balance.
-		Balances::make_free_balance_be(&4, 101); // Parent-bounty curator.
-		Balances::make_free_balance_be(&8, 101); // Child-bounty curator.
+		Balances::make_free_balance_be(&account_id(4), 101); // Parent-bounty curator.
+		Balances::make_free_balance_be(&account_id(8), 101); // Child-bounty curator.
 
-		assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec()));
+		assert_ok!(Bounties::propose_bounty(
+			RuntimeOrigin::signed(account_id(0)),
+			50,
+			b"12345".to_vec()
+		));
 
 		assert_ok!(Bounties::approve_bounty(RuntimeOrigin::root(), 0));
 
 		go_to_block(2);
 
-		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 4, 6));
+		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, account_id(4), 6));
 
-		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(4), 0));
+		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(account_id(4)), 0));
 
 		// Child-bounty.
 		assert_ok!(ChildBounties::add_child_bounty(
-			RuntimeOrigin::signed(4),
+			RuntimeOrigin::signed(account_id(4)),
 			0,
 			10,
 			b"12345-p1".to_vec()
@@ -565,26 +634,32 @@ fn close_child_bounty_active() {
 		assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 });
 
 		// Propose and accept curator for child-bounty.
-		assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 8, 2));
-		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(8), 0, 0));
+		assert_ok!(ChildBounties::propose_curator(
+			RuntimeOrigin::signed(account_id(4)),
+			0,
+			0,
+			account_id(8),
+			2
+		));
+		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(account_id(8)), 0, 0));
 
 		// Close child-bounty in active state.
-		assert_ok!(ChildBounties::close_child_bounty(RuntimeOrigin::signed(4), 0, 0));
+		assert_ok!(ChildBounties::close_child_bounty(RuntimeOrigin::signed(account_id(4)), 0, 0));
 
 		// Check the child-bounty count.
 		assert_eq!(pallet_child_bounties::ParentChildBounties::<Test>::get(0), 0);
 
 		// Ensure child-bounty curator balance is unreserved.
-		assert_eq!(Balances::free_balance(8), 101);
-		assert_eq!(Balances::reserved_balance(8), 0);
+		assert_eq!(Balances::free_balance(account_id(8)), 101);
+		assert_eq!(Balances::reserved_balance(account_id(8)), 0);
 
 		// Parent-bounty account status.
 		assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 50);
 		assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0);
 
 		// Child-bounty account status.
-		assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 0);
-		assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0);
+		assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0, 0)), 0);
+		assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0, 0)), 0);
 	});
 }
 
@@ -598,22 +673,26 @@ fn close_child_bounty_pending() {
 		assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0);
 
 		// Bounty curator initial balance.
-		Balances::make_free_balance_be(&4, 101); // Parent-bounty curator.
-		Balances::make_free_balance_be(&8, 101); // Child-bounty curator.
+		Balances::make_free_balance_be(&account_id(4), 101); // Parent-bounty curator.
+		Balances::make_free_balance_be(&account_id(8), 101); // Child-bounty curator.
 
-		assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec()));
+		assert_ok!(Bounties::propose_bounty(
+			RuntimeOrigin::signed(account_id(0)),
+			50,
+			b"12345".to_vec()
+		));
 
 		assert_ok!(Bounties::approve_bounty(RuntimeOrigin::root(), 0));
 
 		go_to_block(2);
 
 		let parent_fee = 6;
-		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 4, parent_fee));
-		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(4), 0));
+		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, account_id(4), parent_fee));
+		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(account_id(4)), 0));
 
 		// Child-bounty.
 		assert_ok!(ChildBounties::add_child_bounty(
-			RuntimeOrigin::signed(4),
+			RuntimeOrigin::signed(account_id(4)),
 			0,
 			10,
 			b"12345-p1".to_vec()
@@ -623,15 +702,26 @@ fn close_child_bounty_pending() {
 
 		// Propose and accept curator for child-bounty.
 		let child_fee = 4;
-		assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 8, child_fee));
-		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(8), 0, 0));
+		assert_ok!(ChildBounties::propose_curator(
+			RuntimeOrigin::signed(account_id(4)),
+			0,
+			0,
+			account_id(8),
+			child_fee
+		));
+		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(account_id(8)), 0, 0));
 		let expected_child_deposit = CuratorDepositMin::get();
 
-		assert_ok!(ChildBounties::award_child_bounty(RuntimeOrigin::signed(8), 0, 0, 7));
+		assert_ok!(ChildBounties::award_child_bounty(
+			RuntimeOrigin::signed(account_id(8)),
+			0,
+			0,
+			account_id(7)
+		));
 
 		// Close child-bounty in pending_payout state.
 		assert_noop!(
-			ChildBounties::close_child_bounty(RuntimeOrigin::signed(4), 0, 0),
+			ChildBounties::close_child_bounty(RuntimeOrigin::signed(account_id(4)), 0, 0),
 			BountiesError::PendingPayout
 		);
 
@@ -639,12 +729,12 @@ fn close_child_bounty_pending() {
 		assert_eq!(pallet_child_bounties::ParentChildBounties::<Test>::get(0), 1);
 
 		// Ensure no changes in child-bounty curator balance.
-		assert_eq!(Balances::reserved_balance(8), expected_child_deposit);
-		assert_eq!(Balances::free_balance(8), 101 - expected_child_deposit);
+		assert_eq!(Balances::reserved_balance(account_id(8)), expected_child_deposit);
+		assert_eq!(Balances::free_balance(account_id(8)), 101 - expected_child_deposit);
 
 		// Child-bounty account status.
-		assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 10);
-		assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0);
+		assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0, 0)), 10);
+		assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0, 0)), 0);
 	});
 }
 
@@ -658,22 +748,26 @@ fn child_bounty_added_unassign_curator() {
 		assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0);
 
 		// Bounty curator initial balance.
-		Balances::make_free_balance_be(&4, 101); // Parent-bounty curator.
-		Balances::make_free_balance_be(&8, 101); // Child-bounty curator.
+		Balances::make_free_balance_be(&account_id(4), 101); // Parent-bounty curator.
+		Balances::make_free_balance_be(&account_id(8), 101); // Child-bounty curator.
 
-		assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec()));
+		assert_ok!(Bounties::propose_bounty(
+			RuntimeOrigin::signed(account_id(0)),
+			50,
+			b"12345".to_vec()
+		));
 
 		assert_ok!(Bounties::approve_bounty(RuntimeOrigin::root(), 0));
 
 		go_to_block(2);
 
-		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 4, 6));
+		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, account_id(4), 6));
 
-		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(4), 0));
+		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(account_id(4)), 0));
 
 		// Child-bounty.
 		assert_ok!(ChildBounties::add_child_bounty(
-			RuntimeOrigin::signed(4),
+			RuntimeOrigin::signed(account_id(4)),
 			0,
 			10,
 			b"12345-p1".to_vec()
@@ -683,7 +777,7 @@ fn child_bounty_added_unassign_curator() {
 
 		// Unassign curator in added state.
 		assert_noop!(
-			ChildBounties::unassign_curator(RuntimeOrigin::signed(4), 0, 0),
+			ChildBounties::unassign_curator(RuntimeOrigin::signed(account_id(4)), 0, 0),
 			BountiesError::UnexpectedStatus
 		);
 	});
@@ -699,22 +793,26 @@ fn child_bounty_curator_proposed_unassign_curator() {
 		assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0);
 
 		// Bounty curator initial balance.
-		Balances::make_free_balance_be(&4, 101); // Parent-bounty curator.
-		Balances::make_free_balance_be(&8, 101); // Child-bounty curator.
+		Balances::make_free_balance_be(&account_id(4), 101); // Parent-bounty curator.
+		Balances::make_free_balance_be(&account_id(8), 101); // Child-bounty curator.
 
-		assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec()));
+		assert_ok!(Bounties::propose_bounty(
+			RuntimeOrigin::signed(account_id(0)),
+			50,
+			b"12345".to_vec()
+		));
 
 		assert_ok!(Bounties::approve_bounty(RuntimeOrigin::root(), 0));
 
 		go_to_block(2);
 
-		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 4, 6));
+		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, account_id(4), 6));
 
-		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(4), 0));
+		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(account_id(4)), 0));
 
 		// Child-bounty.
 		assert_ok!(ChildBounties::add_child_bounty(
-			RuntimeOrigin::signed(4),
+			RuntimeOrigin::signed(account_id(4)),
 			0,
 			10,
 			b"12345-p1".to_vec()
@@ -723,7 +821,13 @@ fn child_bounty_curator_proposed_unassign_curator() {
 		assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 });
 
 		// Propose curator for child-bounty.
-		assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 8, 2));
+		assert_ok!(ChildBounties::propose_curator(
+			RuntimeOrigin::signed(account_id(4)),
+			0,
+			0,
+			account_id(8),
+			2
+		));
 
 		assert_eq!(
 			pallet_child_bounties::ChildBounties::<Test>::get(0, 0).unwrap(),
@@ -732,15 +836,18 @@ fn child_bounty_curator_proposed_unassign_curator() {
 				value: 10,
 				fee: 2,
 				curator_deposit: 0,
-				status: ChildBountyStatus::CuratorProposed { curator: 8 },
+				status: ChildBountyStatus::CuratorProposed { curator: account_id(8) },
 			}
 		);
 
 		// Random account cannot unassign the curator when in proposed state.
-		assert_noop!(ChildBounties::unassign_curator(RuntimeOrigin::signed(99), 0, 0), BadOrigin);
+		assert_noop!(
+			ChildBounties::unassign_curator(RuntimeOrigin::signed(account_id(99)), 0, 0),
+			BadOrigin
+		);
 
 		// Unassign curator.
-		assert_ok!(ChildBounties::unassign_curator(RuntimeOrigin::signed(4), 0, 0));
+		assert_ok!(ChildBounties::unassign_curator(RuntimeOrigin::signed(account_id(4)), 0, 0));
 
 		// Verify updated child-bounty status.
 		assert_eq!(
@@ -773,23 +880,27 @@ fn child_bounty_active_unassign_curator() {
 		assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0);
 
 		// Bounty curator initial balance.
-		Balances::make_free_balance_be(&4, 101); // Parent-bounty curator.
-		Balances::make_free_balance_be(&6, 101); // Child-bounty curator 1.
-		Balances::make_free_balance_be(&7, 101); // Child-bounty curator 2.
-		Balances::make_free_balance_be(&8, 101); // Child-bounty curator 3.
+		Balances::make_free_balance_be(&account_id(4), 101); // Parent-bounty curator.
+		Balances::make_free_balance_be(&account_id(6), 101); // Child-bounty curator 1.
+		Balances::make_free_balance_be(&account_id(7), 101); // Child-bounty curator 2.
+		Balances::make_free_balance_be(&account_id(8), 101); // Child-bounty curator 3.
 
-		assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec()));
+		assert_ok!(Bounties::propose_bounty(
+			RuntimeOrigin::signed(account_id(0)),
+			50,
+			b"12345".to_vec()
+		));
 
 		assert_ok!(Bounties::approve_bounty(RuntimeOrigin::root(), 0));
 
 		go_to_block(2);
 
-		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 4, 6));
-		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(4), 0));
+		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, account_id(4), 6));
+		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(account_id(4)), 0));
 
 		// Create Child-bounty.
 		assert_ok!(ChildBounties::add_child_bounty(
-			RuntimeOrigin::signed(4),
+			RuntimeOrigin::signed(account_id(4)),
 			0,
 			10,
 			b"12345-p1".to_vec()
@@ -800,8 +911,14 @@ fn child_bounty_active_unassign_curator() {
 
 		// Propose and accept curator for child-bounty.
 		let fee = 6;
-		assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 8, fee));
-		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(8), 0, 0));
+		assert_ok!(ChildBounties::propose_curator(
+			RuntimeOrigin::signed(account_id(4)),
+			0,
+			0,
+			account_id(8),
+			fee
+		));
+		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(account_id(8)), 0, 0));
 		let expected_child_deposit = CuratorDepositMultiplier::get() * fee;
 
 		assert_eq!(
@@ -811,7 +928,7 @@ fn child_bounty_active_unassign_curator() {
 				value: 10,
 				fee,
 				curator_deposit: expected_child_deposit,
-				status: ChildBountyStatus::Active { curator: 8 },
+				status: ChildBountyStatus::Active { curator: account_id(8) },
 			}
 		);
 
@@ -833,13 +950,19 @@ fn child_bounty_active_unassign_curator() {
 		);
 
 		// Ensure child-bounty curator was slashed.
-		assert_eq!(Balances::free_balance(8), 101 - expected_child_deposit);
-		assert_eq!(Balances::reserved_balance(8), 0); // slashed
+		assert_eq!(Balances::free_balance(account_id(8)), 101 - expected_child_deposit);
+		assert_eq!(Balances::reserved_balance(account_id(8)), 0); // slashed
 
 		// Propose and accept curator for child-bounty again.
 		let fee = 2;
-		assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 7, fee));
-		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(7), 0, 0));
+		assert_ok!(ChildBounties::propose_curator(
+			RuntimeOrigin::signed(account_id(4)),
+			0,
+			0,
+			account_id(7),
+			fee
+		));
+		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(account_id(7)), 0, 0));
 		let expected_child_deposit = CuratorDepositMin::get();
 
 		assert_eq!(
@@ -849,14 +972,14 @@ fn child_bounty_active_unassign_curator() {
 				value: 10,
 				fee,
 				curator_deposit: expected_child_deposit,
-				status: ChildBountyStatus::Active { curator: 7 },
+				status: ChildBountyStatus::Active { curator: account_id(7) },
 			}
 		);
 
 		go_to_block(5);
 
 		// Unassign curator again - from parent curator.
-		assert_ok!(ChildBounties::unassign_curator(RuntimeOrigin::signed(4), 0, 0));
+		assert_ok!(ChildBounties::unassign_curator(RuntimeOrigin::signed(account_id(4)), 0, 0));
 
 		// Verify updated child-bounty status.
 		assert_eq!(
@@ -871,12 +994,18 @@ fn child_bounty_active_unassign_curator() {
 		);
 
 		// Ensure child-bounty curator was slashed.
-		assert_eq!(Balances::free_balance(7), 101 - expected_child_deposit);
-		assert_eq!(Balances::reserved_balance(7), 0); // slashed
+		assert_eq!(Balances::free_balance(account_id(7)), 101 - expected_child_deposit);
+		assert_eq!(Balances::reserved_balance(account_id(7)), 0); // slashed
 
 		// Propose and accept curator for child-bounty again.
-		assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 6, 2));
-		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(6), 0, 0));
+		assert_ok!(ChildBounties::propose_curator(
+			RuntimeOrigin::signed(account_id(4)),
+			0,
+			0,
+			account_id(6),
+			2
+		));
+		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(account_id(6)), 0, 0));
 
 		assert_eq!(
 			pallet_child_bounties::ChildBounties::<Test>::get(0, 0).unwrap(),
@@ -885,14 +1014,14 @@ fn child_bounty_active_unassign_curator() {
 				value: 10,
 				fee,
 				curator_deposit: expected_child_deposit,
-				status: ChildBountyStatus::Active { curator: 6 },
+				status: ChildBountyStatus::Active { curator: account_id(6) },
 			}
 		);
 
 		go_to_block(6);
 
 		// Unassign curator again - from child-bounty curator.
-		assert_ok!(ChildBounties::unassign_curator(RuntimeOrigin::signed(6), 0, 0));
+		assert_ok!(ChildBounties::unassign_curator(RuntimeOrigin::signed(account_id(6)), 0, 0));
 
 		// Verify updated child-bounty status.
 		assert_eq!(
@@ -907,13 +1036,19 @@ fn child_bounty_active_unassign_curator() {
 		);
 
 		// Ensure child-bounty curator was **not** slashed.
-		assert_eq!(Balances::free_balance(6), 101); // not slashed
-		assert_eq!(Balances::reserved_balance(6), 0);
+		assert_eq!(Balances::free_balance(account_id(6)), 101); // not slashed
+		assert_eq!(Balances::reserved_balance(account_id(6)), 0);
 
 		// Propose and accept curator for child-bounty one last time.
 		let fee = 2;
-		assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 6, fee));
-		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(6), 0, 0));
+		assert_ok!(ChildBounties::propose_curator(
+			RuntimeOrigin::signed(account_id(4)),
+			0,
+			0,
+			account_id(6),
+			fee
+		));
+		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(account_id(6)), 0, 0));
 		let expected_child_deposit = CuratorDepositMin::get();
 
 		assert_eq!(
@@ -923,7 +1058,7 @@ fn child_bounty_active_unassign_curator() {
 				value: 10,
 				fee,
 				curator_deposit: expected_child_deposit,
-				status: ChildBountyStatus::Active { curator: 6 },
+				status: ChildBountyStatus::Active { curator: account_id(6) },
 			}
 		);
 
@@ -932,14 +1067,14 @@ fn child_bounty_active_unassign_curator() {
 		// Unassign curator again - from non curator; non reject origin; some random guy.
 		// Bounty update period is not yet complete.
 		assert_noop!(
-			ChildBounties::unassign_curator(RuntimeOrigin::signed(3), 0, 0),
+			ChildBounties::unassign_curator(RuntimeOrigin::signed(account_id(3)), 0, 0),
 			BountiesError::Premature
 		);
 
 		go_to_block(20);
 
 		// Unassign child curator from random account after inactivity.
-		assert_ok!(ChildBounties::unassign_curator(RuntimeOrigin::signed(3), 0, 0));
+		assert_ok!(ChildBounties::unassign_curator(RuntimeOrigin::signed(account_id(3)), 0, 0));
 
 		// Verify updated child-bounty status.
 		assert_eq!(
@@ -954,8 +1089,8 @@ fn child_bounty_active_unassign_curator() {
 		);
 
 		// Ensure child-bounty curator was slashed.
-		assert_eq!(Balances::free_balance(6), 101 - expected_child_deposit); // slashed
-		assert_eq!(Balances::reserved_balance(6), 0);
+		assert_eq!(Balances::free_balance(account_id(6)), 101 - expected_child_deposit); // slashed
+		assert_eq!(Balances::reserved_balance(account_id(6)), 0);
 	});
 }
 
@@ -971,23 +1106,27 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() {
 		assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0);
 
 		// Bounty curator initial balance.
-		Balances::make_free_balance_be(&4, 101); // Parent-bounty curator 1.
-		Balances::make_free_balance_be(&5, 101); // Parent-bounty curator 2.
-		Balances::make_free_balance_be(&6, 101); // Child-bounty curator 1.
-		Balances::make_free_balance_be(&7, 101); // Child-bounty curator 2.
-		Balances::make_free_balance_be(&8, 101); // Child-bounty curator 3.
+		Balances::make_free_balance_be(&account_id(4), 101); // Parent-bounty curator 1.
+		Balances::make_free_balance_be(&account_id(5), 101); // Parent-bounty curator 2.
+		Balances::make_free_balance_be(&account_id(6), 101); // Child-bounty curator 1.
+		Balances::make_free_balance_be(&account_id(7), 101); // Child-bounty curator 2.
+		Balances::make_free_balance_be(&account_id(8), 101); // Child-bounty curator 3.
 
-		assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec()));
+		assert_ok!(Bounties::propose_bounty(
+			RuntimeOrigin::signed(account_id(0)),
+			50,
+			b"12345".to_vec()
+		));
 		assert_ok!(Bounties::approve_bounty(RuntimeOrigin::root(), 0));
 
 		go_to_block(2);
 
-		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 4, 6));
-		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(4), 0));
+		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, account_id(4), 6));
+		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(account_id(4)), 0));
 
 		// Create Child-bounty.
 		assert_ok!(ChildBounties::add_child_bounty(
-			RuntimeOrigin::signed(4),
+			RuntimeOrigin::signed(account_id(4)),
 			0,
 			10,
 			b"12345-p1".to_vec()
@@ -998,8 +1137,14 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() {
 
 		// Propose and accept curator for child-bounty.
 		let fee = 8;
-		assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 8, fee));
-		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(8), 0, 0));
+		assert_ok!(ChildBounties::propose_curator(
+			RuntimeOrigin::signed(account_id(4)),
+			0,
+			0,
+			account_id(8),
+			fee
+		));
+		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(account_id(8)), 0, 0));
 		let expected_child_deposit = CuratorDepositMultiplier::get() * fee;
 
 		assert_eq!(
@@ -1009,7 +1154,7 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() {
 				value: 10,
 				fee,
 				curator_deposit: expected_child_deposit,
-				status: ChildBountyStatus::Active { curator: 8 },
+				status: ChildBountyStatus::Active { curator: account_id(8) },
 			}
 		);
 
@@ -1023,7 +1168,7 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() {
 		// Try unassign child-bounty curator - from non curator; non reject
 		// origin; some random guy. Bounty update period is not yet complete.
 		assert_noop!(
-			ChildBounties::unassign_curator(RuntimeOrigin::signed(3), 0, 0),
+			ChildBounties::unassign_curator(RuntimeOrigin::signed(account_id(3)), 0, 0),
 			Error::<Test>::ParentBountyNotActive
 		);
 
@@ -1043,21 +1188,27 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() {
 		);
 
 		// Ensure child-bounty curator was slashed.
-		assert_eq!(Balances::free_balance(8), 101 - expected_child_deposit);
-		assert_eq!(Balances::reserved_balance(8), 0); // slashed
+		assert_eq!(Balances::free_balance(account_id(8)), 101 - expected_child_deposit);
+		assert_eq!(Balances::reserved_balance(account_id(8)), 0); // slashed
 
 		go_to_block(6);
 
 		// Propose and accept curator for parent-bounty again.
-		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 5, 6));
-		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(5), 0));
+		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, account_id(5), 6));
+		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(account_id(5)), 0));
 
 		go_to_block(7);
 
 		// Propose and accept curator for child-bounty again.
 		let fee = 2;
-		assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(5), 0, 0, 7, fee));
-		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(7), 0, 0));
+		assert_ok!(ChildBounties::propose_curator(
+			RuntimeOrigin::signed(account_id(5)),
+			0,
+			0,
+			account_id(7),
+			fee
+		));
+		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(account_id(7)), 0, 0));
 		let expected_deposit = CuratorDepositMin::get();
 
 		assert_eq!(
@@ -1067,24 +1218,24 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() {
 				value: 10,
 				fee,
 				curator_deposit: expected_deposit,
-				status: ChildBountyStatus::Active { curator: 7 },
+				status: ChildBountyStatus::Active { curator: account_id(7) },
 			}
 		);
 
 		go_to_block(8);
 
 		assert_noop!(
-			ChildBounties::unassign_curator(RuntimeOrigin::signed(3), 0, 0),
+			ChildBounties::unassign_curator(RuntimeOrigin::signed(account_id(3)), 0, 0),
 			BountiesError::Premature
 		);
 
 		// Unassign parent bounty curator again.
-		assert_ok!(Bounties::unassign_curator(RuntimeOrigin::signed(5), 0));
+		assert_ok!(Bounties::unassign_curator(RuntimeOrigin::signed(account_id(5)), 0));
 
 		go_to_block(9);
 
 		// Unassign curator again - from parent curator.
-		assert_ok!(ChildBounties::unassign_curator(RuntimeOrigin::signed(7), 0, 0));
+		assert_ok!(ChildBounties::unassign_curator(RuntimeOrigin::signed(account_id(7)), 0, 0));
 
 		// Verify updated child-bounty status.
 		assert_eq!(
@@ -1099,8 +1250,8 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() {
 		);
 
 		// Ensure child-bounty curator was not slashed.
-		assert_eq!(Balances::free_balance(7), 101);
-		assert_eq!(Balances::reserved_balance(7), 0); // slashed
+		assert_eq!(Balances::free_balance(account_id(7)), 101);
+		assert_eq!(Balances::reserved_balance(account_id(7)), 0); // slashed
 	});
 }
 
@@ -1114,27 +1265,36 @@ fn close_parent_with_child_bounty() {
 		assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0);
 
 		// Bounty curator initial balance.
-		Balances::make_free_balance_be(&4, 101); // Parent-bounty curator.
-		Balances::make_free_balance_be(&8, 101); // Child-bounty curator.
+		Balances::make_free_balance_be(&account_id(4), 101); // Parent-bounty curator.
+		Balances::make_free_balance_be(&account_id(8), 101); // Child-bounty curator.
 
-		assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec()));
+		assert_ok!(Bounties::propose_bounty(
+			RuntimeOrigin::signed(account_id(0)),
+			50,
+			b"12345".to_vec()
+		));
 		assert_ok!(Bounties::approve_bounty(RuntimeOrigin::root(), 0));
 
 		// Try add child-bounty.
 		// Should fail, parent bounty not active yet.
 		assert_noop!(
-			ChildBounties::add_child_bounty(RuntimeOrigin::signed(4), 0, 10, b"12345-p1".to_vec()),
+			ChildBounties::add_child_bounty(
+				RuntimeOrigin::signed(account_id(4)),
+				0,
+				10,
+				b"12345-p1".to_vec()
+			),
 			Error::<Test>::ParentBountyNotActive
 		);
 
 		go_to_block(2);
 
-		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 4, 6));
-		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(4), 0));
+		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, account_id(4), 6));
+		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(account_id(4)), 0));
 
 		// Child-bounty.
 		assert_ok!(ChildBounties::add_child_bounty(
-			RuntimeOrigin::signed(4),
+			RuntimeOrigin::signed(account_id(4)),
 			0,
 			10,
 			b"12345-p1".to_vec()
@@ -1155,10 +1315,14 @@ fn close_parent_with_child_bounty() {
 
 		// Check the child-bounty count.
 		assert_eq!(pallet_child_bounties::ParentChildBounties::<Test>::get(0), 0);
+		assert_eq!(pallet_child_bounties::ParentTotalChildBounties::<Test>::get(0), 1);
 
 		// Try close parent-bounty again.
 		// Should pass this time.
 		assert_ok!(Bounties::close_bounty(RuntimeOrigin::root(), 0));
+
+		// Check the total count is removed after the parent bounty removal.
+		assert_eq!(pallet_child_bounties::ParentTotalChildBounties::<Test>::get(0), 0);
 	});
 }
 
@@ -1174,20 +1338,24 @@ fn children_curator_fee_calculation_test() {
 		assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0);
 
 		// Bounty curator initial balance.
-		Balances::make_free_balance_be(&4, 101); // Parent-bounty curator.
-		Balances::make_free_balance_be(&8, 101); // Child-bounty curator.
+		Balances::make_free_balance_be(&account_id(4), 101); // Parent-bounty curator.
+		Balances::make_free_balance_be(&account_id(8), 101); // Child-bounty curator.
 
-		assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec()));
+		assert_ok!(Bounties::propose_bounty(
+			RuntimeOrigin::signed(account_id(0)),
+			50,
+			b"12345".to_vec()
+		));
 		assert_ok!(Bounties::approve_bounty(RuntimeOrigin::root(), 0));
 
 		go_to_block(2);
 
-		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, 4, 6));
-		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(4), 0));
+		assert_ok!(Bounties::propose_curator(RuntimeOrigin::root(), 0, account_id(4), 6));
+		assert_ok!(Bounties::accept_curator(RuntimeOrigin::signed(account_id(4)), 0));
 
 		// Child-bounty.
 		assert_ok!(ChildBounties::add_child_bounty(
-			RuntimeOrigin::signed(4),
+			RuntimeOrigin::signed(account_id(4)),
 			0,
 			10,
 			b"12345-p1".to_vec()
@@ -1199,13 +1367,24 @@ fn children_curator_fee_calculation_test() {
 		let fee = 6;
 
 		// Propose curator for child-bounty.
-		assert_ok!(ChildBounties::propose_curator(RuntimeOrigin::signed(4), 0, 0, 8, fee));
+		assert_ok!(ChildBounties::propose_curator(
+			RuntimeOrigin::signed(account_id(4)),
+			0,
+			0,
+			account_id(8),
+			fee
+		));
 		// Check curator fee added to the sum.
 		assert_eq!(pallet_child_bounties::ChildrenCuratorFees::<Test>::get(0), fee);
 		// Accept curator for child-bounty.
-		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(8), 0, 0));
+		assert_ok!(ChildBounties::accept_curator(RuntimeOrigin::signed(account_id(8)), 0, 0));
 		// Award child-bounty.
-		assert_ok!(ChildBounties::award_child_bounty(RuntimeOrigin::signed(8), 0, 0, 7));
+		assert_ok!(ChildBounties::award_child_bounty(
+			RuntimeOrigin::signed(account_id(8)),
+			0,
+			0,
+			account_id(7)
+		));
 
 		let expected_child_deposit = CuratorDepositMultiplier::get() * fee;
 
@@ -1217,8 +1396,8 @@ fn children_curator_fee_calculation_test() {
 				fee,
 				curator_deposit: expected_child_deposit,
 				status: ChildBountyStatus::PendingPayout {
-					curator: 8,
-					beneficiary: 7,
+					curator: account_id(8),
+					beneficiary: account_id(7),
 					unlock_at: 7
 				},
 			}
@@ -1227,26 +1406,32 @@ fn children_curator_fee_calculation_test() {
 		go_to_block(9);
 
 		// Claim child-bounty.
-		assert_ok!(ChildBounties::claim_child_bounty(RuntimeOrigin::signed(7), 0, 0));
+		assert_ok!(ChildBounties::claim_child_bounty(RuntimeOrigin::signed(account_id(7)), 0, 0));
 
 		// Check the child-bounty count.
 		assert_eq!(pallet_child_bounties::ParentChildBounties::<Test>::get(0), 0);
 
 		// Award the parent bounty.
-		assert_ok!(Bounties::award_bounty(RuntimeOrigin::signed(4), 0, 9));
+		assert_ok!(Bounties::award_bounty(RuntimeOrigin::signed(account_id(4)), 0, account_id(9)));
 
 		go_to_block(15);
 
+		// Check the total count.
+		assert_eq!(pallet_child_bounties::ParentTotalChildBounties::<Test>::get(0), 1);
+
 		// Claim the parent bounty.
-		assert_ok!(Bounties::claim_bounty(RuntimeOrigin::signed(9), 0));
+		assert_ok!(Bounties::claim_bounty(RuntimeOrigin::signed(account_id(9)), 0));
+
+		// Check the total count after the parent bounty removal.
+		assert_eq!(pallet_child_bounties::ParentTotalChildBounties::<Test>::get(0), 0);
 
 		// Ensure parent-bounty curator received correctly reduced fee.
-		assert_eq!(Balances::free_balance(4), 101 + 6 - fee); // 101 + 6 - 2
-		assert_eq!(Balances::reserved_balance(4), 0);
+		assert_eq!(Balances::free_balance(account_id(4)), 101 + 6 - fee); // 101 + 6 - 2
+		assert_eq!(Balances::reserved_balance(account_id(4)), 0);
 
 		// Verify parent-bounty beneficiary balance.
-		assert_eq!(Balances::free_balance(9), 34);
-		assert_eq!(Balances::reserved_balance(9), 0);
+		assert_eq!(Balances::free_balance(account_id(9)), 34);
+		assert_eq!(Balances::reserved_balance(account_id(9)), 0);
 	});
 }
 
@@ -1256,7 +1441,7 @@ fn accept_curator_handles_different_deposit_calculations() {
 	// in a different curator deposit, and if the child curator matches the parent curator.
 	new_test_ext().execute_with(|| {
 		// Setup a parent bounty.
-		let parent_curator = 0;
+		let parent_curator = account_id(0);
 		let parent_index = 0;
 		let parent_value = 1_000_000;
 		let parent_fee = 10_000;
@@ -1285,7 +1470,7 @@ fn accept_curator_handles_different_deposit_calculations() {
 		// Case 1: Parent and child curator are not the same.
 
 		let child_index = 0;
-		let child_curator = 1;
+		let child_curator = account_id(1);
 		let child_value = 1_000;
 		let child_fee = 100;
 		let starting_balance = 100 * child_fee + child_value;
@@ -1352,7 +1537,7 @@ fn accept_curator_handles_different_deposit_calculations() {
 		// Case 3: Upper Limit
 
 		let child_index = 2;
-		let child_curator = 2;
+		let child_curator = account_id(2);
 		let child_value = 10_000;
 		let child_fee = 5_000;
 
@@ -1387,7 +1572,7 @@ fn accept_curator_handles_different_deposit_calculations() {
 		// Case 4: Lower Limit
 
 		let child_index = 3;
-		let child_curator = 3;
+		let child_curator = account_id(3);
 		let child_value = 10_000;
 		let child_fee = 0;
 
@@ -1417,3 +1602,10 @@ fn accept_curator_handles_different_deposit_calculations() {
 		assert_eq!(Balances::reserved_balance(child_curator), expected_deposit);
 	});
 }
+
+#[test]
+fn integrity_test() {
+	new_test_ext().execute_with(|| {
+		ChildBounties::integrity_test();
+	});
+}
diff --git a/substrate/primitives/core/src/crypto.rs b/substrate/primitives/core/src/crypto.rs
index b04d94e2bf4..cf24861e233 100644
--- a/substrate/primitives/core/src/crypto.rs
+++ b/substrate/primitives/core/src/crypto.rs
@@ -17,7 +17,7 @@
 
 //! Cryptographic utilities.
 
-use crate::{ed25519, sr25519};
+use crate::{ed25519, sr25519, U256};
 use alloc::{format, str, vec::Vec};
 #[cfg(all(not(feature = "std"), feature = "serde"))]
 use alloc::{string::String, vec};
@@ -1191,7 +1191,7 @@ macro_rules! impl_from_entropy_base {
 	}
 }
 
-impl_from_entropy_base!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
+impl_from_entropy_base!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, U256);
 
 #[cfg(test)]
 mod tests {
-- 
GitLab