use cfg_traits::PreConditions;
use frame_support::traits::{
BalanceStatus, Currency, ExistenceRequirement, LockIdentifier, LockableCurrency,
ReservableCurrency, SignedImbalance, WithdrawReasons,
};
use super::*;
pub enum CurrencyEffects<AccountId, Balance> {
CanSlash(AccountId, Balance, bool),
EnsureCanWithdraw(AccountId, Balance, WithdrawReasons, Balance, DispatchResult),
Transfer(AccountId, AccountId, Balance, ExistenceRequirement),
Withdraw(AccountId, Balance, WithdrawReasons, ExistenceRequirement),
DepositIntoExisting(AccountId, Balance),
}
impl<T: Config> Currency<T::AccountId> for Pallet<T> {
type Balance = T::Balance;
type NegativeImbalance = <T::NativeFungible as Currency<T::AccountId>>::NegativeImbalance;
type PositiveImbalance = <T::NativeFungible as Currency<T::AccountId>>::PositiveImbalance;
fn total_balance(who: &T::AccountId) -> Self::Balance {
<T::NativeFungible as Currency<T::AccountId>>::total_balance(who)
}
fn can_slash(who: &T::AccountId, value: Self::Balance) -> bool {
T::PreCurrency::check(CurrencyEffects::CanSlash(
who.clone(),
value,
<T::NativeFungible as Currency<T::AccountId>>::can_slash(who, value),
))
}
fn total_issuance() -> Self::Balance {
<T::NativeFungible as Currency<T::AccountId>>::total_issuance()
}
fn minimum_balance() -> Self::Balance {
<T::NativeFungible as Currency<T::AccountId>>::minimum_balance()
}
fn burn(amount: Self::Balance) -> Self::PositiveImbalance {
<T::NativeFungible as Currency<T::AccountId>>::burn(amount)
}
fn issue(amount: Self::Balance) -> Self::NegativeImbalance {
<T::NativeFungible as Currency<T::AccountId>>::issue(amount)
}
fn free_balance(who: &T::AccountId) -> Self::Balance {
<T::NativeFungible as Currency<T::AccountId>>::free_balance(who)
}
fn ensure_can_withdraw(
who: &T::AccountId,
_amount: Self::Balance,
reasons: WithdrawReasons,
new_balance: Self::Balance,
) -> DispatchResult {
ensure!(
T::PreCurrency::check(CurrencyEffects::EnsureCanWithdraw(
who.clone(),
_amount,
reasons,
new_balance,
<T::NativeFungible as Currency<T::AccountId>>::ensure_can_withdraw(
who,
_amount,
reasons,
new_balance,
)
)),
Error::<T>::PreConditionsNotMet
);
Ok(())
}
fn transfer(
source: &T::AccountId,
dest: &T::AccountId,
value: Self::Balance,
existence_requirement: ExistenceRequirement,
) -> DispatchResult {
ensure!(
T::PreCurrency::check(CurrencyEffects::Transfer(
source.clone(),
dest.clone(),
value,
existence_requirement
)),
Error::<T>::PreConditionsNotMet
);
<T::NativeFungible as Currency<T::AccountId>>::transfer(
source,
dest,
value,
existence_requirement,
)
}
fn slash(who: &T::AccountId, value: Self::Balance) -> (Self::NegativeImbalance, Self::Balance) {
<T::NativeFungible as Currency<T::AccountId>>::slash(who, value)
}
fn deposit_into_existing(
who: &T::AccountId,
value: Self::Balance,
) -> Result<Self::PositiveImbalance, DispatchError> {
ensure!(
T::PreCurrency::check(CurrencyEffects::DepositIntoExisting(who.clone(), value,)),
Error::<T>::PreConditionsNotMet
);
<T::NativeFungible as Currency<T::AccountId>>::deposit_into_existing(who, value)
}
fn deposit_creating(who: &T::AccountId, value: Self::Balance) -> Self::PositiveImbalance {
<T::NativeFungible as Currency<T::AccountId>>::deposit_creating(who, value)
}
fn withdraw(
who: &T::AccountId,
value: Self::Balance,
reasons: WithdrawReasons,
liveness: ExistenceRequirement,
) -> Result<Self::NegativeImbalance, DispatchError> {
ensure!(
T::PreCurrency::check(CurrencyEffects::Withdraw(
who.clone(),
value,
reasons,
liveness
)),
Error::<T>::PreConditionsNotMet
);
<T::NativeFungible as Currency<T::AccountId>>::withdraw(who, value, reasons, liveness)
}
fn make_free_balance_be(
who: &T::AccountId,
balance: Self::Balance,
) -> SignedImbalance<Self::Balance, Self::PositiveImbalance> {
<T::NativeFungible as Currency<T::AccountId>>::make_free_balance_be(who, balance)
}
}
pub enum ReservableCurrencyEffects<AccountId, Balance> {
CanReserve(AccountId, Balance, bool),
Reserve(AccountId, Balance),
RepatriateReserved(AccountId, AccountId, Balance, BalanceStatus),
}
impl<T: Config> ReservableCurrency<T::AccountId> for Pallet<T> {
fn can_reserve(who: &T::AccountId, value: Self::Balance) -> bool {
T::PreReservableCurrency::check(ReservableCurrencyEffects::CanReserve(
who.clone(),
value,
<T::NativeFungible as ReservableCurrency<T::AccountId>>::can_reserve(who, value),
))
}
fn slash_reserved(
who: &T::AccountId,
value: Self::Balance,
) -> (Self::NegativeImbalance, Self::Balance) {
<T::NativeFungible as ReservableCurrency<T::AccountId>>::slash_reserved(who, value)
}
fn reserved_balance(who: &T::AccountId) -> Self::Balance {
<T::NativeFungible as ReservableCurrency<T::AccountId>>::reserved_balance(who)
}
fn reserve(who: &T::AccountId, value: Self::Balance) -> DispatchResult {
ensure!(
T::PreReservableCurrency::check(ReservableCurrencyEffects::Reserve(who.clone(), value)),
Error::<T>::PreConditionsNotMet
);
<T::NativeFungible as ReservableCurrency<T::AccountId>>::reserve(who, value)
}
fn unreserve(who: &T::AccountId, value: Self::Balance) -> Self::Balance {
<T::NativeFungible as ReservableCurrency<T::AccountId>>::unreserve(who, value)
}
fn repatriate_reserved(
slashed: &T::AccountId,
beneficiary: &T::AccountId,
value: Self::Balance,
status: BalanceStatus,
) -> Result<Self::Balance, DispatchError> {
ensure!(
T::PreReservableCurrency::check(ReservableCurrencyEffects::RepatriateReserved(
slashed.clone(),
beneficiary.clone(),
value,
status
)),
Error::<T>::PreConditionsNotMet
);
<T::NativeFungible as ReservableCurrency<T::AccountId>>::repatriate_reserved(
slashed,
beneficiary,
value,
status,
)
}
}
impl<T: Config> LockableCurrency<T::AccountId> for Pallet<T> {
type MaxLocks = <T::NativeFungible as LockableCurrency<T::AccountId>>::MaxLocks;
type Moment = <T::NativeFungible as LockableCurrency<T::AccountId>>::Moment;
fn set_lock(
id: LockIdentifier,
who: &T::AccountId,
amount: Self::Balance,
reasons: WithdrawReasons,
) {
<T::NativeFungible as LockableCurrency<T::AccountId>>::set_lock(id, who, amount, reasons)
}
fn extend_lock(
id: LockIdentifier,
who: &T::AccountId,
amount: Self::Balance,
reasons: WithdrawReasons,
) {
<T::NativeFungible as LockableCurrency<T::AccountId>>::extend_lock(id, who, amount, reasons)
}
fn remove_lock(id: LockIdentifier, who: &T::AccountId) {
<T::NativeFungible as LockableCurrency<T::AccountId>>::remove_lock(id, who)
}
}