git.delta.rocks / unique-network / refs/commits / 0dbd5ddfd265

difftreelog

Merge pull request #9 from usetech-llc/feature_limits_nft_78_85_105

Greg Zaitsev2020-10-13parents: #eb6665e #d339ca3.patch.diff
in: master
Transfer rate limit + chain bounds

4 files changed

modifiednode/src/chain_spec.rsdiffbeforeafterboth
--- a/node/src/chain_spec.rs
+++ b/node/src/chain_spec.rs
@@ -130,23 +130,35 @@
         }),
         sudo: Some(SudoConfig { key: root_key }),
         nft: Some(NftConfig {
-            collection: vec![(1, CollectionType { 
-                owner: get_account_id_from_seed::<sr25519::Public>("Alice"),
-                mode: CollectionMode::NFT(50),
-                access: AccessMode::Normal,
-                decimal_points: 0,
-                name: vec!(),
-                description: vec!(),
-                token_prefix: vec!(),
-                custom_data_size: 50,
-                mint_mode: false,
-                offchain_schema: vec!(),
-                sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),
-                unconfirmed_sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),
-            })],
-            nft_item_id: vec!(),
-            fungible_item_id: vec!(),
-            refungible_item_id: vec!(),
+            collection: vec![(
+                1,
+                CollectionType {
+                    owner: get_account_id_from_seed::<sr25519::Public>("Alice"),
+                    mode: CollectionMode::NFT(50),
+                    access: AccessMode::Normal,
+                    decimal_points: 0,
+                    name: vec![],
+                    description: vec![],
+                    token_prefix: vec![],
+                    custom_data_size: 50,
+                    mint_mode: false,
+                    offchain_schema: vec![],
+                    sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),
+                    unconfirmed_sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),
+                },
+            )],
+            nft_item_id: vec![],
+            fungible_item_id: vec![],
+            refungible_item_id: vec![],
+            chain_limit: ChainLimits {
+                collection_numbers_limit: 10,
+                account_token_ownership_limit: 10,
+                collections_admins_limit: 5,
+                custom_data_limit: 2048,
+                nft_sponsor_transfer_timeout: 15,
+                fungible_sponsor_transfer_timeout: 15,
+                refungible_sponsor_transfer_timeout: 15,
+            },
         }),
         contracts: Some(ContractsConfig {
             current_schedule: ContractsSchedule {
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
1#![cfg_attr(not(feature = "std"), no_std)]1#![cfg_attr(not(feature = "std"), no_std)]
22
3#[cfg(feature = "std")]3#[cfg(feature = "std")]
4pub use std::*;
5
6#[cfg(feature = "std")]
4pub use serde::*;7pub use serde::*;
58
6use codec::{Decode, Encode};9use codec::{Decode, Encode};
20 IsSubType, StorageValue,23 IsSubType, StorageValue,
21};24};
2225
23use frame_system::{self as system, ensure_signed};26use frame_system::{self as system, ensure_signed, ensure_root};
24use sp_runtime::sp_std::prelude::Vec;27use sp_runtime::sp_std::prelude::Vec;
25use sp_runtime::{28use sp_runtime::{
26 traits::{29 traits::{
157 pub vesting_date: Moment,160 pub vesting_date: Moment,
158}161}
159162
163#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
164#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
165pub struct BasketItem<AccountId, BlockNumber> {
166 pub address: AccountId,
167 pub start_block: BlockNumber,
168}
169
170#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
171#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
172pub struct ChainLimits {
173 pub collection_numbers_limit: u64,
174 pub account_token_ownership_limit: u64,
175 pub collections_admins_limit: u64,
176 pub custom_data_limit: u32,
177
178 // Timeouts for item types in passed blocks
179 pub nft_sponsor_transfer_timeout: u32,
180 pub fungible_sponsor_transfer_timeout: u32,
181 pub refungible_sponsor_transfer_timeout: u32,
182}
183
160pub trait Trait: system::Trait {184pub trait Trait: system::Trait {
161 type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;185 type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
162}186}
172 ChainVersion: u64;196 ChainVersion: u64;
173 ItemListIndex: map hasher(blake2_128_concat) u64 => u64;197 ItemListIndex: map hasher(blake2_128_concat) u64 => u64;
174198
199 // Chain limits struct
200 pub ChainLimit get(fn chain_limit) config(): ChainLimits;
201
202 // Bound counters
203 CollectionCount: u64;
204 pub AccountItemCount get(fn account_item_count): map hasher(identity) T::AccountId => u64;
205
206 // Basic collections
175 pub Collection get(fn collection) config(): map hasher(identity) u64 => CollectionType<T::AccountId>;207 pub Collection get(fn collection) config(): map hasher(identity) u64 => CollectionType<T::AccountId>;
176 pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec<T::AccountId>;208 pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec<T::AccountId>;
177 pub WhiteList get(fn white_list): map hasher(identity) u64 => Vec<T::AccountId>;209 pub WhiteList get(fn white_list): map hasher(identity) u64 => Vec<T::AccountId>;
190 /// Index list222 /// Index list
191 pub AddressTokens get(fn address_tokens): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) T::AccountId => Vec<u64>;223 pub AddressTokens get(fn address_tokens): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) T::AccountId => Vec<u64>;
192224
225 /// Tokens transfer baskets
226 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => T::BlockNumber;
227 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => Vec<BasketItem<T::AccountId, T::BlockNumber>>;
228 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => T::BlockNumber;
229
193 // Sponsorship230 // Sponsorship
194 pub ContractSponsor get(fn contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;231 pub ContractSponsor get(fn contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;
195 pub UnconfirmedContractSponsor get(fn unconfirmed_contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;232 pub UnconfirmedContractSponsor get(fn unconfirmed_contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;
196 }233 }
197 add_extra_genesis {234 add_extra_genesis {
198 build(|config: &GenesisConfig<T>| {235 build(|config: &GenesisConfig<T>| {
199 // Modification of storage236 // Modification of storage
200 for (_num, _c) in &config.collection {237 for (_num, _c) in &config.collection {
201 <Module<T>>::init_collection(_c);238 <Module<T>>::init_collection(_c);
202 }239 }
212 for (_num, _q, _i) in &config.refungible_item_id {249 for (_num, _q, _i) in &config.refungible_item_id {
213 <Module<T>>::init_refungible_token(_i);250 <Module<T>>::init_refungible_token(_i);
214 }251 }
215 })252 })
216 }253 }
217}254}
218255
295 // Anyone can create a collection332 // Anyone can create a collection
296 let who = ensure_signed(origin)?;333 let who = ensure_signed(origin)?;
297 let custom_data_size = match mode {334 let custom_data_size = match mode {
298 CollectionMode::NFT(size) => size,335 CollectionMode::NFT(size) => {
336
337 // bound Custom data size
338 ensure!(size < ChainLimit::get().custom_data_limit, "Custom data size bound exceeded");
299 CollectionMode::ReFungible(size, _) => size,339 size
340 },
341 CollectionMode::ReFungible(size, _) => {
342
343 // bound Custom data size
344 ensure!(size < ChainLimit::get().custom_data_limit, "Custom data size bound exceeded");
345 size
346 },
300 _ => 0347 _ => 0
301 };348 };
302349
306 _ => 0353 _ => 0
307 };354 };
308355
356 // bound Total number of collections
357 ensure!(CollectionCount::get() < ChainLimit::get().collection_numbers_limit, "Total collections bound exceeded");
358
309 // check params359 // check params
310 ensure!(decimal_points <= 4, "decimal_points parameter must be lower than 4");360 ensure!(decimal_points <= 4, "decimal_points parameter must be lower than 4");
311361
326 .checked_add(1)376 .checked_add(1)
327 .expect("collection id error");377 .expect("collection id error");
328378
379 // bound counter
380 let total = CollectionCount::get()
381 .checked_add(1)
382 .expect("collection counter error");
383
329 CreatedCollectionCount::put(next_id);384 CreatedCollectionCount::put(next_id);
385 CollectionCount::put(total);
330386
331 // Create new collection387 // Create new collection
332 let new_collection = CollectionType {388 let new_collection = CollectionType {
368 let sender = ensure_signed(origin)?;424 let sender = ensure_signed(origin)?;
369 Self::check_owner_permissions(collection_id, sender)?;425 Self::check_owner_permissions(collection_id, sender)?;
370426
371 // TODO Items remove
372 <AddressTokens<T>>::remove_prefix(collection_id);427 <AddressTokens<T>>::remove_prefix(collection_id);
373 <ApprovedList<T>>::remove_prefix(collection_id);428 <ApprovedList<T>>::remove_prefix(collection_id);
374 <Balance<T>>::remove_prefix(collection_id);429 <Balance<T>>::remove_prefix(collection_id);
377 <Collection<T>>::remove(collection_id);432 <Collection<T>>::remove(collection_id);
378 <WhiteList<T>>::remove(collection_id);433 <WhiteList<T>>::remove(collection_id);
379434
435 <NftItemList<T>>::remove_prefix(collection_id);
436 <FungibleItemList<T>>::remove_prefix(collection_id);
437 <ReFungibleItemList<T>>::remove_prefix(collection_id);
438
439 <NftTransferBasket<T>>::remove_prefix(collection_id);
440 <FungibleTransferBasket<T>>::remove_prefix(collection_id);
441 <ReFungibleTransferBasket<T>>::remove_prefix(collection_id);
442
443 if CollectionCount::get() > 0
444 {
445 // bound couter
446 let total = CollectionCount::get()
447 .checked_sub(1)
448 .expect("collection counter error");
449
450 CollectionCount::put(total);
451 }
452
380 Ok(())453 Ok(())
381 }454 }
382455
544 ensure!(!admin_arr.contains(&new_admin_id), "Account already has admin role");617 ensure!(!admin_arr.contains(&new_admin_id), "Account already has admin role");
545 }618 }
546619
620 // Number of collection admins
621 ensure!((admin_arr.len() as u64) < ChainLimit::get().collections_admins_limit, "Number of collection admins bound exceeded");
622
547 admin_arr.push(new_admin_id);623 admin_arr.push(new_admin_id);
548 <AdminList<T>>::insert(collection_id, admin_arr);624 <AdminList<T>>::insert(collection_id, admin_arr);
549625
758834
759 // Transfer permissions check835 // Transfer permissions check
760 let target_collection = <Collection<T>>::get(collection_id);836 let target_collection = <Collection<T>>::get(collection_id);
761 ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id) || 837 ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id) ||
762 Self::is_owner_or_admin_permissions(collection_id, sender.clone()), 838 Self::is_owner_or_admin_permissions(collection_id, sender.clone()),
763 "Only item owner, collection owner and admins can modify item");839 "Only item owner, collection owner and admins can modify item");
764840
765 if target_collection.access == AccessMode::WhiteList {841 if target_collection.access == AccessMode::WhiteList {
810886
811 // Transfer permissions check887 // Transfer permissions check
812 let target_collection = <Collection<T>>::get(collection_id);888 let target_collection = <Collection<T>>::get(collection_id);
813 ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id) || 889 ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id) ||
814 Self::is_owner_or_admin_permissions(collection_id, sender.clone()), 890 Self::is_owner_or_admin_permissions(collection_id, sender.clone()),
815 "Only item owner, collection owner and admins can modify item");891 "Only item owner, collection owner and admins can modify item");
816892
817 if target_collection.access == AccessMode::WhiteList {893 if target_collection.access == AccessMode::WhiteList {
852928
853 // Transfer permissions check929 // Transfer permissions check
854 let target_collection = <Collection<T>>::get(collection_id);930 let target_collection = <Collection<T>>::get(collection_id);
855 ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id) || 931 ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id) ||
856 Self::is_owner_or_admin_permissions(collection_id, sender.clone()), 932 Self::is_owner_or_admin_permissions(collection_id, sender.clone()),
857 "Only item owner, collection owner and admins can approve");933 "Only item owner, collection owner and admins can approve");
858934
859 if target_collection.access == AccessMode::WhiteList {935 if target_collection.access == AccessMode::WhiteList {
919995
920 // Transfer permissions check996 // Transfer permissions check
921 let target_collection = <Collection<T>>::get(collection_id);997 let target_collection = <Collection<T>>::get(collection_id);
922 ensure!(appoved_transfer || Self::is_owner_or_admin_permissions(collection_id, sender.clone()), 998 ensure!(appoved_transfer || Self::is_owner_or_admin_permissions(collection_id, sender.clone()),
923 "Only item owner, collection owner and admins can modify items");999 "Only item owner, collection owner and admins can modify items");
9241000
925 if target_collection.access == AccessMode::WhiteList {1001 if target_collection.access == AccessMode::WhiteList {
9871063
988 Ok(())1064 Ok(())
989 }1065 }
1066
1067 // Sudo permissions function
1068 #[weight = 0]
1069 pub fn set_chain_limits(
1070 origin,
1071 limits: ChainLimits
1072 ) -> DispatchResult {
1073 ensure_root(origin)?;
1074 <ChainLimit>::put(limits);
1075 Ok(())
1076 }
990 }1077 }
991}1078}
9921079
1004 <ItemListIndex>::insert(item.collection, current_index);1091 <ItemListIndex>::insert(item.collection, current_index);
1005 <FungibleItemList<T>>::insert(item.collection, current_index, itemcopy);1092 <FungibleItemList<T>>::insert(item.collection, current_index, itemcopy);
10061093
1094 // Add current block
1095 let v: Vec<BasketItem<T::AccountId, T::BlockNumber>> = Vec::new();
1096 <FungibleTransferBasket<T>>::insert(item.collection, current_index, v);
1097
1007 // Update balance1098 // Update balance
1008 let new_balance = <Balance<T>>::get(item.collection, owner.clone())1099 let new_balance = <Balance<T>>::get(item.collection, owner.clone())
1009 .checked_add(value)1100 .checked_add(value)
1027 <ItemListIndex>::insert(item.collection, current_index);1118 <ItemListIndex>::insert(item.collection, current_index);
1028 <ReFungibleItemList<T>>::insert(item.collection, current_index, itemcopy);1119 <ReFungibleItemList<T>>::insert(item.collection, current_index, itemcopy);
10291120
1121 // Add current block
1122 let block_number: T::BlockNumber = 0.into();
1123 <ReFungibleTransferBasket<T>>::insert(item.collection, current_index, block_number);
1124
1030 // Update balance1125 // Update balance
1031 let new_balance = <Balance<T>>::get(item.collection, owner.clone())1126 let new_balance = <Balance<T>>::get(item.collection, owner.clone())
1032 .checked_add(value)1127 .checked_add(value)
1048 <ItemListIndex>::insert(collection_id, current_index);1143 <ItemListIndex>::insert(collection_id, current_index);
1049 <NftItemList<T>>::insert(collection_id, current_index, item);1144 <NftItemList<T>>::insert(collection_id, current_index, item);
10501145
1146 // Add current block
1147 let block_number: T::BlockNumber = 0.into();
1148 <NftTransferBasket<T>>::insert(collection_id, current_index, block_number);
1149
1051 // Update balance1150 // Update balance
1052 let new_balance = <Balance<T>>::get(collection_id, item_owner.clone())1151 let new_balance = <Balance<T>>::get(collection_id, item_owner.clone())
1053 .checked_add(1)1152 .checked_add(1)
1057 Ok(())1156 Ok(())
1058 }1157 }
10591158
1060 fn burn_refungible_item(collection_id: u64, item_id: u64, owner: T::AccountId) -> DispatchResult {1159 fn burn_refungible_item(
1160 collection_id: u64,
1161 item_id: u64,
1162 owner: T::AccountId,
1163 ) -> DispatchResult {
1061 ensure!(1164 ensure!(
1062 <ReFungibleItemList<T>>::contains_key(collection_id, item_id),1165 <ReFungibleItemList<T>>::contains_key(collection_id, item_id),
1063 "Item does not exists"1166 "Item does not exists"
1149 }1252 }
11501253
1151 fn is_owner_or_admin_permissions(collection_id: u64, subject: T::AccountId) -> bool {1254 fn is_owner_or_admin_permissions(collection_id: u64, subject: T::AccountId) -> bool {
1152
1153 let target_collection = <Collection<T>>::get(collection_id);1255 let target_collection = <Collection<T>>::get(collection_id);
1154 let mut result: bool = subject == target_collection.owner;1256 let mut result: bool = subject == target_collection.owner;
1155 let exists = <AdminList<T>>::contains_key(collection_id);1257 let exists = <AdminList<T>>::contains_key(collection_id);
1163 result1265 result
1164 }1266 }
11651267
1166 fn check_owner_or_admin_permissions(collection_id: u64, subject: T::AccountId) -> DispatchResult {1268 fn check_owner_or_admin_permissions(
1167 1269 collection_id: u64,
1270 subject: T::AccountId,
1271 ) -> DispatchResult {
1168 Self::collection_exists(collection_id)?;1272 Self::collection_exists(collection_id)?;
1169 let result = Self::is_owner_or_admin_permissions(collection_id, subject.clone());1273 let result = Self::is_owner_or_admin_permissions(collection_id, subject.clone());
11701274
1171 ensure!(result, "You do not have permissions to modify this collection");1275 ensure!(
1276 result,
1277 "You do not have permissions to modify this collection"
1278 );
1172 Ok(())1279 Ok(())
1173 }1280 }
11741281
1193 }1300 }
11941301
1195 fn check_white_list(collection_id: u64, address: &T::AccountId) -> DispatchResult {1302 fn check_white_list(collection_id: u64, address: &T::AccountId) -> DispatchResult {
1196
1197 let mes = "Address is not in white list";1303 let mes = "Address is not in white list";
1198 ensure!(<WhiteList<T>>::contains_key(collection_id), mes);1304 ensure!(<WhiteList<T>>::contains_key(collection_id), mes);
1199 let wl = <WhiteList<T>>::get(collection_id);1305 let wl = <WhiteList<T>>::get(collection_id);
1209 owner: T::AccountId,1315 owner: T::AccountId,
1210 new_owner: T::AccountId,1316 new_owner: T::AccountId,
1211 ) -> DispatchResult {1317 ) -> DispatchResult {
1212
1213 ensure!(1318 ensure!(
1214 <FungibleItemList<T>>::contains_key(collection_id, item_id),1319 <FungibleItemList<T>>::contains_key(collection_id, item_id),
1215 "Item not exists"1320 "Item not exists"
1299 owner: T::AccountId,1404 owner: T::AccountId,
1300 new_owner: T::AccountId,1405 new_owner: T::AccountId,
1301 ) -> DispatchResult {1406 ) -> DispatchResult {
1302
1303 ensure!(1407 ensure!(
1304 <ReFungibleItemList<T>>::contains_key(collection_id, item_id),1408 <ReFungibleItemList<T>>::contains_key(collection_id, item_id),
1305 "Item not exists"1409 "Item not exists"
1385 sender: T::AccountId,1489 sender: T::AccountId,
1386 new_owner: T::AccountId,1490 new_owner: T::AccountId,
1387 ) -> DispatchResult {1491 ) -> DispatchResult {
1388
1389 ensure!(1492 ensure!(
1390 <NftItemList<T>>::contains_key(collection_id, item_id),1493 <NftItemList<T>>::contains_key(collection_id, item_id),
1391 "Item not exists"1494 "Item not exists"
1422 Ok(())1525 Ok(())
1423 }1526 }
14241527
1425 fn init_collection(item: &CollectionType<T::AccountId>){1528 fn init_collection(item: &CollectionType<T::AccountId>) {
1529 // check params
1530 assert!(
1531 item.decimal_points <= 4,
1532 "decimal_points parameter must be lower than 4"
1533 );
1534 assert!(
1535 item.name.len() <= 64,
1536 "Collection name can not be longer than 63 char"
1537 );
1538 assert!(
1539 item.name.len() <= 256,
1540 "Collection description can not be longer than 255 char"
1541 );
1542 assert!(
1543 item.token_prefix.len() <= 16,
1544 "Token prefix can not be longer than 15 char"
1545 );
14261546
1427 // check params1547 // Generate next collection ID
1428 assert!(item.decimal_points <= 4, "decimal_points parameter must be lower than 4");
1429 assert!(item.name.len() <= 64, "Collection name can not be longer than 63 char");
1430 assert!(item.name.len() <= 256, "Collection description can not be longer than 255 char");
1431 assert!(item.token_prefix.len() <= 16, "Token prefix can not be longer than 15 char");
1432
1433 // Generate next collection ID
1434 let next_id = CreatedCollectionCount::get()1548 let next_id = CreatedCollectionCount::get()
1435 .checked_add(1)1549 .checked_add(1)
1436 .expect("collection id error");1550 .expect("collection id error");
1437 1551
1438 CreatedCollectionCount::put(next_id); 1552 CreatedCollectionCount::put(next_id);
1439 }1553 }
14401554
1441 fn init_nft_token(item: &NftItemType<T::AccountId>){1555 fn init_nft_token(item: &NftItemType<T::AccountId>) {
1442
1443 let current_index = <ItemListIndex>::get(item.collection)1556 let current_index = <ItemListIndex>::get(item.collection)
1444 .checked_add(1)1557 .checked_add(1)
1457 <Balance<T>>::insert(collection_id, item_owner.clone(), new_balance);1570 <Balance<T>>::insert(collection_id, item_owner.clone(), new_balance);
1458 }1571 }
14591572
1460 fn init_fungible_token(item: &FungibleItemType<T::AccountId>){1573 fn init_fungible_token(item: &FungibleItemType<T::AccountId>) {
1461
1462 let current_index = <ItemListIndex>::get(item.collection)1574 let current_index = <ItemListIndex>::get(item.collection)
1463 .checked_add(1)1575 .checked_add(1)
1476 <Balance<T>>::insert(item.collection, owner.clone(), new_balance);1588 <Balance<T>>::insert(item.collection, owner.clone(), new_balance);
1477 }1589 }
14781590
1479 fn init_refungible_token(item: &ReFungibleItemType<T::AccountId>){1591 fn init_refungible_token(item: &ReFungibleItemType<T::AccountId>) {
1480
1481 let current_index = <ItemListIndex>::get(item.collection)1592 let current_index = <ItemListIndex>::get(item.collection)
1482 .checked_add(1)1593 .checked_add(1)
1497 }1608 }
14981609
1499 fn add_token_index(collection_id: u64, item_index: u64, owner: T::AccountId) -> DispatchResult {1610 fn add_token_index(collection_id: u64, item_index: u64, owner: T::AccountId) -> DispatchResult {
1611
1612 // add to account limit
1613 if <AccountItemCount<T>>::contains_key(owner.clone()) {
1614
1615 // bound Owned tokens by a single address
1616 let count = <AccountItemCount<T>>::get(owner.clone());
1617 ensure!(count < ChainLimit::get().account_token_ownership_limit, "Owned tokens by a single address bound exceeded");
1618
1619 <AccountItemCount<T>>::insert(owner.clone(),
1620 count.checked_add(1).unwrap());
1621 }
1622 else {
1623 <AccountItemCount<T>>::insert(owner.clone(), 1);
1624 }
1625
1500 let list_exists = <AddressTokens<T>>::contains_key(collection_id, owner.clone());1626 let list_exists = <AddressTokens<T>>::contains_key(collection_id, owner.clone());
1501 if list_exists {1627 if list_exists {
1502 let mut list = <AddressTokens<T>>::get(collection_id, owner.clone());1628 let mut list = <AddressTokens<T>>::get(collection_id, owner.clone());
1511 let mut itm = Vec::new();1637 let mut itm = Vec::new();
1512 itm.push(item_index.clone());1638 itm.push(item_index.clone());
1513 <AddressTokens<T>>::insert(collection_id, owner, itm);1639 <AddressTokens<T>>::insert(collection_id, owner, itm);
1640
1514 }1641 }
15151642
1516 Ok(())1643 Ok(())
1521 item_index: u64,1648 item_index: u64,
1522 owner: T::AccountId,1649 owner: T::AccountId,
1523 ) -> DispatchResult {1650 ) -> DispatchResult {
1651
1652 // update counter
1653 <AccountItemCount<T>>::insert(owner.clone(),
1654 <AccountItemCount<T>>::get(owner.clone()).checked_sub(1).unwrap());
1655
1656
1524 let list_exists = <AddressTokens<T>>::contains_key(collection_id, owner.clone());1657 let list_exists = <AddressTokens<T>>::contains_key(collection_id, owner.clone());
1525 if list_exists {1658 if list_exists {
1526 let mut list = <AddressTokens<T>>::get(collection_id, owner.clone());1659 let mut list = <AddressTokens<T>>::get(collection_id, owner.clone());
1628 <Collection<T>>::get(collection_id).sponsor1761 <Collection<T>>::get(collection_id).sponsor
1629 }1762 }
1630 Some(Call::transfer(_new_owner, collection_id, _item_id, _value)) => {1763 Some(Call::transfer(_new_owner, collection_id, _item_id, _value)) => {
1631 <Collection<T>>::get(collection_id).sponsor1764 let _collection_mode = <Collection<T>>::get(collection_id).mode;
1765
1766 // sponsor timeout
1767 let sponsor_transfer = match _collection_mode {
1768 CollectionMode::NFT(_) => {
1769 let basket = <NftTransferBasket<T>>::get(collection_id, _item_id);
1770 let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
1771 let limit_time = basket + ChainLimit::get().nft_sponsor_transfer_timeout.into();
1772 if block_number >= limit_time {
1773 <NftTransferBasket<T>>::insert(collection_id, _item_id, block_number);
1774 true
1775 }
1776 else {
1777 false
1778 }
1779 }
1780 CollectionMode::Fungible(_) => {
1781 let mut basket = <FungibleTransferBasket<T>>::get(collection_id, _item_id);
1782 let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
1783 if basket.iter().any(|i| i.address == _new_owner.clone())
1784 {
1785 let item = basket.iter_mut().find(|i| i.address == _new_owner.clone()).unwrap().clone();
1786 let limit_time = item.start_block + ChainLimit::get().fungible_sponsor_transfer_timeout.into();
1787 if block_number >= limit_time {
1788 basket.retain(|x| x.address == item.address);
1789 basket.push(BasketItem { start_block: block_number, address: _new_owner.clone() });
1790 <FungibleTransferBasket<T>>::insert(collection_id, _item_id, basket);
1791 true
1792 }
1793 else {
1794 false
1795 }
1796 }
1797 else {
1798 basket.push(BasketItem { start_block: block_number, address: _new_owner.clone()});
1799 true
1800 }
1801 }
1802 CollectionMode::ReFungible(_, _) => {
1803 let basket = <ReFungibleTransferBasket<T>>::get(collection_id, _item_id);
1804 let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
1805 let limit_time = basket + ChainLimit::get().nft_sponsor_transfer_timeout.into();
1806 if block_number >= limit_time {
1807 <ReFungibleTransferBasket<T>>::insert(collection_id, _item_id, block_number);
1808 true
1809 } else {
1810 false
1811 }
1812 }
1813 _ => {
1814 false
1815 },
1816 };
1817
1818 if !sponsor_transfer {
1819 T::AccountId::default()
1820 } else {
1821 <Collection<T>>::get(collection_id).sponsor
1822 }
1632 }1823 }
16331824
1634 _ => T::AccountId::default(),1825 _ => T::AccountId::default(),
1745 Ok(())1936 Ok(())
1746 }1937 }
1747}1938}
1748// #endregion1939// #endregion
1940
modifiedpallets/nft/src/mock.rsdiffbeforeafterboth
--- a/pallets/nft/src/mock.rs
+++ b/pallets/nft/src/mock.rs
@@ -65,6 +65,7 @@
 }
 pub type TemplateModule = Module<Test>;
 
+
 // This function basically just builds a genesis storage key/value store according to
 // our desired mockup.
 pub fn new_test_ext() -> sp_io::TestExternalities {
modifiedpallets/nft/src/tests.rsdiffbeforeafterboth
--- a/pallets/nft/src/tests.rs
+++ b/pallets/nft/src/tests.rs
@@ -1,7 +1,8 @@
 // Tests to be written here
 use crate::mock::*;
-use crate::{ApprovePermissions, CollectionMode, AccessMode, Ownership};
+use crate::{AccessMode, ApprovePermissions, CollectionMode, Ownership, ChainLimits};
 use frame_support::{assert_noop, assert_ok};
+use frame_system::{ RawOrigin };
 
 // Use cases tests region
 // #region
@@ -13,6 +14,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -41,6 +52,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::ReFungible(2000, 3);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -79,6 +100,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::Fungible(3);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -109,6 +140,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::Fungible(3);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
         assert_ok!(TemplateModule::create_collection(
@@ -167,6 +208,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::ReFungible(2000, 3);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
         assert_ok!(TemplateModule::create_collection(
@@ -264,6 +315,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -302,6 +363,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
         assert_ok!(TemplateModule::create_collection(
@@ -323,8 +394,16 @@
         assert_eq!(TemplateModule::balance_count(1, 1), 1);
         assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
 
-        assert_ok!(TemplateModule::set_mint_permission(origin1.clone(), 1, true));
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
+        assert_ok!(TemplateModule::set_mint_permission(
+            origin1.clone(),
+            1,
+            true
+        ));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));
@@ -362,6 +441,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::ReFungible(2000, 3);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
         assert_ok!(TemplateModule::create_collection(
@@ -393,8 +482,16 @@
         assert_eq!(TemplateModule::balance_count(1, 1), 1000);
         assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
 
-        assert_ok!(TemplateModule::set_mint_permission(origin1.clone(), 1, true));
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
+        assert_ok!(TemplateModule::set_mint_permission(
+            origin1.clone(),
+            1,
+            true
+        ));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));
@@ -444,6 +541,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::Fungible(3);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
         assert_ok!(TemplateModule::create_collection(
@@ -465,8 +572,16 @@
         assert_eq!(TemplateModule::balance_count(1, 1), 1000);
         assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
 
-        assert_ok!(TemplateModule::set_mint_permission(origin1.clone(), 1, true));
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
+        assert_ok!(TemplateModule::set_mint_permission(
+            origin1.clone(),
+            1,
+            true
+        ));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));
@@ -532,6 +647,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -557,6 +682,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -577,6 +712,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -617,6 +762,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::Fungible(3);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -655,6 +810,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::ReFungible(200, 3);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
         assert_ok!(TemplateModule::create_collection(
@@ -664,9 +829,17 @@
             token_prefix1.clone(),
             mode
         ));
-        
-        assert_ok!(TemplateModule::set_mint_permission(origin1.clone(), 1, true));
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
+
+        assert_ok!(TemplateModule::set_mint_permission(
+            origin1.clone(),
+            1,
+            true
+        ));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));
 
         assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));
@@ -704,6 +877,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
         let origin3 = Origin::signed(3);
@@ -754,6 +937,16 @@
         let origin2 = Origin::signed(2);
         let origin3 = Origin::signed(3);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -809,6 +1002,16 @@
 
         let origin1 = Origin::signed(1);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -881,6 +1084,16 @@
         let nft_mode: CollectionMode = CollectionMode::NFT(2000);
         let origin1 = Origin::signed(1);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -915,6 +1128,16 @@
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -937,8 +1160,16 @@
         assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));
         assert_eq!(TemplateModule::approved(1, (1, 1))[0].approved, 2);
 
-        assert_ok!(TemplateModule::set_mint_permission(origin1.clone(), 1, true));
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
+        assert_ok!(TemplateModule::set_mint_permission(
+            origin1.clone(),
+            1,
+            true
+        ));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));
@@ -972,6 +1203,16 @@
         let mode: CollectionMode = CollectionMode::NFT(2000);
         let origin1 = Origin::signed(1);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -995,6 +1236,16 @@
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -1019,6 +1270,16 @@
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -1027,16 +1288,32 @@
             mode
         ));
 
