git.delta.rocks / unique-network / refs/commits / c6354cf493a0

difftreelog

feat add ApproveForAll to Eth and Sub

Grigoriy Simonov2022-12-06parent: #e7f81f3.patch.diff
in: master

39 files changed

modifiedclient/rpc/src/lib.rsdiffbeforeafterboth
--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -246,6 +246,16 @@
 		token_id: TokenId,
 		at: Option<BlockHash>,
 	) -> Result<Option<String>>;
+
+	/// Get whether an operator is approved by a given owner.
+	#[method(name = "unique_isApprovedForAll")]
+	fn is_approved_for_all(
+		&self,
+		collection: CollectionId,
+		owner: CrossAccountId,
+		operator: CrossAccountId,
+		at: Option<BlockHash>,
+	) -> Result<bool>;
 }
 
 mod app_promotion_unique_rpc {
@@ -569,6 +579,7 @@
 	pass_method!(effective_collection_limits(collection_id: CollectionId) -> Option<CollectionLimits>, unique_api);
 	pass_method!(total_pieces(collection_id: CollectionId, token_id: TokenId) -> Option<String> => |o| o.map(|number| number.to_string()) , unique_api);
 	pass_method!(token_owners(collection: CollectionId, token: TokenId) -> Vec<CrossAccountId>, unique_api);
+	pass_method!(is_approved_for_all(collection: CollectionId, owner: CrossAccountId, operator: CrossAccountId) -> bool, unique_api);
 }
 
 impl<C, Block, BlockNumber, CrossAccountId, AccountId>
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -472,6 +472,18 @@
 			u128,
 		),
 
+		/// Amount pieces of token owned by `sender` was approved for `spender`.
+		ApprovedForAll(
+			/// Id of collection to which item is belong.
+			CollectionId,
+			/// Owner of a wallet.
+			T::CrossAccountId,
+			/// Id for which operator status was granted or rewoked.
+			T::CrossAccountId,
+			/// Is operator status was granted or rewoked.
+			bool,
+		),
+
 		/// The colletion property has been added or edited.
 		CollectionPropertySet(
 			/// Id of collection to which property has been set.
@@ -1521,6 +1533,9 @@
 
 	/// The price of retrieving token owner
 	fn token_owner() -> Weight;
+
+	/// The price of setting approval for all
+	fn set_approval_for_all() -> Weight;
 }
 
 /// Weight info extension trait for refungible pallet.
@@ -1828,6 +1843,20 @@
 
 	/// Get extension for RFT collection.
 	fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>>;
+
+	/// An operator is allowed to transfer all tokens of the sender on their behalf.
+	/// * `owner` - Token owner
+	/// * `operator` - Operator
+	/// * `approve` - Is operator enabled or disabled
+	fn set_approval_for_all(
+		&self,
+		owner: T::CrossAccountId,
+		operator: T::CrossAccountId,
+		approve: bool,
+	) -> DispatchResultWithPostInfo;
+
+	/// Tells whether an operator is approved by a given owner.
+	fn is_approved_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool;
 }
 
 /// Extension for RFT collection.
modifiedpallets/fungible/src/common.rsdiffbeforeafterboth
--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -107,6 +107,10 @@
 	fn token_owner() -> Weight {
 		Weight::zero()
 	}
+
+	fn set_approval_for_all() -> Weight {
+		Weight::zero()
+	}
 }
 
 /// Implementation of `CommonCollectionOperations` for `FungibleHandle`. It wraps FungibleHandle Pallete
@@ -424,4 +428,17 @@
 		}
 		<TotalSupply<T>>::try_get(self.id).ok()
 	}
+
+	fn set_approval_for_all(
+		&self,
+		_owner: T::CrossAccountId,
+		_operator: T::CrossAccountId,
+		_approve: bool,
+	) -> DispatchResultWithPostInfo {
+		fail!(<Error<T>>::SettingApprovalForAllNotAllowed)
+	}
+
+	fn is_approved_for_all(&self, _owner: T::CrossAccountId, _operator: T::CrossAccountId) -> bool {
+		false
+	}
 }
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -127,6 +127,8 @@
 		FungibleDisallowsNesting,
 		/// Setting item properties is not allowed.
 		SettingPropertiesNotAllowed,
+		/// Setting approval for all is not allowed.
+		SettingApprovalForAllNotAllowed,
 	}
 
 	#[pallet::config]
modifiedpallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/benchmarking.rs
+++ b/pallets/nonfungible/src/benchmarking.rs
@@ -222,4 +222,18 @@
 		let item = create_max_item(&collection, &owner, owner.clone())?;
 
 	}: {collection.token_owner(item)}
+
+	set_approval_for_all {
+		bench_init!{
+			owner: sub; collection: collection(owner);
+			operator: cross_from_sub(owner); owner: cross_sub;
+		};
+	}: {<Pallet<T>>::set_approval_for_all(&collection, &owner, &operator, true)}
+
+	is_approved_for_all {
+		bench_init!{
+			owner: sub; collection: collection(owner);
+			operator: cross_from_sub(owner); owner: cross_sub;
+		};
+	}: {<Pallet<T>>::is_approved_for_all(&collection, &owner, &operator)}
 }
modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -122,6 +122,10 @@
 	fn token_owner() -> Weight {
 		<SelfWeightOf<T>>::token_owner()
 	}
+
+	fn set_approval_for_all() -> Weight {
+		<SelfWeightOf<T>>::set_approval_for_all()
+	}
 }
 
 fn map_create_data<T: Config>(
@@ -512,4 +516,20 @@
 			None
 		}
 	}
+
+	fn set_approval_for_all(
+		&self,
+		owner: T::CrossAccountId,
+		operator: T::CrossAccountId,
+		approve: bool,
+	) -> DispatchResultWithPostInfo {
+		with_weight(
+			<Pallet<T>>::set_approval_for_all(self, &owner, &operator, approve),
+			<CommonWeights<T>>::set_approval_for_all(),
+		)
+	}
+
+	fn is_approved_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool {
+		<Pallet<T>>::is_approved_for_all(self, &owner, &operator)
+	}
 }
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -469,15 +469,23 @@
 		Ok(())
 	}
 
-	/// @dev Not implemented
+	/// @notice Sets or unsets the approval of a given operator.
+	///  An operator is allowed to transfer all tokens of the sender on their behalf.
+	/// @param operator Operator
+	/// @param approved Is operator enabled or disabled
+	#[weight(<SelfWeightOf<T>>::set_approval_for_all())]
 	fn set_approval_for_all(
 		&mut self,
-		_caller: caller,
-		_operator: address,
-		_approved: bool,
+		caller: caller,
+		operator: address,
+		approved: bool,
 	) -> Result<void> {
-		// TODO: Not implemetable
-		Err("not implemented".into())
+		let caller = T::CrossAccountId::from_eth(caller);
+		let operator = T::CrossAccountId::from_eth(operator);
+
+		<Pallet<T>>::set_approval_for_all(self, &caller, &operator, approved)
+			.map_err(dispatch_to_evm::<T>)?;
+		Ok(())
 	}
 
 	/// @dev Not implemented
@@ -486,10 +494,13 @@
 		Err("not implemented".into())
 	}
 
-	/// @dev Not implemented
-	fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {
-		// TODO: Not implemetable
-		Err("not implemented".into())
+	/// @notice Tells whether an operator is approved by a given owner.
+	#[weight(<SelfWeightOf<T>>::is_approved_for_all())]
+	fn is_approved_for_all(&self, owner: address, operator: address) -> Result<bool> {
+		let owner = T::CrossAccountId::from_eth(owner);
+		let operator = T::CrossAccountId::from_eth(operator);
+
+		Ok(<Pallet<T>>::is_approved_for_all(self, &owner, &operator))
 	}
 
 	/// @notice Returns collection helper contract address
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -272,6 +272,18 @@
 		QueryKind = OptionQuery,
 	>;
 
+	/// Operator set by a wallet owner that could perform certain transactions on all tokens in the wallet.
+	#[pallet::storage]
+	pub type WalletOperator<T: Config> = StorageNMap<
+		Key = (
+			Key<Twox64Concat, CollectionId>,
+			Key<Blake2_128Concat, T::CrossAccountId>,
+			Key<Blake2_128Concat, T::CrossAccountId>,
+		),
+		Value = bool,
+		QueryKind = OptionQuery,
+	>;
+
 	/// Upgrade from the old schema to properties.
 	#[pallet::hooks]
 	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
@@ -438,6 +450,7 @@
 		<TokensBurnt<T>>::remove(id);
 		let _ = <Allowance<T>>::clear_prefix((id,), u32::MAX, None);
 		let _ = <AccountBalance<T>>::clear_prefix((id,), u32::MAX, None);
+		let _ = <WalletOperator<T>>::clear_prefix((id,), u32::MAX, None);
 		Ok(())
 	}
 
@@ -1193,6 +1206,9 @@
 		if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {
 			return Ok(());
 		}
+		if <WalletOperator<T>>::get((collection.id, from, spender)) == Some(true) {
+			return Ok(());
+		}
 		ensure!(
 			collection.ignores_allowance(spender),
 			<CommonError<T>>::ApprovedValueTooLow
@@ -1326,4 +1342,52 @@
 	) -> DispatchResult {
 		Self::create_multiple_items(collection, sender, vec![data], nesting_budget)
 	}
+
+	/// Sets or unsets the approval of a given operator.
+	///
+	/// An operator is allowed to transfer all token pieces of the sender on their behalf.
+	/// - `owner`: Token owner
+	/// - `operator`: Operator
+	/// - `approve`: Is operator enabled or disabled
+	pub fn set_approval_for_all(
+		collection: &NonfungibleHandle<T>,
+		owner: &T::CrossAccountId,
+		operator: &T::CrossAccountId,
+		approve: bool,
+	) -> DispatchResult {
+		if collection.permissions.access() == AccessMode::AllowList {
+			collection.check_allowlist(owner)?;
+			collection.check_allowlist(operator)?;
+		}
+
+		<PalletCommon<T>>::ensure_correct_receiver(operator)?;
+
+		// =========
+
+		<WalletOperator<T>>::insert((collection.id, owner, operator), approve);
+		<PalletEvm<T>>::deposit_log(
+			ERC721Events::ApprovalForAll {
+				owner: *owner.as_eth(),
+				operator: *operator.as_eth(),
+				approved: approve,
+			}
+			.to_log(collection_id_to_address(collection.id)),
+		);
+		<PalletCommon<T>>::deposit_event(CommonEvent::ApprovedForAll(
+			collection.id,
+			owner.clone(),
+			operator.clone(),
+			approve,
+		));
+		Ok(())
+	}
+
+	/// Tells whether an operator is approved by a given owner.
+	pub fn is_approved_for_all(
+		collection: &NonfungibleHandle<T>,
+		owner: &T::CrossAccountId,
+		operator: &T::CrossAccountId,
+	) -> bool {
+		<WalletOperator<T>>::get((collection.id, owner, operator)).unwrap_or(false)
+	}
 }
modifiedpallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -1020,7 +1020,10 @@
 		dummy = 0;
 	}
 
-	/// @dev Not implemented
+	/// @notice Sets or unsets the approval of a given operator.
+	///  An operator is allowed to transfer all tokens of the sender on their behalf.
+	/// @param operator Operator
+	/// @param approved Is operator enabled or disabled
 	/// @dev EVM selector for this function is: 0xa22cb465,
 	///  or in textual repr: setApprovalForAll(address,bool)
 	function setApprovalForAll(address operator, bool approved) public {
@@ -1040,15 +1043,15 @@
 		return 0x0000000000000000000000000000000000000000;
 	}
 
-	/// @dev Not implemented
+	/// @notice Tells whether an operator is approved by a given owner.
 	/// @dev EVM selector for this function is: 0xe985e9c5,
 	///  or in textual repr: isApprovedForAll(address,address)
-	function isApprovedForAll(address owner, address operator) public view returns (address) {
+	function isApprovedForAll(address owner, address operator) public view returns (bool) {
 		require(false, stub_error);
 		owner;
 		operator;
 		dummy;
-		return 0x0000000000000000000000000000000000000000;
+		return false;
 	}
 
 	/// @notice Returns collection helper contract address
modifiedpallets/nonfungible/src/weights.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/weights.rs
+++ b/pallets/nonfungible/src/weights.rs
@@ -26,6 +26,7 @@
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
 #![allow(unused_imports)]
+#![allow(missing_docs)]
 #![allow(clippy::unnecessary_cast)]
 
 use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
@@ -47,6 +48,8 @@
 	fn set_token_properties(b: u32, ) -> Weight;
 	fn delete_token_properties(b: u32, ) -> Weight;
 	fn token_owner() -> Weight;
+	fn set_approval_for_all() -> Weight;
+	fn is_approved_for_all() -> Weight;
 }
 
 /// Weights for pallet_nonfungible using the Substrate node and recommended hardware.
