git.delta.rocks / unique-network / refs/commits / 40cdf2739a9d

difftreelog

refactor move foreign flag to collection struct

Yaroslav Bolyukin2022-09-16parent: #285030f.patch.diff
in: master

9 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -697,6 +697,26 @@
 ]
 
 [[package]]
+name = "bondrewd"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d1660fac8d3acced44dac64453fafedf5aab2de196b932c727e63e4ae42d1cc"
+dependencies = [
+ "bondrewd-derive",
+]
+
+[[package]]
+name = "bondrewd-derive"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "723da0dee1eef38edc021b0793f892bdc024500c6a5b0727a2efe16f0e0a6977"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "bounded-vec"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5892,6 +5912,7 @@
 name = "pallet-foreign-assets"
 version = "0.1.0"
 dependencies = [
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
  "hex",
@@ -6600,7 +6621,7 @@
 
 [[package]]
 name = "pallet-unique"
-version = "0.1.4"
+version = "0.2.0"
 dependencies = [
  "ethereum",
  "evm-coder",
@@ -12634,6 +12655,7 @@
 name = "up-data-structs"
 version = "0.2.2"
 dependencies = [
+ "bondrewd",
  "derivative",
  "frame-support",
  "frame-system",
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -70,6 +70,7 @@
 	COLLECTION_NUMBER_LIMIT,
 	Collection,
 	RpcCollection,
+	CollectionFlags,
 	CollectionId,
 	CreateItemData,
 	MAX_TOKEN_PREFIX_LENGTH,
@@ -252,9 +253,9 @@
 	}
 
 	/// Checks that the collection was created with, and must be operated upon through **Unique API**.
-	/// Now check only the `external_collection` flag and if it's **true**, then return [`Error::CollectionIsExternal`] error.
+	/// Now check only the `external` flag and if it's **true**, then return [`Error::CollectionIsExternal`] error.
 	pub fn check_is_internal(&self) -> DispatchResult {
-		if self.external_collection {
+		if self.flags.external {
 			return Err(<Error<T>>::CollectionIsExternal)?;
 		}
 
@@ -262,9 +263,9 @@
 	}
 
 	/// Checks that the collection was created with, and must be operated upon through an **assimilated API**.
-	/// Now check only the `external_collection` flag and if it's **false**, then return [`Error::CollectionIsInternal`] error.
+	/// Now check only the `external` flag and if it's **false**, then return [`Error::CollectionIsInternal`] error.
 	pub fn check_is_external(&self) -> DispatchResult {
-		if !self.external_collection {
+		if !self.flags.external {
 			return Err(<Error<T>>::CollectionIsInternal)?;
 		}
 
@@ -345,7 +346,7 @@
 	use frame_support::{Blake2_128Concat, pallet_prelude::*, storage::Key, traits::StorageVersion};
 	use frame_system::pallet_prelude::*;
 	use frame_support::traits::Currency;
-	use up_data_structs::{TokenId, mapping::TokenAddressMapping};
+	use up_data_structs::{TokenId, mapping::TokenAddressMapping, CollectionFlags};
 	use scale_info::TypeInfo;
 	use weights::WeightInfo;
 
@@ -792,7 +793,7 @@
 			sponsorship,
 			limits,
 			permissions,
-			external_collection,
+			flags,
 		} = <CollectionById<T>>::get(collection)?;
 
 		let token_property_permissions = <CollectionPropertyPermissions<T>>::get(collection)
@@ -822,7 +823,8 @@
 			permissions,
 			token_property_permissions,
 			properties,
-			read_only: external_collection,
+			read_only: flags.external,
+			foreign: flags.foreign,
 		})
 	}
 }
@@ -861,11 +863,11 @@
 	///
 	/// * `owner` - The owner of the collection.
 	/// * `data` - Description of the created collection.