-        assert_noop!(TemplateModule::add_to_white_list(origin2.clone(), 1, 3), "You do not have permissions to modify this collection");
+        assert_noop!(
+            TemplateModule::add_to_white_list(origin2.clone(), 1, 3),
+            "You do not have permissions to modify this collection"
+        );
     });
 }
 
 #[test]
 fn nobody_can_add_address_to_white_list_of_nonexisting_collection() {
     new_test_ext().execute_with(|| {
+        let origin1 = Origin::signed(1);
+
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
 
-        let origin1 = Origin::signed(1);
-        assert_noop!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2), "This collection does not exist");
+        assert_noop!(
+            TemplateModule::add_to_white_list(origin1.clone(), 1, 2),
+            "This collection does not exist"
+        );
     });
 }
 
@@ -1049,6 +1326,16 @@
         let mode: CollectionMode = CollectionMode::NFT(2000);
         let origin1 = Origin::signed(1);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -1058,7 +1345,10 @@
         ));
 
         assert_ok!(TemplateModule::destroy_collection(origin1.clone(), 1));
-        assert_noop!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2), "This collection does not exist");
+        assert_noop!(
+            TemplateModule::add_to_white_list(origin1.clone(), 1, 2),
+            "This collection does not exist"
+        );
     });
 }
 
