#![cfg_attr(not(feature = "std"), no_std)]
#![allow(clippy::unused_unit)]
use frame_support::{
pallet_prelude::*,
traits::{
Currency as PalletCurrency, ExistenceRequirement, Get, Imbalance, LockableCurrency as PalletLockableCurrency,
NamedReservableCurrency as PalletNamedReservableCurrency, ReservableCurrency as PalletReservableCurrency,
WithdrawReasons,
},
};
use frame_system::{ensure_root, ensure_signed, pallet_prelude::*};
use orml_traits::{
arithmetic::{Signed, SimpleArithmetic},
currency::TransferAll,
BalanceStatus, BasicCurrency, BasicCurrencyExtended, BasicLockableCurrency, BasicReservableCurrency,
LockIdentifier, MultiCurrency, MultiCurrencyExtended, MultiLockableCurrency, MultiReservableCurrency,
NamedBasicReservableCurrency, NamedMultiReservableCurrency,
};
use orml_utilities::with_transaction_result;
use parity_scale_codec::Codec;
use sp_runtime::{
traits::{CheckedSub, MaybeSerializeDeserialize, StaticLookup, Zero},
DispatchError, DispatchResult,
};
use sp_std::{fmt::Debug, marker, result};
mod mock;
mod tests;
mod weights;
pub use module::*;
pub use weights::WeightInfo;
#[frame_support::pallet]
pub mod module {
use super::*;
pub(crate) type BalanceOf<T> =
<<T as Config>::MultiCurrency as MultiCurrency<<T as frame_system::Config>::AccountId>>::Balance;
pub(crate) type CurrencyIdOf<T> =
<<T as Config>::MultiCurrency as MultiCurrency<<T as frame_system::Config>::AccountId>>::CurrencyId;
pub(crate) type AmountOf<T> =
<<T as Config>::MultiCurrency as MultiCurrencyExtended<<T as frame_system::Config>::AccountId>>::Amount;
pub(crate) type ReserveIdentifierOf<T> = <<T as Config>::MultiCurrency as NamedMultiReservableCurrency<
<T as frame_system::Config>::AccountId,
>>::ReserveIdentifier;
#[pallet::config]
pub trait Config: frame_system::Config {
type MultiCurrency: TransferAll<Self::AccountId>
+ MultiCurrencyExtended<Self::AccountId>
+ MultiLockableCurrency<Self::AccountId>
+ MultiReservableCurrency<Self::AccountId>
+ NamedMultiReservableCurrency<Self::AccountId>;
type NativeCurrency: BasicCurrencyExtended<Self::AccountId, Balance = BalanceOf<Self>, Amount = AmountOf<Self>>
+ BasicLockableCurrency<Self::AccountId, Balance = BalanceOf<Self>>
+ BasicReservableCurrency<Self::AccountId, Balance = BalanceOf<Self>>
+ NamedBasicReservableCurrency<Self::AccountId, ReserveIdentifierOf<Self>, Balance = BalanceOf<Self>>;
#[pallet::constant]
type GetNativeCurrencyId: Get<CurrencyIdOf<Self>>;
type WeightInfo: WeightInfo;
}
#[pallet::error]
pub enum Error<T> {
AmountIntoBalanceFailed,
BalanceTooLow,
DepositFailed,
}
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight(T::WeightInfo::transfer_non_native_currency())]
pub fn transfer(
origin: OriginFor<T>,
dest: <T::Lookup as StaticLookup>::Source,
currency_id: CurrencyIdOf<T>,
#[pallet::compact] amount: BalanceOf<T>,
) -> DispatchResult {
let from = ensure_signed(origin)?;
let to = T::Lookup::lookup(dest)?;
<Self as MultiCurrency<T::AccountId>>::transfer(currency_id, &from, &to, amount)
}
#[pallet::call_index(1)]
#[pallet::weight(T::WeightInfo::transfer_native_currency())]
pub fn transfer_native_currency(
origin: OriginFor<T>,
dest: <T::Lookup as StaticLookup>::Source,
#[pallet::compact] amount: BalanceOf<T>,
) -> DispatchResult {
let from = ensure_signed(origin)?;
let to = T::Lookup::lookup(dest)?;
T::NativeCurrency::transfer(&from, &to, amount)
}
#[pallet::call_index(2)]
#[pallet::weight(T::WeightInfo::update_balance_non_native_currency())]
pub fn update_balance(
origin: OriginFor<T>,
who: <T::Lookup as StaticLookup>::Source,
currency_id: CurrencyIdOf<T>,
amount: AmountOf<T>,
) -> DispatchResult {
ensure_root(origin)?;
let dest = T::Lookup::lookup(who)?;
<Self as MultiCurrencyExtended<T::AccountId>>::update_balance(currency_id, &dest, amount)
}
}
}
impl<T: Config> MultiCurrency<T::AccountId> for Pallet<T> {
type CurrencyId = CurrencyIdOf<T>;
type Balance = BalanceOf<T>;
fn minimum_balance(currency_id: Self::CurrencyId) -> Self::Balance {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::minimum_balance()
} else {
T::MultiCurrency::minimum_balance(currency_id)
}
}
fn total_issuance(currency_id: Self::CurrencyId) -> Self::Balance {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::total_issuance()
} else {
T::MultiCurrency::total_issuance(currency_id)
}
}
fn total_balance(currency_id: Self::CurrencyId, who: &T::AccountId) -> Self::Balance {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::total_balance(who)
} else {
T::MultiCurrency::total_balance(currency_id, who)
}
}
fn free_balance(currency_id: Self::CurrencyId, who: &T::AccountId) -> Self::Balance {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::free_balance(who)
} else {
T::MultiCurrency::free_balance(currency_id, who)
}
}
fn ensure_can_withdraw(currency_id: Self::CurrencyId, who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::ensure_can_withdraw(who, amount)
} else {
T::MultiCurrency::ensure_can_withdraw(currency_id, who, amount)
}
}
fn transfer(
currency_id: Self::CurrencyId,
from: &T::AccountId,
to: &T::AccountId,
amount: Self::Balance,
) -> DispatchResult {
if amount.is_zero() || from == to {
return Ok(());
}
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::transfer(from, to, amount)
} else {
T::MultiCurrency::transfer(currency_id, from, to, amount)
}
}
fn deposit(currency_id: Self::CurrencyId, who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
if amount.is_zero() {
return Ok(());
}
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::deposit(who, amount)
} else {
T::MultiCurrency::deposit(currency_id, who, amount)
}
}
fn withdraw(currency_id: Self::CurrencyId, who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
if amount.is_zero() {
return Ok(());
}
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::withdraw(who, amount)
} else {
T::MultiCurrency::withdraw(currency_id, who, amount)
}
}
fn can_slash(currency_id: Self::CurrencyId, who: &T::AccountId, amount: Self::Balance) -> bool {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::can_slash(who, amount)
} else {
T::MultiCurrency::can_slash(currency_id, who, amount)
}
}
fn slash(currency_id: Self::CurrencyId, who: &T::AccountId, amount: Self::Balance) -> Self::Balance {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::slash(who, amount)
} else {
T::MultiCurrency::slash(currency_id, who, amount)
}
}
}
impl<T: Config> MultiCurrencyExtended<T::AccountId> for Pallet<T> {
type Amount = AmountOf<T>;
fn update_balance(currency_id: Self::CurrencyId, who: &T::AccountId, by_amount: Self::Amount) -> DispatchResult {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::update_balance(who, by_amount)
} else {
T::MultiCurrency::update_balance(currency_id, who, by_amount)
}
}
}
impl<T: Config> MultiLockableCurrency<T::AccountId> for Pallet<T> {
type Moment = BlockNumberFor<T>;
fn set_lock(
lock_id: LockIdentifier,
currency_id: Self::CurrencyId,
who: &T::AccountId,
amount: Self::Balance,
) -> DispatchResult {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::set_lock(lock_id, who, amount)
} else {
T::MultiCurrency::set_lock(lock_id, currency_id, who, amount)
}
}
fn extend_lock(
lock_id: LockIdentifier,
currency_id: Self::CurrencyId,
who: &T::AccountId,
amount: Self::Balance,
) -> DispatchResult {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::extend_lock(lock_id, who, amount)
} else {
T::MultiCurrency::extend_lock(lock_id, currency_id, who, amount)
}
}
fn remove_lock(lock_id: LockIdentifier, currency_id: Self::CurrencyId, who: &T::AccountId) -> DispatchResult {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::remove_lock(lock_id, who)
} else {
T::MultiCurrency::remove_lock(lock_id, currency_id, who)
}
}
}
impl<T: Config> MultiReservableCurrency<T::AccountId> for Pallet<T> {
fn can_reserve(currency_id: Self::CurrencyId, who: &T::AccountId, value: Self::Balance) -> bool {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::can_reserve(who, value)
} else {
T::MultiCurrency::can_reserve(currency_id, who, value)
}
}
fn slash_reserved(currency_id: Self::CurrencyId, who: &T::AccountId, value: Self::Balance) -> Self::Balance {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::slash_reserved(who, value)
} else {
T::MultiCurrency::slash_reserved(currency_id, who, value)
}
}
fn reserved_balance(currency_id: Self::CurrencyId, who: &T::AccountId) -> Self::Balance {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::reserved_balance(who)
} else {
T::MultiCurrency::reserved_balance(currency_id, who)
}
}
fn reserve(currency_id: Self::CurrencyId, who: &T::AccountId, value: Self::Balance) -> DispatchResult {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::reserve(who, value)
} else {
T::MultiCurrency::reserve(currency_id, who, value)
}
}
fn unreserve(currency_id: Self::CurrencyId, who: &T::AccountId, value: Self::Balance) -> Self::Balance {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::unreserve(who, value)
} else {
T::MultiCurrency::unreserve(currency_id, who, value)
}
}
fn repatriate_reserved(
currency_id: Self::CurrencyId,
slashed: &T::AccountId,
beneficiary: &T::AccountId,
value: Self::Balance,
status: BalanceStatus,
) -> result::Result<Self::Balance, DispatchError> {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::repatriate_reserved(slashed, beneficiary, value, status)
} else {
T::MultiCurrency::repatriate_reserved(currency_id, slashed, beneficiary, value, status)
}
}
}
impl<T: Config> NamedMultiReservableCurrency<T::AccountId> for Pallet<T> {
type ReserveIdentifier = ReserveIdentifierOf<T>;
fn slash_reserved_named(
id: &Self::ReserveIdentifier,
currency_id: Self::CurrencyId,
who: &T::AccountId,
value: Self::Balance,
) -> Self::Balance {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::slash_reserved_named(id, who, value)
} else {
T::MultiCurrency::slash_reserved_named(id, currency_id, who, value)
}
}
fn reserved_balance_named(
id: &Self::ReserveIdentifier,
currency_id: Self::CurrencyId,
who: &T::AccountId,
) -> Self::Balance {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::reserved_balance_named(id, who)
} else {
T::MultiCurrency::reserved_balance_named(id, currency_id, who)
}
}
fn reserve_named(
id: &Self::ReserveIdentifier,
currency_id: Self::CurrencyId,
who: &T::AccountId,
value: Self::Balance,
) -> DispatchResult {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::reserve_named(id, who, value)
} else {
T::MultiCurrency::reserve_named(id, currency_id, who, value)
}
}
fn unreserve_named(
id: &Self::ReserveIdentifier,
currency_id: Self::CurrencyId,
who: &T::AccountId,
value: Self::Balance,
) -> Self::Balance {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::unreserve_named(id, who, value)
} else {
T::MultiCurrency::unreserve_named(id, currency_id, who, value)
}
}
fn repatriate_reserved_named(
id: &Self::ReserveIdentifier,
currency_id: Self::CurrencyId,
slashed: &T::AccountId,
beneficiary: &T::AccountId,
value: Self::Balance,
status: BalanceStatus,
) -> result::Result<Self::Balance, DispatchError> {
if currency_id == T::GetNativeCurrencyId::get() {
T::NativeCurrency::repatriate_reserved_named(id, slashed, beneficiary, value, status)
} else {
T::MultiCurrency::repatriate_reserved_named(id, currency_id, slashed, beneficiary, value, status)
}
}
}
pub struct Currency<T, GetCurrencyId>(marker::PhantomData<T>, marker::PhantomData<GetCurrencyId>);
impl<T, GetCurrencyId> BasicCurrency<T::AccountId> for Currency<T, GetCurrencyId>
where
T: Config,
GetCurrencyId: Get<CurrencyIdOf<T>>,
{
type Balance = BalanceOf<T>;
fn minimum_balance() -> Self::Balance {
<Pallet<T>>::minimum_balance(GetCurrencyId::get())
}
fn total_issuance() -> Self::Balance {
<Pallet<T>>::total_issuance(GetCurrencyId::get())
}
fn total_balance(who: &T::AccountId) -> Self::Balance {
<Pallet<T>>::total_balance(GetCurrencyId::get(), who)
}
fn free_balance(who: &T::AccountId) -> Self::Balance {
<Pallet<T>>::free_balance(GetCurrencyId::get(), who)
}
fn ensure_can_withdraw(who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
<Pallet<T>>::ensure_can_withdraw(GetCurrencyId::get(), who, amount)
}
fn transfer(from: &T::AccountId, to: &T::AccountId, amount: Self::Balance) -> DispatchResult {
<Pallet<T> as MultiCurrency<T::AccountId>>::transfer(GetCurrencyId::get(), from, to, amount)
}
fn deposit(who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
<Pallet<T>>::deposit(GetCurrencyId::get(), who, amount)
}
fn withdraw(who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
<Pallet<T>>::withdraw(GetCurrencyId::get(), who, amount)
}
fn can_slash(who: &T::AccountId, amount: Self::Balance) -> bool {
<Pallet<T>>::can_slash(GetCurrencyId::get(), who, amount)
}
fn slash(who: &T::AccountId, amount: Self::Balance) -> Self::Balance {
<Pallet<T>>::slash(GetCurrencyId::get(), who, amount)
}
}
impl<T, GetCurrencyId> BasicCurrencyExtended<T::AccountId> for Currency<T, GetCurrencyId>
where
T: Config,
GetCurrencyId: Get<CurrencyIdOf<T>>,
{
type Amount = AmountOf<T>;
fn update_balance(who: &T::AccountId, by_amount: Self::Amount) -> DispatchResult {
<Pallet<T> as MultiCurrencyExtended<T::AccountId>>::update_balance(GetCurrencyId::get(), who, by_amount)
}
}
impl<T, GetCurrencyId> BasicLockableCurrency<T::AccountId> for Currency<T, GetCurrencyId>
where
T: Config,
GetCurrencyId: Get<CurrencyIdOf<T>>,
{
type Moment = BlockNumberFor<T>;
fn set_lock(lock_id: LockIdentifier, who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
<Pallet<T> as MultiLockableCurrency<T::AccountId>>::set_lock(lock_id, GetCurrencyId::get(), who, amount)
}
fn extend_lock(lock_id: LockIdentifier, who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
<Pallet<T> as MultiLockableCurrency<T::AccountId>>::extend_lock(lock_id, GetCurrencyId::get(), who, amount)
}
fn remove_lock(lock_id: LockIdentifier, who: &T::AccountId) -> DispatchResult {
<Pallet<T> as MultiLockableCurrency<T::AccountId>>::remove_lock(lock_id, GetCurrencyId::get(), who)
}
}
impl<T, GetCurrencyId> BasicReservableCurrency<T::AccountId> for Currency<T, GetCurrencyId>
where
T: Config,
GetCurrencyId: Get<CurrencyIdOf<T>>,
{
fn can_reserve(who: &T::AccountId, value: Self::Balance) -> bool {
<Pallet<T> as MultiReservableCurrency<T::AccountId>>::can_reserve(GetCurrencyId::get(), who, value)
}
fn slash_reserved(who: &T::AccountId, value: Self::Balance) -> Self::Balance {
<Pallet<T> as MultiReservableCurrency<T::AccountId>>::slash_reserved(GetCurrencyId::get(), who, value)
}
fn reserved_balance(who: &T::AccountId) -> Self::Balance {
<Pallet<T> as MultiReservableCurrency<T::AccountId>>::reserved_balance(GetCurrencyId::get(), who)
}
fn reserve(who: &T::AccountId, value: Self::Balance) -> DispatchResult {
<Pallet<T> as MultiReservableCurrency<T::AccountId>>::reserve(GetCurrencyId::get(), who, value)
}
fn unreserve(who: &T::AccountId, value: Self::Balance) -> Self::Balance {
<Pallet<T> as MultiReservableCurrency<T::AccountId>>::unreserve(GetCurrencyId::get(), who, value)
}
fn repatriate_reserved(
slashed: &T::AccountId,
beneficiary: &T::AccountId,
value: Self::Balance,
status: BalanceStatus,
) -> result::Result<Self::Balance, DispatchError> {
<Pallet<T> as MultiReservableCurrency<T::AccountId>>::repatriate_reserved(
GetCurrencyId::get(),
slashed,
beneficiary,
value,
status,
)
}
}
impl<T, GetCurrencyId> NamedBasicReservableCurrency<T::AccountId, ReserveIdentifierOf<T>> for Currency<T, GetCurrencyId>
where
T: Config,
GetCurrencyId: Get<CurrencyIdOf<T>>,
{
fn slash_reserved_named(id: &ReserveIdentifierOf<T>, who: &T::AccountId, value: Self::Balance) -> Self::Balance {
<Pallet<T> as NamedMultiReservableCurrency<T::AccountId>>::slash_reserved_named(
id,
GetCurrencyId::get(),
who,
value,
)
}
fn reserved_balance_named(id: &ReserveIdentifierOf<T>, who: &T::AccountId) -> Self::Balance {
<Pallet<T> as NamedMultiReservableCurrency<T::AccountId>>::reserved_balance_named(id, GetCurrencyId::get(), who)
}
fn reserve_named(id: &ReserveIdentifierOf<T>, who: &T::AccountId, value: Self::Balance) -> DispatchResult {
<Pallet<T> as NamedMultiReservableCurrency<T::AccountId>>::reserve_named(id, GetCurrencyId::get(), who, value)
}
fn unreserve_named(id: &ReserveIdentifierOf<T>, who: &T::AccountId, value: Self::Balance) -> Self::Balance {
<Pallet<T> as NamedMultiReservableCurrency<T::AccountId>>::unreserve_named(id, GetCurrencyId::get(), who, value)
}
fn repatriate_reserved_named(
id: &ReserveIdentifierOf<T>,
slashed: &T::AccountId,
beneficiary: &T::AccountId,
value: Self::Balance,
status: BalanceStatus,
) -> result::Result<Self::Balance, DispatchError> {
<Pallet<T> as NamedMultiReservableCurrency<T::AccountId>>::repatriate_reserved_named(
id,
GetCurrencyId::get(),
slashed,
beneficiary,
value,
status,
)
}
}
pub type NativeCurrencyOf<T> = Currency<T, <T as Config>::GetNativeCurrencyId>;
pub struct BasicCurrencyAdapter<T, Currency, Amount, Moment>(marker::PhantomData<(T, Currency, Amount, Moment)>);
type PalletBalanceOf<A, Currency> = <Currency as PalletCurrency<A>>::Balance;
impl<T, AccountId, Currency, Amount, Moment> BasicCurrency<AccountId>
for BasicCurrencyAdapter<T, Currency, Amount, Moment>
where
Currency: PalletCurrency<AccountId>,
T: Config,
{
type Balance = PalletBalanceOf<AccountId, Currency>;
fn minimum_balance() -> Self::Balance {
Currency::minimum_balance()
}
fn total_issuance() -> Self::Balance {
Currency::total_issuance()
}
fn total_balance(who: &AccountId) -> Self::Balance {
Currency::total_balance(who)
}
fn free_balance(who: &AccountId) -> Self::Balance {
Currency::free_balance(who)
}
fn ensure_can_withdraw(who: &AccountId, amount: Self::Balance) -> DispatchResult {
let new_balance = Self::free_balance(who)
.checked_sub(&amount)
.ok_or(Error::<T>::BalanceTooLow)?;
Currency::ensure_can_withdraw(who, amount, WithdrawReasons::all(), new_balance)
}
fn transfer(from: &AccountId, to: &AccountId, amount: Self::Balance) -> DispatchResult {
Currency::transfer(from, to, amount, ExistenceRequirement::AllowDeath)
}
fn deposit(who: &AccountId, amount: Self::Balance) -> DispatchResult {
if !amount.is_zero() {
let deposit_result = Currency::deposit_creating(who, amount);
let actual_deposit = deposit_result.peek();
ensure!(actual_deposit == amount, Error::<T>::DepositFailed);
}
Ok(())
}
fn withdraw(who: &AccountId, amount: Self::Balance) -> DispatchResult {
Currency::withdraw(who, amount, WithdrawReasons::all(), ExistenceRequirement::AllowDeath).map(|_| ())
}
fn can_slash(who: &AccountId, amount: Self::Balance) -> bool {
Currency::can_slash(who, amount)
}
fn slash(who: &AccountId, amount: Self::Balance) -> Self::Balance {
let (_, gap) = Currency::slash(who, amount);
gap
}
}
impl<T, AccountId, Currency, Amount, Moment> BasicCurrencyExtended<AccountId>
for BasicCurrencyAdapter<T, Currency, Amount, Moment>
where
Amount: Signed
+ TryInto<PalletBalanceOf<AccountId, Currency>>
+ TryFrom<PalletBalanceOf<AccountId, Currency>>
+ SimpleArithmetic
+ Codec
+ Copy
+ MaybeSerializeDeserialize
+ Debug
+ Default
+ parity_scale_codec::MaxEncodedLen,
Currency: PalletCurrency<AccountId>,
T: Config,
{
type Amount = Amount;
fn update_balance(who: &AccountId, by_amount: Self::Amount) -> DispatchResult {
let by_balance = by_amount
.abs()
.try_into()
.map_err(|_| Error::<T>::AmountIntoBalanceFailed)?;
if by_amount.is_positive() {
Self::deposit(who, by_balance)
} else {
Self::withdraw(who, by_balance)
}
}
}
impl<T, AccountId, Currency, Amount, Moment> BasicLockableCurrency<AccountId>
for BasicCurrencyAdapter<T, Currency, Amount, Moment>
where
Currency: PalletLockableCurrency<AccountId>,
T: Config,
{
type Moment = Moment;
fn set_lock(lock_id: LockIdentifier, who: &AccountId, amount: Self::Balance) -> DispatchResult {
Currency::set_lock(lock_id, who, amount, WithdrawReasons::all());
Ok(())
}
fn extend_lock(lock_id: LockIdentifier, who: &AccountId, amount: Self::Balance) -> DispatchResult {
Currency::extend_lock(lock_id, who, amount, WithdrawReasons::all());
Ok(())
}
fn remove_lock(lock_id: LockIdentifier, who: &AccountId) -> DispatchResult {
Currency::remove_lock(lock_id, who);
Ok(())
}
}
impl<T, AccountId, Currency, Amount, Moment> BasicReservableCurrency<AccountId>
for BasicCurrencyAdapter<T, Currency, Amount, Moment>
where
Currency: PalletReservableCurrency<AccountId>,
T: Config,
{
fn can_reserve(who: &AccountId, value: Self::Balance) -> bool {
Currency::can_reserve(who, value)
}
fn slash_reserved(who: &AccountId, value: Self::Balance) -> Self::Balance {
let (_, gap) = Currency::slash_reserved(who, value);
gap
}
fn reserved_balance(who: &AccountId) -> Self::Balance {
Currency::reserved_balance(who)
}
fn reserve(who: &AccountId, value: Self::Balance) -> DispatchResult {
Currency::reserve(who, value)
}
fn unreserve(who: &AccountId, value: Self::Balance) -> Self::Balance {
Currency::unreserve(who, value)
}
fn repatriate_reserved(
slashed: &AccountId,
beneficiary: &AccountId,
value: Self::Balance,
status: BalanceStatus,
) -> result::Result<Self::Balance, DispatchError> {
Currency::repatriate_reserved(slashed, beneficiary, value, status)
}
}
impl<T, AccountId, Currency, Amount, Moment, ReserveIdentifier>
NamedBasicReservableCurrency<AccountId, ReserveIdentifier> for BasicCurrencyAdapter<T, Currency, Amount, Moment>
where
Currency: PalletNamedReservableCurrency<AccountId, ReserveIdentifier = ReserveIdentifier>,
T: Config,
{
fn slash_reserved_named(id: &ReserveIdentifier, who: &AccountId, value: Self::Balance) -> Self::Balance {
let (_, gap) = Currency::slash_reserved_named(id, who, value);
gap
}
fn reserved_balance_named(id: &ReserveIdentifier, who: &AccountId) -> Self::Balance {
Currency::reserved_balance_named(id, who)
}
fn reserve_named(id: &ReserveIdentifier, who: &AccountId, value: Self::Balance) -> DispatchResult {
Currency::reserve_named(id, who, value)
}
fn unreserve_named(id: &ReserveIdentifier, who: &AccountId, value: Self::Balance) -> Self::Balance {
Currency::unreserve_named(id, who, value)
}
fn repatriate_reserved_named(
id: &ReserveIdentifier,
slashed: &AccountId,
beneficiary: &AccountId,
value: Self::Balance,
status: BalanceStatus,
) -> result::Result<Self::Balance, DispatchError> {
Currency::repatriate_reserved_named(id, slashed, beneficiary, value, status)
}
}
impl<T: Config> TransferAll<T::AccountId> for Pallet<T> {
fn transfer_all(source: &T::AccountId, dest: &T::AccountId) -> DispatchResult {
with_transaction_result(|| {
T::MultiCurrency::transfer_all(source, dest)?;
T::NativeCurrency::transfer(source, dest, T::NativeCurrency::free_balance(source))
})
}
}