-	/// * `is_external` - Marks that collection managet by not "Unique network".
+	/// * `flags` - Extra flags to store.
 	pub fn init_collection(
 		owner: T::CrossAccountId,
 		data: CreateCollectionData<T::AccountId>,
-		is_external: bool,
+		flags: CollectionFlags,
 	) -> Result<CollectionId, DispatchError> {
 		{
 			ensure!(
@@ -909,7 +911,7 @@
 					Self::clamp_permissions(data.mode.clone(), &Default::default(), permissions)
 				})
 				.unwrap_or_else(|| Ok(CollectionPermissions::default()))?,
-			external_collection: is_external,
+			flags,
 		};
 
 		let mut collection_properties = up_data_structs::CollectionProperties::get();
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -83,8 +83,8 @@
 use frame_support::{ensure};
 use pallet_evm::account::CrossAccountId;
 use up_data_structs::{
-	AccessMode, CollectionId, TokenId, CreateCollectionData, mapping::TokenAddressMapping,
-	budget::Budget,
+	AccessMode, CollectionId, CollectionFlags, TokenId, CreateCollectionData,
+	mapping::TokenAddressMapping, budget::Budget,
 };
 use pallet_common::{
 	Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,
@@ -167,11 +167,6 @@
 		Value = u128,
 		QueryKind = ValueQuery,
 	>;
-
-	/// Foreign collection flag
-	#[pallet::storage]
-	pub type ForeignCollection<T: Config> =
-		StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = bool, QueryKind = ValueQuery>;
 }
 
 /// Wrapper around untyped collection handle, asserting inner collection is of fungible type.
@@ -217,7 +212,7 @@
 		owner: T::CrossAccountId,
 		data: CreateCollectionData<T::AccountId>,
 	) -> Result<CollectionId, DispatchError> {
-		<PalletCommon<T>>::init_collection(owner, data, false)
+		<PalletCommon<T>>::init_collection(owner, data, CollectionFlags::default())
 	}
 
 	/// Initializes the collection with ForeignCollection flag. Returns [CollectionId] on success, [DispatchError] otherwise.
@@ -225,8 +220,14 @@
 		owner: T::CrossAccountId,
 		data: CreateCollectionData<T::AccountId>,
 	) -> Result<CollectionId, DispatchError> {
-		let id = <PalletCommon<T>>::init_collection(owner, data, false)?;
-		<ForeignCollection<T>>::insert(id, true);
+		let id = <PalletCommon<T>>::init_collection(
+			owner,
+			data,
+			CollectionFlags {
+				foreign: true,
+				..Default::default()
+			},
+		)?;
 		Ok(id)
 	}
 
@@ -245,7 +246,6 @@
 
 		PalletCommon::destroy_collection(collection.0, sender)?;
 
-		<ForeignCollection<T>>::remove(id);
 		<TotalSupply<T>>::remove(id);
 		let _ = <Balance<T>>::clear_prefix((id,), u32::MAX, None);
 		let _ = <Allowance<T>>::clear_prefix((id,), u32::MAX, None);
@@ -274,10 +274,7 @@
 			.ok_or(<CommonError<T>>::TokenValueTooLow)?;
 
 		// Foreign collection check
-		ensure!(
-			!<ForeignCollection<T>>::get(collection.id),
-			<CommonError<T>>::NoPermission
-		);
+		ensure!(!collection.flags.foreign, <CommonError<T>>::NoPermission);
 
 		if collection.permissions.access() == AccessMode::AllowList {
 			collection.check_allowlist(owner)?;
@@ -502,10 +499,7 @@
 		nesting_budget: &dyn Budget,
 	) -> DispatchResult {
 		// Foreign collection check
-		ensure!(
-			!<ForeignCollection<T>>::get(collection.id),
-			<CommonError<T>>::NoPermission
-		);
+		ensure!(!collection.flags.foreign, <CommonError<T>>::NoPermission);
 
 		if !collection.is_owner_or_admin(sender) {
 			ensure!(
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -100,10 +100,10 @@
 	weights::{PostDispatchInfo, Pays},
 };
 use up_data_structs::{
-	AccessMode, CollectionId, CustomDataLimit, TokenId, CreateCollectionData, CreateNftExData,
-	mapping::TokenAddressMapping, budget::Budget, Property, PropertyPermission, PropertyKey,
-	PropertyValue, PropertyKeyPermission, Properties, PropertyScope, TrySetProperty, TokenChild,
-	AuxPropertyValue,
+	AccessMode, CollectionId, CollectionFlags, CustomDataLimit, TokenId, CreateCollectionData,
+	CreateNftExData, mapping::TokenAddressMapping, budget::Budget, Property, PropertyPermission,
+	PropertyKey, PropertyValue, PropertyKeyPermission, Properties, PropertyScope, TrySetProperty,
+	TokenChild, AuxPropertyValue,
 };
 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
 use pallet_common::{
@@ -408,7 +408,14 @@
 		data: CreateCollectionData<T::AccountId>,
 		is_external: bool,
 	) -> Result<CollectionId, DispatchError> {
-		<PalletCommon<T>>::init_collection(owner, data, is_external)
+		<PalletCommon<T>>::init_collection(
+			owner,
+			data,
+			CollectionFlags {
+				external: is_external,
+				..Default::default()
+			},
+		)
 	}
 
 	/// Destroy NFT collection
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
112use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};112use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};
113use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};113use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
114use up_data_structs::{114use up_data_structs::{
115 AccessMode, budget::Budget, CollectionId, CollectionMode, CollectionPropertiesVec,115 AccessMode, budget::Budget, CollectionId, CollectionMode, CollectionFlags,
116 CreateCollectionData, CustomDataLimit, mapping::TokenAddressMapping, MAX_ITEMS_PER_BATCH,116 CollectionPropertiesVec, CreateCollectionData, CustomDataLimit, mapping::TokenAddressMapping,
117 MAX_REFUNGIBLE_PIECES, Property, PropertyKey, PropertyKeyPermission, PropertyPermission,117 MAX_ITEMS_PER_BATCH, MAX_REFUNGIBLE_PIECES, Property, PropertyKey, PropertyKeyPermission,
118 PropertyScope, PropertyValue, TokenId, TrySetProperty,118 PropertyPermission, PropertyScope, PropertyValue, TokenId, TrySetProperty,
375 owner: T::CrossAccountId,375 owner: T::CrossAccountId,
376 data: CreateCollectionData<T::AccountId>,376 data: CreateCollectionData<T::AccountId>,
377 ) -> Result<CollectionId, DispatchError> {377 ) -> Result<CollectionId, DispatchError> {
378 <PalletCommon<T>>::init_collection(owner, data, false)378 <PalletCommon<T>>::init_collection(owner, data, CollectionFlags::default())
379 }379 }
380380
381 /// Destroy RFT collection381 /// Destroy RFT collection
modifiedprimitives/data-structs/Cargo.tomldiffbeforeafterboth
--- a/primitives/data-structs/Cargo.toml
+++ b/primitives/data-structs/Cargo.toml
@@ -27,6 +27,7 @@
 struct-versioning = { path = "../../crates/struct-versioning" }
 pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
 rmrk-traits = { default-features = false, path = "../rmrk-traits" }
+bondrewd = { version = "0.1.14", features = ["derive"], default-features = false }
 
 [features]
 default = ["std"]