@@ -1066,13 +1356,22 @@
 #[test]
 fn address_is_already_added_to_white_list() {
     new_test_ext().execute_with(|| {
-
         let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
         let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
         let origin1 = Origin::signed(1);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -1091,13 +1390,22 @@
 #[test]
 fn owner_can_remove_address_from_white_list() {
     new_test_ext().execute_with(|| {
-        
         let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
         let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
         let origin1 = Origin::signed(1);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -1107,7 +1415,11 @@
         ));
 
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
-        assert_ok!(TemplateModule::remove_from_white_list(origin1.clone(), 1, 2));
+        assert_ok!(TemplateModule::remove_from_white_list(
+            origin1.clone(),
+            1,
+            2
+        ));
         assert_eq!(TemplateModule::white_list(1).len(), 0);
     });
 }
@@ -1115,7 +1427,6 @@
 #[test]
 fn admin_can_remove_address_from_white_list() {
     new_test_ext().execute_with(|| {
-
         let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
         let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
@@ -1123,6 +1434,16 @@
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -1134,7 +1455,11 @@
         assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));
 
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));
-        assert_ok!(TemplateModule::remove_from_white_list(origin2.clone(), 1, 3));
+        assert_ok!(TemplateModule::remove_from_white_list(
+            origin2.clone(),
+            1,
+            3
+        ));
         assert_eq!(TemplateModule::white_list(1).len(), 0);
     });
 }
