From eebdb063c480a858821337929d9f86c68cd2bfc8 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 5 Nov 2019 17:52:15 +1300 Subject: [PATCH 1/9] Added a public transfer_some function and a private transfer_inner fn --- srml/balances/src/lib.rs | 108 +++++++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 37 deletions(-) diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 71f37cb8f8193..eff72a81308e1 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -407,7 +407,24 @@ decl_module! { ) { let transactor = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; - >::transfer(&transactor, &dest, value)?; + + Self::transfer_inner(&transactor, &dest, value, ExistenceRequirement::AllowDeath)?; + } + + /// Transfer some liquid free balance to another account, while checking that the transfer + /// will not kill the account. + /// + /// 99% of the time you want `transfer` instead. + #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + pub fn transfer_some( + origin, + dest: ::Source, + #[compact] value: T::Balance + ) { + let transactor = ensure_signed(origin)?; + let dest = T::Lookup::lookup(dest)?; + + Self::transfer_inner(&transactor, &dest, value, ExistenceRequirement::KeepAlive)?; } /// Set the balances of a given account. @@ -852,42 +869,7 @@ where } fn transfer(transactor: &T::AccountId, dest: &T::AccountId, value: Self::Balance) -> Result { - let from_balance = Self::free_balance(transactor); - let to_balance = Self::free_balance(dest); - let would_create = to_balance.is_zero(); - let fee = if would_create { T::CreationFee::get() } else { T::TransferFee::get() }; - let liability = match value.checked_add(&fee) { - Some(l) => l, - None => return Err("got overflow after adding a fee to value"), - }; - - let new_from_balance = match from_balance.checked_sub(&liability) { - None => return Err("balance too low to send value"), - Some(b) => b, - }; - if would_create && value < T::ExistentialDeposit::get() { - return Err("value too low to create account"); - } - Self::ensure_can_withdraw(transactor, value, WithdrawReason::Transfer.into(), new_from_balance)?; - - // NOTE: total stake being stored in the same type means that this could never overflow - // but better to be safe than sorry. - let new_to_balance = match to_balance.checked_add(&value) { - Some(b) => b, - None => return Err("destination balance too high to receive value"), - }; - - if transactor != dest { - Self::set_free_balance(transactor, new_from_balance); - if !>::exists(dest) { - Self::new_account(dest, new_to_balance); - } - Self::set_free_balance(dest, new_to_balance); - T::TransferPayment::on_unbalanced(NegativeImbalance::new(fee)); - Self::deposit_event(RawEvent::Transfer(transactor.clone(), dest.clone(), value, fee)); - } - - Ok(()) + Self::transfer_inner(transactor, dest, value, ExistenceRequirement::AllowDeath) } fn withdraw( @@ -1151,3 +1133,55 @@ where Self::total_balance(who).is_zero() } } + +impl, I: Instance> Module { + fn transfer_inner( + transactor: &T::AccountId, + dest: &T::AccountId, + value: T::Balance, + existential_requirement: ExistenceRequirement, + ) -> Result { + let from_balance = Self::free_balance(transactor); + let to_balance = Self::free_balance(dest); + let would_create = to_balance.is_zero(); + let fee = if would_create { T::CreationFee::get() } else { T::TransferFee::get() }; + let liability = match value.checked_add(&fee) { + Some(l) => l, + None => return Err("got overflow after adding a fee to value"), + }; + + let new_from_balance = match from_balance.checked_sub(&liability) { + None => return Err("balance too low to send value"), + Some(b) => b, + }; + if would_create && value < T::ExistentialDeposit::get() { + return Err("value too low to create account"); + } + Self::ensure_can_withdraw(transactor, value, WithdrawReason::Transfer.into(), new_from_balance)?; + + // NOTE: total stake being stored in the same type means that this could never overflow + // but better to be safe than sorry. + let new_to_balance = match to_balance.checked_add(&value) { + Some(b) => b, + None => return Err("destination balance too high to receive value"), + }; + + if transactor != dest { + if existential_requirement == ExistenceRequirement::KeepAlive { + if new_from_balance < T::ExistentialDeposit::get() { + return Err("payment would kill account"); + } + } + + Self::set_free_balance(transactor, new_from_balance); + if !>::exists(dest) { + Self::new_account(dest, new_to_balance); + } + Self::set_free_balance(dest, new_to_balance); + T::TransferPayment::on_unbalanced(NegativeImbalance::new(fee)); + Self::deposit_event(RawEvent::Transfer(transactor.clone(), dest.clone(), value, fee)); + } + + Ok(()) + } +} From 412ff6604c44d8dab85c597275921edadda35871 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 5 Nov 2019 18:47:34 +1300 Subject: [PATCH 2/9] Move transfer_some to the end of the module impl to fix failing contracts test --- srml/balances/src/lib.rs | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index eff72a81308e1..3df244f4b1021 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -411,22 +411,6 @@ decl_module! { Self::transfer_inner(&transactor, &dest, value, ExistenceRequirement::AllowDeath)?; } - /// Transfer some liquid free balance to another account, while checking that the transfer - /// will not kill the account. - /// - /// 99% of the time you want `transfer` instead. - #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] - pub fn transfer_some( - origin, - dest: ::Source, - #[compact] value: T::Balance - ) { - let transactor = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest)?; - - Self::transfer_inner(&transactor, &dest, value, ExistenceRequirement::KeepAlive)?; - } - /// Set the balances of a given account. /// /// This will alter `FreeBalance` and `ReservedBalance` in storage. it will @@ -481,6 +465,23 @@ decl_module! { let dest = T::Lookup::lookup(dest)?; >::transfer(&source, &dest, value)?; } + + /// Transfer some liquid free balance to another account, while checking that the transfer + /// will not kill the account. + /// + /// 99% of the time you want `transfer` instead. + #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + pub fn transfer_some( + origin, + dest: ::Source, + #[compact] value: T::Balance + ) { + let transactor = ensure_signed(origin)?; + let dest = T::Lookup::lookup(dest)?; + + Self::transfer_inner(&transactor, &dest, value, ExistenceRequirement::KeepAlive)?; + } + } } From e659ee66919a6dea11b38145677ceb97fe331e16 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 5 Nov 2019 18:49:04 +1300 Subject: [PATCH 3/9] Change whitespace --- srml/balances/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 3df244f4b1021..104b4b0807055 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -407,7 +407,6 @@ decl_module! { ) { let transactor = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; - Self::transfer_inner(&transactor, &dest, value, ExistenceRequirement::AllowDeath)?; } @@ -465,7 +464,7 @@ decl_module! { let dest = T::Lookup::lookup(dest)?; >::transfer(&source, &dest, value)?; } - + /// Transfer some liquid free balance to another account, while checking that the transfer /// will not kill the account. /// From caa9476f8f92a894c544b4b67794f330fa4cefd3 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 5 Nov 2019 18:52:15 +1300 Subject: [PATCH 4/9] Remove needless change to transfer logic --- srml/balances/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 104b4b0807055..92127912b6024 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -407,7 +407,7 @@ decl_module! { ) { let transactor = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; - Self::transfer_inner(&transactor, &dest, value, ExistenceRequirement::AllowDeath)?; + >::transfer(&source, &dest, value)?; } /// Set the balances of a given account. From 91e73bd9609241a5c7a14a6af9bfe6677a494dc3 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 5 Nov 2019 18:52:45 +1300 Subject: [PATCH 5/9] Fix error --- srml/balances/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 92127912b6024..0e3e418dbe884 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -407,7 +407,7 @@ decl_module! { ) { let transactor = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; - >::transfer(&source, &dest, value)?; + >::transfer(&transactor, &dest, value)?; } /// Set the balances of a given account. From e95212de4f215d2023cf884ce6abbfcef49b7d4a Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 5 Nov 2019 08:20:19 +0000 Subject: [PATCH 6/9] Update srml/balances/src/lib.rs Co-Authored-By: joe petrowski <25483142+joepetrowski@users.noreply.github.com> --- srml/balances/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 0e3e418dbe884..b83161c1e545f 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -1168,7 +1168,7 @@ impl, I: Instance> Module { if transactor != dest { if existential_requirement == ExistenceRequirement::KeepAlive { - if new_from_balance < T::ExistentialDeposit::get() { + if new_from_balance < Self::minimum_balance() { return Err("payment would kill account"); } } From ac0baa23a92650e1c2e8b1c30060bfa66eb44338 Mon Sep 17 00:00:00 2001 From: Ashley Date: Wed, 6 Nov 2019 15:17:32 +1300 Subject: [PATCH 7/9] Improve documentation and add test --- srml/balances/src/lib.rs | 14 +++++++++----- srml/balances/src/tests.rs | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index b83161c1e545f..bef0dcdf30ba6 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -397,6 +397,8 @@ decl_module! { /// `T::OnNewAccount::on_new_account` to be called. /// - Removing enough funds from an account will trigger /// `T::DustRemoval::on_unbalanced` and `T::OnFreeBalanceZero::on_free_balance_zero`. + /// - `transfer_keep_alive` works the same way as `transfer`, but has an additional + /// check that the transfer will not kill the origin account. /// /// # #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] @@ -465,12 +467,14 @@ decl_module! { >::transfer(&source, &dest, value)?; } - /// Transfer some liquid free balance to another account, while checking that the transfer - /// will not kill the account. + /// Same as the [`transfer`] call, but with a check that the transfer will not kill the + /// origin account. /// - /// 99% of the time you want `transfer` instead. + /// 99% of the time you want [`transfer`] instead. + /// + /// [`transfer`]: struct.Module.html#method.transfer #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] - pub fn transfer_some( + pub fn transfer_keep_alive( origin, dest: ::Source, #[compact] value: T::Balance @@ -1169,7 +1173,7 @@ impl, I: Instance> Module { if transactor != dest { if existential_requirement == ExistenceRequirement::KeepAlive { if new_from_balance < Self::minimum_balance() { - return Err("payment would kill account"); + return Err("transfer would kill account"); } } diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs index 839ac67991c83..e6c1752a8ca4d 100644 --- a/srml/balances/src/tests.rs +++ b/srml/balances/src/tests.rs @@ -746,3 +746,17 @@ fn burn_must_work() { assert_eq!(Balances::total_issuance(), init_total_issuance); }); } + +#[test] +fn transfer_keep_alive_works() { + ExtBuilder::default().existential_deposit(1).build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 100); + assert_err!( + Balances::transfer_keep_alive(Some(1).into(), 2, 100), + "transfer would kill account" + ); + assert_eq!(Balances::is_dead_account(&1), false); + assert_eq!(Balances::total_balance(&1), 100); + assert_eq!(Balances::total_balance(&2), 0); + }); +} From 8b1559f34b83a51b92f970d7e02ee9ec80ab7ddc Mon Sep 17 00:00:00 2001 From: Ashley Date: Thu, 7 Nov 2019 00:56:38 +0000 Subject: [PATCH 8/9] Update srml/balances/src/lib.rs Co-Authored-By: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- srml/balances/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index bef0dcdf30ba6..65bf81ce0a4fc 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -1143,7 +1143,7 @@ impl, I: Instance> Module { transactor: &T::AccountId, dest: &T::AccountId, value: T::Balance, - existential_requirement: ExistenceRequirement, + existence_requirement: ExistenceRequirement, ) -> Result { let from_balance = Self::free_balance(transactor); let to_balance = Self::free_balance(dest); From 1b620038009306c8cef448fd6cc256505f0c479d Mon Sep 17 00:00:00 2001 From: Ashley Date: Thu, 7 Nov 2019 14:23:59 +1300 Subject: [PATCH 9/9] Switch to changing Currency trait instead --- srml/balances/src/lib.rs | 109 ++++++++++++++++------------------ srml/balances/src/tests.rs | 42 ++++++------- srml/generic-asset/src/lib.rs | 7 ++- srml/support/src/traits.rs | 1 + 4 files changed, 79 insertions(+), 80 deletions(-) diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 65bf81ce0a4fc..e22dba3fee477 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -409,7 +409,7 @@ decl_module! { ) { let transactor = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; - >::transfer(&transactor, &dest, value)?; + >::transfer(&transactor, &dest, value, ExistenceRequirement::AllowDeath)?; } /// Set the balances of a given account. @@ -464,7 +464,7 @@ decl_module! { ensure_root(origin)?; let source = T::Lookup::lookup(source)?; let dest = T::Lookup::lookup(dest)?; - >::transfer(&source, &dest, value)?; + >::transfer(&source, &dest, value, ExistenceRequirement::AllowDeath)?; } /// Same as the [`transfer`] call, but with a check that the transfer will not kill the @@ -481,8 +481,7 @@ decl_module! { ) { let transactor = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; - - Self::transfer_inner(&transactor, &dest, value, ExistenceRequirement::KeepAlive)?; + >::transfer(&transactor, &dest, value, ExistenceRequirement::KeepAlive)?; } } @@ -872,8 +871,54 @@ where } } - fn transfer(transactor: &T::AccountId, dest: &T::AccountId, value: Self::Balance) -> Result { - Self::transfer_inner(transactor, dest, value, ExistenceRequirement::AllowDeath) + fn transfer( + transactor: &T::AccountId, + dest: &T::AccountId, + value: Self::Balance, + existence_requirement: ExistenceRequirement, + ) -> Result { + let from_balance = Self::free_balance(transactor); + let to_balance = Self::free_balance(dest); + let would_create = to_balance.is_zero(); + let fee = if would_create { T::CreationFee::get() } else { T::TransferFee::get() }; + let liability = match value.checked_add(&fee) { + Some(l) => l, + None => return Err("got overflow after adding a fee to value"), + }; + + let new_from_balance = match from_balance.checked_sub(&liability) { + None => return Err("balance too low to send value"), + Some(b) => b, + }; + if would_create && value < T::ExistentialDeposit::get() { + return Err("value too low to create account"); + } + Self::ensure_can_withdraw(transactor, value, WithdrawReason::Transfer.into(), new_from_balance)?; + + // NOTE: total stake being stored in the same type means that this could never overflow + // but better to be safe than sorry. + let new_to_balance = match to_balance.checked_add(&value) { + Some(b) => b, + None => return Err("destination balance too high to receive value"), + }; + + if transactor != dest { + if existence_requirement == ExistenceRequirement::KeepAlive { + if new_from_balance < Self::minimum_balance() { + return Err("transfer would kill account"); + } + } + + Self::set_free_balance(transactor, new_from_balance); + if !>::exists(dest) { + Self::new_account(dest, new_to_balance); + } + Self::set_free_balance(dest, new_to_balance); + T::TransferPayment::on_unbalanced(NegativeImbalance::new(fee)); + Self::deposit_event(RawEvent::Transfer(transactor.clone(), dest.clone(), value, fee)); + } + + Ok(()) } fn withdraw( @@ -1137,55 +1182,3 @@ where Self::total_balance(who).is_zero() } } - -impl, I: Instance> Module { - fn transfer_inner( - transactor: &T::AccountId, - dest: &T::AccountId, - value: T::Balance, - existence_requirement: ExistenceRequirement, - ) -> Result { - let from_balance = Self::free_balance(transactor); - let to_balance = Self::free_balance(dest); - let would_create = to_balance.is_zero(); - let fee = if would_create { T::CreationFee::get() } else { T::TransferFee::get() }; - let liability = match value.checked_add(&fee) { - Some(l) => l, - None => return Err("got overflow after adding a fee to value"), - }; - - let new_from_balance = match from_balance.checked_sub(&liability) { - None => return Err("balance too low to send value"), - Some(b) => b, - }; - if would_create && value < T::ExistentialDeposit::get() { - return Err("value too low to create account"); - } - Self::ensure_can_withdraw(transactor, value, WithdrawReason::Transfer.into(), new_from_balance)?; - - // NOTE: total stake being stored in the same type means that this could never overflow - // but better to be safe than sorry. - let new_to_balance = match to_balance.checked_add(&value) { - Some(b) => b, - None => return Err("destination balance too high to receive value"), - }; - - if transactor != dest { - if existential_requirement == ExistenceRequirement::KeepAlive { - if new_from_balance < Self::minimum_balance() { - return Err("transfer would kill account"); - } - } - - Self::set_free_balance(transactor, new_from_balance); - if !>::exists(dest) { - Self::new_account(dest, new_to_balance); - } - Self::set_free_balance(dest, new_to_balance); - T::TransferPayment::on_unbalanced(NegativeImbalance::new(fee)); - Self::deposit_event(RawEvent::Transfer(transactor.clone(), dest.clone(), value, fee)); - } - - Ok(()) - } -} diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs index e6c1752a8ca4d..8afec6f697de1 100644 --- a/srml/balances/src/tests.rs +++ b/srml/balances/src/tests.rs @@ -24,7 +24,7 @@ use sr_primitives::traits::SignedExtension; use support::{ assert_noop, assert_ok, assert_err, traits::{LockableCurrency, LockIdentifier, WithdrawReason, WithdrawReasons, - Currency, ReservableCurrency} + Currency, ReservableCurrency, ExistenceRequirement::AllowDeath} }; use transaction_payment::ChargeTransactionPayment; use system::RawOrigin; @@ -39,7 +39,7 @@ fn basic_locking_should_work() { assert_eq!(Balances::free_balance(&1), 10); Balances::set_lock(ID_1, &1, 9, u64::max_value(), WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 5), + >::transfer(&1, &2, 5, AllowDeath), "account liquidity restrictions prevent withdrawal" ); }); @@ -49,7 +49,7 @@ fn basic_locking_should_work() { fn partial_locking_should_work() { ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); }); } @@ -58,7 +58,7 @@ fn lock_removal_should_work() { ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all()); Balances::remove_lock(ID_1, &1); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); }); } @@ -67,7 +67,7 @@ fn lock_replacement_should_work() { ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all()); Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); }); } @@ -76,7 +76,7 @@ fn double_locking_should_work() { ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); Balances::set_lock(ID_2, &1, 5, u64::max_value(), WithdrawReasons::all()); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); }); } @@ -86,7 +86,7 @@ fn combination_locking_should_work() { Balances::set_lock(ID_1, &1, u64::max_value(), 0, WithdrawReasons::none()); Balances::set_lock(ID_2, &1, 0, u64::max_value(), WithdrawReasons::none()); Balances::set_lock(ID_3, &1, 0, 0, WithdrawReasons::all()); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); }); } @@ -95,17 +95,17 @@ fn lock_value_extension_should_work() { ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); Balances::extend_lock(ID_1, &1, 2, u64::max_value(), WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); Balances::extend_lock(ID_1, &1, 8, u64::max_value(), WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 3), + >::transfer(&1, &2, 3, AllowDeath), "account liquidity restrictions prevent withdrawal" ); }); @@ -120,7 +120,7 @@ fn lock_reasons_should_work() { .execute_with(|| { Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Transfer.into()); assert_noop!( - >::transfer(&1, &2, 1), + >::transfer(&1, &2, 1, AllowDeath), "account liquidity restrictions prevent withdrawal" ); assert_ok!(>::reserve(&1, 1)); @@ -134,7 +134,7 @@ fn lock_reasons_should_work() { ).is_ok()); Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Reserve.into()); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); assert_noop!( >::reserve(&1, 1), "account liquidity restrictions prevent withdrawal" @@ -148,7 +148,7 @@ fn lock_reasons_should_work() { ).is_ok()); Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::TransactionPayment.into()); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); assert_ok!(>::reserve(&1, 1)); assert!( as SignedExtension>::pre_dispatch( ChargeTransactionPayment::from(1), @@ -165,12 +165,12 @@ fn lock_block_number_should_work() { ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 1), + >::transfer(&1, &2, 1, AllowDeath), "account liquidity restrictions prevent withdrawal" ); System::set_block_number(2); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); }); } @@ -179,18 +179,18 @@ fn lock_block_number_extension_should_work() { ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); Balances::extend_lock(ID_1, &1, 10, 1, WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); System::set_block_number(2); Balances::extend_lock(ID_1, &1, 10, 8, WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 3), + >::transfer(&1, &2, 3, AllowDeath), "account liquidity restrictions prevent withdrawal" ); }); @@ -201,17 +201,17 @@ fn lock_reasons_extension_should_work() { ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, 10, 10, WithdrawReason::Transfer.into()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReasons::none()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReason::Reserve.into()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); }); diff --git a/srml/generic-asset/src/lib.rs b/srml/generic-asset/src/lib.rs index 38bff08e12d0b..fda3b6ae048f4 100644 --- a/srml/generic-asset/src/lib.rs +++ b/srml/generic-asset/src/lib.rs @@ -1096,7 +1096,12 @@ where Zero::zero() } - fn transfer(transactor: &T::AccountId, dest: &T::AccountId, value: Self::Balance) -> Result { + fn transfer( + transactor: &T::AccountId, + dest: &T::AccountId, + value: Self::Balance, + _: ExistenceRequirement, // no existential deposit policy for generic asset + ) -> Result { >::make_transfer(&U::asset_id(), transactor, dest, value) } diff --git a/srml/support/src/traits.rs b/srml/support/src/traits.rs index b321aeaeb9fe9..41dd0ec36e3f5 100644 --- a/srml/support/src/traits.rs +++ b/srml/support/src/traits.rs @@ -395,6 +395,7 @@ pub trait Currency { source: &AccountId, dest: &AccountId, value: Self::Balance, + existence_requirement: ExistenceRequirement, ) -> result::Result<(), &'static str>; /// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the