addedprimitives/data-structs/src/bondrewd_codec.rsdiffbeforeafterboth
--- /dev/null
+++ b/primitives/data-structs/src/bondrewd_codec.rs
@@ -0,0 +1,31 @@
+//! Integration between bondrewd and parity scale codec
+//! Maybe we can move it to scale-codec itself in future?
+
+#[macro_export]
+macro_rules! bondrewd_codec {
+	($T:ty) => {
+		impl Encode for $T {
+			fn encode_to<O: codec::Output + ?Sized>(&self, dest: &mut O) {
+				dest.write(&self.into_bytes())
+			}
+		}
+		impl codec::Decode for $T {
+			fn decode<I: codec::Input + ?Sized>(from: &mut I) -> Result<Self, codec::Error> {
+				let mut bytes = [0; Self::BYTE_SIZE];
+				from.read(&mut bytes)?;
+				Ok(Self::from_bytes(bytes))
+			}
+		}
+		impl MaxEncodedLen for $T {
+			fn max_encoded_len() -> usize {
+				Self::BYTE_SIZE
+			}
+		}
+		impl TypeInfo for $T {
+			type Identity = [u8; Self::BYTE_SIZE];
+			fn type_info() -> scale_info::Type {
+				<[u8; Self::BYTE_SIZE] as TypeInfo>::type_info()
+			}
+		}
+	};
+}
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -36,6 +36,7 @@
 use sp_core::U256;
 use sp_runtime::{ArithmeticError, sp_std::prelude::Vec, Permill};
 use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
+use bondrewd::Bitfields;
 use frame_support::{BoundedVec, traits::ConstU32};
 use derivative::Derivative;
 use scale_info::TypeInfo;
@@ -54,6 +55,7 @@
 	FixedPart as RmrkFixedPart, SlotPart as RmrkSlotPart,
 };
 
+mod bondrewd_codec;
 mod bounded;
 pub mod budget;
 pub mod mapping;
@@ -357,6 +359,21 @@
 pub type CollectionDescription = BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>;
 pub type CollectionTokenPrefix = BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>;
 
+#[derive(Bitfields, Clone, Copy, PartialEq, Eq, Debug, Default)]
+#[bondrewd(enforce_bytes = 1)]
+pub struct CollectionFlags {
+	/// Tokens in foreign collections can be transferred, but not burnt
+	#[bondrewd(bits = "0..1")]
+	pub foreign: bool,
+	/// External collections can't be managed using `unique` api
+	#[bondrewd(bits = "7..8")]
+	pub external: bool,
+
+	#[bondrewd(reserve, bits = "1..7")]
+	pub reserved: u8,
+}
+bondrewd_codec!(CollectionFlags);
+
 /// Base structure for represent collection.
 ///
 /// Used to provide basic functionality for all types of collections.
@@ -404,9 +421,8 @@
 	#[version(2.., upper(Default::default()))]
 	pub permissions: CollectionPermissions,
 
-	/// Marks that this collection is not "unique", and managed from external.
-	#[version(2.., upper(false))]
-	pub external_collection: bool,
+	#[version(2.., upper(Default::default()))]
+	pub flags: CollectionFlags,
 
 	#[version(..2)]
 	pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,
@@ -454,6 +470,9 @@
 
 	/// Is collection read only.
 	pub read_only: bool,
+
+	/// Is collection is foreign.
+	pub foreign: bool,
 }
 
 /// Data used for create collection.
modifiedprimitives/data-structs/src/migration.rsdiffbeforeafterboth
--- a/primitives/data-structs/src/migration.rs
+++ b/primitives/data-structs/src/migration.rs
@@ -38,3 +38,26 @@
 	test_to_option(SponsoringRateLimit::SponsoringDisabled);
 	test_to_option(SponsoringRateLimit::Blocks(10));
 }
+
+#[test]
+fn collection_flags_have_same_encoding_as_bool() {
+	use crate::CollectionFlags;
+	use codec::Encode;
+
+	assert_eq!(
+		true.encode(),
+		CollectionFlags {
+			external: true,
+			..Default::default()
+		}
+		.encode()
+	);
+	assert_eq!(
+		false.encode(),
+		CollectionFlags {
+			external: false,
+			..Default::default()
+		}
+		.encode()
+	);
+}