@@ -1142,7 +1467,6 @@
 #[test]
 fn nonprivileged_user_cannot_remove_address_from_white_list() {
     new_test_ext().execute_with(|| {
-
         let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
         let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
@@ -1150,6 +1474,16 @@
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -1159,7 +1493,10 @@
         ));
 
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
-        assert_noop!(TemplateModule::remove_from_white_list(origin2.clone(), 1, 2), "You do not have permissions to modify this collection");
+        assert_noop!(
+            TemplateModule::remove_from_white_list(origin2.clone(), 1, 2),
+            "You do not have permissions to modify this collection"
+        );
         assert_eq!(TemplateModule::white_list(1)[0], 2);
     });
 }
@@ -1167,16 +1504,28 @@
 #[test]
 fn nobody_can_remove_address_from_white_list_of_nonexisting_collection() {
     new_test_ext().execute_with(|| {
+        let origin1 = Origin::signed(1);
+
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
 
-        let origin1 = Origin::signed(1);
-        assert_noop!(TemplateModule::remove_from_white_list(origin1.clone(), 1, 2), "This collection does not exist");
+        assert_noop!(
+            TemplateModule::remove_from_white_list(origin1.clone(), 1, 2),
+            "This collection does not exist"
+        );
     });
 }
 
 #[test]
 fn nobody_can_remove_address_from_white_list_of_deleted_collection() {
     new_test_ext().execute_with(|| {
-
         let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
         let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
@@ -1184,6 +1533,16 @@
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -1194,7 +1553,10 @@
 
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
         assert_ok!(TemplateModule::destroy_collection(origin1.clone(), 1));
-        assert_noop!(TemplateModule::remove_from_white_list(origin2.clone(), 1, 2), "This collection does not exist");
+        assert_noop!(
+            TemplateModule::remove_from_white_list(origin2.clone(), 1, 2),
+            "This collection does not exist"
+        );
         assert_eq!(TemplateModule::white_list(1).len(), 0);
     });
 }
