Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Account touch trait #14063

Merged
merged 10 commits into from
May 4, 2023
Merged
6 changes: 5 additions & 1 deletion frame/assets/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,17 +308,21 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
}

/// Creates an account for `who` to hold asset `id` with a zero balance and takes a deposit.
///
/// If invoked `permissionless = true` than a depositor can be anyone, if `permissioned = false`
/// a depositor must be the asset's `Admin` or `Freezer`.
joepetrowski marked this conversation as resolved.
Show resolved Hide resolved
pub(super) fn do_touch(
id: T::AssetId,
who: T::AccountId,
depositor: T::AccountId,
permissionless: bool,
) -> 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);
ensure!(
&depositor == &who || &depositor == &details.admin || &depositor == &details.freezer,
permissionless || &depositor == &details.admin || &depositor == &details.freezer,
Error::<T, I>::NoPermission
);
let reason = Self::new_account(&who, &mut details, Some((&depositor, deposit)))?;
Expand Down
22 changes: 18 additions & 4 deletions frame/assets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ impl<AssetId, AccountId> AssetsCallback<AssetId, AccountId> for () {}
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
use frame_support::{pallet_prelude::*, traits::AccountTouch};
use frame_system::pallet_prelude::*;

/// The current storage version.
Expand Down Expand Up @@ -1485,7 +1485,7 @@ pub mod pallet {
pub fn touch(origin: OriginFor<T>, id: T::AssetIdParameter) -> DispatchResult {
let who = ensure_signed(origin)?;
let id: T::AssetId = id.into();
Self::do_touch(id, who.clone(), who)
Self::do_touch(id, who.clone(), who, true)
}

/// Return the deposit (if any) of an asset account or a consumer reference (if any) of an
Expand Down Expand Up @@ -1575,8 +1575,7 @@ pub mod pallet {
let origin = ensure_signed(origin)?;
let who = T::Lookup::lookup(who)?;
let id: T::AssetId = id.into();

Self::do_touch(id, who, origin)
Self::do_touch(id, who, origin, false)
}

/// Return the deposit (if any) of a target asset account. Useful if you are the depositor.
Expand All @@ -1601,6 +1600,21 @@ pub mod pallet {
Self::do_refund_other(id, &who, &origin)
}
}

/// Implements [AccountTouch] trait.
/// Note that a depositor can be any account, without any specific privilege.
/// This implementation is supposed to be used only for creation of system accounts.
impl<T: Config<I>, I: 'static> AccountTouch<T::AssetId, T::AccountId> for Pallet<T, I> {
type Balance = DepositBalanceOf<T, I>;

fn deposit() -> Self::Balance {
muharem marked this conversation as resolved.
Show resolved Hide resolved
T::AssetAccountDeposit::get()
}

fn touch(asset: T::AssetId, who: T::AccountId, depositor: T::AccountId) -> DispatchResult {
Self::do_touch(asset, who, depositor, true)
}
}
}

sp_core::generate_feature_enabled_macro!(runtime_benchmarks_enabled, feature = "runtime-benchmarks", $);
4 changes: 2 additions & 2 deletions frame/support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ pub use filter::{ClearFilterGuard, FilterStack, FilterStackGuard, InstanceFilter
mod misc;
pub use misc::{
defensive_prelude::{self, *},
Backing, ConstBool, ConstI128, ConstI16, ConstI32, ConstI64, ConstI8, ConstU128, ConstU16,
ConstU32, ConstU64, ConstU8, DefensiveMax, DefensiveMin, DefensiveSaturating,
AccountTouch, Backing, ConstBool, ConstI128, ConstI16, ConstI32, ConstI64, ConstI8, ConstU128,
ConstU16, ConstU32, ConstU64, ConstU8, DefensiveMax, DefensiveMin, DefensiveSaturating,
DefensiveTruncateFrom, EnsureInherentsAreFirst, EqualPrivilegeOnly, EstimateCallFee,
ExecuteBlock, ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsSubType, IsType,
Len, OffchainWorker, OnKilledAccount, OnNewAccount, PrivilegeCmp, SameOrOther, Time,
Expand Down
14 changes: 13 additions & 1 deletion frame/support/src/traits/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

//! Smaller traits used in FRAME which don't need their own file.

use crate::dispatch::Parameter;
use crate::dispatch::{DispatchResult, Parameter};
use codec::{CompactLen, Decode, DecodeLimit, Encode, EncodeLike, Input, MaxEncodedLen};
use impl_trait_for_tuples::impl_for_tuples;
use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter};
Expand Down Expand Up @@ -1154,6 +1154,18 @@ impl<Hash> PreimageRecipient<Hash> for () {
fn unnote_preimage(_: &Hash) {}
}

/// Trait for creating an asset account with a deposit taken from a specified by client depositor.
muharem marked this conversation as resolved.
Show resolved Hide resolved
pub trait AccountTouch<AssetId, AccountId> {
/// The type for currency units of the deposit.
type Balance;

/// The deposit amount of a native currency required for creating an asset account.
fn deposit() -> Self::Balance;
muharem marked this conversation as resolved.
Show resolved Hide resolved
muharem marked this conversation as resolved.
Show resolved Hide resolved

/// Create an account for `who` of the `asset` with a deposit taken from the `depositor`.
fn touch(asset: AssetId, who: AccountId, depositor: AccountId) -> DispatchResult;
}

#[cfg(test)]
mod test {
use super::*;
Expand Down