referrerpolicy=no-referrer-when-downgrade

pallet_nfts/features/
lock.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! This module contains helper methods to configure locks on collections and items for the NFTs
19//! pallet.
20
21use crate::*;
22use frame_support::pallet_prelude::*;
23
24impl<T: Config<I>, I: 'static> Pallet<T, I> {
25	/// Locks a collection with specified settings.
26	///
27	/// The origin must be the owner of the collection to lock it. This function disables certain
28	/// settings on the collection. The only setting that can't be disabled is `DepositRequired`.
29	///
30	/// Note: it's possible only to lock the setting, but not to unlock it after.
31
32	///
33	/// - `origin`: The origin of the transaction, representing the account attempting to lock the
34	///   collection.
35	/// - `collection`: The identifier of the collection to be locked.
36	/// - `lock_settings`: The collection settings to be locked.
37	pub(crate) fn do_lock_collection(
38		origin: T::AccountId,
39		collection: T::CollectionId,
40		lock_settings: CollectionSettings,
41	) -> DispatchResult {
42		ensure!(Self::collection_owner(collection) == Some(origin), Error::<T, I>::NoPermission);
43		ensure!(
44			!lock_settings.is_disabled(CollectionSetting::DepositRequired),
45			Error::<T, I>::WrongSetting
46		);
47		CollectionConfigOf::<T, I>::try_mutate(collection, |maybe_config| {
48			let config = maybe_config.as_mut().ok_or(Error::<T, I>::NoConfig)?;
49
50			for setting in lock_settings.get_disabled() {
51				config.disable_setting(setting);
52			}
53
54			Self::deposit_event(Event::<T, I>::CollectionLocked { collection });
55			Ok(())
56		})
57	}
58
59	/// Locks the transfer of an item within a collection.
60	///
61	/// The origin must have the `Freezer` role within the collection to lock the transfer of the
62	/// item. This function disables the `Transferable` setting on the item, preventing it from
63	/// being transferred to other accounts.
64	///
65	/// - `origin`: The origin of the transaction, representing the account attempting to lock the
66	///   item transfer.
67	/// - `collection`: The identifier of the collection to which the item belongs.
68	/// - `item`: The identifier of the item to be locked for transfer.
69	pub(crate) fn do_lock_item_transfer(
70		origin: T::AccountId,
71		collection: T::CollectionId,
72		item: T::ItemId,
73	) -> DispatchResult {
74		ensure!(
75			Self::has_role(&collection, &origin, CollectionRole::Freezer),
76			Error::<T, I>::NoPermission
77		);
78
79		let mut config = Self::get_item_config(&collection, &item)?;
80		if !config.has_disabled_setting(ItemSetting::Transferable) {
81			config.disable_setting(ItemSetting::Transferable);
82		}
83		ItemConfigOf::<T, I>::insert(&collection, &item, config);
84
85		Self::deposit_event(Event::<T, I>::ItemTransferLocked { collection, item });
86		Ok(())
87	}
88
89	/// Unlocks the transfer of an item within a collection.
90	///
91	/// The origin must have the `Freezer` role within the collection to unlock the transfer of the
92	/// item. This function enables the `Transferable` setting on the item, allowing it to be
93	/// transferred to other accounts.
94	///
95	/// - `origin`: The origin of the transaction, representing the account attempting to unlock the
96	///   item transfer.
97	/// - `collection`: The identifier of the collection to which the item belongs.
98	/// - `item`: The identifier of the item to be unlocked for transfer.
99	pub(crate) fn do_unlock_item_transfer(
100		origin: T::AccountId,
101		collection: T::CollectionId,
102		item: T::ItemId,
103	) -> DispatchResult {
104		ensure!(
105			Self::has_role(&collection, &origin, CollectionRole::Freezer),
106			Error::<T, I>::NoPermission
107		);
108
109		let mut config = Self::get_item_config(&collection, &item)?;
110		if config.has_disabled_setting(ItemSetting::Transferable) {
111			config.enable_setting(ItemSetting::Transferable);
112		}
113		ItemConfigOf::<T, I>::insert(&collection, &item, config);
114
115		Self::deposit_event(Event::<T, I>::ItemTransferUnlocked { collection, item });
116		Ok(())
117	}
118
119	/// Locks the metadata and attributes of an item within a collection.
120	///
121	/// The origin must have the `Admin` role within the collection to lock the metadata and
122	/// attributes of the item. This function disables the `UnlockedMetadata` and
123	/// `UnlockedAttributes` settings on the item, preventing modifications to its metadata and
124	/// attributes.
125	///
126	/// - `maybe_check_origin`: An optional origin representing the account attempting to lock the
127	///   item properties. If provided, this account must have the `Admin` role within the
128	///   collection. If `None`, no permission check is performed, and the function can be called
129	///   from any origin.
130	/// - `collection`: The identifier of the collection to which the item belongs.
131	/// - `item`: The identifier of the item to be locked for properties.
132	/// - `lock_metadata`: A boolean indicating whether to lock the metadata of the item.
133	/// - `lock_attributes`: A boolean indicating whether to lock the attributes of the item.
134	pub(crate) fn do_lock_item_properties(
135		maybe_check_origin: Option<T::AccountId>,
136		collection: T::CollectionId,
137		item: T::ItemId,
138		lock_metadata: bool,
139		lock_attributes: bool,
140	) -> DispatchResult {
141		if let Some(check_origin) = &maybe_check_origin {
142			ensure!(
143				Self::has_role(&collection, &check_origin, CollectionRole::Admin),
144				Error::<T, I>::NoPermission
145			);
146		}
147
148		ItemConfigOf::<T, I>::try_mutate(collection, item, |maybe_config| {
149			let config = maybe_config.as_mut().ok_or(Error::<T, I>::UnknownItem)?;
150
151			if lock_metadata {
152				config.disable_setting(ItemSetting::UnlockedMetadata);
153			}
154			if lock_attributes {
155				config.disable_setting(ItemSetting::UnlockedAttributes);
156			}
157
158			Self::deposit_event(Event::<T, I>::ItemPropertiesLocked {
159				collection,
160				item,
161				lock_metadata,
162				lock_attributes,
163			});
164			Ok(())
165		})
166	}
167}