mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 17:31:05 +00:00
Fungibles and Non-Fungibles Create and Destroy Traits + Assets and Uniques Implementation (#9844)
* refactor `do_destroy` * destroy trait * refactor do_force_create * impl create trait * do not bleed weight into api * Do the same for uniques * add docs
This commit is contained in:
@@ -478,4 +478,88 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
Self::deposit_event(Event::Transferred(id, source.clone(), dest.clone(), credit));
|
||||
Ok(credit)
|
||||
}
|
||||
|
||||
/// Create a new asset without taking a deposit.
|
||||
///
|
||||
/// * `id`: The `AssetId` you want the new asset to have. Must not already be in use.
|
||||
/// * `owner`: The owner, issuer, admin, and freezer of this asset upon creation.
|
||||
/// * `is_sufficient`: Whether this asset needs users to have an existential deposit to hold
|
||||
/// this asset.
|
||||
/// * `min_balance`: The minimum balance a user is allowed to have of this asset before they are
|
||||
/// considered dust and cleaned up.
|
||||
pub(super) fn do_force_create(
|
||||
id: T::AssetId,
|
||||
owner: T::AccountId,
|
||||
is_sufficient: bool,
|
||||
min_balance: T::Balance,
|
||||
) -> DispatchResult {
|
||||
ensure!(!Asset::<T, I>::contains_key(id), Error::<T, I>::InUse);
|
||||
ensure!(!min_balance.is_zero(), Error::<T, I>::MinBalanceZero);
|
||||
|
||||
Asset::<T, I>::insert(
|
||||
id,
|
||||
AssetDetails {
|
||||
owner: owner.clone(),
|
||||
issuer: owner.clone(),
|
||||
admin: owner.clone(),
|
||||
freezer: owner.clone(),
|
||||
supply: Zero::zero(),
|
||||
deposit: Zero::zero(),
|
||||
min_balance,
|
||||
is_sufficient,
|
||||
accounts: 0,
|
||||
sufficients: 0,
|
||||
approvals: 0,
|
||||
is_frozen: false,
|
||||
},
|
||||
);
|
||||
Self::deposit_event(Event::ForceCreated(id, owner));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Destroy an existing asset.
|
||||
///
|
||||
/// * `id`: The asset you want to destroy.
|
||||
/// * `witness`: Witness data needed about the current state of the asset, used to confirm
|
||||
/// complexity of the operation.
|
||||
/// * `maybe_check_owner`: An optional check before destroying the asset, if the provided
|
||||
/// account is the owner of that asset. Can be used for authorization checks.
|
||||
pub(super) fn do_destroy(
|
||||
id: T::AssetId,
|
||||
witness: DestroyWitness,
|
||||
maybe_check_owner: Option<T::AccountId>,
|
||||
) -> Result<DestroyWitness, DispatchError> {
|
||||
Asset::<T, I>::try_mutate_exists(id, |maybe_details| {
|
||||
let mut details = maybe_details.take().ok_or(Error::<T, I>::Unknown)?;
|
||||
if let Some(check_owner) = maybe_check_owner {
|
||||
ensure!(details.owner == check_owner, Error::<T, I>::NoPermission);
|
||||
}
|
||||
ensure!(details.accounts <= witness.accounts, Error::<T, I>::BadWitness);
|
||||
ensure!(details.sufficients <= witness.sufficients, Error::<T, I>::BadWitness);
|
||||
ensure!(details.approvals <= witness.approvals, Error::<T, I>::BadWitness);
|
||||
|
||||
for (who, v) in Account::<T, I>::drain_prefix(id) {
|
||||
Self::dead_account(id, &who, &mut details, v.sufficient);
|
||||
}
|
||||
debug_assert_eq!(details.accounts, 0);
|
||||
debug_assert_eq!(details.sufficients, 0);
|
||||
|
||||
let metadata = Metadata::<T, I>::take(&id);
|
||||
T::Currency::unreserve(
|
||||
&details.owner,
|
||||
details.deposit.saturating_add(metadata.deposit),
|
||||
);
|
||||
|
||||
for ((owner, _), approval) in Approvals::<T, I>::drain_prefix((&id,)) {
|
||||
T::Currency::unreserve(&owner, approval.deposit);
|
||||
}
|
||||
Self::deposit_event(Event::Destroyed(id));
|
||||
|
||||
Ok(DestroyWitness {
|
||||
accounts: details.accounts,
|
||||
sufficients: details.sufficients,
|
||||
approvals: details.approvals,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,3 +147,30 @@ impl<T: Config<I>, I: 'static> fungibles::Unbalanced<T::AccountId> for Pallet<T,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> fungibles::Create<T::AccountId> for Pallet<T, I> {
|
||||
fn create(
|
||||
id: T::AssetId,
|
||||
admin: T::AccountId,
|
||||
is_sufficient: bool,
|
||||
min_balance: Self::Balance,
|
||||
) -> DispatchResult {
|
||||
Self::do_force_create(id, admin, is_sufficient, min_balance)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> fungibles::Destroy<T::AccountId> for Pallet<T, I> {
|
||||
type DestroyWitness = DestroyWitness;
|
||||
|
||||
fn get_destroy_witness(asset: &T::AssetId) -> Option<Self::DestroyWitness> {
|
||||
Asset::<T, I>::get(asset).map(|asset_details| asset_details.destroy_witness())
|
||||
}
|
||||
|
||||
fn destroy(
|
||||
id: T::AssetId,
|
||||
witness: Self::DestroyWitness,
|
||||
maybe_check_owner: Option<T::AccountId>,
|
||||
) -> Result<Self::DestroyWitness, DispatchError> {
|
||||
Self::do_destroy(id, witness, maybe_check_owner)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +143,7 @@ use codec::HasCompact;
|
||||
use frame_support::{
|
||||
dispatch::{DispatchError, DispatchResult},
|
||||
ensure,
|
||||
pallet_prelude::DispatchResultWithPostInfo,
|
||||
traits::{
|
||||
tokens::{fungibles, DepositConsequence, WithdrawConsequence},
|
||||
BalanceStatus::Reserved,
|
||||
@@ -437,29 +438,7 @@ pub mod pallet {
|
||||
) -> DispatchResult {
|
||||
T::ForceOrigin::ensure_origin(origin)?;
|
||||
let owner = T::Lookup::lookup(owner)?;
|
||||
|
||||
ensure!(!Asset::<T, I>::contains_key(id), Error::<T, I>::InUse);
|
||||
ensure!(!min_balance.is_zero(), Error::<T, I>::MinBalanceZero);
|
||||
|
||||
Asset::<T, I>::insert(
|
||||
id,
|
||||
AssetDetails {
|
||||
owner: owner.clone(),
|
||||
issuer: owner.clone(),
|
||||
admin: owner.clone(),
|
||||
freezer: owner.clone(),
|
||||
supply: Zero::zero(),
|
||||
deposit: Zero::zero(),
|
||||
min_balance,
|
||||
is_sufficient,
|
||||
accounts: 0,
|
||||
sufficients: 0,
|
||||
approvals: 0,
|
||||
is_frozen: false,
|
||||
},
|
||||
);
|
||||
Self::deposit_event(Event::ForceCreated(id, owner));
|
||||
Ok(())
|
||||
Self::do_force_create(id, owner, is_sufficient, min_balance)
|
||||
}
|
||||
|
||||
/// Destroy a class of fungible assets.
|
||||
@@ -494,39 +473,13 @@ pub mod pallet {
|
||||
Ok(_) => None,
|
||||
Err(origin) => Some(ensure_signed(origin)?),
|
||||
};
|
||||
Asset::<T, I>::try_mutate_exists(id, |maybe_details| {
|
||||
let mut details = maybe_details.take().ok_or(Error::<T, I>::Unknown)?;
|
||||
if let Some(check_owner) = maybe_check_owner {
|
||||
ensure!(details.owner == check_owner, Error::<T, I>::NoPermission);
|
||||
}
|
||||
ensure!(details.accounts <= witness.accounts, Error::<T, I>::BadWitness);
|
||||
ensure!(details.sufficients <= witness.sufficients, Error::<T, I>::BadWitness);
|
||||
ensure!(details.approvals <= witness.approvals, Error::<T, I>::BadWitness);
|
||||
|
||||
for (who, v) in Account::<T, I>::drain_prefix(id) {
|
||||
Self::dead_account(id, &who, &mut details, v.sufficient);
|
||||
}
|
||||
debug_assert_eq!(details.accounts, 0);
|
||||
debug_assert_eq!(details.sufficients, 0);
|
||||
|
||||
let metadata = Metadata::<T, I>::take(&id);
|
||||
T::Currency::unreserve(
|
||||
&details.owner,
|
||||
details.deposit.saturating_add(metadata.deposit),
|
||||
);
|
||||
|
||||
for ((owner, _), approval) in Approvals::<T, I>::drain_prefix((&id,)) {
|
||||
T::Currency::unreserve(&owner, approval.deposit);
|
||||
}
|
||||
Self::deposit_event(Event::Destroyed(id));
|
||||
|
||||
Ok(Some(T::WeightInfo::destroy(
|
||||
details.accounts.saturating_sub(details.sufficients),
|
||||
details.sufficients,
|
||||
details.approvals,
|
||||
))
|
||||
.into())
|
||||
})
|
||||
let details = Self::do_destroy(id, witness, maybe_check_owner)?;
|
||||
Ok(Some(T::WeightInfo::destroy(
|
||||
details.accounts.saturating_sub(details.sufficients),
|
||||
details.sufficients,
|
||||
details.approvals,
|
||||
))
|
||||
.into())
|
||||
}
|
||||
|
||||
/// Mint assets of a particular class.
|
||||
|
||||
Reference in New Issue
Block a user