@@ -1209,6 +1571,16 @@
         let mode: CollectionMode = CollectionMode::NFT(2000);
         let origin1 = Origin::signed(1);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
             col_name1.clone(),
@@ -1218,8 +1590,16 @@
         ));
 
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
-        assert_ok!(TemplateModule::remove_from_white_list(origin1.clone(), 1, 2));
-        assert_ok!(TemplateModule::remove_from_white_list(origin1.clone(), 1, 2));
+        assert_ok!(TemplateModule::remove_from_white_list(
+            origin1.clone(),
+            1,
+            2
+        ));
+        assert_ok!(TemplateModule::remove_from_white_list(
+            origin1.clone(),
+            1,
+            2
+        ));
         assert_eq!(TemplateModule::white_list(1).len(), 0);
     });
 }
@@ -1233,6 +1613,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -1250,16 +1640,17 @@
             1
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
-        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
-
-        assert_noop!(TemplateModule::transfer(
+        assert_ok!(TemplateModule::set_public_access_mode(
             origin1.clone(),
-            3,
             1,
-            1,
-            1
-        ), "Address is not in white list");
+            AccessMode::WhiteList
+        ));
+        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
+
+        assert_noop!(
+            TemplateModule::transfer(origin1.clone(), 3, 1, 1, 1),
+            "Address is not in white list"
+        );
     });
 }
 