@@ -195,6 +198,16 @@
 		Weight::from_ref_time(4_366_000)
 			.saturating_add(T::DbWeight::get().reads(1 as u64))
 	}
+	// Storage: Nonfungible WalletOperator (r:0 w:1)
+	fn set_approval_for_all() -> Weight {
+		Weight::from_ref_time(16_231_000 as u64)
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
+	// Storage: Nonfungible WalletOperator (r:1 w:0)
+	fn is_approved_for_all() -> Weight {
+		Weight::from_ref_time(6_161_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(1 as u64))
+	}
 }
 
 // For backwards compatibility and tests
@@ -342,4 +355,14 @@
 		Weight::from_ref_time(4_366_000)
 			.saturating_add(RocksDbWeight::get().reads(1 as u64))
 	}
+	// Storage: Nonfungible WalletOperator (r:0 w:1)
+	fn set_approval_for_all() -> Weight {
+		Weight::from_ref_time(16_231_000 as u64)
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
+	// Storage: Nonfungible WalletOperator (r:1 w:0)
+	fn is_approved_for_all() -> Weight {
+		Weight::from_ref_time(6_161_000 as u64)
+			.saturating_add(RocksDbWeight::get().reads(1 as u64))
+	}
 }
modifiedpallets/refungible/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/refungible/src/benchmarking.rs
+++ b/pallets/refungible/src/benchmarking.rs
@@ -290,4 +290,18 @@
 		};
 		let item = create_max_item(&collection, &sender, [(owner.clone(), 100)])?;
 	}: {<Pallet<T>>::token_owner(collection.id, item)}
+
+	set_approval_for_all {
+		bench_init!{
+			owner: sub; collection: collection(owner);
+			operator: cross_from_sub(owner); owner: cross_sub;
+		};
+	}: {<Pallet<T>>::set_approval_for_all(&collection, &owner, &operator, true)}
+
+	is_approved_for_all {
+		bench_init!{
+			owner: sub; collection: collection(owner);
+			operator: cross_from_sub(owner); owner: cross_sub;
+		};
+	}: {<Pallet<T>>::is_approved_for_all(&collection, &owner, &operator)}
 }
modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -152,6 +152,10 @@
 	fn token_owner() -> Weight {
 		<SelfWeightOf<T>>::token_owner()
 	}
+
+	fn set_approval_for_all() -> Weight {
+		<SelfWeightOf<T>>::set_approval_for_all()
+	}
 }
 
 fn map_create_data<T: Config>(
@@ -516,6 +520,22 @@
 	fn total_pieces(&self, token: TokenId) -> Option<u128> {
 		<Pallet<T>>::total_pieces(self.id, token)
 	}
+
+	fn set_approval_for_all(
+		&self,
+		owner: T::CrossAccountId,
+		operator: T::CrossAccountId,
+		approve: bool,
+	) -> DispatchResultWithPostInfo {
+		with_weight(
+			<Pallet<T>>::set_approval_for_all(self, &owner, &operator, approve),
+			<CommonWeights<T>>::set_approval_for_all(),
+		)
+	}
+
+	fn is_approved_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool {
+		<Pallet<T>>::is_approved_for_all(self, &owner, &operator)
+	}
 }
 
 impl<T: Config> RefungibleExtensions<T> for RefungibleHandle<T> {
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -461,15 +461,23 @@
 		Err("not implemented".into())
 	}
 
-	/// @dev Not implemented
+	/// @notice Sets or unsets the approval of a given operator.
+	///  An operator is allowed to transfer all tokens of the sender on their behalf.
+	/// @param operator Operator
+	/// @param approved Is operator enabled or disabled
+	#[weight(<SelfWeightOf<T>>::set_approval_for_all())]
 	fn set_approval_for_all(
 		&mut self,
-		_caller: caller,
-		_operator: address,
-		_approved: bool,
+		caller: caller,
+		operator: address,
+		approved: bool,
 	) -> Result<void> {
-		// TODO: Not implemetable
-		Err("not implemented".into())
+		let caller = T::CrossAccountId::from_eth(caller);
+		let operator = T::CrossAccountId::from_eth(operator);
+
+		<Pallet<T>>::set_approval_for_all(self, &caller, &operator, approved)
+			.map_err(dispatch_to_evm::<T>)?;
+		Ok(())
 	}
 
 	/// @dev Not implemented
@@ -478,10 +486,13 @@
 		Err("not implemented".into())
 	}
 
-	/// @dev Not implemented
-	fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {
-		// TODO: Not implemetable
-		Err("not implemented".into())
+	/// @notice Tells whether an operator is approved by a given owner.
+	#[weight(<SelfWeightOf<T>>::is_approved_for_all())]
+	fn is_approved_for_all(&self, owner: address, operator: address) -> Result<bool> {
+		let owner = T::CrossAccountId::from_eth(owner);
+		let operator = T::CrossAccountId::from_eth(operator);
+
+		Ok(<Pallet<T>>::is_approved_for_all(self, &owner, &operator))
 	}
 
 	/// @notice Returns collection helper contract address
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -273,6 +273,18 @@
 		QueryKind = ValueQuery,
 	>;
 
+	/// Operator set by a wallet owner that could perform certain transactions on all tokens in the wallet.
+	#[pallet::storage]
+	pub type WalletOperator<T: Config> = StorageNMap<
+		Key = (
+			Key<Twox64Concat, CollectionId>,
+			Key<Blake2_128Concat, T::CrossAccountId>,
+			Key<Blake2_128Concat, T::CrossAccountId>,
+		),
+		Value = bool,
+		QueryKind = OptionQuery,
+	>;
+
 	#[pallet::hooks]
 	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
 		fn on_runtime_upgrade() -> Weight {
@@ -1161,6 +1173,12 @@
 		}
 		let allowance =
 			<Allowance<T>>::get((collection.id, token, from, &spender)).checked_sub(amount);
+
+		// Allowance if any would be reduced if spender is also wallet operator
+		if <WalletOperator<T>>::get((collection.id, from, spender)) == Some(true) {
+			return Ok(allowance);
+		}
+
 		if allowance.is_none() {
 			ensure!(
 				collection.ignores_allowance(spender),
@@ -1387,4 +1405,52 @@
 			Some(res)
 		}
 	}
+
+	/// Sets or unsets the approval of a given operator.
+	///
+	/// An operator is allowed to transfer all tokens of the sender on their behalf.
+	/// - `owner`: Token owner
+	/// - `operator`: Operator
+	/// - `approve`: Is operator enabled or disabled
+	pub fn set_approval_for_all(
+		collection: &RefungibleHandle<T>,
+		owner: &T::CrossAccountId,
+		operator: &T::CrossAccountId,
+		approve: bool,
+	) -> DispatchResult {
+		if collection.permissions.access() == AccessMode::AllowList {
+			collection.check_allowlist(owner)?;
+			collection.check_allowlist(operator)?;
+		}
+
+		<PalletCommon<T>>::ensure_correct_receiver(operator)?;
+
+		// =========
+
+		<WalletOperator<T>>::insert((collection.id, owner, operator), approve);
+		<PalletEvm<T>>::deposit_log(
+			ERC721Events::ApprovalForAll {
+				owner: *owner.as_eth(),
+				operator: *operator.as_eth(),
+				approved: approve,
+			}
+			.to_log(collection_id_to_address(collection.id)),
+		);
+		<PalletCommon<T>>::deposit_event(CommonEvent::ApprovedForAll(
+			collection.id,
+			owner.clone(),
+			operator.clone(),
+			approve,
+		));
+		Ok(())
+	}
+
+	/// Tells whether an operator is approved by a given owner.
+	pub fn is_approved_for_all(
+		collection: &RefungibleHandle<T>,
+		owner: &T::CrossAccountId,
+		operator: &T::CrossAccountId,
+	) -> bool {
+		<WalletOperator<T>>::get((collection.id, owner, operator)).unwrap_or(false)
+	}
 }
modifiedpallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth
--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -1017,7 +1017,10 @@
 		dummy = 0;
 	}
 
-	/// @dev Not implemented
+	/// @notice Sets or unsets the approval of a given operator.
+	///  An operator is allowed to transfer all tokens of the sender on their behalf.
+	/// @param operator Operator
+	/// @param approved Is operator enabled or disabled
 	/// @dev EVM selector for this function is: 0xa22cb465,
 	///  or in textual repr: setApprovalForAll(address,bool)
 	function setApprovalForAll(address operator, bool approved) public {
@@ -1037,15 +1040,15 @@
 		return 0x0000000000000000000000000000000000000000;
 	}
 
-	/// @dev Not implemented
+	/// @notice Tells whether an operator is approved by a given owner.
 	/// @dev EVM selector for this function is: 0xe985e9c5,
 	///  or in textual repr: isApprovedForAll(address,address)
