--- a/pallets/nft/src/lib.rs +++ b/pallets/nft/src/lib.rs @@ -348,6 +348,8 @@ TokenValueTooLow, /// Size of item is too large. NftSizeLimitExceeded, + /// Owned amount is lesser than tried to approve + CantAfford, /// No approve found ApproveNotFound, /// Requested value more than approved. @@ -1083,9 +1085,20 @@ // Transfer permissions check let target_collection = >::get(collection_id); - ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id) || - Self::is_owner_or_admin_permissions(collection_id, sender.clone()), - Error::::NoPermission); + let allowance_limit = if Self::is_owner_or_admin_permissions( + collection_id, + sender.clone(), + ) { + None + } else if let Some(amount) = Self::owned_amount( + sender.clone(), + collection_id, + item_id, + ) { + Some(amount) + } else { + fail!(Error::::NoPermission); + }; if target_collection.access == AccessMode::WhiteList { Self::check_white_list(collection_id, &sender)?; @@ -1097,6 +1110,9 @@ if allowance_exists { allowance += >::get(collection_id, (item_id, &sender, &spender)); } + if let Some(limit) = allowance_limit { + ensure!(limit >= allowance, Error::::CantAfford); + } >::insert(collection_id, (item_id, sender.clone(), spender.clone()), allowance); Ok(()) @@ -1866,6 +1882,36 @@ Ok(()) } + fn owned_amount( + subject: T::AccountId, + collection_id: CollectionId, + item_id: TokenId, + ) -> Option { + let target_collection = >::get(collection_id); + + match target_collection.mode { + CollectionMode::NFT => { + if >::get(collection_id, item_id).owner == subject { + return Some(1) + } + None + }, + CollectionMode::Fungible(_) => { + if >::contains_key(collection_id, &subject) { + return Some(>::get(collection_id, &subject) + .value); + } + None + }, + CollectionMode::ReFungible => >::get(collection_id, item_id) + .owner + .iter() + .find(|i| i.owner == subject) + .map(|i| i.fraction), + CollectionMode::Invalid => None, + } + } + fn is_item_owner(subject: T::AccountId, collection_id: CollectionId, item_id: TokenId) -> bool { let target_collection = >::get(collection_id);