@@ -1271,6 +1662,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -1288,24 +1689,28 @@
             1
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
 
         // do approve
         assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1));
         assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);
-
-        assert_ok!(TemplateModule::remove_from_white_list(origin1.clone(), 1, 1));
 
-        assert_noop!(TemplateModule::transfer_from(
+        assert_ok!(TemplateModule::remove_from_white_list(
             origin1.clone(),
-            1,
-            3,
             1,
-            1,
             1
-        ), "Address is not in white list");
+        ));
+
+        assert_noop!(
+            TemplateModule::transfer_from(origin1.clone(), 1, 3, 1, 1, 1),
+            "Address is not in white list"
+        );
     });
 }
 
@@ -1318,6 +1723,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -1335,16 +1750,17 @@
             1
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
-        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));
-
-        assert_noop!(TemplateModule::transfer(
+        assert_ok!(TemplateModule::set_public_access_mode(
             origin1.clone(),
-            3,
             1,
-            1,
-            1
-        ), "Address is not in white list");
+            AccessMode::WhiteList
+        ));
+        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));
+
+        assert_noop!(
+            TemplateModule::transfer(origin1.clone(), 3, 1, 1, 1),
+            "Address is not in white list"
+        );
     });
 }
 
@@ -1356,6 +1772,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -1373,7 +1799,11 @@
             1
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
 