-	function isApprovedForAll(address owner, address operator) public view returns (address) {
+	function isApprovedForAll(address owner, address operator) public view returns (bool) {
 		require(false, stub_error);
 		owner;
 		operator;
 		dummy;
-		return 0x0000000000000000000000000000000000000000;
+		return false;
 	}
 
 	/// @notice Returns collection helper contract address
modifiedpallets/refungible/src/weights.rsdiffbeforeafterboth
before · pallets/refungible/src/weights.rs
1// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs23//! Autogenerated weights for pallet_refungible4//!5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev6//! DATE: 2022-08-15, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`7//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 102489// Executed Command:10// target/release/unique-collator11// benchmark12// pallet13// --pallet14// pallet-refungible15// --wasm-execution16// compiled17// --extrinsic18// *19// --template20// .maintain/frame-weight-template.hbs21// --steps=5022// --repeat=8023// --heap-pages=409624// --output=./pallets/refungible/src/weights.rs2526#![cfg_attr(rustfmt, rustfmt_skip)]27#![allow(unused_parens)]28#![allow(unused_imports)]29#![allow(clippy::unnecessary_cast)]3031use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};32use sp_std::marker::PhantomData;3334/// Weight functions needed for pallet_refungible.35pub trait WeightInfo {36	fn create_item() -> Weight;37	fn create_multiple_items(b: u32, ) -> Weight;38	fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight;39	fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight;40	fn burn_item_partial() -> Weight;41	fn burn_item_fully() -> Weight;42	fn transfer_normal() -> Weight;43	fn transfer_creating() -> Weight;44	fn transfer_removing() -> Weight;45	fn transfer_creating_removing() -> Weight;46	fn approve() -> Weight;47	fn transfer_from_normal() -> Weight;48	fn transfer_from_creating() -> Weight;49	fn transfer_from_removing() -> Weight;50	fn transfer_from_creating_removing() -> Weight;51	fn burn_from() -> Weight;52	fn set_token_property_permissions(b: u32, ) -> Weight;53	fn set_token_properties(b: u32, ) -> Weight;54	fn delete_token_properties(b: u32, ) -> Weight;55	fn repartition_item() -> Weight;56	fn token_owner() -> Weight;57}5859/// Weights for pallet_refungible using the Substrate node and recommended hardware.60pub struct SubstrateWeight<T>(PhantomData<T>);61impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {62	// Storage: Refungible TokensMinted (r:1 w:1)63	// Storage: Refungible AccountBalance (r:1 w:1)64	// Storage: Refungible Balance (r:0 w:1)65	// Storage: Refungible TotalSupply (r:0 w:1)66	// Storage: Refungible Owned (r:0 w:1)67	fn create_item() -> Weight {68		Weight::from_ref_time(29_527_000)69			.saturating_add(T::DbWeight::get().reads(2 as u64))70			.saturating_add(T::DbWeight::get().writes(5 as u64))71	}72	// Storage: Refungible TokensMinted (r:1 w:1)73	// Storage: Refungible AccountBalance (r:1 w:1)74	// Storage: Refungible Balance (r:0 w:4)75	// Storage: Refungible TotalSupply (r:0 w:4)76	// Storage: Refungible Owned (r:0 w:4)77	fn create_multiple_items(b: u32, ) -> Weight {78		Weight::from_ref_time(28_541_000)79			// Standard Error: 4_00080			.saturating_add(Weight::from_ref_time(6_671_000).saturating_mul(b as u64))81			.saturating_add(T::DbWeight::get().reads(2 as u64))82			.saturating_add(T::DbWeight::get().writes(2 as u64))83			.saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(b as u64)))84	}85	// Storage: Refungible TokensMinted (r:1 w:1)86	// Storage: Refungible AccountBalance (r:4 w:4)87	// Storage: Refungible Balance (r:0 w:4)88	// Storage: Refungible TotalSupply (r:0 w:4)89	// Storage: Refungible Owned (r:0 w:4)90	fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {91		Weight::from_ref_time(24_366_000)92			// Standard Error: 5_00093			.saturating_add(Weight::from_ref_time(9_338_000).saturating_mul(b as u64))94			.saturating_add(T::DbWeight::get().reads(1 as u64))95			.saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(b as u64)))96			.saturating_add(T::DbWeight::get().writes(1 as u64))97			.saturating_add(T::DbWeight::get().writes((4 as u64).saturating_mul(b as u64)))98	}99	// Storage: Refungible TokensMinted (r:1 w:1)100	// Storage: Refungible TotalSupply (r:0 w:1)101	// Storage: Refungible AccountBalance (r:4 w:4)102	// Storage: Refungible Balance (r:0 w:4)103	// Storage: Refungible Owned (r:0 w:4)104	fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {105		Weight::from_ref_time(27_574_000)106			// Standard Error: 4_000107			.saturating_add(Weight::from_ref_time(7_193_000).saturating_mul(b as u64))108			.saturating_add(T::DbWeight::get().reads(1 as u64))109			.saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(b as u64)))110			.saturating_add(T::DbWeight::get().writes(2 as u64))111			.saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(b as u64)))112	}113	// Storage: Refungible TotalSupply (r:1 w:1)114	// Storage: Refungible Balance (r:3 w:1)115	// Storage: Refungible AccountBalance (r:1 w:1)116	// Storage: Refungible Owned (r:0 w:1)117	fn burn_item_partial() -> Weight {118		Weight::from_ref_time(42_943_000)119			.saturating_add(T::DbWeight::get().reads(5 as u64))120			.saturating_add(T::DbWeight::get().writes(4 as u64))121	}122	// Storage: Refungible TotalSupply (r:1 w:1)123	// Storage: Refungible Balance (r:1 w:1)124	// Storage: Refungible AccountBalance (r:1 w:1)125	// Storage: Refungible TokensBurnt (r:1 w:1)126	// Storage: Refungible Owned (r:0 w:1)127	// Storage: Refungible TokenProperties (r:0 w:1)128	fn burn_item_fully() -> Weight {129		Weight::from_ref_time(36_861_000)130			.saturating_add(T::DbWeight::get().reads(4 as u64))131			.saturating_add(T::DbWeight::get().writes(6 as u64))132	}133	// Storage: Refungible Balance (r:2 w:2)134	// Storage: Refungible TotalSupply (r:1 w:0)135	fn transfer_normal() -> Weight {136		Weight::from_ref_time(27_789_000)137			.saturating_add(T::DbWeight::get().reads(3 as u64))138			.saturating_add(T::DbWeight::get().writes(2 as u64))139	}140	// Storage: Refungible Balance (r:2 w:2)141	// Storage: Refungible AccountBalance (r:1 w:1)142	// Storage: Refungible TotalSupply (r:1 w:0)143	// Storage: Refungible Owned (r:0 w:1)144	fn transfer_creating() -> Weight {145		Weight::from_ref_time(32_893_000)146			.saturating_add(T::DbWeight::get().reads(4 as u64))147			.saturating_add(T::DbWeight::get().writes(4 as u64))148	}149	// Storage: Refungible Balance (r:2 w:2)150	// Storage: Refungible AccountBalance (r:1 w:1)151	// Storage: Refungible TotalSupply (r:1 w:0)152	// Storage: Refungible Owned (r:0 w:1)153	fn transfer_removing() -> Weight {154		Weight::from_ref_time(34_703_000)155			.saturating_add(T::DbWeight::get().reads(4 as u64))156			.saturating_add(T::DbWeight::get().writes(4 as u64))157	}158	// Storage: Refungible Balance (r:2 w:2)159	// Storage: Refungible AccountBalance (r:2 w:2)160	// Storage: Refungible TotalSupply (r:1 w:0)161	// Storage: Refungible Owned (r:0 w:2)162	fn transfer_creating_removing() -> Weight {163		Weight::from_ref_time(37_547_000)164			.saturating_add(T::DbWeight::get().reads(5 as u64))165			.saturating_add(T::DbWeight::get().writes(6 as u64))166	}167	// Storage: Refungible Balance (r:1 w:0)168	// Storage: Refungible Allowance (r:0 w:1)169	fn approve() -> Weight {170		Weight::from_ref_time(20_039_000)171			.saturating_add(T::DbWeight::get().reads(1 as u64))172			.saturating_add(T::DbWeight::get().writes(1 as u64))173	}174	// Storage: Refungible Allowance (r:1 w:1)175	// Storage: Refungible Balance (r:2 w:2)176	// Storage: Refungible TotalSupply (r:1 w:0)177	fn transfer_from_normal() -> Weight {178		Weight::from_ref_time(37_628_000)179			.saturating_add(T::DbWeight::get().reads(4 as u64))180			.saturating_add(T::DbWeight::get().writes(3 as u64))181	}182	// Storage: Refungible Allowance (r:1 w:1)183	// Storage: Refungible Balance (r:2 w:2)184	// Storage: Refungible AccountBalance (r:1 w:1)185	// Storage: Refungible TotalSupply (r:1 w:0)186	// Storage: Refungible Owned (r:0 w:1)187	fn transfer_from_creating() -> Weight {188		Weight::from_ref_time(42_072_000)189			.saturating_add(T::DbWeight::get().reads(5 as u64))190			.saturating_add(T::DbWeight::get().writes(5 as u64))191	}192	// Storage: Refungible Allowance (r:1 w:1)193	// Storage: Refungible Balance (r:2 w:2)194	// Storage: Refungible AccountBalance (r:1 w:1)195	// Storage: Refungible TotalSupply (r:1 w:0)196	// Storage: Refungible Owned (r:0 w:1)197	fn transfer_from_removing() -> Weight {198		Weight::from_ref_time(43_024_000)199			.saturating_add(T::DbWeight::get().reads(5 as u64))200			.saturating_add(T::DbWeight::get().writes(5 as u64))201	}202	// Storage: Refungible Allowance (r:1 w:1)203	// Storage: Refungible Balance (r:2 w:2)204	// Storage: Refungible AccountBalance (r:2 w:2)205	// Storage: Refungible TotalSupply (r:1 w:0)206	// Storage: Refungible Owned (r:0 w:2)207	fn transfer_from_creating_removing() -> Weight {208		Weight::from_ref_time(45_910_000)209			.saturating_add(T::DbWeight::get().reads(6 as u64))210			.saturating_add(T::DbWeight::get().writes(7 as u64))211	}212	// Storage: Refungible Allowance (r:1 w:1)213	// Storage: Refungible TotalSupply (r:1 w:1)214	// Storage: Refungible Balance (r:1 w:1)215	// Storage: Refungible AccountBalance (r:1 w:1)216	// Storage: Refungible TokensBurnt (r:1 w:1)217	// Storage: Refungible Owned (r:0 w:1)218	// Storage: Refungible TokenProperties (r:0 w:1)219	fn burn_from() -> Weight {220		Weight::from_ref_time(48_584_000)221			.saturating_add(T::DbWeight::get().reads(5 as u64))222			.saturating_add(T::DbWeight::get().writes(7 as u64))223	}224	// Storage: Common CollectionPropertyPermissions (r:1 w:1)225	fn set_token_property_permissions(b: u32, ) -> Weight {226		(Weight::from_ref_time(0))227			// Standard Error: 60_000228			.saturating_add(Weight::from_ref_time(15_533_000).saturating_mul(b as u64))229			.saturating_add(T::DbWeight::get().reads(1 as u64))230			.saturating_add(T::DbWeight::get().writes(1 as u64))231	}232	// Storage: Common CollectionPropertyPermissions (r:1 w:0)233	// Storage: Refungible TokenProperties (r:1 w:1)234	fn set_token_properties(b: u32, ) -> Weight {235		(Weight::from_ref_time(0))236			// Standard Error: 3_609_000237			.saturating_add(Weight::from_ref_time(590_204_000).saturating_mul(b as u64))238			.saturating_add(T::DbWeight::get().reads(2 as u64))239			.saturating_add(T::DbWeight::get().writes(1 as u64))240	}241	// Storage: Common CollectionPropertyPermissions (r:1 w:0)242	// Storage: Refungible TokenProperties (r:1 w:1)243	fn delete_token_properties(b: u32, ) -> Weight {244		(Weight::from_ref_time(0))245			// Standard Error: 3_637_000246			.saturating_add(Weight::from_ref_time(603_468_000).saturating_mul(b as u64))247			.saturating_add(T::DbWeight::get().reads(2 as u64))248			.saturating_add(T::DbWeight::get().writes(1 as u64))249	}250	// Storage: Refungible TotalSupply (r:1 w:1)251	// Storage: Refungible Balance (r:1 w:1)252	fn repartition_item() -> Weight {253		Weight::from_ref_time(22_356_000)254			.saturating_add(T::DbWeight::get().reads(2 as u64))255			.saturating_add(T::DbWeight::get().writes(2 as u64))256	}257	// Storage: Refungible Balance (r:2 w:0)258	fn token_owner() -> Weight {259		Weight::from_ref_time(9_431_000)260			.saturating_add(T::DbWeight::get().reads(2 as u64))261	}262}263264// For backwards compatibility and tests265impl WeightInfo for () {266	// Storage: Refungible TokensMinted (r:1 w:1)267	// Storage: Refungible AccountBalance (r:1 w:1)268	// Storage: Refungible Balance (r:0 w:1)269	// Storage: Refungible TotalSupply (r:0 w:1)270	// Storage: Refungible Owned (r:0 w:1)271	fn create_item() -> Weight {272		Weight::from_ref_time(29_527_000)273			.saturating_add(RocksDbWeight::get().reads(2 as u64))274			.saturating_add(RocksDbWeight::get().writes(5 as u64))275	}276	// Storage: Refungible TokensMinted (r:1 w:1)277	// Storage: Refungible AccountBalance (r:1 w:1)278	// Storage: Refungible Balance (r:0 w:4)279	// Storage: Refungible TotalSupply (r:0 w:4)280	// Storage: Refungible Owned (r:0 w:4)281	fn create_multiple_items(b: u32, ) -> Weight {282		Weight::from_ref_time(28_541_000)283			// Standard Error: 4_000284			.saturating_add(Weight::from_ref_time(6_671_000).saturating_mul(b as u64))285			.saturating_add(RocksDbWeight::get().reads(2 as u64))286			.saturating_add(RocksDbWeight::get().writes(2 as u64))287			.saturating_add(RocksDbWeight::get().writes((3 as u64).saturating_mul(b as u64)))288	}289	// Storage: Refungible TokensMinted (r:1 w:1)290	// Storage: Refungible AccountBalance (r:4 w:4)291	// Storage: Refungible Balance (r:0 w:4)292	// Storage: Refungible TotalSupply (r:0 w:4)293	// Storage: Refungible Owned (r:0 w:4)294	fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {295		Weight::from_ref_time(24_366_000)296			// Standard Error: 5_000297			.saturating_add(Weight::from_ref_time(9_338_000).saturating_mul(b as u64))298			.saturating_add(RocksDbWeight::get().reads(1 as u64))299			.saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(b as u64)))300			.saturating_add(RocksDbWeight::get().writes(1 as u64))301			.saturating_add(RocksDbWeight::get().writes((4 as u64).saturating_mul(b as u64)))302	}303	// Storage: Refungible TokensMinted (r:1 w:1)304	// Storage: Refungible TotalSupply (r:0 w:1)305	// Storage: Refungible AccountBalance (r:4 w:4)306	// Storage: Refungible Balance (r:0 w:4)307	// Storage: Refungible Owned (r:0 w:4)308	fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {309		Weight::from_ref_time(27_574_000)310			// Standard Error: 4_000311			.saturating_add(Weight::from_ref_time(7_193_000).saturating_mul(b as u64))312			.saturating_add(RocksDbWeight::get().reads(1 as u64))313			.saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(b as u64)))314			.saturating_add(RocksDbWeight::get().writes(2 as u64))315			.saturating_add(RocksDbWeight::get().writes((3 as u64).saturating_mul(b as u64)))316	}317	// Storage: Refungible TotalSupply (r:1 w:1)318	// Storage: Refungible Balance (r:3 w:1)319	// Storage: Refungible AccountBalance (r:1 w:1)320	// Storage: Refungible Owned (r:0 w:1)321	fn burn_item_partial() -> Weight {322		Weight::from_ref_time(42_943_000)323			.saturating_add(RocksDbWeight::get().reads(5 as u64))324			.saturating_add(RocksDbWeight::get().writes(4 as u64))325	}326	// Storage: Refungible TotalSupply (r:1 w:1)327	// Storage: Refungible Balance (r:1 w:1)328	// Storage: Refungible AccountBalance (r:1 w:1)329	// Storage: Refungible TokensBurnt (r:1 w:1)330	// Storage: Refungible Owned (r:0 w:1)331	// Storage: Refungible TokenProperties (r:0 w:1)332	fn burn_item_fully() -> Weight {333		Weight::from_ref_time(36_861_000)334			.saturating_add(RocksDbWeight::get().reads(4 as u64))335			.saturating_add(RocksDbWeight::get().writes(6 as u64))336	}337	// Storage: Refungible Balance (r:2 w:2)338	// Storage: Refungible TotalSupply (r:1 w:0)339	fn transfer_normal() -> Weight {340		Weight::from_ref_time(27_789_000)341			.saturating_add(RocksDbWeight::get().reads(3 as u64))342			.saturating_add(RocksDbWeight::get().writes(2 as u64))343	}344	// Storage: Refungible Balance (r:2 w:2)345	// Storage: Refungible AccountBalance (r:1 w:1)346	// Storage: Refungible TotalSupply (r:1 w:0)347	// Storage: Refungible Owned (r:0 w:1)348	fn transfer_creating() -> Weight {349		Weight::from_ref_time(32_893_000)350			.saturating_add(RocksDbWeight::get().reads(4 as u64))351			.saturating_add(RocksDbWeight::get().writes(4 as u64))352	}353	// Storage: Refungible Balance (r:2 w:2)354	// Storage: Refungible AccountBalance (r:1 w:1)355	// Storage: Refungible TotalSupply (r:1 w:0)356	// Storage: Refungible Owned (r:0 w:1)357	fn transfer_removing() -> Weight {358		Weight::from_ref_time(34_703_000)359			.saturating_add(RocksDbWeight::get().reads(4 as u64))360			.saturating_add(RocksDbWeight::get().writes(4 as u64))361	}362	// Storage: Refungible Balance (r:2 w:2)363	// Storage: Refungible AccountBalance (r:2 w:2)364	// Storage: Refungible TotalSupply (r:1 w:0)365	// Storage: Refungible Owned (r:0 w:2)366	fn transfer_creating_removing() -> Weight {367		Weight::from_ref_time(37_547_000)368			.saturating_add(RocksDbWeight::get().reads(5 as u64))369			.saturating_add(RocksDbWeight::get().writes(6 as u64))370	}371	// Storage: Refungible Balance (r:1 w:0)372	// Storage: Refungible Allowance (r:0 w:1)373	fn approve() -> Weight {374		Weight::from_ref_time(20_039_000)375			.saturating_add(RocksDbWeight::get().reads(1 as u64))376			.saturating_add(RocksDbWeight::get().writes(1 as u64))377	}378	// Storage: Refungible Allowance (r:1 w:1)379	// Storage: Refungible Balance (r:2 w:2)380	// Storage: Refungible TotalSupply (r:1 w:0)381	fn transfer_from_normal() -> Weight {382		Weight::from_ref_time(37_628_000)383			.saturating_add(RocksDbWeight::get().reads(4 as u64))384			.saturating_add(RocksDbWeight::get().writes(3 as u64))385	}386	// Storage: Refungible Allowance (r:1 w:1)387	// Storage: Refungible Balance (r:2 w:2)388	// Storage: Refungible AccountBalance (r:1 w:1)389	// Storage: Refungible TotalSupply (r:1 w:0)390	// Storage: Refungible Owned (r:0 w:1)391	fn transfer_from_creating() -> Weight {392		Weight::from_ref_time(42_072_000)393			.saturating_add(RocksDbWeight::get().reads(5 as u64))394			.saturating_add(RocksDbWeight::get().writes(5 as u64))395	}396	// Storage: Refungible Allowance (r:1 w:1)397	// Storage: Refungible Balance (r:2 w:2)398	// Storage: Refungible AccountBalance (r:1 w:1)399	// Storage: Refungible TotalSupply (r:1 w:0)400	// Storage: Refungible Owned (r:0 w:1)401	fn transfer_from_removing() -> Weight {402		Weight::from_ref_time(43_024_000)403			.saturating_add(RocksDbWeight::get().reads(5 as u64))404			.saturating_add(RocksDbWeight::get().writes(5 as u64))405	}406	// Storage: Refungible Allowance (r:1 w:1)407	// Storage: Refungible Balance (r:2 w:2)408	// Storage: Refungible AccountBalance (r:2 w:2)409	// Storage: Refungible TotalSupply (r:1 w:0)410	// Storage: Refungible Owned (r:0 w:2)411	fn transfer_from_creating_removing() -> Weight {412		Weight::from_ref_time(45_910_000)413			.saturating_add(RocksDbWeight::get().reads(6 as u64))414			.saturating_add(RocksDbWeight::get().writes(7 as u64))415	}416	// Storage: Refungible Allowance (r:1 w:1)417	// Storage: Refungible TotalSupply (r:1 w:1)418	// Storage: Refungible Balance (r:1 w:1)419	// Storage: Refungible AccountBalance (r:1 w:1)420	// Storage: Refungible TokensBurnt (r:1 w:1)421	// Storage: Refungible Owned (r:0 w:1)422	// Storage: Refungible TokenProperties (r:0 w:1)423	fn burn_from() -> Weight {424		Weight::from_ref_time(48_584_000)425			.saturating_add(RocksDbWeight::get().reads(5 as u64))426			.saturating_add(RocksDbWeight::get().writes(7 as u64))427	}428	// Storage: Common CollectionPropertyPermissions (r:1 w:1)429	fn set_token_property_permissions(b: u32, ) -> Weight {430		(Weight::from_ref_time(0))431			// Standard Error: 60_000432			.saturating_add(Weight::from_ref_time(15_533_000).saturating_mul(b as u64))433			.saturating_add(RocksDbWeight::get().reads(1 as u64))434			.saturating_add(RocksDbWeight::get().writes(1 as u64))435	}436	// Storage: Common CollectionPropertyPermissions (r:1 w:0)437	// Storage: Refungible TokenProperties (r:1 w:1)438	fn set_token_properties(b: u32, ) -> Weight {439		(Weight::from_ref_time(0))440			// Standard Error: 3_609_000441			.saturating_add(Weight::from_ref_time(590_204_000).saturating_mul(b as u64))442			.saturating_add(RocksDbWeight::get().reads(2 as u64))443			.saturating_add(RocksDbWeight::get().writes(1 as u64))444	}445	// Storage: Common CollectionPropertyPermissions (r:1 w:0)446	// Storage: Refungible TokenProperties (r:1 w:1)447	fn delete_token_properties(b: u32, ) -> Weight {448		(Weight::from_ref_time(0))449			// Standard Error: 3_637_000450			.saturating_add(Weight::from_ref_time(603_468_000).saturating_mul(b as u64))451			.saturating_add(RocksDbWeight::get().reads(2 as u64))452			.saturating_add(RocksDbWeight::get().writes(1 as u64))453	}454	// Storage: Refungible TotalSupply (r:1 w:1)455	// Storage: Refungible Balance (r:1 w:1)456	fn repartition_item() -> Weight {457		Weight::from_ref_time(22_356_000)458			.saturating_add(RocksDbWeight::get().reads(2 as u64))459			.saturating_add(RocksDbWeight::get().writes(2 as u64))460	}461	// Storage: Refungible Balance (r:2 w:0)462	fn token_owner() -> Weight {463		Weight::from_ref_time(9_431_000)464			.saturating_add(RocksDbWeight::get().reads(2 as u64))465	}466}
after · pallets/refungible/src/weights.rs
1// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs23//! Autogenerated weights for pallet_refungible4//!5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev6//! DATE: 2022-11-25, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`7//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 102489// Executed Command:10// target/release/unique-collator11// benchmark12// pallet13// --pallet14// pallet-refungible15// --wasm-execution16// compiled17// --extrinsic18// *19// --template20// .maintain/frame-weight-template.hbs21// --steps=5022// --repeat=8023// --heap-pages=409624// --output=./pallets/refungible/src/weights.rs2526#![cfg_attr(rustfmt, rustfmt_skip)]27#![allow(unused_parens)]28#![allow(unused_imports)]29#![allow(missing_docs)]30#![allow(clippy::unnecessary_cast)]3132use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};33use sp_std::marker::PhantomData;3435/// Weight functions needed for pallet_refungible.36pub trait WeightInfo {37	fn create_item() -> Weight;38	fn create_multiple_items(b: u32, ) -> Weight;39	fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight;40	fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight;41	fn burn_item_partial() -> Weight;42	fn burn_item_fully() -> Weight;43	fn transfer_normal() -> Weight;44	fn transfer_creating() -> Weight;45	fn transfer_removing() -> Weight;46	fn transfer_creating_removing() -> Weight;47	fn approve() -> Weight;48	fn transfer_from_normal() -> Weight;49	fn transfer_from_creating() -> Weight;50	fn transfer_from_removing() -> Weight;51	fn transfer_from_creating_removing() -> Weight;52	fn burn_from() -> Weight;53	fn set_token_property_permissions(b: u32, ) -> Weight;54	fn set_token_properties(b: u32, ) -> Weight;55	fn delete_token_properties(b: u32, ) -> Weight;56	fn repartition_item() -> Weight;57	fn token_owner() -> Weight;58	fn set_approval_for_all() -> Weight;59	fn is_approved_for_all() -> Weight;60}6162/// Weights for pallet_refungible using the Substrate node and recommended hardware.63pub struct SubstrateWeight<T>(PhantomData<T>);64impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {65	// Storage: Refungible TokensMinted (r:1 w:1)66	// Storage: Refungible AccountBalance (r:1 w:1)67	// Storage: Refungible Balance (r:0 w:1)68	// Storage: Refungible TotalSupply (r:0 w:1)69	// Storage: Refungible Owned (r:0 w:1)70	fn create_item() -> Weight {71		Weight::from_ref_time(29_527_000)72			.saturating_add(T::DbWeight::get().reads(2 as u64))73			.saturating_add(T::DbWeight::get().writes(5 as u64))74	}75	// Storage: Refungible TokensMinted (r:1 w:1)76	// Storage: Refungible AccountBalance (r:1 w:1)77	// Storage: Refungible Balance (r:0 w:4)78	// Storage: Refungible TotalSupply (r:0 w:4)79	// Storage: Refungible Owned (r:0 w:4)80	fn create_multiple_items(b: u32, ) -> Weight {81		Weight::from_ref_time(28_541_000)82			// Standard Error: 4_00083			.saturating_add(Weight::from_ref_time(6_671_000).saturating_mul(b as u64))84			.saturating_add(T::DbWeight::get().reads(2 as u64))85			.saturating_add(T::DbWeight::get().writes(2 as u64))86			.saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(b as u64)))87	}88	// Storage: Refungible TokensMinted (r:1 w:1)89	// Storage: Refungible AccountBalance (r:4 w:4)90	// Storage: Refungible Balance (r:0 w:4)91	// Storage: Refungible TotalSupply (r:0 w:4)92	// Storage: Refungible Owned (r:0 w:4)93	fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {94		Weight::from_ref_time(24_366_000)95			// Standard Error: 5_00096			.saturating_add(Weight::from_ref_time(9_338_000).saturating_mul(b as u64))97			.saturating_add(T::DbWeight::get().reads(1 as u64))98			.saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(b as u64)))99			.saturating_add(T::DbWeight::get().writes(1 as u64))100			.saturating_add(T::DbWeight::get().writes((4 as u64).saturating_mul(b as u64)))101	}102	// Storage: Refungible TokensMinted (r:1 w:1)103	// Storage: Refungible TotalSupply (r:0 w:1)104	// Storage: Refungible AccountBalance (r:4 w:4)105	// Storage: Refungible Balance (r:0 w:4)106	// Storage: Refungible Owned (r:0 w:4)107	fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {108		Weight::from_ref_time(27_574_000)109			// Standard Error: 4_000110			.saturating_add(Weight::from_ref_time(7_193_000).saturating_mul(b as u64))111			.saturating_add(T::DbWeight::get().reads(1 as u64))112			.saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(b as u64)))113			.saturating_add(T::DbWeight::get().writes(2 as u64))114			.saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(b as u64)))115	}116	// Storage: Refungible TotalSupply (r:1 w:1)117	// Storage: Refungible Balance (r:3 w:1)118	// Storage: Refungible AccountBalance (r:1 w:1)119	// Storage: Refungible Owned (r:0 w:1)120	fn burn_item_partial() -> Weight {121		Weight::from_ref_time(42_943_000)122			.saturating_add(T::DbWeight::get().reads(5 as u64))123			.saturating_add(T::DbWeight::get().writes(4 as u64))124	}125	// Storage: Refungible TotalSupply (r:1 w:1)126	// Storage: Refungible Balance (r:1 w:1)127	// Storage: Refungible AccountBalance (r:1 w:1)128	// Storage: Refungible TokensBurnt (r:1 w:1)129	// Storage: Refungible Owned (r:0 w:1)130	// Storage: Refungible TokenProperties (r:0 w:1)131	fn burn_item_fully() -> Weight {132		Weight::from_ref_time(36_861_000)133			.saturating_add(T::DbWeight::get().reads(4 as u64))134			.saturating_add(T::DbWeight::get().writes(6 as u64))135	}136	// Storage: Refungible Balance (r:2 w:2)137	// Storage: Refungible TotalSupply (r:1 w:0)138	fn transfer_normal() -> Weight {139		Weight::from_ref_time(27_789_000)140			.saturating_add(T::DbWeight::get().reads(3 as u64))141			.saturating_add(T::DbWeight::get().writes(2 as u64))142	}143	// Storage: Refungible Balance (r:2 w:2)144	// Storage: Refungible AccountBalance (r:1 w:1)145	// Storage: Refungible TotalSupply (r:1 w:0)146	// Storage: Refungible Owned (r:0 w:1)147	fn transfer_creating() -> Weight {148		Weight::from_ref_time(32_893_000)149			.saturating_add(T::DbWeight::get().reads(4 as u64))150			.saturating_add(T::DbWeight::get().writes(4 as u64))151	}152	// Storage: Refungible Balance (r:2 w:2)153	// Storage: Refungible AccountBalance (r:1 w:1)154	// Storage: Refungible TotalSupply (r:1 w:0)155	// Storage: Refungible Owned (r:0 w:1)156	fn transfer_removing() -> Weight {157		Weight::from_ref_time(34_703_000)158			.saturating_add(T::DbWeight::get().reads(4 as u64))159			.saturating_add(T::DbWeight::get().writes(4 as u64))160	}161	// Storage: Refungible Balance (r:2 w:2)162	// Storage: Refungible AccountBalance (r:2 w:2)163	// Storage: Refungible TotalSupply (r:1 w:0)164	// Storage: Refungible Owned (r:0 w:2)165	fn transfer_creating_removing() -> Weight {166		Weight::from_ref_time(37_547_000)167			.saturating_add(T::DbWeight::get().reads(5 as u64))168			.saturating_add(T::DbWeight::get().writes(6 as u64))169	}170	// Storage: Refungible Balance (r:1 w:0)171	// Storage: Refungible Allowance (r:0 w:1)172	fn approve() -> Weight {173		Weight::from_ref_time(20_039_000)174			.saturating_add(T::DbWeight::get().reads(1 as u64))175			.saturating_add(T::DbWeight::get().writes(1 as u64))176	}177	// Storage: Refungible Allowance (r:1 w:1)178	// Storage: Refungible Balance (r:2 w:2)179	// Storage: Refungible TotalSupply (r:1 w:0)180	fn transfer_from_normal() -> Weight {181		Weight::from_ref_time(37_628_000)182			.saturating_add(T::DbWeight::get().reads(4 as u64))183			.saturating_add(T::DbWeight::get().writes(3 as u64))184	}185	// Storage: Refungible Allowance (r:1 w:1)186	// Storage: Refungible Balance (r:2 w:2)187	// Storage: Refungible AccountBalance (r:1 w:1)188	// Storage: Refungible TotalSupply (r:1 w:0)189	// Storage: Refungible Owned (r:0 w:1)190	fn transfer_from_creating() -> Weight {191		Weight::from_ref_time(42_072_000)192			.saturating_add(T::DbWeight::get().reads(5 as u64))193			.saturating_add(T::DbWeight::get().writes(5 as u64))194	}195	// Storage: Refungible Allowance (r:1 w:1)196	// Storage: Refungible Balance (r:2 w:2)197	// Storage: Refungible AccountBalance (r:1 w:1)198	// Storage: Refungible TotalSupply (r:1 w:0)199	// Storage: Refungible Owned (r:0 w:1)200	fn transfer_from_removing() -> Weight {201		Weight::from_ref_time(43_024_000)202			.saturating_add(T::DbWeight::get().reads(5 as u64))203			.saturating_add(T::DbWeight::get().writes(5 as u64))204	}205	// Storage: Refungible Allowance (r:1 w:1)206	// Storage: Refungible Balance (r:2 w:2)207	// Storage: Refungible AccountBalance (r:2 w:2)208	// Storage: Refungible TotalSupply (r:1 w:0)209	// Storage: Refungible Owned (r:0 w:2)210	fn transfer_from_creating_removing() -> Weight {211		Weight::from_ref_time(45_910_000)212			.saturating_add(T::DbWeight::get().reads(6 as u64))213			.saturating_add(T::DbWeight::get().writes(7 as u64))214	}215	// Storage: Refungible Allowance (r:1 w:1)216	// Storage: Refungible TotalSupply (r:1 w:1)217	// Storage: Refungible Balance (r:1 w:1)218	// Storage: Refungible AccountBalance (r:1 w:1)219	// Storage: Refungible TokensBurnt (r:1 w:1)220	// Storage: Refungible Owned (r:0 w:1)221	// Storage: Refungible TokenProperties (r:0 w:1)222	fn burn_from() -> Weight {223		Weight::from_ref_time(48_584_000)224			.saturating_add(T::DbWeight::get().reads(5 as u64))225			.saturating_add(T::DbWeight::get().writes(7 as u64))226	}227	// Storage: Common CollectionPropertyPermissions (r:1 w:1)228	fn set_token_property_permissions(b: u32, ) -> Weight {229		(Weight::from_ref_time(0))230			// Standard Error: 60_000231			.saturating_add(Weight::from_ref_time(15_533_000).saturating_mul(b as u64))232			.saturating_add(T::DbWeight::get().reads(1 as u64))233			.saturating_add(T::DbWeight::get().writes(1 as u64))234	}235	// Storage: Common CollectionPropertyPermissions (r:1 w:0)236	// Storage: Refungible TokenProperties (r:1 w:1)237	fn set_token_properties(b: u32, ) -> Weight {238		(Weight::from_ref_time(0))239			// Standard Error: 3_609_000240			.saturating_add(Weight::from_ref_time(590_204_000).saturating_mul(b as u64))241			.saturating_add(T::DbWeight::get().reads(2 as u64))242			.saturating_add(T::DbWeight::get().writes(1 as u64))243	}244	// Storage: Common CollectionPropertyPermissions (r:1 w:0)245	// Storage: Refungible TokenProperties (r:1 w:1)246	fn delete_token_properties(b: u32, ) -> Weight {247		(Weight::from_ref_time(0))248			// Standard Error: 3_637_000249			.saturating_add(Weight::from_ref_time(603_468_000).saturating_mul(b as u64))250			.saturating_add(T::DbWeight::get().reads(2 as u64))251			.saturating_add(T::DbWeight::get().writes(1 as u64))252	}253	// Storage: Refungible TotalSupply (r:1 w:1)254	// Storage: Refungible Balance (r:1 w:1)255	fn repartition_item() -> Weight {256		Weight::from_ref_time(22_356_000)257			.saturating_add(T::DbWeight::get().reads(2 as u64))258			.saturating_add(T::DbWeight::get().writes(2 as u64))259	}260	// Storage: Refungible Balance (r:2 w:0)261	fn token_owner() -> Weight {262		Weight::from_ref_time(9_431_000)263			.saturating_add(T::DbWeight::get().reads(2 as u64))264	}265	// Storage: Refungible WalletOperator (r:0 w:1)266	fn set_approval_for_all() -> Weight {267		Weight::from_ref_time(16_150_000 as u64)268			.saturating_add(T::DbWeight::get().writes(1 as u64))269	}270	// Storage: Refungible WalletOperator (r:1 w:0)271	fn is_approved_for_all() -> Weight {272		Weight::from_ref_time(5_901_000 as u64)273			.saturating_add(T::DbWeight::get().reads(1 as u64))274	}275}276277// For backwards compatibility and tests278impl WeightInfo for () {279	// Storage: Refungible TokensMinted (r:1 w:1)280	// Storage: Refungible AccountBalance (r:1 w:1)281	// Storage: Refungible Balance (r:0 w:1)282	// Storage: Refungible TotalSupply (r:0 w:1)283	// Storage: Refungible Owned (r:0 w:1)284	fn create_item() -> Weight {285		Weight::from_ref_time(29_527_000)286			.saturating_add(RocksDbWeight::get().reads(2 as u64))287			.saturating_add(RocksDbWeight::get().writes(5 as u64))288	}289	// Storage: Refungible TokensMinted (r:1 w:1)290	// Storage: Refungible AccountBalance (r:1 w:1)291	// Storage: Refungible Balance (r:0 w:4)292	// Storage: Refungible TotalSupply (r:0 w:4)293	// Storage: Refungible Owned (r:0 w:4)294	fn create_multiple_items(b: u32, ) -> Weight {295		Weight::from_ref_time(28_541_000)296			// Standard Error: 4_000297			.saturating_add(Weight::from_ref_time(6_671_000).saturating_mul(b as u64))298			.saturating_add(RocksDbWeight::get().reads(2 as u64))299			.saturating_add(RocksDbWeight::get().writes(2 as u64))300			.saturating_add(RocksDbWeight::get().writes((3 as u64).saturating_mul(b as u64)))301	}302	// Storage: Refungible TokensMinted (r:1 w:1)303	// Storage: Refungible AccountBalance (r:4 w:4)304	// Storage: Refungible Balance (r:0 w:4)305	// Storage: Refungible TotalSupply (r:0 w:4)306	// Storage: Refungible Owned (r:0 w:4)307	fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {308		Weight::from_ref_time(24_366_000)309			// Standard Error: 5_000310			.saturating_add(Weight::from_ref_time(9_338_000).saturating_mul(b as u64))311			.saturating_add(RocksDbWeight::get().reads(1 as u64))312			.saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(b as u64)))313			.saturating_add(RocksDbWeight::get().writes(1 as u64))314			.saturating_add(RocksDbWeight::get().writes((4 as u64).saturating_mul(b as u64)))315	}316	// Storage: Refungible TokensMinted (r:1 w:1)317	// Storage: Refungible TotalSupply (r:0 w:1)318	// Storage: Refungible AccountBalance (r:4 w:4)319	// Storage: Refungible Balance (r:0 w:4)320	// Storage: Refungible Owned (r:0 w:4)321	fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {322		Weight::from_ref_time(27_574_000)323			// Standard Error: 4_000324			.saturating_add(Weight::from_ref_time(7_193_000).saturating_mul(b as u64))325			.saturating_add(RocksDbWeight::get().reads(1 as u64))326			.saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(b as u64)))327			.saturating_add(RocksDbWeight::get().writes(2 as u64))328			.saturating_add(RocksDbWeight::get().writes((3 as u64).saturating_mul(b as u64)))329	}330	// Storage: Refungible TotalSupply (r:1 w:1)331	// Storage: Refungible Balance (r:3 w:1)332	// Storage: Refungible AccountBalance (r:1 w:1)333	// Storage: Refungible Owned (r:0 w:1)334	fn burn_item_partial() -> Weight {335		Weight::from_ref_time(42_943_000)336			.saturating_add(RocksDbWeight::get().reads(5 as u64))337			.saturating_add(RocksDbWeight::get().writes(4 as u64))338	}339	// Storage: Refungible TotalSupply (r:1 w:1)340	// Storage: Refungible Balance (r:1 w:1)341	// Storage: Refungible AccountBalance (r:1 w:1)342	// Storage: Refungible TokensBurnt (r:1 w:1)343	// Storage: Refungible Owned (r:0 w:1)344	// Storage: Refungible TokenProperties (r:0 w:1)345	fn burn_item_fully() -> Weight {346		Weight::from_ref_time(36_861_000)347			.saturating_add(RocksDbWeight::get().reads(4 as u64))348			.saturating_add(RocksDbWeight::get().writes(6 as u64))349	}350	// Storage: Refungible Balance (r:2 w:2)351	// Storage: Refungible TotalSupply (r:1 w:0)352	fn transfer_normal() -> Weight {353		Weight::from_ref_time(27_789_000)354			.saturating_add(RocksDbWeight::get().reads(3 as u64))355			.saturating_add(RocksDbWeight::get().writes(2 as u64))356	}357	// Storage: Refungible Balance (r:2 w:2)358	// Storage: Refungible AccountBalance (r:1 w:1)359	// Storage: Refungible TotalSupply (r:1 w:0)360	// Storage: Refungible Owned (r:0 w:1)361	fn transfer_creating() -> Weight {362		Weight::from_ref_time(32_893_000)363			.saturating_add(RocksDbWeight::get().reads(4 as u64))364			.saturating_add(RocksDbWeight::get().writes(4 as u64))365	}366	// Storage: Refungible Balance (r:2 w:2)367	// Storage: Refungible AccountBalance (r:1 w:1)368	// Storage: Refungible TotalSupply (r:1 w:0)369	// Storage: Refungible Owned (r:0 w:1)370	fn transfer_removing() -> Weight {371		Weight::from_ref_time(34_703_000)372			.saturating_add(RocksDbWeight::get().reads(4 as u64))373			.saturating_add(RocksDbWeight::get().writes(4 as u64))374	}375	// Storage: Refungible Balance (r:2 w:2)376	// Storage: Refungible AccountBalance (r:2 w:2)377	// Storage: Refungible TotalSupply (r:1 w:0)378	// Storage: Refungible Owned (r:0 w:2)379	fn transfer_creating_removing() -> Weight {380		Weight::from_ref_time(37_547_000)381			.saturating_add(RocksDbWeight::get().reads(5 as u64))382			.saturating_add(RocksDbWeight::get().writes(6 as u64))383	}384	// Storage: Refungible Balance (r:1 w:0)385	// Storage: Refungible Allowance (r:0 w:1)386	fn approve() -> Weight {387		Weight::from_ref_time(20_039_000)388			.saturating_add(RocksDbWeight::get().reads(1 as u64))389			.saturating_add(RocksDbWeight::get().writes(1 as u64))390	}391	// Storage: Refungible Allowance (r:1 w:1)392	// Storage: Refungible Balance (r:2 w:2)393	// Storage: Refungible TotalSupply (r:1 w:0)394	fn transfer_from_normal() -> Weight {395		Weight::from_ref_time(37_628_000)396			.saturating_add(RocksDbWeight::get().reads(4 as u64))397			.saturating_add(RocksDbWeight::get().writes(3 as u64))398	}399	// Storage: Refungible Allowance (r:1 w:1)400	// Storage: Refungible Balance (r:2 w:2)401	// Storage: Refungible AccountBalance (r:1 w:1)402	// Storage: Refungible TotalSupply (r:1 w:0)403	// Storage: Refungible Owned (r:0 w:1)404	fn transfer_from_creating() -> Weight {405		Weight::from_ref_time(42_072_000)406			.saturating_add(RocksDbWeight::get().reads(5 as u64))407			.saturating_add(RocksDbWeight::get().writes(5 as u64))408	}409	// Storage: Refungible Allowance (r:1 w:1)410	// Storage: Refungible Balance (r:2 w:2)411	// Storage: Refungible AccountBalance (r:1 w:1)412	// Storage: Refungible TotalSupply (r:1 w:0)413	// Storage: Refungible Owned (r:0 w:1)414	fn transfer_from_removing() -> Weight {415		Weight::from_ref_time(43_024_000)416			.saturating_add(RocksDbWeight::get().reads(5 as u64))417			.saturating_add(RocksDbWeight::get().writes(5 as u64))418	}419	// Storage: Refungible Allowance (r:1 w:1)420	// Storage: Refungible Balance (r:2 w:2)421	// Storage: Refungible AccountBalance (r:2 w:2)422	// Storage: Refungible TotalSupply (r:1 w:0)423	// Storage: Refungible Owned (r:0 w:2)424	fn transfer_from_creating_removing() -> Weight {425		Weight::from_ref_time(45_910_000)426			.saturating_add(RocksDbWeight::get().reads(6 as u64))427			.saturating_add(RocksDbWeight::get().writes(7 as u64))428	}429	// Storage: Refungible Allowance (r:1 w:1)430	// Storage: Refungible TotalSupply (r:1 w:1)431	// Storage: Refungible Balance (r:1 w:1)432	// Storage: Refungible AccountBalance (r:1 w:1)433	// Storage: Refungible TokensBurnt (r:1 w:1)434	// Storage: Refungible Owned (r:0 w:1)435	// Storage: Refungible TokenProperties (r:0 w:1)436	fn burn_from() -> Weight {437		Weight::from_ref_time(48_584_000)438			.saturating_add(RocksDbWeight::get().reads(5 as u64))439			.saturating_add(RocksDbWeight::get().writes(7 as u64))440	}441	// Storage: Common CollectionPropertyPermissions (r:1 w:1)442	fn set_token_property_permissions(b: u32, ) -> Weight {443		(Weight::from_ref_time(0))444			// Standard Error: 60_000445			.saturating_add(Weight::from_ref_time(15_533_000).saturating_mul(b as u64))446			.saturating_add(RocksDbWeight::get().reads(1 as u64))447			.saturating_add(RocksDbWeight::get().writes(1 as u64))448	}449	// Storage: Common CollectionPropertyPermissions (r:1 w:0)450	// Storage: Refungible TokenProperties (r:1 w:1)451	fn set_token_properties(b: u32, ) -> Weight {452		(Weight::from_ref_time(0))453			// Standard Error: 3_609_000454			.saturating_add(Weight::from_ref_time(590_204_000).saturating_mul(b as u64))455			.saturating_add(RocksDbWeight::get().reads(2 as u64))456			.saturating_add(RocksDbWeight::get().writes(1 as u64))457	}458	// Storage: Common CollectionPropertyPermissions (r:1 w:0)459	// Storage: Refungible TokenProperties (r:1 w:1)460	fn delete_token_properties(b: u32, ) -> Weight {461		(Weight::from_ref_time(0))462			// Standard Error: 3_637_000463			.saturating_add(Weight::from_ref_time(603_468_000).saturating_mul(b as u64))464			.saturating_add(RocksDbWeight::get().reads(2 as u64))465			.saturating_add(RocksDbWeight::get().writes(1 as u64))466	}467	// Storage: Refungible TotalSupply (r:1 w:1)468	// Storage: Refungible Balance (r:1 w:1)469	fn repartition_item() -> Weight {470		Weight::from_ref_time(22_356_000)471			.saturating_add(RocksDbWeight::get().reads(2 as u64))472			.saturating_add(RocksDbWeight::get().writes(2 as u64))473	}474	// Storage: Refungible Balance (r:2 w:0)475	fn token_owner() -> Weight {476		Weight::from_ref_time(9_431_000)477			.saturating_add(RocksDbWeight::get().reads(2 as u64))478	}479	// Storage: Refungible WalletOperator (r:0 w:1)480	fn set_approval_for_all() -> Weight {481		Weight::from_ref_time(16_150_000 as u64)482			.saturating_add(RocksDbWeight::get().writes(1 as u64))483	}484	// Storage: Refungible WalletOperator (r:1 w:0)485	fn is_approved_for_all() -> Weight {486		Weight::from_ref_time(5_901_000 as u64)487			.saturating_add(RocksDbWeight::get().reads(1 as u64))488	}489}
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -1126,6 +1126,28 @@
 				}
 			})
 		}
