From a72ce9424c600f3612c452ed961fcbce345b9d07 Mon Sep 17 00:00:00 2001
From: Muharem <ismailov.m.h@gmail.com>
Date: Sun, 7 Jul 2024 13:45:16 +0200
Subject: [PATCH] Assets: can_decrease/increase for destroying asset is not
 successful (#3286)

Functions `can_decrease` and `can_increase` do not return successful
consequence results for assets undergoing destruction; instead, they
return the `UnknownAsset` consequence variant.

This update aligns their behavior with similar functions, such as
`reducible_balance`, `increase_balance`, `decrease_balance`, and `burn`,
which return an `AssetNotLive` error for assets in the process of being
destroyed.
---
 prdoc/pr_3286.prdoc                     | 16 +++++++++++
 substrate/frame/assets/src/functions.rs |  6 +++++
 substrate/frame/assets/src/tests.rs     | 35 ++++++++++++++++++++++++-
 3 files changed, 56 insertions(+), 1 deletion(-)
 create mode 100644 prdoc/pr_3286.prdoc

diff --git a/prdoc/pr_3286.prdoc b/prdoc/pr_3286.prdoc
new file mode 100644
index 0000000000000..6ec3f6552a4a7
--- /dev/null
+++ b/prdoc/pr_3286.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: "Assets: can_decrease/increase for destroying asset is not successful"
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      Functions `can_decrease` and `can_increase` do not return successful consequence results 
+      for assets undergoing destruction; instead, they return the `UnknownAsset` consequence variant.
+      This update aligns their behavior with similar functions, such as `reducible_balance`,
+      `increase_balance`, `decrease_balance`, and `burn`, which return an `AssetNotLive` error
+      for assets in the process of being destroyed.
+
+crates:
+  - name: pallet-assets
diff --git a/substrate/frame/assets/src/functions.rs b/substrate/frame/assets/src/functions.rs
index 2fb8aee1a970c..1e4a9522759c3 100644
--- a/substrate/frame/assets/src/functions.rs
+++ b/substrate/frame/assets/src/functions.rs
@@ -132,6 +132,9 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
 			Some(details) => details,
 			None => return DepositConsequence::UnknownAsset,
 		};
+		if details.status == AssetStatus::Destroying {
+			return DepositConsequence::UnknownAsset
+		}
 		if increase_supply && details.supply.checked_add(&amount).is_none() {
 			return DepositConsequence::Overflow
 		}
@@ -175,6 +178,9 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
 		if details.status == AssetStatus::Frozen {
 			return Frozen
 		}
+		if details.status == AssetStatus::Destroying {
+			return UnknownAsset
+		}
 		if amount.is_zero() {
 			return Success
 		}
diff --git a/substrate/frame/assets/src/tests.rs b/substrate/frame/assets/src/tests.rs
index 62106d47a1562..c751fbdcaf1bb 100644
--- a/substrate/frame/assets/src/tests.rs
+++ b/substrate/frame/assets/src/tests.rs
@@ -22,7 +22,11 @@ use crate::{mock::*, Error};
 use frame_support::{
 	assert_noop, assert_ok,
 	dispatch::GetDispatchInfo,
-	traits::{fungibles::InspectEnumerable, tokens::Preservation::Protect, Currency},
+	traits::{
+		fungibles::InspectEnumerable,
+		tokens::{Preservation::Protect, Provenance},
+		Currency,
+	},
 };
 use pallet_balances::Error as BalancesError;
 use sp_io::storage;
@@ -1778,6 +1782,35 @@ fn asset_destroy_refund_existence_deposit() {
 	});
 }
 
+#[test]
+fn increasing_or_decreasing_destroying_asset_should_not_work() {
+	new_test_ext().execute_with(|| {
+		use frame_support::traits::fungibles::Inspect;
+
+		let admin = 1;
+		let admin_origin = RuntimeOrigin::signed(admin);
+
+		assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, admin, true, 1));
+		assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100));
+		assert_eq!(Assets::balance(0, 1), 100);
+
+		assert_eq!(Assets::can_deposit(0, &1, 10, Provenance::Extant), DepositConsequence::Success);
+		assert_eq!(Assets::can_withdraw(0, &1, 10), WithdrawConsequence::<_>::Success);
+		assert_eq!(Assets::can_increase(0, &1, 10, false), DepositConsequence::Success);
+		assert_eq!(Assets::can_decrease(0, &1, 10, false), WithdrawConsequence::<_>::Success);
+
+		assert_ok!(Assets::start_destroy(admin_origin, 0));
+
+		assert_eq!(
+			Assets::can_deposit(0, &1, 10, Provenance::Extant),
+			DepositConsequence::UnknownAsset
+		);
+		assert_eq!(Assets::can_withdraw(0, &1, 10), WithdrawConsequence::<_>::UnknownAsset);
+		assert_eq!(Assets::can_increase(0, &1, 10, false), DepositConsequence::UnknownAsset);
+		assert_eq!(Assets::can_decrease(0, &1, 10, false), WithdrawConsequence::<_>::UnknownAsset);
+	});
+}
+
 #[test]
 fn asset_id_cannot_be_reused() {
 	new_test_ext().execute_with(|| {