From d6af4735770f902f10f92c69fc03945462f4ac2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Sun, 8 Dec 2024 23:01:45 -0500 Subject: [PATCH] fix: `ensure_account_can_die` should happen before mutating `dest` on `transfer_and_die`. --- substrate/frame/assets/src/functions.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/substrate/frame/assets/src/functions.rs b/substrate/frame/assets/src/functions.rs index 4a9cc1aa162e..a920ea8698d9 100644 --- a/substrate/frame/assets/src/functions.rs +++ b/substrate/frame/assets/src/functions.rs @@ -688,6 +688,15 @@ impl, I: 'static> Pallet { debug_assert!(source_account.balance >= debit, "checked in prep; qed"); source_account.balance = source_account.balance.saturating_sub(debit); + // Pre-check that an account can die if is below min balance + if source_account.balance < details.min_balance { + source_died = + Some(Self::dead_account(source, details, &source_account.reason, false)); + if let Some(Remove) = source_died { + Self::ensure_account_can_die(id.clone(), source)?; + } + } + Account::::try_mutate(&id, &dest, |maybe_account| -> DispatchResult { match maybe_account { Some(ref mut account) => { @@ -714,10 +723,7 @@ impl, I: 'static> Pallet { // Remove source account if it's now dead. if source_account.balance < details.min_balance { debug_assert!(source_account.balance.is_zero(), "checked in prep; qed"); - source_died = - Some(Self::dead_account(source, details, &source_account.reason, false)); if let Some(Remove) = source_died { - Self::ensure_account_can_die(id.clone(), source)?; Account::::remove(&id, &source); return Ok(()) }