mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 09:21:05 +00:00
Allow Creation of Asset Accounts That Don't Exist Yet and Add Blocked Status (#13843)
* prevent frozen accounts from receiving assets * refund deposits correctly * plus refund_other * add benchmarks * start migration work * docs * add migration logic * fix freeze_creating benchmark * support instanced migrations * review * correct deposit refund * only allow depositor, admin, or account origin to refund deposits * make sure refund actually removes account * do refund changes * Asset's account deposit owner (#13874) * assets deposit owner * doc typo * remove migration * empty commit * can transfer to frozen account * remove allow_burn from refund_other * storage version back to 1 * update doc * fix benches * update docs * more tests * Update frame/assets/src/types.rs * refund updating the reason * refactor * separate refund and refund_foreign * refunds, touch_other, tests * fixes * fmt * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_assets * tests: asserts asset account counts * Account touch trait (#14063) * assets touch trait * docs * move touch trait into support/traits * permissionless flag for do_touch * Apply suggestions from code review Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * move trait to misc, drop option * Apply suggestions from code review Co-authored-by: Gavin Wood <gavin@parity.io> * correct doc * Update frame/assets/src/functions.rs --------- Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Gavin Wood <gavin@parity.io> Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Block asset account (#14070) * replace is_fronzen flag by status enum * block asset account * remove redundant brackets * fix typo * fmt * Apply suggestions from code review Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> * rename permissionless to check_depositor * doc fix * use account id lookup instead account id * add benchmark for touch_other --------- Co-authored-by: muharem <ismailov.m.h@gmail.com> Co-authored-by: command-bot <> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Gavin Wood <gavin@parity.io> Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>
This commit is contained in:
@@ -82,6 +82,10 @@
|
||||
//! * `approve_transfer`: Create or increase an delegated transfer.
|
||||
//! * `cancel_approval`: Rescind a previous approval.
|
||||
//! * `transfer_approved`: Transfer third-party's assets to another account.
|
||||
//! * `touch`: Create an asset account for non-provider assets. Caller must place a deposit.
|
||||
//! * `refund`: Return the deposit (if any) of the caller's asset account or a consumer reference
|
||||
//! (if any) of the caller's account.
|
||||
//! * `refund_other`: Return the deposit (if any) of a specified asset account.
|
||||
//!
|
||||
//! ### Permissioned Functions
|
||||
//!
|
||||
@@ -98,12 +102,16 @@
|
||||
//! * `burn`: Decreases the asset balance of an account; called by the asset class's Admin.
|
||||
//! * `force_transfer`: Transfers between arbitrary accounts; called by the asset class's Admin.
|
||||
//! * `freeze`: Disallows further `transfer`s from an account; called by the asset class's Freezer.
|
||||
//! * `thaw`: Allows further `transfer`s from an account; called by the asset class's Admin.
|
||||
//! * `thaw`: Allows further `transfer`s to and from an account; called by the asset class's Admin.
|
||||
//! * `transfer_ownership`: Changes an asset class's Owner; called by the asset class's Owner.
|
||||
//! * `set_team`: Changes an asset class's Admin, Freezer and Issuer; called by the asset class's
|
||||
//! Owner.
|
||||
//! * `set_metadata`: Set the metadata of an asset class; called by the asset class's Owner.
|
||||
//! * `clear_metadata`: Remove the metadata of an asset class; called by the asset class's Owner.
|
||||
//! * `touch_other`: Create an asset account for specified account. Caller must place a deposit;
|
||||
//! called by the asset class's Freezer or Admin.
|
||||
//! * `block`: Disallows further `transfer`s to and from an account; called by the asset class's
|
||||
//! Freezer.
|
||||
//!
|
||||
//! Please refer to the [`Call`] enum and its associated variants for documentation on each
|
||||
//! function.
|
||||
@@ -194,7 +202,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.
|
||||
@@ -519,6 +527,10 @@ pub mod pallet {
|
||||
AssetStatusChanged { asset_id: T::AssetId },
|
||||
/// The min_balance of an asset has been updated by the asset owner.
|
||||
AssetMinBalanceChanged { asset_id: T::AssetId, new_min_balance: T::Balance },
|
||||
/// Some account `who` was created with a deposit from `depositor`.
|
||||
Touched { asset_id: T::AssetId, who: T::AccountId, depositor: T::AccountId },
|
||||
/// Some account `who` was blocked.
|
||||
Blocked { asset_id: T::AssetId, who: T::AccountId },
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
@@ -911,7 +923,9 @@ pub mod pallet {
|
||||
Self::do_transfer(id, &source, &dest, amount, Some(origin), f).map(|_| ())
|
||||
}
|
||||
|
||||
/// Disallow further unprivileged transfers from an account.
|
||||
/// Disallow further unprivileged transfers of an asset `id` from an account `who`. `who`
|
||||
/// must already exist as an entry in `Account`s of the asset. If you want to freeze an
|
||||
/// account that does not have an entry, use `touch_other` first.
|
||||
///
|
||||
/// Origin must be Signed and the sender should be the Freezer of the asset `id`.
|
||||
///
|
||||
@@ -939,7 +953,8 @@ pub mod pallet {
|
||||
let who = T::Lookup::lookup(who)?;
|
||||
|
||||
Account::<T, I>::try_mutate(id, &who, |maybe_account| -> DispatchResult {
|
||||
maybe_account.as_mut().ok_or(Error::<T, I>::NoAccount)?.is_frozen = true;
|
||||
maybe_account.as_mut().ok_or(Error::<T, I>::NoAccount)?.status =
|
||||
AccountStatus::Frozen;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -947,7 +962,7 @@ pub mod pallet {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Allow unprivileged transfers from an account again.
|
||||
/// Allow unprivileged transfers to and from an account again.
|
||||
///
|
||||
/// Origin must be Signed and the sender should be the Admin of the asset `id`.
|
||||
///
|
||||
@@ -975,7 +990,8 @@ pub mod pallet {
|
||||
let who = T::Lookup::lookup(who)?;
|
||||
|
||||
Account::<T, I>::try_mutate(id, &who, |maybe_account| -> DispatchResult {
|
||||
maybe_account.as_mut().ok_or(Error::<T, I>::NoAccount)?.is_frozen = false;
|
||||
maybe_account.as_mut().ok_or(Error::<T, I>::NoAccount)?.status =
|
||||
AccountStatus::Liquid;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -1471,22 +1487,25 @@ pub mod pallet {
|
||||
///
|
||||
/// Emits `Touched` event when successful.
|
||||
#[pallet::call_index(26)]
|
||||
#[pallet::weight(T::WeightInfo::mint())]
|
||||
#[pallet::weight(T::WeightInfo::touch())]
|
||||
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, ensure_signed(origin)?)
|
||||
Self::do_touch(id, who.clone(), who, false)
|
||||
}
|
||||
|
||||
/// Return the deposit (if any) of an asset account.
|
||||
/// Return the deposit (if any) of an asset account or a consumer reference (if any) of an
|
||||
/// account.
|
||||
///
|
||||
/// The origin must be Signed.
|
||||
///
|
||||
/// - `id`: The identifier of the asset for the account to be created.
|
||||
/// - `id`: The identifier of the asset for which the caller would like the deposit
|
||||
/// refunded.
|
||||
/// - `allow_burn`: If `true` then assets may be destroyed in order to complete the refund.
|
||||
///
|
||||
/// Emits `Refunded` event when successful.
|
||||
#[pallet::call_index(27)]
|
||||
#[pallet::weight(T::WeightInfo::mint())]
|
||||
#[pallet::weight(T::WeightInfo::refund())]
|
||||
pub fn refund(
|
||||
origin: OriginFor<T>,
|
||||
id: T::AssetIdParameter,
|
||||
@@ -1541,6 +1560,104 @@ pub mod pallet {
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Create an asset account for `who`.
|
||||
///
|
||||
/// A deposit will be taken from the signer account.
|
||||
///
|
||||
/// - `origin`: Must be Signed by `Freezer` or `Admin` of the asset `id`; 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.
|
||||
/// - `who`: The account to be created.
|
||||
///
|
||||
/// Emits `Touched` event when successful.
|
||||
#[pallet::call_index(29)]
|
||||
#[pallet::weight(T::WeightInfo::touch_other())]
|
||||
pub fn touch_other(
|
||||
origin: OriginFor<T>,
|
||||
id: T::AssetIdParameter,
|
||||
who: AccountIdLookupOf<T>,
|
||||
) -> DispatchResult {
|
||||
let origin = ensure_signed(origin)?;
|
||||
let who = T::Lookup::lookup(who)?;
|
||||
let id: T::AssetId = id.into();
|
||||
Self::do_touch(id, who, origin, true)
|
||||
}
|
||||
|
||||
/// Return the deposit (if any) of a target asset account. Useful if you are the depositor.
|
||||
///
|
||||
/// The origin must be Signed and either the account owner, depositor, or asset `Admin`. In
|
||||
/// order to burn a non-zero balance of the asset, the caller must be the account and should
|
||||
/// use `refund`.
|
||||
///
|
||||
/// - `id`: The identifier of the asset for the account holding a deposit.
|
||||
/// - `who`: The account to refund.
|
||||
///
|
||||
/// Emits `Refunded` event when successful.
|
||||
#[pallet::call_index(30)]
|
||||
#[pallet::weight(T::WeightInfo::refund_other())]
|
||||
pub fn refund_other(
|
||||
origin: OriginFor<T>,
|
||||
id: T::AssetIdParameter,
|
||||
who: AccountIdLookupOf<T>,
|
||||
) -> DispatchResult {
|
||||
let origin = ensure_signed(origin)?;
|
||||
let who = T::Lookup::lookup(who)?;
|
||||
let id: T::AssetId = id.into();
|
||||
Self::do_refund_other(id, &who, &origin)
|
||||
}
|
||||
|
||||
/// Disallow further unprivileged transfers of an asset `id` to and from an account `who`.
|
||||
///
|
||||
/// Origin must be Signed and the sender should be the Freezer of the asset `id`.
|
||||
///
|
||||
/// - `id`: The identifier of the account's asset.
|
||||
/// - `who`: The account to be unblocked.
|
||||
///
|
||||
/// Emits `Blocked`.
|
||||
///
|
||||
/// Weight: `O(1)`
|
||||
#[pallet::call_index(31)]
|
||||
pub fn block(
|
||||
origin: OriginFor<T>,
|
||||
id: T::AssetIdParameter,
|
||||
who: AccountIdLookupOf<T>,
|
||||
) -> DispatchResult {
|
||||
let origin = ensure_signed(origin)?;
|
||||
let id: T::AssetId = id.into();
|
||||
|
||||
let d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?;
|
||||
ensure!(
|
||||
d.status == AssetStatus::Live || d.status == AssetStatus::Frozen,
|
||||
Error::<T, I>::AssetNotLive
|
||||
);
|
||||
ensure!(origin == d.freezer, Error::<T, I>::NoPermission);
|
||||
let who = T::Lookup::lookup(who)?;
|
||||
|
||||
Account::<T, I>::try_mutate(id, &who, |maybe_account| -> DispatchResult {
|
||||
maybe_account.as_mut().ok_or(Error::<T, I>::NoAccount)?.status =
|
||||
AccountStatus::Blocked;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Self::deposit_event(Event::<T, I>::Blocked { asset_id: id, who });
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// 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_required() -> Self::Balance {
|
||||
T::AssetAccountDeposit::get()
|
||||
}
|
||||
|
||||
fn touch(asset: T::AssetId, who: T::AccountId, depositor: T::AccountId) -> DispatchResult {
|
||||
Self::do_touch(asset, who, depositor, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user