As noted in this PR,
Asset accounts (i.e. the storage of a specific account's balance of a
specific asset) can now have three reasons for existing: the old two
(i.e. the asset being "sufficient" or taking up a consumer reference)
as well as having a deposit explicitly held for the asset-account.
This deposit is placed by using the new touch function and refunded by
using the new refund function.
Notice the touch()
function inside the assets pallet:
/// Create an asset account for non-provider assets.
///
/// A deposit will be taken from the signer account.
///
/// - `origin`: Must be Signed; the signer account must have sufficient funds for a deposit
/// to be taken.
/// - `id`: The identifier of the asset for the account to be created.
///
/// Emits `Touched` event when successful.
#[pallet::call_index(26)]
#[pallet::weight(T::WeightInfo::mint())]
pub fn touch(origin: OriginFor<T>, id: T::AssetIdParameter) -> DispatchResult {
let id: T::AssetId = id.into();
Self::do_touch(id, ensure_signed(origin)?)
}
And inside the do_touch()
function, AssetAccountDeposit
is used:
/// Creates a account for `who` to hold asset `id` with a zero balance and takes a deposit.
pub(super) fn do_touch(id: T::AssetId, who: T::AccountId) -> DispatchResult {
ensure!(!Account::<T, I>::contains_key(id, &who), Error::<T, I>::AlreadyExists);
let deposit = T::AssetAccountDeposit::get();
let mut details = Asset::<T, I>::get(&id).ok_or(Error::<T, I>::Unknown)?;
ensure!(details.status == AssetStatus::Live, Error::<T, I>::AssetNotLive);
let reason = Self::new_account(&who, &mut details, Some(deposit))?;
T::Currency::reserve(&who, deposit)?;
Asset::<T, I>::insert(&id, details);
Account::<T, I>::insert(
id,
&who,
AssetAccountOf::<T, I> {
balance: Zero::zero(),
is_frozen: false,
reason,
extra: T::Extra::default(),
},
);
Ok(())
}
If you want to learn more about providers
, consumers
, and sufficients
, there is a great doc here: