difftreelog
feat burn_from
in: master
1 file changed
pallets/nft/src/lib.rsdiffbeforeafterboth987 /// * item_id: ID of NFT to burn.987 /// * item_id: ID of NFT to burn.988 #[weight = <SelfWeightOf<T>>::burn_item()]988 #[weight = <SelfWeightOf<T>>::burn_item()]989 #[transactional]989 #[transactional]990 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, item_owner: T::CrossAccountId, value: u128) -> DispatchResult {990 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResult {991992 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);993 let target_collection = Self::get_collection(collection_id)?;994995 Self::burn_item_internal(&sender, &target_collection, item_id, value, true)?;996997 target_collection.submit_logs()998 }9991000 /// Destroys a concrete instance of NFT on behalf of the owner1001 /// See also: [`approve`]1002 ///1003 /// # Permissions1004 ///1005 /// * Collection Owner.1006 /// * Collection Admin.1007 /// * Current NFT Owner.1008 ///1009 /// # Arguments1010 ///1011 /// * collection_id: ID of the collection.1012 ///1013 /// * item_id: ID of NFT to burn.1014 ///1015 /// * from: owner of item1016 #[weight = <SelfWeightOf<T>>::burn_item()]1017 #[transactional]1018 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResult {9911019992 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1020 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);993 let target_collection = Self::get_collection(collection_id)?;1021 let target_collection = Self::get_collection(collection_id)?;9941022995 Self::burn_item_internal(&sender, &target_collection, item_id, &item_owner, value)?;1023 Self::burn_from_internal(&sender, &target_collection, &from, item_id, value)?;9961024997 target_collection.submit_logs()1025 target_collection.submit_logs()998 }1026 }1593 }1621 }159416221595 pub fn burn_item_internal(1623 pub fn burn_item_internal(1596 sender: &T::CrossAccountId,1624 owner: &T::CrossAccountId,1597 collection: &CollectionHandle<T>,1625 collection: &CollectionHandle<T>,1598 item_id: TokenId,1626 item_id: TokenId,1599 item_owner: &T::CrossAccountId,1627 value: u128,1600 value: u128,1628 allow_escalation: bool,1601 ) -> DispatchResult {1629 ) -> DispatchResult {1602 ensure!(1630 ensure!(1603 Self::is_item_owner(sender, collection, item_id)?1631 Self::is_item_owner(owner, collection, item_id)?1604 || (collection.limits.owner_can_transfer1632 || (allow_escalation1633 && collection.limits.owner_can_transfer1605 && Self::is_owner_or_admin_permissions(collection, sender)?),1634 && Self::is_owner_or_admin_permissions(collection, owner)?),1606 Error::<T>::NoPermission1635 Error::<T>::NoPermission1607 );1636 );160816371609 if collection.access == AccessMode::WhiteList {1638 if collection.access == AccessMode::WhiteList {1610 Self::check_white_list(collection, sender)?;1639 Self::check_white_list(collection, owner)?;1611 }1640 }161216411613 match collection.mode {1642 match collection.mode {1617 _ => fail!(<Error<T>>::TokenValueTooLow),1646 _ => fail!(<Error<T>>::TokenValueTooLow),1618 },1647 },1619 CollectionMode::Fungible(_) => Self::burn_fungible_item(collection, owner, value)?,1648 CollectionMode::Fungible(_) => Self::burn_fungible_item(collection, owner, value)?,1620 CollectionMode::ReFungible => Self::burn_refungible_item(collection, item_id, owner, value)?,1649 CollectionMode::ReFungible => {1650 Self::burn_refungible_item(collection, item_id, owner, value)?1651 }1621 _ => (),1652 _ => (),1622 };1653 };162316541624 Ok(())1655 Ok(())1625 }1656 }16571658 pub fn burn_from_internal(1659 sender: &T::CrossAccountId,1660 collection: &CollectionHandle<T>,1661 from: &T::CrossAccountId,1662 item_id: TokenId,1663 amount: u128,1664 ) -> DispatchResult {1665 if sender == from {1666 // Transfer by `from`, because it is either equal to sender, or derived from him1667 return Self::burn_item_internal(from, collection, item_id, amount, true);1668 }16691670 // Check approval1671 collection.consume_sload()?;1672 let approval: u128 =1673 <Allowances<T>>::get(collection.id, (item_id, from.as_sub(), sender.as_sub()));16741675 // Transfer permissions check1676 ensure!(1677 approval >= amount1678 || (collection.limits.owner_can_transfer1679 && Self::is_owner_or_admin_permissions(collection, sender)?),1680 Error::<T>::NoPermission1681 );16821683 if collection.access == AccessMode::WhiteList {1684 Self::check_white_list(collection, sender)?;1685 }16861687 // Reduce approval by transferred amount or remove if remaining approval drops to 01688 let allowance = approval.saturating_sub(amount);1689 collection.consume_sstore()?;1690 if allowance > 0 {1691 <Allowances<T>>::insert(1692 collection.id,1693 (item_id, from.as_sub(), sender.as_sub()),1694 allowance,1695 );1696 } else {1697 <Allowances<T>>::remove(collection.id, (item_id, from.as_sub(), sender.as_sub()));1698 }16991700 // Escalation is disallowed here, because we need to be sure that passed owner is real1701 Self::burn_item_internal(from, collection, item_id, amount, false)?;17021703 if matches!(collection.mode, CollectionMode::Fungible(_)) {1704 collection.log(ERC20Events::Approval {1705 owner: *from.as_eth(),1706 spender: *sender.as_eth(),1707 value: allowance.into(),1708 })?;1709 }17101711 Ok(())1712 }162617131627 pub fn toggle_white_list_internal(1714 pub fn toggle_white_list_internal(1628 sender: &T::CrossAccountId,1715 sender: &T::CrossAccountId,