+
+		/// Sets or unsets the approval of a given operator.
+		///
+		/// An operator is allowed to transfer all tokens of the sender on their behalf.
+		///
+		/// # Arguments
+		///
+		/// * `owner`: Token owner
+		/// * `operator`: Operator
+		/// * `approve`: Is operator enabled or disabled
+		#[weight = T::CommonWeightInfo::set_approval_for_all()]
+		pub fn set_approval_for_all(
+			origin,
+			collection_id: CollectionId,
+			operator: T::CrossAccountId,
+			approve: bool,
+		) -> DispatchResultWithPostInfo {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			dispatch_tx::<T, _>(collection_id, |d| {
+				d.set_approval_for_all(sender, operator, approve)
+			})
+		}
 	}
 }
 
modifiedprimitives/rpc/src/lib.rsdiffbeforeafterboth
--- a/primitives/rpc/src/lib.rs
+++ b/primitives/rpc/src/lib.rs
@@ -132,5 +132,8 @@
 		fn total_pieces(collection_id: CollectionId, token_id: TokenId) -> Result<Option<u128>>;
 
 		fn token_owners(collection: CollectionId, token: TokenId) -> Result<Vec<CrossAccountId>>;
+
+		/// Get whether an operator is approved by a given owner.
+		fn is_approved_for_all(collection: CollectionId, owner: CrossAccountId, operator: CrossAccountId) -> Result<bool>;
 	}
 }
modifiedruntime/common/runtime_apis.rsdiffbeforeafterboth
--- a/runtime/common/runtime_apis.rs
+++ b/runtime/common/runtime_apis.rs
@@ -187,6 +187,10 @@
                 fn total_pieces(collection: CollectionId, token_id: TokenId) -> Result<Option<u128>, DispatchError> {
                     dispatch_unique_runtime!(collection.total_pieces(token_id))
                 }
+
+		        fn is_approved_for_all(collection: CollectionId, owner: CrossAccountId, operator: CrossAccountId) -> Result<bool, DispatchError> {
+                    dispatch_unique_runtime!(collection.is_approved_for_all(owner, operator))
+                }
             }
 
             impl app_promotion_rpc::AppPromotionApi<Block, BlockNumber, CrossAccountId, AccountId> for Runtime {
modifiedruntime/common/weights.rsdiffbeforeafterboth
--- a/runtime/common/weights.rs
+++ b/runtime/common/weights.rs
@@ -120,6 +120,10 @@
 	fn token_owner() -> Weight {
 		max_weight_of!(token_owner())
 	}
+
+	fn set_approval_for_all() -> Weight {
+		max_weight_of!(set_approval_for_all())
+	}
 }
 
 #[cfg(feature = "refungible")]
modifiedtests/src/approve.test.tsdiffbeforeafterboth
--- a/tests/src/approve.test.ts
+++ b/tests/src/approve.test.ts
@@ -603,3 +603,40 @@
     await expect(approveTx()).to.be.rejected;
   });
 });