@@ -1381,16 +1811,16 @@
         assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1));
         assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);
 
-        assert_ok!(TemplateModule::remove_from_white_list(origin1.clone(), 1, 2));
-
-        assert_noop!(TemplateModule::transfer_from(
+        assert_ok!(TemplateModule::remove_from_white_list(
             origin1.clone(),
-            1,
-            3,
             1,
-            1,
-            1
-        ), "Address is not in white list");
+            2
+        ));
+
+        assert_noop!(
+            TemplateModule::transfer_from(origin1.clone(), 1, 3, 1, 1, 1),
+            "Address is not in white list"
+        );
     });
 }
 
@@ -1403,6 +1833,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -1420,8 +1860,15 @@
             1
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
-        assert_noop!(TemplateModule::burn_item(origin1.clone(), 1, 1), "Address is not in white list");
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
+        assert_noop!(
+            TemplateModule::burn_item(origin1.clone(), 1, 1),
+            "Address is not in white list"
+        );
     });
 }
 
@@ -1434,6 +1881,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -1442,10 +1899,17 @@
             token_prefix1.clone(),
             mode
         ));
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
 
         // do approve
-        assert_noop!(TemplateModule::approve(origin1.clone(), 1, 1, 1), "Address is not in white list");
+        assert_noop!(
+            TemplateModule::approve(origin1.clone(), 1, 1, 1),
+            "Address is not in white list"
+        );
     });
 }
 
@@ -1459,6 +1923,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -1476,17 +1950,15 @@
             1
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
 
-        assert_ok!(TemplateModule::transfer(
-            origin1.clone(),
-            2,
-            1,
-            1,
-            1
-        ));
+        assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1));
     });
 }
 
@@ -1498,6 +1970,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -1515,7 +1997,11 @@
             1
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
 
@@ -1543,6 +2029,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -1552,8 +2048,16 @@
             mode
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
-        assert_ok!(TemplateModule::set_mint_permission(origin1.clone(), 1, false));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
+        assert_ok!(TemplateModule::set_mint_permission(
+            origin1.clone(),
+            1,
+            false
+        ));
 
         assert_ok!(TemplateModule::create_item(
             origin1.clone(),
@@ -1573,6 +2077,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
         assert_ok!(TemplateModule::create_collection(
@@ -1583,8 +2097,16 @@
             mode
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
-        assert_ok!(TemplateModule::set_mint_permission(origin1.clone(), 1, false));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
+        assert_ok!(TemplateModule::set_mint_permission(
+            origin1.clone(),
+            1,
+            false
+        ));
 
         assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));
 
@@ -1606,6 +2128,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
         assert_ok!(TemplateModule::create_collection(
@@ -1616,16 +2148,22 @@
             mode
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
-        assert_ok!(TemplateModule::set_mint_permission(origin1.clone(), 1, false));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
+        assert_ok!(TemplateModule::set_mint_permission(
+            origin1.clone(),
+            1,
+            false
+        ));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
 
-        assert_noop!(TemplateModule::create_item(
-            origin2.clone(),
-            1,
-            [1, 2, 3].to_vec(),
-            2
-        ), "Collection is not in mint mode");
+        assert_noop!(
+            TemplateModule::create_item(origin2.clone(), 1, [1, 2, 3].to_vec(), 2),
+            "Collection is not in mint mode"
+        );
     });
 }
 
@@ -1638,6 +2176,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
         assert_ok!(TemplateModule::create_collection(
@@ -1648,15 +2196,21 @@
             mode
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
-        assert_ok!(TemplateModule::set_mint_permission(origin1.clone(), 1, false));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
+        assert_ok!(TemplateModule::set_mint_permission(
+            origin1.clone(),
+            1,
+            false
+        ));
 
-        assert_noop!(TemplateModule::create_item(
-            origin2.clone(),
-            1,
-            [1, 2, 3].to_vec(),
-            2
-        ), "Collection is not in mint mode");
+        assert_noop!(
+            TemplateModule::create_item(origin2.clone(), 1, [1, 2, 3].to_vec(), 2),
+            "Collection is not in mint mode"
+        );
     });
 }
 
@@ -1669,6 +2223,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         assert_ok!(TemplateModule::create_collection(
             origin1.clone(),
@@ -1678,8 +2242,16 @@
             mode
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
-        assert_ok!(TemplateModule::set_mint_permission(origin1.clone(), 1, true));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
+        assert_ok!(TemplateModule::set_mint_permission(
+            origin1.clone(),
+            1,
+            true
+        ));
 
         assert_ok!(TemplateModule::create_item(
             origin1.clone(),
@@ -1699,6 +2271,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
         assert_ok!(TemplateModule::create_collection(
@@ -1709,8 +2291,16 @@
             mode
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
-        assert_ok!(TemplateModule::set_mint_permission(origin1.clone(), 1, true));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
+        assert_ok!(TemplateModule::set_mint_permission(
+            origin1.clone(),
+            1,
+            true
+        ));
 
         assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));
 
@@ -1732,6 +2322,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
         assert_ok!(TemplateModule::create_collection(
@@ -1742,15 +2342,21 @@
             mode
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
-        assert_ok!(TemplateModule::set_mint_permission(origin1.clone(), 1, true));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
+        assert_ok!(TemplateModule::set_mint_permission(
+            origin1.clone(),
+            1,
+            true
+        ));
 
-        assert_noop!(TemplateModule::create_item(
-            origin2.clone(),
-            1,
-            [1, 2, 3].to_vec(),
-            2
-        ), "Address is not in white list");
+        assert_noop!(
+            TemplateModule::create_item(origin2.clone(), 1, [1, 2, 3].to_vec(), 2),
+            "Address is not in white list"
+        );
     });
 }
 
@@ -1763,6 +2369,16 @@
         let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
         let mode: CollectionMode = CollectionMode::NFT(2000);
 
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
         let origin1 = Origin::signed(1);
         let origin2 = Origin::signed(2);
         assert_ok!(TemplateModule::create_collection(
@@ -1773,8 +2389,16 @@
             mode
         ));
 
-        assert_ok!(TemplateModule::set_public_access_mode(origin1.clone(), 1, AccessMode::WhiteList));
-        assert_ok!(TemplateModule::set_mint_permission(origin1.clone(), 1, true));
+        assert_ok!(TemplateModule::set_public_access_mode(
+            origin1.clone(),
+            1,
+            AccessMode::WhiteList
+        ));
+        assert_ok!(TemplateModule::set_mint_permission(
+            origin1.clone(),
+            1,
+            true
+        ));
         assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));
 
         assert_ok!(TemplateModule::create_item(
@@ -1786,4 +2410,290 @@
     });
 }
 
