Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Ensure charge fee and transfer asset won't kill accounts.
  • Loading branch information
shaunxw committed Feb 21, 2019
commit f8a848dc05e4566d76bba4e8d32efcd99a0b69ee
6 changes: 6 additions & 0 deletions core/sr-primitives/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ pub trait ChargeFee<AccountId>: ChargeBytesFee<AccountId> {
type Amount;

/// Charge `amount` of fees from `transactor`. Return Ok iff the payment was successful.
///
/// NOTE: Should not kill `transactor`'s account.
fn charge_fee(transactor: &AccountId, amount: Self::Amount) -> Result<(), &'static str>;

/// Refund `amount` of previous charged fees from `transactor`. Return Ok iff the refund was successful.
Expand All @@ -151,9 +153,13 @@ pub trait TransferAsset<AccountId> {
type Amount;

/// Transfer asset from `from` account to `to` account with `amount` of asset.
///
/// NOTE: Should not kill `from`'s account.
fn transfer(from: &AccountId, to: &AccountId, amount: Self::Amount) -> Result<(), &'static str>;

/// Remove asset from `who` account by deducing `amount` in the account balances.
///
/// NOTE: Should not kill `who`'s account.
fn remove_from(who: &AccountId, amount: Self::Amount) -> Result<(), &'static str>;

/// Add asset to `who` account by increasing `amount` in the account balances.
Expand Down
21 changes: 16 additions & 5 deletions srml/balances/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ decl_module! {
) {
let transactor = ensure_signed(origin)?;
let dest = T::Lookup::lookup(dest)?;
Self::make_transfer(&transactor, &dest, value)?;
Self::make_transfer(&transactor, &dest, value, true)?;
}

/// Set the balances of a given account.
Expand Down Expand Up @@ -305,8 +305,14 @@ impl<T: Trait> Module<T> {
Ok(Self::set_free_balance(who, b - value))
}

/// Transfer some liquid free balance to another staker.
pub fn make_transfer(transactor: &T::AccountId, dest: &T::AccountId, value: T::Balance) -> Result {
/// Transfer some liquid free balance to another account. If `can_kill`, will enforce
/// ExistentialDeposit law anulling the `transactor`'s account as needed.
pub fn make_transfer(
transactor: &T::AccountId,
dest: &T::AccountId,
value: T::Balance,
can_kill: bool,
) -> Result {
let from_balance = Self::free_balance(transactor);
let to_balance = Self::free_balance(dest);
let would_create = to_balance.is_zero();
Expand Down Expand Up @@ -334,6 +340,10 @@ impl<T: Trait> Module<T> {
None => return Err("destination balance too high to receive value"),
};

if !can_kill {
ensure!(new_from_balance >= Self::existential_deposit(), "balance too low to send value")
}

if transactor != dest {
T::ChargeFee::charge_fee(transactor, fee)?;

Expand Down Expand Up @@ -511,13 +521,14 @@ impl<T: Trait> TransferAsset<T::AccountId> for Module<T> {
type Amount = T::Balance;

fn transfer(from: &T::AccountId, to: &T::AccountId, amount: T::Balance) -> Result {
Self::make_transfer(from, to, amount)
Self::make_transfer(from, to, amount, false)
}

fn remove_from(who: &T::AccountId, value: T::Balance) -> Result {
T::EnsureAccountLiquid::ensure_account_liquid(who)?;
let b = Self::free_balance(who);
ensure!(b >= value, "account has too few funds");
// ensure `who`'s account won't be killed.
ensure!(b >= value + Self::existential_deposit(), "account has too few funds");
Self::set_free_balance(who, b - value);
Self::decrease_total_stake_by(value);
Ok(())
Expand Down