+
+describe('Normal user can approve other users to be wallet operator:', () => {
+  let alice: IKeyringPair;
+  let bob: IKeyringPair;
+
+  before(async () => {
+    await usingPlaygrounds(async (helper, privateKey) => {
+      const donor = await privateKey({filename: __filename});
+      [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);
+    });
+  });
+
+  itSub('[nft] Enable and disable approval', async ({helper}) => {
+    const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+    await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});
+    const checkBeforeApprovalTx = () => helper.nft.isApprovedForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
+    expect(await checkBeforeApprovalTx()).to.be.false;
+    await helper.nft.setApprovalForAll(alice, collectionId, {Substrate: bob.address}, true);
+    const checkAfterApprovalTx = () => helper.nft.isApprovedForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
+    expect(await checkAfterApprovalTx()).to.be.true;
+    await helper.nft.setApprovalForAll(alice, collectionId, {Substrate: bob.address}, false);
+    const checkAfterDisapprovalTx = () => helper.nft.isApprovedForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
+    expect(await checkAfterDisapprovalTx()).to.be.false;
+  });
+
+  itSub.ifWithPallets('[rft] Enable and disable approval', [Pallets.ReFungible], async ({helper}) => {
+    const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+    const checkBeforeApprovalTx = () => helper.rft.isApprovedForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
+    expect(await checkBeforeApprovalTx()).to.be.false;
+    await helper.rft.setApprovalForAll(alice, collectionId, {Substrate: bob.address}, true);
+    const checkAfterApprovalTx = () => helper.rft.isApprovedForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
+    expect(await checkAfterApprovalTx()).to.be.true;
+    await helper.rft.setApprovalForAll(alice, collectionId, {Substrate: bob.address}, false);
+    const checkAfterDisapprovalTx = () => helper.rft.isApprovedForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
+    expect(await checkAfterDisapprovalTx()).to.be.false;
+  });
+});
modifiedtests/src/eth/abi/nonFungible.jsondiffbeforeafterboth
--- a/tests/src/eth/abi/nonFungible.json
+++ b/tests/src/eth/abi/nonFungible.json
@@ -384,7 +384,7 @@
       { "internalType": "address", "name": "operator", "type": "address" }
     ],
     "name": "isApprovedForAll",
