diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock
index beb234518041e84020b5a7c32d48540c8220ee35..239395c95ccabb81b4b52f1bd509174254e13587 100644
--- a/substrate/Cargo.lock
+++ b/substrate/Cargo.lock
@@ -6329,8 +6329,8 @@ dependencies = [
  "frame-support",
  "frame-system",
  "pallet-balances",
- "pallet-root-testing",
  "pallet-collective",
+ "pallet-root-testing",
  "pallet-timestamp",
  "parity-scale-codec",
  "scale-info",
diff --git a/substrate/frame/assets/src/impl_fungibles.rs b/substrate/frame/assets/src/impl_fungibles.rs
index b005131176f4994d023a65a1c82a880910b3d077..6e0a9ac08ebb136c740d094121b00870d753262d 100644
--- a/substrate/frame/assets/src/impl_fungibles.rs
+++ b/substrate/frame/assets/src/impl_fungibles.rs
@@ -179,6 +179,24 @@ impl<T: Config<I>, I: 'static> fungibles::Create<T::AccountId> for Pallet<T, I>
 	}
 }
 
+impl<T: Config<I>, I: 'static> fungibles::Destroy<T::AccountId> for Pallet<T, I> {
+	fn start_destroy(id: T::AssetId, maybe_check_owner: Option<T::AccountId>) -> DispatchResult {
+		Self::do_start_destroy(id, maybe_check_owner)
+	}
+
+	fn destroy_accounts(id: T::AssetId, max_items: u32) -> Result<u32, DispatchError> {
+		Self::do_destroy_accounts(id, max_items)
+	}
+
+	fn destroy_approvals(id: T::AssetId, max_items: u32) -> Result<u32, DispatchError> {
+		Self::do_destroy_approvals(id, max_items)
+	}
+
+	fn finish_destroy(id: T::AssetId) -> DispatchResult {
+		Self::do_finish_destroy(id)
+	}
+}
+
 impl<T: Config<I>, I: 'static> fungibles::metadata::Inspect<<T as SystemConfig>::AccountId>
 	for Pallet<T, I>
 {
diff --git a/substrate/frame/support/src/traits/tokens/fungibles.rs b/substrate/frame/support/src/traits/tokens/fungibles.rs
index 9bdd5a10d794427f0194b3b32f7c369b115f2ce2..8c370e9a0d8b59d31bb59d12439f424cc23713b6 100644
--- a/substrate/frame/support/src/traits/tokens/fungibles.rs
+++ b/substrate/frame/support/src/traits/tokens/fungibles.rs
@@ -267,25 +267,51 @@ pub trait Create<AccountId>: Inspect<AccountId> {
 
 /// Trait for providing the ability to destroy existing fungible assets.
 pub trait Destroy<AccountId>: Inspect<AccountId> {
-	/// The witness data needed to destroy an asset.
-	type DestroyWitness;
-
-	/// Provide the appropriate witness data needed to destroy an asset.
-	fn get_destroy_witness(id: &Self::AssetId) -> Option<Self::DestroyWitness>;
-
-	/// Destroy an existing fungible asset.
-	/// * `id`: The `AssetId` to be destroyed.
-	/// * `witness`: Any witness data that needs to be provided to complete the operation
-	///   successfully.
+	/// Start the destruction an existing fungible asset.
+	/// * `id`: The `AssetId` to be destroyed. successfully.
 	/// * `maybe_check_owner`: An optional account id that can be used to authorize the destroy
-	///   command. If not provided, we will not do any authorization checks before destroying the
+	///   command. If not provided, no authorization checks will be performed before destroying
 	///   asset.
+	fn start_destroy(id: Self::AssetId, maybe_check_owner: Option<AccountId>) -> DispatchResult;
+
+	/// Destroy all accounts associated with a given asset.
+	/// `destroy_accounts` should only be called after `start_destroy` has been called, and the
+	/// asset is in a `Destroying` state
 	///
-	/// If successful, this function will return the actual witness data from the destroyed asset.
-	/// This may be different than the witness data provided, and can be used to refund weight.
-	fn destroy(
-		id: Self::AssetId,
-		witness: Self::DestroyWitness,
-		maybe_check_owner: Option<AccountId>,
-	) -> Result<Self::DestroyWitness, DispatchError>;
+	/// * `id`: The identifier of the asset to be destroyed. This must identify an existing asset.
+	/// * `max_items`: The maximum number of accounts to be destroyed for a given call of the
+	///   function. This value should be small enough to allow the operation fit into a logical
+	///   block.
+	///
+	///	Response:
+	/// * u32: Total number of approvals which were actually destroyed
+	///
+	/// Due to weight restrictions, this function may need to be called multiple
+	/// times to fully destroy all approvals. It will destroy `max_items` approvals at a
+	/// time.
+	fn destroy_accounts(id: Self::AssetId, max_items: u32) -> Result<u32, DispatchError>;
+	/// Destroy all approvals associated with a given asset up to the `max_items`
+	/// `destroy_approvals` should only be called after `start_destroy` has been called, and the
+	/// asset is in a `Destroying` state
+	///
+	/// * `id`: The identifier of the asset to be destroyed. This must identify an existing asset.
+	/// * `max_items`: The maximum number of accounts to be destroyed for a given call of the
+	///   function. This value should be small enough to allow the operation fit into a logical
+	///   block.
+	///
+	///	Response:
+	/// * u32: Total number of approvals which were actually destroyed
+	///
+	/// Due to weight restrictions, this function may need to be called multiple
+	/// times to fully destroy all approvals. It will destroy `max_items` approvals at a
+	/// time.
+	fn destroy_approvals(id: Self::AssetId, max_items: u32) -> Result<u32, DispatchError>;
+
+	/// Complete destroying asset and unreserve currency.
+	/// `finish_destroy` should only be called after `start_destroy` has been called, and the
+	/// asset is in a `Destroying` state. All accounts or approvals should be destroyed before
+	/// hand.
+	///
+	/// * `id`: The identifier of the asset to be destroyed. This must identify an existing asset.
+	fn finish_destroy(id: Self::AssetId) -> DispatchResult;
 }