mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-18 17:35:42 +00:00
[NFTs] Track item's metadata depositor (#13124)
* Refactor do_mint() * Track the depositor of item's metadata * Revert back the access control * On collection destroy return the metadata deposit * Clear the metadata on item burn returning the deposit * Address comments * Fix clippy * Don't return Ok on non-existing attribute removal
This commit is contained in:
@@ -19,19 +19,21 @@ use crate::*;
|
||||
use frame_support::pallet_prelude::*;
|
||||
|
||||
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
/// Note: if `maybe_depositor` is None, that means the depositor will be a collection's owner
|
||||
pub(crate) fn do_set_item_metadata(
|
||||
maybe_check_owner: Option<T::AccountId>,
|
||||
collection: T::CollectionId,
|
||||
item: T::ItemId,
|
||||
data: BoundedVec<u8, T::StringLimit>,
|
||||
maybe_depositor: Option<T::AccountId>,
|
||||
) -> DispatchResult {
|
||||
let is_root = maybe_check_owner.is_none();
|
||||
let mut collection_details =
|
||||
Collection::<T, I>::get(&collection).ok_or(Error::<T, I>::UnknownCollection)?;
|
||||
|
||||
let item_config = Self::get_item_config(&collection, &item)?;
|
||||
ensure!(
|
||||
maybe_check_owner.is_none() ||
|
||||
item_config.is_setting_enabled(ItemSetting::UnlockedMetadata),
|
||||
is_root || item_config.is_setting_enabled(ItemSetting::UnlockedMetadata),
|
||||
Error::<T, I>::LockedItemMetadata
|
||||
);
|
||||
|
||||
@@ -45,24 +47,38 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
if metadata.is_none() {
|
||||
collection_details.item_metadatas.saturating_inc();
|
||||
}
|
||||
let old_deposit = metadata.take().map_or(Zero::zero(), |m| m.deposit);
|
||||
collection_details.owner_deposit.saturating_reduce(old_deposit);
|
||||
|
||||
let old_deposit = metadata
|
||||
.take()
|
||||
.map_or(ItemMetadataDeposit { account: None, amount: Zero::zero() }, |m| m.deposit);
|
||||
|
||||
let mut deposit = Zero::zero();
|
||||
if collection_config.is_setting_enabled(CollectionSetting::DepositRequired) &&
|
||||
maybe_check_owner.is_some()
|
||||
if collection_config.is_setting_enabled(CollectionSetting::DepositRequired) && !is_root
|
||||
{
|
||||
deposit = T::DepositPerByte::get()
|
||||
.saturating_mul(((data.len()) as u32).into())
|
||||
.saturating_add(T::MetadataDepositBase::get());
|
||||
}
|
||||
if deposit > old_deposit {
|
||||
T::Currency::reserve(&collection_details.owner, deposit - old_deposit)?;
|
||||
} else if deposit < old_deposit {
|
||||
T::Currency::unreserve(&collection_details.owner, old_deposit - deposit);
|
||||
}
|
||||
collection_details.owner_deposit.saturating_accrue(deposit);
|
||||
|
||||
*metadata = Some(ItemMetadata { deposit, data: data.clone() });
|
||||
// the previous deposit was taken from the item's owner
|
||||
if old_deposit.account.is_some() && maybe_depositor.is_none() {
|
||||
T::Currency::unreserve(&old_deposit.account.unwrap(), old_deposit.amount);
|
||||
T::Currency::reserve(&collection_details.owner, deposit)?;
|
||||
} else if deposit > old_deposit.amount {
|
||||
T::Currency::reserve(&collection_details.owner, deposit - old_deposit.amount)?;
|
||||
} else if deposit < old_deposit.amount {
|
||||
T::Currency::unreserve(&collection_details.owner, old_deposit.amount - deposit);
|
||||
}
|
||||
|
||||
if maybe_depositor.is_none() {
|
||||
collection_details.owner_deposit.saturating_accrue(deposit);
|
||||
collection_details.owner_deposit.saturating_reduce(old_deposit.amount);
|
||||
}
|
||||
|
||||
*metadata = Some(ItemMetadata {
|
||||
deposit: ItemMetadataDeposit { account: maybe_depositor, amount: deposit },
|
||||
data: data.clone(),
|
||||
});
|
||||
|
||||
Collection::<T, I>::insert(&collection, &collection_details);
|
||||
Self::deposit_event(Event::ItemMetadataSet { collection, item, data });
|
||||
@@ -75,8 +91,14 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
collection: T::CollectionId,
|
||||
item: T::ItemId,
|
||||
) -> DispatchResult {
|
||||
let is_root = maybe_check_owner.is_none();
|
||||
let metadata = ItemMetadataOf::<T, I>::take(collection, item)
|
||||
.ok_or(Error::<T, I>::MetadataNotFound)?;
|
||||
let mut collection_details =
|
||||
Collection::<T, I>::get(&collection).ok_or(Error::<T, I>::UnknownCollection)?;
|
||||
let depositor_account =
|
||||
metadata.deposit.account.unwrap_or(collection_details.owner.clone());
|
||||
|
||||
if let Some(check_owner) = &maybe_check_owner {
|
||||
ensure!(check_owner == &collection_details.owner, Error::<T, I>::NoPermission);
|
||||
}
|
||||
@@ -85,20 +107,19 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
let is_locked = Self::get_item_config(&collection, &item)
|
||||
.map_or(false, |c| c.has_disabled_setting(ItemSetting::UnlockedMetadata));
|
||||
|
||||
ensure!(maybe_check_owner.is_none() || !is_locked, Error::<T, I>::LockedItemMetadata);
|
||||
ensure!(is_root || !is_locked, Error::<T, I>::LockedItemMetadata);
|
||||
|
||||
ItemMetadataOf::<T, I>::try_mutate_exists(collection, item, |metadata| {
|
||||
if metadata.is_some() {
|
||||
collection_details.item_metadatas.saturating_dec();
|
||||
}
|
||||
let deposit = metadata.take().ok_or(Error::<T, I>::UnknownItem)?.deposit;
|
||||
T::Currency::unreserve(&collection_details.owner, deposit);
|
||||
collection_details.owner_deposit.saturating_reduce(deposit);
|
||||
collection_details.item_metadatas.saturating_dec();
|
||||
T::Currency::unreserve(&depositor_account, metadata.deposit.amount);
|
||||
|
||||
Collection::<T, I>::insert(&collection, &collection_details);
|
||||
Self::deposit_event(Event::ItemMetadataCleared { collection, item });
|
||||
Ok(())
|
||||
})
|
||||
if depositor_account == collection_details.owner {
|
||||
collection_details.owner_deposit.saturating_reduce(metadata.deposit.amount);
|
||||
}
|
||||
|
||||
Collection::<T, I>::insert(&collection, &collection_details);
|
||||
Self::deposit_event(Event::ItemMetadataCleared { collection, item });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn do_set_collection_metadata(
|
||||
|
||||
Reference in New Issue
Block a user