-    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
+    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
     "stateMutability": "view",
     "type": "function"
   },
modifiedtests/src/eth/abi/reFungible.jsondiffbeforeafterboth
--- a/tests/src/eth/abi/reFungible.json
+++ b/tests/src/eth/abi/reFungible.json
@@ -366,7 +366,7 @@
       { "internalType": "address", "name": "operator", "type": "address" }
     ],
     "name": "isApprovedForAll",
-    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
+    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
     "stateMutability": "view",
     "type": "function"
   },
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -671,7 +671,10 @@
 	///  or in textual repr: approve(address,uint256)
 	function approve(address approved, uint256 tokenId) external;
 
-	/// @dev Not implemented
+	/// @notice Sets or unsets the approval of a given operator.
+	///  An operator is allowed to transfer all tokens of the sender on their behalf.
+	/// @param operator Operator
+	/// @param approved Is operator enabled or disabled
 	/// @dev EVM selector for this function is: 0xa22cb465,
 	///  or in textual repr: setApprovalForAll(address,bool)
 	function setApprovalForAll(address operator, bool approved) external;
@@ -681,10 +684,10 @@
 	///  or in textual repr: getApproved(uint256)
 	function getApproved(uint256 tokenId) external view returns (address);
 
-	/// @dev Not implemented
+	/// @notice Tells whether an operator is approved by a given owner.
 	/// @dev EVM selector for this function is: 0xe985e9c5,
 	///  or in textual repr: isApprovedForAll(address,address)
-	function isApprovedForAll(address owner, address operator) external view returns (address);
+	function isApprovedForAll(address owner, address operator) external view returns (bool);
 
 	/// @notice Returns collection helper contract address
 	/// @dev EVM selector for this function is: 0x1896cce6,
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -668,7 +668,10 @@
 	///  or in textual repr: approve(address,uint256)
 	function approve(address approved, uint256 tokenId) external;
 
-	/// @dev Not implemented
+	/// @notice Sets or unsets the approval of a given operator.
+	///  An operator is allowed to transfer all tokens of the sender on their behalf.
+	/// @param operator Operator
+	/// @param approved Is operator enabled or disabled
 	/// @dev EVM selector for this function is: 0xa22cb465,
 	///  or in textual repr: setApprovalForAll(address,bool)
 	function setApprovalForAll(address operator, bool approved) external;
@@ -678,10 +681,10 @@
 	///  or in textual repr: getApproved(uint256)
 	function getApproved(uint256 tokenId) external view returns (address);
 
-	/// @dev Not implemented
+	/// @notice Tells whether an operator is approved by a given owner.
 	/// @dev EVM selector for this function is: 0xe985e9c5,
 	///  or in textual repr: isApprovedForAll(address,address)
-	function isApprovedForAll(address owner, address operator) external view returns (address);
+	function isApprovedForAll(address owner, address operator) external view returns (bool);
 
 	/// @notice Returns collection helper contract address
 	/// @dev EVM selector for this function is: 0x1896cce6,
modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -249,6 +249,114 @@
     }
   });
 
+  itEth('Can perform setApprovalForAll()', async ({helper}) => {
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const operator = helper.eth.createAccount();
+
+    const collection = await helper.nft.mintCollection(minter, {});
+
+    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+    const approvedBefore = await contract.methods.isApprovedForAll(owner, operator).call();
+    expect(approvedBefore).to.be.equal(false);
+
+    {
+      const result = await contract.methods.setApprovalForAll(operator, true).send({from: owner});
+
+      expect(result.events.ApprovalForAll).to.be.like({
+        address: collectionAddress,
+        event: 'ApprovalForAll',
+        returnValues: {
+          owner,
+          operator,
+          approved: true,
+        },
+      });
+
+      const approvedAfter = await contract.methods.isApprovedForAll(owner, operator).call();
+      expect(approvedAfter).to.be.equal(true);
+    }
+
+    {
+      const result = await contract.methods.setApprovalForAll(operator, false).send({from: owner});
+
+      expect(result.events.ApprovalForAll).to.be.like({
+        address: collectionAddress,
+        event: 'ApprovalForAll',
+        returnValues: {
+          owner,
+          operator,
+          approved: false,
+        },
+      });
+
+      const approvedAfter = await contract.methods.isApprovedForAll(owner, operator).call();
+      expect(approvedAfter).to.be.equal(false);
+    }
+  });
+
+  itEth('Can perform burn with ApprovalForAll', async ({helper}) => {
+    const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});
+
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const operator = await helper.eth.createAccountWithBalance(donor, 100n);
+
+    const token = await collection.mintToken(minter, {Ethereum: owner});
+
+    const address = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(address, 'nft');
+
+    {
+      await contract.methods.setApprovalForAll(operator, true).send({from: owner});
+      const ownerCross = helper.ethCrossAccount.fromAddress(owner);
+      const result = await contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: operator});
+      const events = result.events.Transfer;
+
+      expect(events).to.be.like({
+        address,
+        event: 'Transfer',
+        returnValues: {
+          from: owner,
+          to: '0x0000000000000000000000000000000000000000',
+          tokenId: token.tokenId.toString(),
+        },
+      });
+    }
+  });
+  
+  itEth('Can perform transfer with ApprovalForAll', async ({helper}) => {
+    const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});
+
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const operator = await helper.eth.createAccountWithBalance(donor);
+    const receiver = charlie;
+
+    const token = await collection.mintToken(minter, {Ethereum: owner});
+
+    const address = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(address, 'nft');
+
+    {
+      await contract.methods.setApprovalForAll(operator, true).send({from: owner});
+      const ownerCross = helper.ethCrossAccount.fromAddress(owner);
+      const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);
+      const result = await contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: operator});
+      const event = result.events.Transfer;
+      expect(event).to.be.like({
+        address: helper.ethAddress.fromCollectionId(collection.collectionId),
+        event: 'Transfer',
+        returnValues: {
+          from: owner,
+          to: helper.address.substrateToEth(receiver.address),
+          tokenId: token.tokenId.toString(),
+        },
+      });
+    }
+
+    expect(await token.getOwner()).to.be.like({Substrate: receiver.address});
+  });
+
   itEth('Can perform burnFromCross()', async ({helper}) => {
     const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});
     const ownerSub = bob;
@@ -822,3 +930,53 @@
     expect(symbol).to.equal('CHANGE');
   });
 });
+
+describe('Negative tests', () => {
+  let donor: IKeyringPair;
+  let minter: IKeyringPair;
+  let alice: IKeyringPair;
+  let bob: IKeyringPair;
+
+  before(async function() {
+    await usingEthPlaygrounds(async (helper, privateKey) => {
+      donor = await privateKey({filename: __filename});
+      [minter, alice, bob] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+    });
+  });
+
+  itEth('[negative] Cant perform burn without approval', async ({helper}) => {
+    const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});
+
+    const owner = bob;
+    const spender = await helper.eth.createAccountWithBalance(donor, 100n);
+
+    const token = await collection.mintToken(minter, {Substrate: owner.address});
+
+    const address = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(address, 'nft');
+
+    {
+      const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);
+      await expect(contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender})).to.be.rejected;
+    }
+  });
+
+  itEth('[negative] Cant perform transfer without approval', async ({helper}) => {
+    const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});
+    const owner = bob;
+    const receiver = alice;
+
+    const spender = await helper.eth.createAccountWithBalance(donor, 100n);
+
+    const token = await collection.mintToken(minter, {Substrate: owner.address});
+
+    const address = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(address, 'nft');
+
+    {
+      const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);
+      const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);
+      await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected;
+    }
+  });
+});
modifiedtests/src/eth/reFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/reFungible.test.ts
+++ b/tests/src/eth/reFungible.test.ts
@@ -169,6 +169,136 @@
     }
   });
 
+  itEth('Can perform setApprovalForAll()', async ({helper}) => {
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const operator = helper.eth.createAccount();
+
+    const collection = await helper.rft.mintCollection(minter, {});
+
+    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+
+    const approvedBefore = await contract.methods.isApprovedForAll(owner, operator).call();
+    expect(approvedBefore).to.be.equal(false);
+
+    {
+      const result = await contract.methods.setApprovalForAll(operator, true).send({from: owner});
+
+      expect(result.events.ApprovalForAll).to.be.like({
+        address: collectionAddress,
+        event: 'ApprovalForAll',
+        returnValues: {
+          owner,
+          operator,
+          approved: true,
+        },
+      });
+
+      const approvedAfter = await contract.methods.isApprovedForAll(owner, operator).call();
+      expect(approvedAfter).to.be.equal(true);
+    }
+
+    {
+      const result = await contract.methods.setApprovalForAll(operator, false).send({from: owner});
+
+      expect(result.events.ApprovalForAll).to.be.like({
+        address: collectionAddress,
+        event: 'ApprovalForAll',
+        returnValues: {
+          owner,
+          operator,
+          approved: false,
+        },
+      });
+
+      const approvedAfter = await contract.methods.isApprovedForAll(owner, operator).call();
+      expect(approvedAfter).to.be.equal(false);
+    }
+  });
+
+  itEth('Can perform burn with ApprovalForAll', async ({helper}) => {
+    const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});
+
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const operator = await helper.eth.createAccountWithBalance(donor, 100n);
+
+    const token = await collection.mintToken(minter, 100n, {Ethereum: owner});
+
+    const address = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(address, 'rft');
+
+    {
+      await contract.methods.setApprovalForAll(operator, true).send({from: owner});
+      const ownerCross = helper.ethCrossAccount.fromAddress(owner);
+      const result = await contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: operator});
+      const events = result.events.Transfer;
+
+      expect(events).to.be.like({
+        address,
+        event: 'Transfer',
+        returnValues: {
+          from: owner,
+          to: '0x0000000000000000000000000000000000000000',
+          tokenId: token.tokenId.toString(),
+        },
+      });
+    }
+  });
+
+  itEth('Can perform burn with approve and approvalForAll', async ({helper}) => {
+    const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});
+
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const operator = await helper.eth.createAccountWithBalance(donor, 100n);
+
+    const token = await collection.mintToken(minter, 100n, {Ethereum: owner});
+
+    const address = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(address, 'rft');
+
+    const rftToken = helper.ethNativeContract.rftTokenById(token.collectionId, token.tokenId, owner);
+
+    {
+      await rftToken.methods.approve(operator, 15n).send({from: owner});
+      await contract.methods.setApprovalForAll(operator, true).send({from: owner});
+      await rftToken.methods.burnFrom(owner, 10n).send({from: operator});
+      const allowance = await rftToken.methods.allowance(owner, operator).call();
+      expect(allowance).to.be.equal('5');
+    }
+  });
+  
+  itEth('Can perform transfer with ApprovalForAll', async ({helper}) => {
+    const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});
+
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const operator = await helper.eth.createAccountWithBalance(donor);
+    const receiver = charlie;
+
+    const token = await collection.mintToken(minter, 100n, {Ethereum: owner});
+
+    const address = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(address, 'rft');
+
+    {
+      await contract.methods.setApprovalForAll(operator, true).send({from: owner});
+      const ownerCross = helper.ethCrossAccount.fromAddress(owner);
+      const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);
+      const result = await contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: operator});
+      const event = result.events.Transfer;
+      expect(event).to.be.like({
+        address: helper.ethAddress.fromCollectionId(collection.collectionId),
+        event: 'Transfer',
+        returnValues: {
+          from: owner,
+          to: helper.address.substrateToEth(receiver.address),
+          tokenId: token.tokenId.toString(),
+        },
+      });
+    }
+
+    expect(await token.getTop10Owners()).to.be.like([{Substrate: receiver.address}]);
+  });
+
   itEth('Can perform burn()', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
     const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Burny', '6', '6');
@@ -594,3 +724,52 @@
     expect(symbol).to.equal('12');
   });
 });
