Skip to content

Commit

Permalink
Merge pull request #18 from ComposableFi/connor/fungibles-backport
Browse files Browse the repository at this point in the history
  • Loading branch information
PoisonPhang authored Nov 10, 2022
2 parents fd75550 + e38a7b7 commit 9bdc51a
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 63 deletions.
109 changes: 58 additions & 51 deletions frame/balances/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ impl BitOr for Reasons {
type Output = Reasons;
fn bitor(self, other: Reasons) -> Reasons {
if self == other {
return self
return self;
}
Reasons::All
}
Expand Down Expand Up @@ -801,11 +801,11 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
mint: bool,
) -> DepositConsequence {
if amount.is_zero() {
return DepositConsequence::Success
return DepositConsequence::Success;
}

if mint && TotalIssuance::<T, I>::get().checked_add(&amount).is_none() {
return DepositConsequence::Overflow
return DepositConsequence::Overflow;
}

let new_total_balance = match account.total().checked_add(&amount) {
Expand All @@ -814,7 +814,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
};

if new_total_balance < T::ExistentialDeposit::get() {
return DepositConsequence::BelowMinimum
return DepositConsequence::BelowMinimum;
}

// NOTE: We assume that we are a provider, so don't need to do any checks in the
Expand All @@ -829,11 +829,11 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
account: &AccountData<T::Balance>,
) -> WithdrawConsequence<T::Balance> {
if amount.is_zero() {
return WithdrawConsequence::Success
return WithdrawConsequence::Success;
}

if TotalIssuance::<T, I>::get().checked_sub(&amount).is_none() {
return WithdrawConsequence::Underflow
return WithdrawConsequence::Underflow;
}

let new_total_balance = match account.total().checked_sub(&amount) {
Expand All @@ -850,7 +850,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
if frame_system::Pallet::<T>::can_dec_provider(who) {
WithdrawConsequence::ReducedToZero(new_total_balance)
} else {
return WithdrawConsequence::WouldDie
return WithdrawConsequence::WouldDie;
}
} else {
WithdrawConsequence::Success
Expand All @@ -865,7 +865,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
// Eventual free funds must be no less than the frozen balance.
let min_balance = account.frozen(Reasons::All);
if new_free_balance < min_balance {
return WithdrawConsequence::Frozen
return WithdrawConsequence::Frozen;
}

success
Expand Down Expand Up @@ -1006,14 +1006,14 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
status: Status,
) -> Result<T::Balance, DispatchError> {
if value.is_zero() {
return Ok(Zero::zero())
return Ok(Zero::zero());
}

if slashed == beneficiary {
return match status {
Status::Free => Ok(Self::unreserve(slashed, value)),
Status::Reserved => Ok(value.saturating_sub(Self::reserved_balance(slashed))),
}
};
}

let ((actual, _maybe_one_dust), _maybe_other_dust) = Self::try_mutate_account_with_dust(
Expand All @@ -1026,16 +1026,18 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
let actual = cmp::min(from_account.reserved, value);
ensure!(best_effort || actual == value, Error::<T, I>::InsufficientBalance);
match status {
Status::Free =>
Status::Free => {
to_account.free = to_account
.free
.checked_add(&actual)
.ok_or(ArithmeticError::Overflow)?,
Status::Reserved =>
.ok_or(ArithmeticError::Overflow)?
},
Status::Reserved => {
to_account.reserved = to_account
.reserved
.checked_add(&actual)
.ok_or(ArithmeticError::Overflow)?,
.ok_or(ArithmeticError::Overflow)?
},
}
from_account.reserved -= actual;
Ok(actual)
Expand Down Expand Up @@ -1094,7 +1096,7 @@ impl<T: Config<I>, I: 'static> fungible::Inspect<T::AccountId> for Pallet<T, I>
impl<T: Config<I>, I: 'static> fungible::Mutate<T::AccountId> for Pallet<T, I> {
fn mint_into(who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
if amount.is_zero() {
return Ok(())
return Ok(());
}
Self::try_mutate_account(who, |account, _is_new| -> DispatchResult {
Self::deposit_consequence(who, amount, account, true).into_result()?;
Expand All @@ -1111,7 +1113,7 @@ impl<T: Config<I>, I: 'static> fungible::Mutate<T::AccountId> for Pallet<T, I> {
amount: Self::Balance,
) -> Result<Self::Balance, DispatchError> {
if amount.is_zero() {
return Ok(Self::Balance::zero())
return Ok(Self::Balance::zero());
}
let actual = Self::try_mutate_account(
who,
Expand Down Expand Up @@ -1142,15 +1144,19 @@ impl<T: Config<I>, I: 'static> fungible::Transfer<T::AccountId> for Pallet<T, I>

impl<T: Config<I>, I: 'static> fungible::Unbalanced<T::AccountId> for Pallet<T, I> {
fn set_balance(who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
Self::mutate_account(who, |account| {
account.free = amount;
Self::mutate_account(who, |account| -> DispatchResult {
// Balance is the same type and will not overflow
// The provided `fungibles::Unbalanced` functions always provide `set_balance` with `free + reserved + amount`
// free = new_balance - reserved
account.free =
amount.checked_sub(&account.reserved).ok_or(ArithmeticError::Underflow)?;
Self::deposit_event(Event::BalanceSet {
who: who.clone(),
free: account.free,
reserved: account.reserved,
});
})?;
Ok(())
Ok(())
})?
}

fn set_total_issuance(amount: Self::Balance) {
Expand All @@ -1166,7 +1172,7 @@ impl<T: Config<I>, I: 'static> fungible::InspectHold<T::AccountId> for Pallet<T,
let a = Self::account(who);
let min_balance = T::ExistentialDeposit::get().max(a.frozen(Reasons::All));
if a.reserved.checked_add(&amount).is_none() {
return false
return false;
}
// We require it to be min_balance + amount to ensure that the full reserved funds may be
// slashed without compromising locked funds or destroying the account.
Expand All @@ -1180,7 +1186,7 @@ impl<T: Config<I>, I: 'static> fungible::InspectHold<T::AccountId> for Pallet<T,
impl<T: Config<I>, I: 'static> fungible::MutateHold<T::AccountId> for Pallet<T, I> {
fn hold(who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
if amount.is_zero() {
return Ok(())
return Ok(());
}
ensure!(Self::can_reserve(who, amount), Error::<T, I>::InsufficientBalance);
Self::mutate_account(who, |a| {
Expand All @@ -1195,7 +1201,7 @@ impl<T: Config<I>, I: 'static> fungible::MutateHold<T::AccountId> for Pallet<T,
best_effort: bool,
) -> Result<T::Balance, DispatchError> {
if amount.is_zero() {
return Ok(amount)
return Ok(amount);
}
// Done on a best-effort basis.
Self::try_mutate_account(who, |a, _| {
Expand Down Expand Up @@ -1401,7 +1407,7 @@ where
// Check if `value` amount of free balance can be slashed from `who`.
fn can_slash(who: &T::AccountId, value: Self::Balance) -> bool {
if value.is_zero() {
return true
return true;
}
Self::free_balance(who) >= value
}
Expand All @@ -1418,7 +1424,7 @@ where
// Is a no-op if amount to be burned is zero.
fn burn(mut amount: Self::Balance) -> Self::PositiveImbalance {
if amount.is_zero() {
return PositiveImbalance::zero()
return PositiveImbalance::zero();
}
<TotalIssuance<T, I>>::mutate(|issued| {
*issued = issued.checked_sub(&amount).unwrap_or_else(|| {
Expand All @@ -1434,7 +1440,7 @@ where
// Is a no-op if amount to be issued it zero.
fn issue(mut amount: Self::Balance) -> Self::NegativeImbalance {
if amount.is_zero() {
return NegativeImbalance::zero()
return NegativeImbalance::zero();
}
<TotalIssuance<T, I>>::mutate(|issued| {
*issued = issued.checked_add(&amount).unwrap_or_else(|| {
Expand Down Expand Up @@ -1464,7 +1470,7 @@ where
new_balance: T::Balance,
) -> DispatchResult {
if amount.is_zero() {
return Ok(())
return Ok(());
}
let min_balance = Self::account(who).frozen(reasons.into());
ensure!(new_balance >= min_balance, Error::<T, I>::LiquidityRestrictions);
Expand All @@ -1480,7 +1486,7 @@ where
existence_requirement: ExistenceRequirement,
) -> DispatchResult {
if value.is_zero() || transactor == dest {
return Ok(())
return Ok(());
}

Self::try_mutate_account_with_dust(
Expand Down Expand Up @@ -1548,10 +1554,10 @@ where
/// inconsistent or `can_slash` wasn't used appropriately.
fn slash(who: &T::AccountId, value: Self::Balance) -> (Self::NegativeImbalance, Self::Balance) {
if value.is_zero() {
return (NegativeImbalance::zero(), Zero::zero())
return (NegativeImbalance::zero(), Zero::zero());
}
if Self::total_balance(who).is_zero() {
return (NegativeImbalance::zero(), value)
return (NegativeImbalance::zero(), value);
}

for attempt in 0..2 {
Expand Down Expand Up @@ -1600,7 +1606,7 @@ where
who: who.clone(),
amount: value.saturating_sub(not_slashed),
});
return (imbalance, not_slashed)
return (imbalance, not_slashed);
},
Err(_) => (),
}
Expand All @@ -1618,7 +1624,7 @@ where
value: Self::Balance,
) -> Result<Self::PositiveImbalance, DispatchError> {
if value.is_zero() {
return Ok(PositiveImbalance::zero())
return Ok(PositiveImbalance::zero());
}

Self::try_mutate_account(
Expand All @@ -1643,7 +1649,7 @@ where
/// - `value` is so large it would cause the balance of `who` to overflow.
fn deposit_creating(who: &T::AccountId, value: Self::Balance) -> Self::PositiveImbalance {
if value.is_zero() {
return Self::PositiveImbalance::zero()
return Self::PositiveImbalance::zero();
}

Self::try_mutate_account(
Expand Down Expand Up @@ -1676,7 +1682,7 @@ where
liveness: ExistenceRequirement,
) -> result::Result<Self::NegativeImbalance, DispatchError> {
if value.is_zero() {
return Ok(NegativeImbalance::zero())
return Ok(NegativeImbalance::zero());
}

Self::try_mutate_account(
Expand Down Expand Up @@ -1749,7 +1755,7 @@ where
/// Always `true` if value to be reserved is zero.
fn can_reserve(who: &T::AccountId, value: Self::Balance) -> bool {
if value.is_zero() {
return true
return true;
}
Self::account(who).free.checked_sub(&value).map_or(false, |new_balance| {
Self::ensure_can_withdraw(who, value, WithdrawReasons::RESERVE, new_balance).is_ok()
Expand All @@ -1765,7 +1771,7 @@ where
/// Is a no-op if value to be reserved is zero.
fn reserve(who: &T::AccountId, value: Self::Balance) -> DispatchResult {
if value.is_zero() {
return Ok(())
return Ok(());
}

Self::try_mutate_account(who, |account, _| -> DispatchResult {
Expand All @@ -1785,10 +1791,10 @@ where
/// Is a no-op if the value to be unreserved is zero or the account does not exist.
fn unreserve(who: &T::AccountId, value: Self::Balance) -> Self::Balance {
if value.is_zero() {
return Zero::zero()
return Zero::zero();
}
if Self::total_balance(who).is_zero() {
return value
return value;
}

let actual = match Self::mutate_account(who, |account| {
Expand All @@ -1804,7 +1810,7 @@ where
// This should never happen since we don't alter the total amount in the account.
// If it ever does, then we should fail gracefully though, indicating that nothing
// could be done.
return value
return value;
},
};

Expand All @@ -1821,10 +1827,10 @@ where
value: Self::Balance,
) -> (Self::NegativeImbalance, Self::Balance) {
if value.is_zero() {
return (NegativeImbalance::zero(), Zero::zero())
return (NegativeImbalance::zero(), Zero::zero());
}
if Self::total_balance(who).is_zero() {
return (NegativeImbalance::zero(), value)
return (NegativeImbalance::zero(), value);
}

// NOTE: `mutate_account` may fail if it attempts to reduce the balance to the point that an
Expand Down Expand Up @@ -1853,7 +1859,7 @@ where
who: who.clone(),
amount: value.saturating_sub(not_slashed),
});
return (imbalance, not_slashed)
return (imbalance, not_slashed);
},
Err(_) => (),
}
Expand Down Expand Up @@ -1902,7 +1908,7 @@ where
value: Self::Balance,
) -> DispatchResult {
if value.is_zero() {
return Ok(())
return Ok(());
}

Reserves::<T, I>::try_mutate(who, |reserves| -> DispatchResult {
Expand Down Expand Up @@ -1931,7 +1937,7 @@ where
value: Self::Balance,
) -> Self::Balance {
if value.is_zero() {
return Zero::zero()
return Zero::zero();
}

Reserves::<T, I>::mutate_exists(who, |maybe_reserves| -> Self::Balance {
Expand Down Expand Up @@ -1978,7 +1984,7 @@ where
value: Self::Balance,
) -> (Self::NegativeImbalance, Self::Balance) {
if value.is_zero() {
return (NegativeImbalance::zero(), Zero::zero())
return (NegativeImbalance::zero(), Zero::zero());
}

Reserves::<T, I>::mutate(who, |reserves| -> (Self::NegativeImbalance, Self::Balance) {
Expand Down Expand Up @@ -2017,15 +2023,16 @@ where
status: Status,
) -> Result<Self::Balance, DispatchError> {
if value.is_zero() {
return Ok(Zero::zero())
return Ok(Zero::zero());
}

if slashed == beneficiary {
return match status {
Status::Free => Ok(Self::unreserve_named(id, slashed, value)),
Status::Reserved =>
Ok(value.saturating_sub(Self::reserved_balance_named(id, slashed))),
}
Status::Reserved => {
Ok(value.saturating_sub(Self::reserved_balance_named(id, slashed)))
},
};
}

Reserves::<T, I>::try_mutate(slashed, |reserves| -> Result<Self::Balance, DispatchError> {
Expand Down Expand Up @@ -2123,7 +2130,7 @@ where
reasons: WithdrawReasons,
) {
if amount.is_zero() || reasons.is_empty() {
return
return;
}
let mut new_lock = Some(BalanceLock { id, amount, reasons: reasons.into() });
let mut locks = Self::locks(who)
Expand All @@ -2145,7 +2152,7 @@ where
reasons: WithdrawReasons,
) {
if amount.is_zero() || reasons.is_empty() {
return
return;
}
let mut new_lock = Some(BalanceLock { id, amount, reasons: reasons.into() });
let mut locks = Self::locks(who)
Expand Down
Loading

0 comments on commit 9bdc51a

Please sign in to comment.