-// #endregion
\ No newline at end of file
+// Total number of collections. Positive test
+#[test]
+fn total_number_collections_bound() {
+    new_test_ext().execute_with(|| {
+        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+        let mode: CollectionMode = CollectionMode::NFT(2000);
+
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
+        let origin1 = Origin::signed(1);
+        assert_ok!(TemplateModule::create_collection(
+            origin1.clone(),
+            col_name1.clone(),
+            col_desc1.clone(),
+            token_prefix1.clone(),
+            mode
+        ));
+    });
+}
+
+// Total number of collections. Negotive test
+#[test]
+fn total_number_collections_bound_neg() {
+    new_test_ext().execute_with(|| {
+        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+        let mode: CollectionMode = CollectionMode::NFT(2000);
+
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
+        let origin1 = Origin::signed(1);
+
+        for _ in 0..10 {
+
+            assert_ok!(TemplateModule::create_collection(
+                origin1.clone(),
+                col_name1.clone(),
+                col_desc1.clone(),
+                token_prefix1.clone(),
+                mode.clone()
+            ));
+        }
+
+        // 11-th collection in chain. Expects error
+        assert_noop!(TemplateModule::create_collection(
+            origin1.clone(),
+            col_name1.clone(),
+            col_desc1.clone(),
+            token_prefix1.clone(),
+            mode.clone()
+        ), "Total collections bound exceeded");
+    });
+}
+
+// Owned tokens by a single address. Positive test
+#[test]
+fn owned_tokens_bound() {
+    new_test_ext().execute_with(|| {
+        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+        let mode: CollectionMode = CollectionMode::NFT(2000);
+
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
+        let origin1 = Origin::signed(1);
+        assert_ok!(TemplateModule::create_collection(
+            origin1.clone(),
+            col_name1.clone(),
+            col_desc1.clone(),
+            token_prefix1.clone(),
+            mode
+        ));
+
+        assert_ok!(TemplateModule::create_item(
+            origin1.clone(),
+            1,
+            [1, 2, 3].to_vec(),
+            1
+        ));
+
+        assert_ok!(TemplateModule::create_item(
+            origin1.clone(),
+            1,
+            [1, 2, 3].to_vec(),
+            1
+        ));
+    });
+}
+
+// Owned tokens by a single address. Negotive test
+#[test]
+fn owned_tokens_bound_neg() {
+    new_test_ext().execute_with(|| {
+        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+        let mode: CollectionMode = CollectionMode::NFT(2000);
+
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 1,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
+        let origin1 = Origin::signed(1);
+        assert_ok!(TemplateModule::create_collection(
+            origin1.clone(),
+            col_name1.clone(),
+            col_desc1.clone(),
+            token_prefix1.clone(),
+            mode
+        ));
+
+        assert_ok!(TemplateModule::create_item(
+            origin1.clone(),
+            1,
+            [1, 2, 3].to_vec(),
+            1
+        ));
+
+        assert_noop!(TemplateModule::create_item(
+            origin1.clone(),
+            1,
+            [1, 2, 3].to_vec(),
+            1
+        ), "Owned tokens by a single address bound exceeded");
+    });
+}
+
+// Number of collection admins. Positive test
+#[test]
+fn collection_admins_bound() {
+    new_test_ext().execute_with(|| {
+        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+        let mode: CollectionMode = CollectionMode::NFT(2000);
+
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 2,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
+        let origin1 = Origin::signed(1);
+        assert_ok!(TemplateModule::create_collection(
+            origin1.clone(),
+            col_name1.clone(),
+            col_desc1.clone(),
+            token_prefix1.clone(),
+            mode
+        ));
+
+        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));
+        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 3));
+    });
+}
+
+// Number of collection admins. Negotive test
+#[test]
+fn collection_admins_bound_neg() {
+    new_test_ext().execute_with(|| {
+        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+        let mode: CollectionMode = CollectionMode::NFT(2000);
+
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 1,
+            collections_admins_limit: 1,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
+        let origin1 = Origin::signed(1);
+        assert_ok!(TemplateModule::create_collection(
+            origin1.clone(),
+            col_name1.clone(),
+            col_desc1.clone(),
+            token_prefix1.clone(),
+            mode
+        ));
+
+        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));
+        assert_noop!(TemplateModule::add_collection_admin(origin1.clone(), 1, 3), "Number of collection admins bound exceeded");
+    });
+}
+
+// Custom data size. Positive test
+#[test]
+fn custom_data_size_bound() {
+    new_test_ext().execute_with(|| {
+        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+        let mode: CollectionMode = CollectionMode::NFT(2000);
+
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 2048,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
+        let origin1 = Origin::signed(1);
+        assert_ok!(TemplateModule::create_collection(
+            origin1.clone(),
+            col_name1.clone(),
+            col_desc1.clone(),
+            token_prefix1.clone(),
+            mode
+        ));
+    });
+}
+
+// Custom data size. Negotive test
+#[test]
+fn custom_data_size_bound_neg() {
+    new_test_ext().execute_with(|| {
+        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+        let mode: CollectionMode = CollectionMode::NFT(2000);
+
+        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 
+            collection_numbers_limit: 10,
+            account_token_ownership_limit: 10,
+            collections_admins_limit: 5,
+            custom_data_limit: 200,
+            nft_sponsor_transfer_timeout: 15,
+            fungible_sponsor_transfer_timeout: 15,
+            refungible_sponsor_transfer_timeout: 15,          
+        }));
+
+        let origin1 = Origin::signed(1);
+        assert_noop!(TemplateModule::create_collection(
+            origin1.clone(),
+            col_name1.clone(),
+            col_desc1.clone(),
+            token_prefix1.clone(),
+            mode
+        ), "Custom data size bound exceeded");
+    });
+}
+// #endregion