+
+describe('Negative tests', () => {
+  let donor: IKeyringPair;
+  let minter: IKeyringPair;
+  let alice: IKeyringPair;
+
+  before(async function() {
+    await usingEthPlaygrounds(async (helper, privateKey) => {
+      donor = await privateKey({filename: __filename});
+      [minter, alice] = await helper.arrange.createAccounts([100n, 100n], donor);
+    });
+  });
+
+  itEth('[negative] Cant perform burn without approval', async ({helper}) => {
+    const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});
+
+    const owner = await helper.eth.createAccountWithBalance(donor, 100n);
+    const spender = await helper.eth.createAccountWithBalance(donor, 100n);
+
+    const token = await collection.mintToken(minter, 100n, {Ethereum: owner});
+
+    const address = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(address, 'rft');
+
+    {
+      const ownerCross = helper.ethCrossAccount.fromAddress(owner);
+      await expect(contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender})).to.be.rejected;
+    }
+  });
+
+  itEth('[negative] Cant perform transfer without approval', async ({helper}) => {
+    const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});
+    const owner = await helper.eth.createAccountWithBalance(donor, 100n);
+    const receiver = alice;
+
+    const spender = await helper.eth.createAccountWithBalance(donor, 100n);
+
+    const token = await collection.mintToken(minter, 100n, {Ethereum: owner});
+
+    const address = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(address, 'rft');
+
+    {
+      const ownerCross = helper.ethCrossAccount.fromAddress(owner);
+      const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);
+      await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected;
+    }
+  });
+});
modifiedtests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-errors.ts
+++ b/tests/src/interfaces/augment-api-errors.ts
@@ -386,6 +386,10 @@
        **/
       NotFungibleDataUsedToMintFungibleCollectionToken: AugmentedError<ApiType>;
       /**
+       * Setting approval for all is not allowed.
+       **/
+      SettingApprovalForAllNotAllowed: AugmentedError<ApiType>;
+      /**
        * Setting item properties is not allowed.
        **/
       SettingPropertiesNotAllowed: AugmentedError<ApiType>;
modifiedtests/src/interfaces/augment-api-events.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-events.ts
+++ b/tests/src/interfaces/augment-api-events.ts
@@ -107,6 +107,10 @@
        **/
       Approved: AugmentedEvent<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;
       /**
+       * Amount pieces of token owned by `sender` was approved for `spender`.
+       **/
+      ApprovedForAll: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, bool]>;
+      /**
        * New collection was created
        **/
       CollectionCreated: AugmentedEvent<ApiType, [u32, u8, AccountId32]>;
modifiedtests/src/interfaces/augment-api-query.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-query.ts
+++ b/tests/src/interfaces/augment-api-query.ts
@@ -442,6 +442,10 @@
        **/
       tokensMinted: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;
       /**
+       * Operator set by a wallet owner that could perform certain transactions on all tokens in the wallet.
+       **/
+      walletOperator: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<Option<bool>>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]>;
+      /**
        * Generic query
        **/
       [key: string]: QueryableStorageEntry<ApiType>;
@@ -645,6 +649,10 @@
        **/
       totalSupply: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<u128>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;
       /**
+       * Operator set by a wallet owner that could perform certain transactions on all tokens in the wallet.
+       **/
+      walletOperator: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<Option<bool>>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]>;
+      /**
        * Generic query
        **/
       [key: string]: QueryableStorageEntry<ApiType>;
modifiedtests/src/interfaces/augment-api-rpc.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-rpc.ts
+++ b/tests/src/interfaces/augment-api-rpc.ts
@@ -720,6 +720,10 @@
        **/
       effectiveCollectionLimits: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<UpDataStructsCollectionLimits>>>;
       /**
+       * Tells whether an operator is approved by a given owner.
+       **/
+      isApprovedForAll: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, owner: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, operator: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<bool>>>;
+      /**
        * Get the last token ID created in a collection
        **/
       lastTokenId: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<u32>>;
modifiedtests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-tx.ts
+++ b/tests/src/interfaces/augment-api-tx.ts
@@ -1545,6 +1545,18 @@
        **/
       repartition: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u128]>;
       /**
+       * Sets or unsets the approval of a given operator.
+       * 
+       * An operator is allowed to transfer all tokens of the sender on their behalf.
+       * 
+       * # Arguments
+       * 
+       * * `owner`: Token owner
+       * * `operator`: Operator
+       * * `approve`: Is operator enabled or disabled
+       **/
+      setApprovalForAll: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, operator: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, approve: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, bool]>;
+      /**
        * Set specific limits of a collection. Empty, or None fields mean chain default.
        * 
        * # Permissions
modifiedtests/src/interfaces/default/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/default/types.ts
+++ b/tests/src/interfaces/default/types.ts
@@ -1286,6 +1286,8 @@
   readonly asTransfer: ITuple<[u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;
   readonly isApproved: boolean;
   readonly asApproved: ITuple<[u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;
+  readonly isApprovedForAll: boolean;
+  readonly asApprovedForAll: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, bool]>;
   readonly isCollectionPropertySet: boolean;
   readonly asCollectionPropertySet: ITuple<[u32, Bytes]>;
   readonly isCollectionPropertyDeleted: boolean;
@@ -1296,7 +1298,7 @@
   readonly asTokenPropertyDeleted: ITuple<[u32, u32, Bytes]>;
   readonly isPropertyPermissionSet: boolean;
   readonly asPropertyPermissionSet: ITuple<[u32, Bytes]>;
-  readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet';
+  readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'ApprovedForAll' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet';
 }
 
 /** @name PalletConfigurationCall */
@@ -1603,7 +1605,8 @@
   readonly isFungibleItemsDontHaveData: boolean;
   readonly isFungibleDisallowsNesting: boolean;
   readonly isSettingPropertiesNotAllowed: boolean;
-  readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
+  readonly isSettingApprovalForAllNotAllowed: boolean;
+  readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed' | 'SettingApprovalForAllNotAllowed';
 }
 
 /** @name PalletInflationCall */
@@ -2309,7 +2312,13 @@
     readonly tokenId: u32;
     readonly amount: u128;
   } & Struct;
-  readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition';
+  readonly isSetApprovalForAll: boolean;
+  readonly asSetApprovalForAll: {
+    readonly collectionId: u32;
+    readonly operator: PalletEvmAccountBasicCrossAccountIdRepr;
+    readonly approve: bool;
+  } & Struct;
+  readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetApprovalForAll';
 }
 
 /** @name PalletUniqueError */
modifiedtests/src/interfaces/lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/lookup.ts
+++ b/tests/src/interfaces/lookup.ts
@@ -1046,6 +1046,7 @@
       ItemDestroyed: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,u128)',
       Transfer: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,u128)',
       Approved: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,u128)',
+      ApprovedForAll: '(u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,bool)',
       CollectionPropertySet: '(u32,Bytes)',
       CollectionPropertyDeleted: '(u32,Bytes)',
       TokenPropertySet: '(u32,u32,Bytes)',
@@ -1054,7 +1055,7 @@
     }
   },
   /**
-   * Lookup99: pallet_structure::pallet::Event<T>
+   * Lookup100: pallet_structure::pallet::Event<T>
    **/
   PalletStructureEvent: {
     _enum: {
@@ -1062,7 +1063,7 @@
     }
   },
   /**
-   * Lookup100: pallet_rmrk_core::pallet::Event<T>
+   * Lookup101: pallet_rmrk_core::pallet::Event<T>
    **/
   PalletRmrkCoreEvent: {
     _enum: {
@@ -1139,7 +1140,7 @@
     }
   },
   /**
-   * Lookup101: rmrk_traits::nft::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>
+   * Lookup102: rmrk_traits::nft::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>
    **/
   RmrkTraitsNftAccountIdOrCollectionNftTuple: {
     _enum: {
@@ -2302,7 +2303,12 @@
       repartition: {
         collectionId: 'u32',
         tokenId: 'u32',
-        amount: 'u128'
+        amount: 'u128',
+      },
+      set_approval_for_all: {
+        collectionId: 'u32',
+        operator: 'PalletEvmAccountBasicCrossAccountIdRepr',
+        approve: 'bool'
       }
     }
   },
@@ -3445,7 +3451,7 @@
    * Lookup430: pallet_fungible::pallet::Error<T>
    **/
   PalletFungibleError: {
-    _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed']
+    _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed', 'SettingApprovalForAllNotAllowed']
   },
   /**
    * Lookup431: pallet_refungible::ItemData
modifiedtests/src/interfaces/types-lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -1182,6 +1182,8 @@
     readonly asTransfer: ITuple<[u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;
     readonly isApproved: boolean;
     readonly asApproved: ITuple<[u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;
+    readonly isApprovedForAll: boolean;
+    readonly asApprovedForAll: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, bool]>;
     readonly isCollectionPropertySet: boolean;
     readonly asCollectionPropertySet: ITuple<[u32, Bytes]>;
     readonly isCollectionPropertyDeleted: boolean;
@@ -1192,17 +1194,17 @@
     readonly asTokenPropertyDeleted: ITuple<[u32, u32, Bytes]>;
     readonly isPropertyPermissionSet: boolean;
     readonly asPropertyPermissionSet: ITuple<[u32, Bytes]>;
-    readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet';
+    readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'ApprovedForAll' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet';
   }
 
-  /** @name PalletStructureEvent (99) */
+  /** @name PalletStructureEvent (100) */
   interface PalletStructureEvent extends Enum {
     readonly isExecuted: boolean;
     readonly asExecuted: Result<Null, SpRuntimeDispatchError>;
     readonly type: 'Executed';
   }
 
-  /** @name PalletRmrkCoreEvent (100) */
+  /** @name PalletRmrkCoreEvent (101) */
   interface PalletRmrkCoreEvent extends Enum {
     readonly isCollectionCreated: boolean;
     readonly asCollectionCreated: {
@@ -1292,7 +1294,7 @@
     readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'IssuerChanged' | 'CollectionLocked' | 'NftMinted' | 'NftBurned' | 'NftSent' | 'NftAccepted' | 'NftRejected' | 'PropertySet' | 'ResourceAdded' | 'ResourceRemoval' | 'ResourceAccepted' | 'ResourceRemovalAccepted' | 'PrioritySet';
   }
 
-  /** @name RmrkTraitsNftAccountIdOrCollectionNftTuple (101) */
+  /** @name RmrkTraitsNftAccountIdOrCollectionNftTuple (102) */
   interface RmrkTraitsNftAccountIdOrCollectionNftTuple extends Enum {
     readonly isAccountId: boolean;
     readonly asAccountId: AccountId32;
@@ -2539,7 +2541,13 @@
       readonly tokenId: u32;
       readonly amount: u128;
     } & Struct;
-    readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition';
+    readonly isSetApprovalForAll: boolean;
+    readonly asSetApprovalForAll: {
+      readonly collectionId: u32;
+      readonly operator: PalletEvmAccountBasicCrossAccountIdRepr;
+      readonly approve: bool;
+    } & Struct;
+    readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetApprovalForAll';
   }
 
   /** @name UpDataStructsCollectionMode (240) */
@@ -3655,7 +3663,8 @@
     readonly isFungibleItemsDontHaveData: boolean;
     readonly isFungibleDisallowsNesting: boolean;
     readonly isSettingPropertiesNotAllowed: boolean;
-    readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
+    readonly isSettingApprovalForAllNotAllowed: boolean;
+    readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed' | 'SettingApprovalForAllNotAllowed';
   }
 
   /** @name PalletRefungibleItemData (431) */
modifiedtests/src/interfaces/unique/definitions.tsdiffbeforeafterboth
--- a/tests/src/interfaces/unique/definitions.ts
+++ b/tests/src/interfaces/unique/definitions.ts
@@ -175,5 +175,10 @@
       [collectionParam, tokenParam], 
       'Option<u128>',
     ),
+    isApprovedForAll: fun(
+      'Tells whether an operator is approved by a given owner.', 
+      [collectionParam, crossAccountParam('owner'), crossAccountParam('operator')], 
+      'Option<bool>',
+    ),
   },
 };
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -1413,6 +1413,32 @@
   getTokenObject(_collectionId: number, _tokenId: number): any {
     return null;
   }
+
+  /**
+   * Tells whether an operator is approved by a given owner.
+   * @param collectionId ID of collection
+   * @param owner owner address
+	 * @param operator operator addrees
+   * @returns true if operator is enabled
+   */
+  async isApprovedForAll(collectionId: number, owner: ICrossAccountId, operator: ICrossAccountId): Promise<boolean> {
+    return (await this.helper.callRpc('api.rpc.unique.isApprovedForAll', [collectionId, owner, operator])).toJSON();
+  }
+
+  /** Sets or unsets the approval of a given operator.
+	 *  An operator is allowed to transfer all tokens of the sender on their behalf.
+	 *  @param operator Operator
+	 *  @param approved Is operator enabled or disabled
+   *  @returns ```true``` if extrinsic success, otherwise ```false```
+   */
+  async setApprovalForAll(signer: TSigner, collectionId: number, operator: ICrossAccountId, approved: boolean): Promise<boolean> {
+    const result = await this.helper.executeExtrinsic(
+      signer,
+      'api.tx.unique.setApprovalForAll', [collectionId, operator, approved],
+      true,
+    );
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'ApprovedForAll');
+  }
 }