git.delta.rocks / unique-network / refs/commits / 353c1c657ac7

difftreelog

refactor! rewrite collections accessors

Yaroslav Bolyukin2021-03-05parent: #a84a730.patch.diff
in: master
Squashed from multiple

4 files changed

modifiednode/src/chain_spec.rsdiffbeforeafterboth
179 .collect(),179 .collect(),
180 }),180 }),
181 pallet_nft: Some(NftConfig {181 pallet_nft: Some(NftConfig {
182 collection: vec![(182 collection_id: vec![(
183 1,183 1,
184 CollectionType {184 Collection {
185 id: 1,
185 owner: get_account_id_from_seed::<sr25519::Public>("Alice"),186 owner: get_account_id_from_seed::<sr25519::Public>("Alice"),
186 mode: CollectionMode::NFT,187 mode: CollectionMode::NFT,
187 access: AccessMode::Normal,188 access: AccessMode::Normal,
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -125,7 +125,8 @@
 
 #[derive(Encode, Decode, Clone, PartialEq)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-pub struct CollectionType<T: Config> {
+pub struct Collection<T: Config> {
+    pub id: CollectionId,
     pub owner: T::AccountId,
     pub mode: CollectionMode,
     pub access: AccessMode,
@@ -426,7 +427,7 @@
         pub AccountItemCount get(fn account_item_count): map hasher(twox_64_concat) T::AccountId => u32;
 
         // Basic collections
-        pub Collection get(fn collection) config(): map hasher(identity) CollectionId => Option<CollectionType<T>> = None;
+        pub CollectionById get(fn collection_id) config(): map hasher(identity) CollectionId => Option<Collection<T>> = None;
         pub AdminList get(fn admin_list_collection): map hasher(identity) CollectionId => Vec<T::AccountId>;
         pub WhiteList get(fn white_list): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => bool;
 
@@ -464,7 +465,7 @@
     add_extra_genesis {
         build(|config: &GenesisConfig<T>| {
             // Modification of storage
-            for (_num, _c) in &config.collection {
+            for (_num, _c) in &config.collection_id {
                 <Module<T>>::init_collection(_c);
             }
 
@@ -615,7 +616,8 @@
             };
 
             // Create new collection
-            let new_collection = CollectionType {
+            let new_collection = Collection {
+                id: next_id,
                 owner: who.clone(),
                 name: collection_name,
                 mode: mode.clone(),
@@ -634,7 +636,7 @@
             };
 
             // Add new collection to map
-            <Collection<T>>::insert(next_id, new_collection);
+            <CollectionById<T>>::insert(next_id, new_collection);
 
             // call event
             Self::deposit_event(RawEvent::Created(next_id, mode.into(), who.clone()));
@@ -655,10 +657,9 @@
         pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {
 
             let sender = ensure_signed(origin)?;
-            Self::check_owner_permissions(collection_id, sender)?;
-
-            let target_collection = <Collection<T>>::get(collection_id);
-            if !target_collection.limits.owner_can_destroy {
+            let collection = Self::get_collection(collection_id)?;
+            Self::check_owner_permissions(&collection, sender)?;
+            if !collection.limits.owner_can_destroy {
                 fail!(Error::<T>::NoPermission);
             }
 
@@ -667,7 +668,7 @@
             <Balance<T>>::remove_prefix(collection_id);
             <ItemListIndex>::remove(collection_id);
             <AdminList<T>>::remove(collection_id);
-            <Collection<T>>::remove(collection_id);
+            <CollectionById<T>>::remove(collection_id);
             <WhiteList<T>>::remove_prefix(collection_id);
 
             <NftItemList<T>>::remove_prefix(collection_id);
@@ -709,7 +710,8 @@
         pub fn add_to_white_list(origin, collection_id: CollectionId, address: T::AccountId) -> DispatchResult{
 
             let sender = ensure_signed(origin)?;
-            Self::check_owner_or_admin_permissions(collection_id, sender)?;
+            let collection = Self::get_collection(collection_id)?;
+            Self::check_owner_or_admin_permissions(&collection, sender)?;
 
             <WhiteList<T>>::insert(collection_id, address, true);
             
@@ -732,7 +734,8 @@
         pub fn remove_from_white_list(origin, collection_id: CollectionId, address: T::AccountId) -> DispatchResult{
 
             let sender = ensure_signed(origin)?;
-            Self::check_owner_or_admin_permissions(collection_id, sender)?;
+            let collection = Self::get_collection(collection_id)?;
+            Self::check_owner_or_admin_permissions(&collection, sender)?;
 
             <WhiteList<T>>::remove(collection_id, address);
 
@@ -755,10 +758,10 @@
         {
             let sender = ensure_signed(origin)?;
 
-            Self::check_owner_permissions(collection_id, sender)?;
-            let mut target_collection = <Collection<T>>::get(collection_id).unwrap();
+            let mut target_collection = Self::get_collection(collection_id)?;
+            Self::check_owner_permissions(&target_collection, sender)?;
             target_collection.access = mode;
-            <Collection<T>>::insert(collection_id, target_collection);
+            Self::save_collection(target_collection);
 
             Ok(())
         }
@@ -781,10 +784,10 @@
         {
             let sender = ensure_signed(origin)?;
 
-            Self::check_owner_permissions(collection_id, sender)?;
-            let mut target_collection = <Collection<T>>::get(collection_id).unwrap();
+            let mut target_collection = Self::get_collection(collection_id)?;
+            Self::check_owner_permissions(&target_collection, sender)?;
             target_collection.mint_mode = mint_permission;
-            <Collection<T>>::insert(collection_id, target_collection);
+            Self::save_collection(target_collection);
 
             Ok(())
         }
@@ -804,10 +807,10 @@
         pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {
 
             let sender = ensure_signed(origin)?;
-            Self::check_owner_permissions(collection_id, sender)?;
-            let mut target_collection = <Collection<T>>::get(collection_id).unwrap();
+            let mut target_collection = Self::get_collection(collection_id)?;
+            Self::check_owner_permissions(&target_collection, sender)?;
             target_collection.owner = new_owner;
-            <Collection<T>>::insert(collection_id, target_collection);
+            Self::save_collection(target_collection);
 
             Ok(())
         }
@@ -829,7 +832,8 @@
         pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::AccountId) -> DispatchResult {
 
             let sender = ensure_signed(origin)?;
-            Self::check_owner_or_admin_permissions(collection_id, sender)?;
+            let collection = Self::get_collection(collection_id)?;
+            Self::check_owner_or_admin_permissions(&collection, sender)?;
             let mut admin_arr: Vec<T::AccountId> = Vec::new();
 
             if <AdminList<T>>::contains_key(collection_id)
@@ -863,7 +867,8 @@
         pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::AccountId) -> DispatchResult {
 
             let sender = ensure_signed(origin)?;
-            Self::check_owner_or_admin_permissions(collection_id, sender)?;
+            let collection = Self::get_collection(collection_id)?;
+            Self::check_owner_or_admin_permissions(&collection, sender)?;
             ensure!(<AdminList<T>>::contains_key(collection_id), Error::<T>::AdminNotFound);
 
             let mut admin_arr = <AdminList<T>>::get(collection_id);
@@ -886,13 +891,12 @@
         pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {
 
             let sender = ensure_signed(origin)?;
-
-            let mut target_collection = <Collection<T>>::get(collection_id).ok_or(Error::<T>::CollectionNotFound)?;
-            ensure!(sender == target_collection.owner, Error::<T>::NoPermission);
+            let mut target_collection = Self::get_collection(collection_id)?;
+            Self::check_owner_permissions(&target_collection, sender)?;
 
             target_collection.sponsor = new_sponsor;
             target_collection.sponsor_confirmed = false;
-            <Collection<T>>::insert(collection_id, target_collection);
+            Self::save_collection(target_collection);
 
             Ok(())
         }
@@ -909,11 +913,11 @@
 
             let sender = ensure_signed(origin)?;
 
-            let mut target_collection = <Collection<T>>::get(collection_id).ok_or(Error::<T>::CollectionNotFound)?;
+            let mut target_collection = Self::get_collection(collection_id)?;
             ensure!(sender == target_collection.sponsor, Error::<T>::ConfirmUnsetSponsorFail);
 
             target_collection.sponsor_confirmed = true;
-            <Collection<T>>::insert(collection_id, target_collection);
+            Self::save_collection(target_collection);
 
             Ok(())
         }
@@ -932,12 +936,12 @@
 
             let sender = ensure_signed(origin)?;
 
-            let mut target_collection = <Collection<T>>::get(collection_id).ok_or(Error::<T>::CollectionNotFound)?;
-            ensure!(sender == target_collection.owner, Error::<T>::NoPermission);
+            let mut target_collection = Self::get_collection(collection_id)?;
+            Self::check_owner_permissions(&target_collection, sender)?;
 
             target_collection.sponsor = T::AccountId::default();
             target_collection.sponsor_confirmed = false;
-            <Collection<T>>::insert(collection_id, target_collection);
+            Self::save_collection(target_collection);
 
             Ok(())
         }
@@ -971,13 +975,11 @@
 
             let sender = ensure_signed(origin)?;
 
-            Self::collection_exists(collection_id)?;
+            let target_collection = Self::get_collection(collection_id)?;
 
-            let target_collection = <Collection<T>>::get(collection_id).unwrap();
-
-            Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner)?;
+            Self::can_create_items_in_collection(&target_collection, &sender, &owner)?;
             Self::validate_create_item_args(&target_collection, &data)?;
-            Self::create_item_no_validation(collection_id, owner, data)?;
+            Self::create_item_no_validation(&target_collection, owner, data)?;
 
             Ok(())
         }
@@ -1008,16 +1010,15 @@
             ensure!(items_data.len() > 0, Error::<T>::EmptyArgument);
             let sender = ensure_signed(origin)?;
 
-            Self::collection_exists(collection_id)?;
-            let target_collection = <Collection<T>>::get(collection_id).unwrap();
+            let target_collection = Self::get_collection(collection_id)?;
 
-            Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner)?;
+            Self::can_create_items_in_collection(&target_collection, &sender, &owner)?;
 
             for data in &items_data {
                 Self::validate_create_item_args(&target_collection, data)?;
             }
             for data in &items_data {
-                Self::create_item_no_validation(collection_id, owner.clone(), data.clone())?;
+                Self::create_item_no_validation(&target_collection, owner.clone(), data.clone())?;
             }
 
             Ok(())
@@ -1040,33 +1041,32 @@
         pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResult {
 
             let sender = ensure_signed(origin)?;
-            Self::collection_exists(collection_id)?;
 
             // Transfer permissions check
-            let target_collection = <Collection<T>>::get(collection_id).unwrap();
+            let target_collection = Self::get_collection(collection_id)?;
             ensure!(
-                Self::is_item_owner(sender.clone(), collection_id, item_id) ||
+                Self::is_item_owner(sender.clone(), &target_collection, item_id) ||
                 (
                     target_collection.limits.owner_can_transfer &&
-                    Self::is_owner_or_admin_permissions(collection_id, sender.clone())
+                    Self::is_owner_or_admin_permissions(&target_collection, sender.clone())
                 ),
                 Error::<T>::NoPermission
             );
 
             if target_collection.access == AccessMode::WhiteList {
-                Self::check_white_list(collection_id, &sender)?;
+                Self::check_white_list(&target_collection, &sender)?;
             }
 
             match target_collection.mode
             {
-                CollectionMode::NFT => Self::burn_nft_item(collection_id, item_id)?,
-                CollectionMode::Fungible(_)  => Self::burn_fungible_item(&sender, collection_id, value)?,
-                CollectionMode::ReFungible  => Self::burn_refungible_item(collection_id, item_id, &sender)?,
+                CollectionMode::NFT => Self::burn_nft_item(&target_collection, item_id)?,
+                CollectionMode::Fungible(_)  => Self::burn_fungible_item(&sender, &target_collection, value)?,
+                CollectionMode::ReFungible  => Self::burn_refungible_item(&target_collection, item_id, &sender)?,
                 _ => ()
             };
 
             // call event
-            Self::deposit_event(RawEvent::ItemDestroyed(collection_id, item_id));
+            Self::deposit_event(RawEvent::ItemDestroyed(target_collection.id, item_id));
 
             Ok(())
         }
@@ -1097,7 +1097,9 @@
         #[weight = <T as Config>::WeightInfo::transfer()]
         pub fn transfer(origin, recipient: T::AccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResult {
             let sender = ensure_signed(origin)?;
-            Self::transfer_internal(sender, recipient, collection_id, item_id, value)
+            let collection = Self::get_collection(collection_id)?;
+
+            Self::transfer_internal(sender, recipient, &collection, item_id, value)
         }
 
         /// Set, change, or remove approved address to transfer the ownership of the NFT.
@@ -1119,23 +1121,22 @@
         pub fn approve(origin, spender: T::AccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResult {
 
             let sender = ensure_signed(origin)?;
+            let target_collection = Self::get_collection(collection_id)?;
 
-            Self::collection_exists(collection_id)?;
-            Self::token_exists(collection_id, item_id, &sender)?;
+            Self::token_exists(&target_collection, item_id, &sender)?;
 
             // Transfer permissions check
-            let target_collection = <Collection<T>>::get(collection_id).unwrap();
             let allowance_limit = if (
                 target_collection.limits.owner_can_transfer &&
                 Self::is_owner_or_admin_permissions(
-                    collection_id,
+                    &target_collection,
                     sender.clone(),
                 )
             ) {
                 None
             } else if let Some(amount) = Self::owned_amount(
                 sender.clone(),
-                collection_id,
+                &target_collection,
                 item_id,
             ) {
                 Some(amount)
@@ -1144,8 +1145,8 @@
             };
 
             if target_collection.access == AccessMode::WhiteList {
-                Self::check_white_list(collection_id, &sender)?;
-                Self::check_white_list(collection_id, &spender)?;
+                Self::check_white_list(&target_collection, &sender)?;
+                Self::check_white_list(&target_collection, &spender)?;
             }
 
             let allowance_exists = <Allowances<T>>::contains_key(collection_id, (item_id, &sender, &spender));
@@ -1184,6 +1185,8 @@
         pub fn transfer_from(origin, from: T::AccountId, recipient: T::AccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResult {
 
             let sender = ensure_signed(origin)?;
+            let target_collection = Self::get_collection(collection_id)?;
+
             let mut appoved_transfer = false;
 
             // Check approval
@@ -1193,25 +1196,23 @@
                 ensure!(approval >= value, Error::<T>::TokenValueNotEnough);
                 appoved_transfer = true;
             }
-
-            let target_collection = <Collection<T>>::get(collection_id).unwrap();
 
             // Limits check
-            Self::is_correct_transfer(collection_id, &target_collection, &recipient)?;
+            Self::is_correct_transfer(&target_collection, &recipient)?;
 
             // Transfer permissions check         
             ensure!(
                 appoved_transfer || 
                 (
                     target_collection.limits.owner_can_transfer &&
-                    Self::is_owner_or_admin_permissions(collection_id, sender.clone())
+                    Self::is_owner_or_admin_permissions(&target_collection, sender.clone())
                 ),
                 Error::<T>::NoPermission
             );
 
             if target_collection.access == AccessMode::WhiteList {
-                Self::check_white_list(collection_id, &sender)?;
-                Self::check_white_list(collection_id, &recipient)?;
+                Self::check_white_list(&target_collection, &sender)?;
+                Self::check_white_list(&target_collection, &recipient)?;
             }
 
             // Reduce approval by transferred amount or remove if remaining approval drops to 0
@@ -1224,9 +1225,9 @@
 
             match target_collection.mode
             {
-                CollectionMode::NFT => Self::transfer_nft(collection_id, item_id, from, recipient)?,
-                CollectionMode::Fungible(_)  => Self::transfer_fungible(collection_id, value, &from, &recipient)?,
-                CollectionMode::ReFungible  => Self::transfer_refungible(collection_id, item_id, value, from.clone(), recipient)?,
+                CollectionMode::NFT => Self::transfer_nft(&target_collection, item_id, from, recipient)?,
+                CollectionMode::Fungible(_)  => Self::transfer_fungible(&target_collection, value, &from, &recipient)?,
+                CollectionMode::ReFungible  => Self::transfer_refungible(&target_collection, item_id, value, from.clone(), recipient)?,
                 _ => ()
             };
 
@@ -1269,21 +1270,20 @@
         ) -> DispatchResult {
             let sender = ensure_signed(origin)?;
             
-            Self::collection_exists(collection_id)?;
-            Self::token_exists(collection_id, item_id, &sender)?;
+            let target_collection = Self::get_collection(collection_id)?;
+            Self::token_exists(&target_collection, item_id, &sender)?;
 
             ensure!(ChainLimit::get().custom_data_limit >= data.len() as u32, Error::<T>::TokenVariableDataLimitExceeded);
 
             // Modify permissions check
-            let target_collection = <Collection<T>>::get(collection_id).unwrap();
-            ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id) ||
-                Self::is_owner_or_admin_permissions(collection_id, sender.clone()),
+            ensure!(Self::is_item_owner(sender.clone(), &target_collection, item_id) ||
+                Self::is_owner_or_admin_permissions(&target_collection, sender.clone()),
                 Error::<T>::NoPermission);
 
             match target_collection.mode
             {
-                CollectionMode::NFT => Self::set_nft_variable_data(collection_id, item_id, data)?,
-                CollectionMode::ReFungible  => Self::set_re_fungible_variable_data(collection_id, item_id, data)?,
+                CollectionMode::NFT => Self::set_nft_variable_data(&target_collection, item_id, data)?,
+                CollectionMode::ReFungible  => Self::set_re_fungible_variable_data(&target_collection, item_id, data)?,
                 CollectionMode::Fungible(_) => fail!(Error::<T>::CantStoreMetadataInFungibleTokens),
                 _ => fail!(Error::<T>::UnexpectedCollectionType)
             };
@@ -1312,10 +1312,10 @@
             version: SchemaVersion
         ) -> DispatchResult {
             let sender = ensure_signed(origin)?;
-            Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
-            let mut target_collection = <Collection<T>>::get(collection_id).unwrap();
+            let mut target_collection = Self::get_collection(collection_id)?;
+            Self::check_owner_or_admin_permissions(&target_collection, sender.clone())?;
             target_collection.schema_version = version;
-            <Collection<T>>::insert(collection_id, target_collection);
+            Self::save_collection(target_collection);
 
             Ok(())
         }
@@ -1339,14 +1339,14 @@
             schema: Vec<u8>
         ) -> DispatchResult {
             let sender = ensure_signed(origin)?;
-            Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
+            let mut target_collection = Self::get_collection(collection_id)?;
+            Self::check_owner_or_admin_permissions(&target_collection, sender.clone())?;
 
             // check schema limit
             ensure!(schema.len() as u32 <= ChainLimit::get().offchain_schema_limit, "");
 
-            let mut target_collection = <Collection<T>>::get(collection_id).unwrap();
             target_collection.offchain_schema = schema;
-            <Collection<T>>::insert(collection_id, target_collection);
+            Self::save_collection(target_collection);
 
             Ok(())
         }
@@ -1370,14 +1370,14 @@
             schema: Vec<u8>
         ) -> DispatchResult {
             let sender = ensure_signed(origin)?;
-            Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
+            let mut target_collection = Self::get_collection(collection_id)?;
+            Self::check_owner_or_admin_permissions(&target_collection, sender.clone())?;
 
             // check schema limit
             ensure!(schema.len() as u32 <= ChainLimit::get().const_on_chain_schema_limit, "");
 
-            let mut target_collection = <Collection<T>>::get(collection_id).unwrap();
             target_collection.const_on_chain_schema = schema;
-            <Collection<T>>::insert(collection_id, target_collection);
+            Self::save_collection(target_collection);
 
             Ok(())
         }
@@ -1401,14 +1401,14 @@
             schema: Vec<u8>
         ) -> DispatchResult {
             let sender = ensure_signed(origin)?;
-            Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
+            let mut target_collection = Self::get_collection(collection_id)?;
+            Self::check_owner_or_admin_permissions(&target_collection, sender.clone())?;
 
             // check schema limit
             ensure!(schema.len() as u32 <= ChainLimit::get().variable_on_chain_schema_limit, "");
 
-            let mut target_collection = <Collection<T>>::get(collection_id).unwrap();
             target_collection.variable_on_chain_schema = schema;
-            <Collection<T>>::insert(collection_id, target_collection);
+            Self::save_collection(target_collection);
 
             Ok(())
         }
@@ -1577,8 +1577,8 @@
             new_limits: CollectionLimits<T::BlockNumber>,
         ) -> DispatchResult {
             let sender = ensure_signed(origin)?;
-            Self::check_owner_permissions(collection_id, sender.clone())?;
-            let mut target_collection = <Collection<T>>::get(collection_id).unwrap();
+            let mut target_collection = Self::get_collection(collection_id)?;
+            Self::check_owner_permissions(&target_collection, sender.clone())?;
             let old_limits = target_collection.limits;
             let chain_limits = ChainLimit::get();
 
@@ -1599,7 +1599,7 @@
             );
 
             target_collection.limits = new_limits;
-            <Collection<T>>::insert(collection_id, target_collection);
+            Self::save_collection(target_collection);
 
             Ok(())
         } 
@@ -1607,39 +1607,37 @@
 }
 
 impl<T: Config> Module<T> {
-
-    pub fn transfer_internal(sender: T::AccountId, recipient: T::AccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResult {
 
-        let target_collection = <Collection<T>>::get(collection_id).unwrap();
-
+    pub fn transfer_internal(sender: T::AccountId, recipient: T::AccountId, target_collection: &Collection<T>, item_id: TokenId, value: u128) -> DispatchResult {
         // Limits check
-        Self::is_correct_transfer(collection_id, &target_collection, &recipient)?;
+        Self::is_correct_transfer(target_collection, &recipient)?;
 
         // Transfer permissions check
-        ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id) ||
-            Self::is_owner_or_admin_permissions(collection_id, sender.clone()),
+        ensure!(Self::is_item_owner(sender.clone(), target_collection, item_id) ||
+            Self::is_owner_or_admin_permissions(target_collection, sender.clone()),
             Error::<T>::NoPermission);
 
         if target_collection.access == AccessMode::WhiteList {
-            Self::check_white_list(collection_id, &sender)?;
-            Self::check_white_list(collection_id, &recipient)?;
+            Self::check_white_list(target_collection, &sender)?;
+            Self::check_white_list(target_collection, &recipient)?;
         }
 
         match target_collection.mode
         {
-            CollectionMode::NFT => Self::transfer_nft(collection_id, item_id, sender.clone(), recipient.clone())?,
-            CollectionMode::Fungible(_)  => Self::transfer_fungible(collection_id, value, &sender, &recipient)?,
-            CollectionMode::ReFungible  => Self::transfer_refungible(collection_id, item_id, value, sender.clone(), recipient.clone())?,
+            CollectionMode::NFT => Self::transfer_nft(target_collection, item_id, sender.clone(), recipient.clone())?,
+            CollectionMode::Fungible(_)  => Self::transfer_fungible(target_collection, value, &sender, &recipient)?,
+            CollectionMode::ReFungible  => Self::transfer_refungible(target_collection, item_id, value, sender.clone(), recipient.clone())?,
             _ => ()
         };
 
-        Self::deposit_event(RawEvent::Transfer(collection_id, item_id, sender, recipient, value));
+        Self::deposit_event(RawEvent::Transfer(target_collection.id, item_id, sender, recipient, value));
 
         Ok(())
     }
 
 
-    fn is_correct_transfer(collection_id: CollectionId, collection: &CollectionType<T>, recipient: &T::AccountId) -> DispatchResult {
+    fn is_correct_transfer(collection: &Collection<T>, recipient: &T::AccountId) -> DispatchResult {
+        let collection_id = collection.id;
 
         // check token limit and account token limit
         let account_items: u32 = <AddressTokens<T>>::get(collection_id, recipient).len() as u32;
@@ -1648,7 +1646,8 @@
         Ok(())
     }
 
-    fn can_create_items_in_collection(collection_id: CollectionId, collection: &CollectionType<T>, sender: &T::AccountId, owner: &T::AccountId) -> DispatchResult {
+    fn can_create_items_in_collection(collection: &Collection<T>, sender: &T::AccountId, owner: &T::AccountId) -> DispatchResult {
+        let collection_id = collection.id;
 
         // check token limit and account token limit
         let total_items: u32 = ItemListIndex::get(collection_id);
@@ -1656,16 +1655,16 @@
         ensure!(collection.limits.token_limit > total_items,  Error::<T>::CollectionTokenLimitExceeded);
         ensure!(collection.limits.account_token_ownership_limit > account_items,  Error::<T>::AccountTokenLimitExceeded);
 
-        if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) {
+        if !Self::is_owner_or_admin_permissions(collection, sender.clone()) {
             ensure!(collection.mint_mode == true, Error::<T>::PublicMintingNotAllowed);
-            Self::check_white_list(collection_id, owner)?;
-            Self::check_white_list(collection_id, sender)?;
+            Self::check_white_list(collection, owner)?;
+            Self::check_white_list(collection, sender)?;
         }
 
         Ok(())
     }
 
-    fn validate_create_item_args(target_collection: &CollectionType<T>, data: &CreateItemData) -> DispatchResult {
+    fn validate_create_item_args(target_collection: &Collection<T>, data: &CreateItemData) -> DispatchResult {
         match target_collection.mode
         {
             CollectionMode::NFT => {
@@ -1703,7 +1702,9 @@
         Ok(())
     }
 
-    fn create_item_no_validation(collection_id: CollectionId, owner: T::AccountId, data: CreateItemData) -> DispatchResult {
+    fn create_item_no_validation(collection: &Collection<T>, owner: T::AccountId, data: CreateItemData) -> DispatchResult {
+        let collection_id = collection.id;
+
         match data
         {
             CreateItemData::NFT(data) => {
@@ -1713,10 +1714,10 @@
                     variable_data: data.variable_data
                 };
 
-                Self::add_nft_item(collection_id, item)?;
+                Self::add_nft_item(collection, item)?;
             },
             CreateItemData::Fungible(data) => {
-                Self::add_fungible_item(collection_id, &owner, data.value)?;
+                Self::add_fungible_item(collection, &owner, data.value)?;
             },
             CreateItemData::ReFungible(data) => {
                 let mut owner_list = Vec::new();
@@ -1728,7 +1729,7 @@
                     variable_data: data.variable_data
                 };
 
-                Self::add_refungible_item(collection_id, item)?;
+                Self::add_refungible_item(collection, item)?;
             }
         };
 
@@ -1738,7 +1739,8 @@
         Ok(())
     }
 
-    fn add_fungible_item(collection_id: CollectionId, owner: &T::AccountId, value: u128) -> DispatchResult {
+    fn add_fungible_item(collection: &Collection<T>, owner: &T::AccountId, value: u128) -> DispatchResult {
+        let collection_id = collection.id;
 
         // Does new owner already have an account?
         let mut balance: u128 = 0;
@@ -1761,7 +1763,9 @@
         Ok(())
     }
 
-    fn add_refungible_item(collection_id: CollectionId, item: ReFungibleItemType<T::AccountId>) -> DispatchResult {
+    fn add_refungible_item(collection: &Collection<T>, item: ReFungibleItemType<T::AccountId>) -> DispatchResult {
+        let collection_id = collection.id;
+
         let current_index = <ItemListIndex>::get(collection_id)
             .checked_add(1)
             .ok_or(Error::<T>::NumOverflow)?;
@@ -1784,7 +1788,9 @@
         Ok(())
     }
 
-    fn add_nft_item(collection_id: CollectionId, item: NftItemType<T::AccountId>) -> DispatchResult {
+    fn add_nft_item(collection: &Collection<T>, item: NftItemType<T::AccountId>) -> DispatchResult {
+        let collection_id = collection.id;
+
         let current_index = <ItemListIndex>::get(collection_id)
             .checked_add(1)
             .ok_or(Error::<T>::NumOverflow)?;
@@ -1805,10 +1811,12 @@
     }
 
     fn burn_refungible_item(
-        collection_id: CollectionId,
+        collection: &Collection<T>,
         item_id: TokenId,
         owner: &T::AccountId,
     ) -> DispatchResult {
+        let collection_id = collection.id;
+
         ensure!(
             <ReFungibleItemList<T>>::contains_key(collection_id, item_id),
             Error::<T>::TokenNotFound
@@ -1849,7 +1857,9 @@
         Ok(())
     }
 
-    fn burn_nft_item(collection_id: CollectionId, item_id: TokenId) -> DispatchResult {
+    fn burn_nft_item(collection: &Collection<T>, item_id: TokenId) -> DispatchResult {
+        let collection_id = collection.id;
+
         ensure!(
             <NftItemList<T>>::contains_key(collection_id, item_id),
             Error::<T>::TokenNotFound
@@ -1868,7 +1878,9 @@
         Ok(())
     }
 
-    fn burn_fungible_item(owner: &T::AccountId, collection_id: CollectionId, value: u128) -> DispatchResult {
+    fn burn_fungible_item(owner: &T::AccountId, collection: &Collection<T>, value: u128) -> DispatchResult {
+        let collection_id = collection.id;
+
         ensure!(
             <FungibleItemList<T>>::contains_key(collection_id, owner),
             Error::<T>::TokenNotFound
@@ -1893,18 +1905,16 @@
         Ok(())
     }
 
-    fn collection_exists(collection_id: CollectionId) -> DispatchResult {
-        ensure!(
-            <Collection<T>>::contains_key(collection_id),
-            Error::<T>::CollectionNotFound
-        );
-        Ok(())
+    pub fn get_collection(collection_id: CollectionId) -> Result<Collection<T>, sp_runtime::DispatchError> {
+        Ok(<CollectionById<T>>::get(collection_id)
+            .ok_or(Error::<T>::CollectionNotFound)?)
     }
 
-    fn check_owner_permissions(collection_id: CollectionId, subject: T::AccountId) -> DispatchResult {
-        Self::collection_exists(collection_id)?;
+    fn save_collection(collection: Collection<T>) {
+        <CollectionById<T>>::insert(collection.id, collection);
+    }
 
-        let target_collection = <Collection<T>>::get(collection_id).unwrap();
+    fn check_owner_permissions(target_collection: &Collection<T>, subject: T::AccountId) -> DispatchResult {
         ensure!(
             subject == target_collection.owner,
             Error::<T>::NoPermission
@@ -1913,13 +1923,12 @@
         Ok(())
     }
 
-    fn is_owner_or_admin_permissions(collection_id: CollectionId, subject: T::AccountId) -> bool {
-        let target_collection = <Collection<T>>::get(collection_id).unwrap();
-        let mut result: bool = subject == target_collection.owner;
-        let exists = <AdminList<T>>::contains_key(collection_id);
+    fn is_owner_or_admin_permissions(collection: &Collection<T>, subject: T::AccountId) -> bool {
+        let mut result: bool = subject == collection.owner;
+        let exists = <AdminList<T>>::contains_key(collection.id);
 
         if !result & exists {
-            if <AdminList<T>>::get(collection_id).contains(&subject) {
+            if <AdminList<T>>::get(collection.id).contains(&subject) {
                 result = true
             }
         }
@@ -1928,11 +1937,10 @@
     }
 
     fn check_owner_or_admin_permissions(
-        collection_id: CollectionId,
+        collection: &Collection<T>,
         subject: T::AccountId,
     ) -> DispatchResult {
-        Self::collection_exists(collection_id)?;
-        let result = Self::is_owner_or_admin_permissions(collection_id, subject.clone());
+        let result = Self::is_owner_or_admin_permissions(collection, subject.clone());
 
         ensure!(
             result,
@@ -1943,10 +1951,10 @@
 
     fn owned_amount(
         subject: T::AccountId,
-        collection_id: CollectionId,
+        target_collection: &Collection<T>,
         item_id: TokenId,
     ) -> Option<u128> {
-        let target_collection = <Collection<T>>::get(collection_id);
+        let collection_id = target_collection.id;
 
         match target_collection.mode {
             CollectionMode::NFT => {
@@ -1971,8 +1979,8 @@
         }
     }
 
-    fn is_item_owner(subject: T::AccountId, collection_id: CollectionId, item_id: TokenId) -> bool {
-        let target_collection = <Collection<T>>::get(collection_id).unwrap();
+    fn is_item_owner(subject: T::AccountId, target_collection: &Collection<T>, item_id: TokenId) -> bool {
+        let collection_id = target_collection.id;
 
         match target_collection.mode {
             CollectionMode::NFT => {
@@ -1991,7 +1999,9 @@
         }
     }
 
-    fn check_white_list(collection_id: CollectionId, address: &T::AccountId) -> DispatchResult {
+    fn check_white_list(collection: &Collection<T>, address: &T::AccountId) -> DispatchResult {
+        let collection_id = collection.id;
+
         let mes = Error::<T>::AddresNotInWhiteList;
         ensure!(<WhiteList<T>>::contains_key(collection_id, address), mes);
 
@@ -2001,11 +2011,11 @@
     /// Check if token exists. In case of Fungible, check if there is an entry for 
     /// the owner in fungible balances double map
     fn token_exists(
-        collection_id: CollectionId,
+        target_collection: &Collection<T>,
         item_id: TokenId,
         owner: &T::AccountId
     ) -> DispatchResult {
-        let target_collection = <Collection<T>>::get(collection_id).unwrap();
+        let collection_id = target_collection.id;
         let exists = match target_collection.mode
         {
             CollectionMode::NFT => <NftItemList<T>>::contains_key(collection_id, item_id),
@@ -2019,18 +2029,19 @@
     }
 
     fn transfer_fungible(
-        collection_id: CollectionId,
+        collection: &Collection<T>,
         value: u128,
         owner: &T::AccountId,
         recipient: &T::AccountId,
     ) -> DispatchResult {
-        Self::token_exists(collection_id, 0, owner)?;
+        let collection_id = collection.id;
+        Self::token_exists(&collection, 0, owner)?;
 
         let mut balance = <FungibleItemList<T>>::get(collection_id, owner);
         ensure!(balance.value >= value, Error::<T>::TokenValueTooLow);
 
         // Send balance to recipient (updates balanceOf of recipient)
-        Self::add_fungible_item(collection_id, recipient, value)?;
+        Self::add_fungible_item(collection, recipient, value)?;
 
         // update balanceOf of sender
         <Balance<T>>::insert(collection_id, (*owner).clone(), balance.value - value);
@@ -2048,13 +2059,14 @@
     }
 
     fn transfer_refungible(
-        collection_id: CollectionId,
+        collection: &Collection<T>,
         item_id: TokenId,
         value: u128,
         owner: T::AccountId,
         new_owner: T::AccountId,
     ) -> DispatchResult {
-        Self::token_exists(collection_id, item_id, &owner)?;
+        let collection_id = collection.id;
+        Self::token_exists(collection, item_id, &owner)?;
 
         let full_item = <ReFungibleItemList<T>>::get(collection_id, item_id);
         let item = full_item
@@ -2130,12 +2142,13 @@
     }
 
     fn transfer_nft(
-        collection_id: CollectionId,
+        collection: &Collection<T>,
         item_id: TokenId,
         sender: T::AccountId,
         new_owner: T::AccountId,
     ) -> DispatchResult {
-        Self::token_exists(collection_id, item_id, &sender)?;
+        let collection_id = collection.id;
+        Self::token_exists(&collection, item_id, &sender)?;
 
         let mut item = <NftItemList<T>>::get(collection_id, item_id);
 
@@ -2167,10 +2180,11 @@
     }
     
     fn set_re_fungible_variable_data(
-        collection_id: CollectionId,
+        collection: &Collection<T>,
         item_id: TokenId,
         data: Vec<u8>
     ) -> DispatchResult {
+        let collection_id = collection.id;
         let mut item = <ReFungibleItemList<T>>::get(collection_id, item_id);
 
         item.variable_data = data;
@@ -2181,10 +2195,11 @@
     }
 
     fn set_nft_variable_data(
-        collection_id: CollectionId,
+        collection: &Collection<T>,
         item_id: TokenId,
         data: Vec<u8>
     ) -> DispatchResult {
+        let collection_id = collection.id;
         let mut item = <NftItemList<T>>::get(collection_id, item_id);
         
         item.variable_data = data;
@@ -2194,7 +2209,7 @@
         Ok(())
     }
 
-    fn init_collection(item: &CollectionType<T>) {
+    fn init_collection(item: &Collection<T>) {
         // check params
         assert!(
             item.decimal_points <= MAX_DECIMAL_POINTS,
@@ -2274,7 +2289,6 @@
     }
 
     fn add_token_index(collection_id: CollectionId, item_index: TokenId, owner: &T::AccountId) -> DispatchResult {
-
         // add to account limit
         if <AccountItemCount<T>>::contains_key(owner) {
 
@@ -2449,38 +2463,34 @@
 
         // Determine who is paying transaction fee based on ecnomic model
         // Parse call to extract collection ID and access collection sponsor
-        let mut sponsor: T::AccountId = match IsSubType::<Call<T>>::is_sub_type(call) {
+        let mut sponsor: Option<T::AccountId> = (|| match IsSubType::<Call<T>>::is_sub_type(call) {
             Some(Call::create_item(collection_id, _owner, _properties)) => {
-                let collection = <Collection<T>>::get(collection_id).unwrap();
+                let collection = <CollectionById<T>>::get(collection_id)?;
 
                 // sponsor timeout
                 let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
 
                 let limit = collection.limits.sponsor_transfer_timeout;
-                let mut sponsored = true;
                 if <CreateItemBasket<T>>::contains_key((collection_id, &who)) {
                     let last_tx_block = <CreateItemBasket<T>>::get((collection_id, &who));
                     let limit_time = last_tx_block + limit.into();
                     if block_number <= limit_time {
-                        sponsored = false;
+                        return None;
                     }
-                }
-                if sponsored {
-                    <CreateItemBasket<T>>::insert((collection_id, who.clone()), block_number);
                 }
+                <CreateItemBasket<T>>::insert((collection_id, who.clone()), block_number);
 
                 // check free create limit
                 if (collection.limits.sponsored_data_size >= (_properties.len() as u32)) &&
-                   (collection.sponsor_confirmed) &&
-                   (sponsored)
+                   (collection.sponsor_confirmed)
                 {
-                    collection.sponsor
+                    Some(collection.sponsor)
                 } else {
-                    T::AccountId::default()
+                    None
                 }
             }
             Some(Call::transfer(_new_owner, collection_id, item_id, _value)) => {
-                let collection = <Collection<T>>::get(collection_id).unwrap();
+                let collection = <CollectionById<T>>::get(collection_id)?;
                 
                 let mut sponsor_transfer = false;
                 if collection.sponsor_confirmed {
@@ -2568,16 +2578,16 @@
                 }
 
                 if !sponsor_transfer {
-                    T::AccountId::default()
+                    None
                 } else {
-                    collection.sponsor
+                    Some(collection.sponsor)
                 }
             }
 
             Some(Call::set_variable_meta_data(collection_id, item_id, data)) => {
                 let mut sponsor_metadata_changes = false;
 
-                let collection = <Collection<T>>::get(collection_id).unwrap();
+                let collection = <CollectionById<T>>::get(collection_id)?;
 
                 if
                     collection.sponsor_confirmed &&
@@ -2600,17 +2610,35 @@
                 }
 
                 if !sponsor_metadata_changes {
-                    T::AccountId::default()
+                    None
                 } else {
-                    collection.sponsor
+                    Some(collection.sponsor)
                 }
             }
 
-            _ => T::AccountId::default(),
-        };
+            _ => None,
+        })();
+
+        match IsSubType::<pallet_contracts::Call<T>>::is_sub_type(call) {
+            Some(pallet_contracts::Call::call(dest, _value, _gas_limit, _data)) => {
 
+                let called_contract: T::AccountId = T::Lookup::lookup((*dest).clone()).unwrap_or(T::AccountId::default());
+
+                let owned_contract = <ContractOwner<T>>::contains_key(called_contract.clone())
+                  && <ContractOwner<T>>::get(called_contract.clone()) == *who;
+                let white_list_enabled = <ContractWhiteListEnabled<T>>::contains_key(called_contract.clone()) && <ContractWhiteListEnabled<T>>::get(called_contract.clone());
+                  
+                if !owned_contract && white_list_enabled {
+                    if !<ContractWhiteList<T>>::contains_key(called_contract.clone(), who) {
+                        return Err(InvalidTransaction::Call.into());
+                    }
+                }
+            },
+            _ => {},
+        }
+
         // Sponsor smart contracts
-        sponsor = match IsSubType::<pallet_contracts::Call<T>>::is_sub_type(call) {
+        sponsor = sponsor.or_else(|| match IsSubType::<pallet_contracts::Call<T>>::is_sub_type(call) {
 
             // On instantiation: set the contract owner
             Some(pallet_contracts::Call::instantiate(_endowment, _gas_limit, code_hash, _data, salt)) => {
@@ -2622,7 +2650,7 @@
                 );
                 <ContractOwner<T>>::insert(new_contract_address.clone(), who.clone());
 
-                T::AccountId::default()
+                None
             },
 
             // When the contract is called, check if the sponsoring is enabled and pay fees from contract endowment if it is
@@ -2630,16 +2658,6 @@
 
                 let called_contract: T::AccountId = T::Lookup::lookup((*dest).clone()).unwrap_or(T::AccountId::default());
 
-                let owned_contract = <ContractOwner<T>>::contains_key(called_contract.clone())
-                  && <ContractOwner<T>>::get(called_contract.clone()) == *who;
-                let white_list_enabled = <ContractWhiteListEnabled<T>>::contains_key(called_contract.clone()) && <ContractWhiteListEnabled<T>>::get(called_contract.clone());
-                  
-                if !owned_contract && white_list_enabled {
-                    if !<ContractWhiteList<T>>::contains_key(called_contract.clone(), who) {
-                        return Err(InvalidTransaction::Call.into());
-                    }
-                }
-
                 let mut sponsor_transfer = false;
                 if <ContractSponsoringRateLimit<T>>::contains_key(called_contract.clone()) {
                     let last_tx_block = <ContractSponsorBasket<T>>::get((&called_contract, &who));
@@ -2655,26 +2673,21 @@
                     sponsor_transfer = false;
                 }
                
-                
-                let mut sp = T::AccountId::default();
                 if sponsor_transfer {
                     if <ContractSelfSponsoring<T>>::contains_key(called_contract.clone()) {
                         if <ContractSelfSponsoring<T>>::get(called_contract.clone()) {
-                            sp = called_contract;
+                            return Some(called_contract);
                         }
                     }
                 }
 
-                sp
+                None
             },
 
-            _ => sponsor,
-        };
+            _ => None,
+        });
 
-        let mut who_pays_fee: T::AccountId = sponsor.clone();
-        if sponsor == T::AccountId::default() {
-            who_pays_fee = who.clone();
-        }
+        let who_pays_fee = sponsor.unwrap_or_else(|| who.clone());
 
 		<<T as transaction_payment::Config>::OnChargeTransaction as transaction_payment::OnChargeTransaction<T>>::withdraw_fee(&who_pays_fee, call, info, fee, tip)
 			.map(|i| (fee, i))
modifiedruntime/src/chain_extension.rsdiffbeforeafterboth
--- a/runtime/src/chain_extension.rs
+++ b/runtime/src/chain_extension.rs
@@ -60,7 +60,9 @@
                 }
                 let recipient = AccountId32::from(bytes_rec);
 
-                match pallet_nft::Module::<Runtime>::transfer_internal(sender, recipient, input.collection_id, input.token_id, input.amount) {
+                let collection = pallet_nft::Module::<Runtime>::get_collection(input.collection_id)?;
+
+                match pallet_nft::Module::<Runtime>::transfer_internal(sender, recipient, &collection, input.token_id, input.amount) {
                     Ok(_) => Ok(RetVal::Converging(func_id)),
                     _ => Err(DispatchError::Other("Transfer error"))
                 }
modifiedruntime_types.jsondiffbeforeafterboth
--- a/runtime_types.json
+++ b/runtime_types.json
@@ -31,7 +31,8 @@
       "ConstData": "Vec<u8>",
       "VariableData": "Vec<u8>"
     },
-    "CollectionType": {
+    "Collection": {
+      "Id": "CollectionId",
       "Owner": "AccountId",
       "Mode": "CollectionMode",
       "Access": "AccessMode",