From 0b7086fb4c87b416475f4e5289e7b9a83d6b82c6 Mon Sep 17 00:00:00 2001 From: kozyrevdev <73348153+kozyrevdev@users.noreply.github.com> Date: Thu, 26 Aug 2021 11:20:42 +0000 Subject: [PATCH] Merge pull request #179 from UniqueNetwork/fix/update-contracts-intergration Fix contracts intergration --- --- a/Cargo.lock +++ b/Cargo.lock @@ -4935,12 +4935,15 @@ name = "nft-data-structs" version = "0.9.0" dependencies = [ + "derivative", "frame-support", "frame-system", + "max-encoded-len", "parity-scale-codec", "serde", "sp-core", "sp-runtime", + "sp-std", ] [[package]] @@ -4999,6 +5002,7 @@ "cumulus-primitives-core", "cumulus-primitives-timestamp", "cumulus-primitives-utility", + "derivative", "fp-rpc", "frame-benchmarking", "frame-executive", @@ -5007,6 +5011,7 @@ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "hex-literal", + "max-encoded-len", "nft-data-structs", "pallet-aura", "pallet-balances", --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -202,18 +202,6 @@ nft_item_id: vec![], fungible_item_id: vec![], refungible_item_id: vec![], - chain_limit: ChainLimits { - collection_numbers_limit: 100000, - account_token_ownership_limit: 1000000, - collections_admins_limit: 5, - custom_data_limit: 2048, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - const_on_chain_schema_limit: 1024, - }, }, parachain_info: nft_runtime::ParachainInfoConfig { parachain_id: id }, aura: nft_runtime::AuraConfig { --- a/pallets/nft/Cargo.toml +++ b/pallets/nft/Cargo.toml @@ -41,6 +41,7 @@ 'evm-coder/std', 'pallet-evm-coder-substrate/std', ] +limit-testing = ["nft-data-structs/limit-testing"] ################################################################################ # Substrate Dependencies --- a/pallets/nft/src/default_weights.rs +++ b/pallets/nft/src/default_weights.rs @@ -117,11 +117,6 @@ .saturating_add(DbWeight::get().reads(2_u64)) .saturating_add(DbWeight::get().writes(1_u64)) } - fn set_chain_limits() -> Weight { - 1_300_000_u64 - .saturating_add(DbWeight::get().reads(0_u64)) - .saturating_add(DbWeight::get().writes(1_u64)) - } fn set_contract_sponsoring_rate_limit() -> Weight { 3_500_000_u64 .saturating_add(DbWeight::get().reads(0_u64)) --- a/pallets/nft/src/eth/sponsoring.rs +++ b/pallets/nft/src/eth/sponsoring.rs @@ -1,12 +1,12 @@ //! Implements EVM sponsoring logic via OnChargeEVMTransaction use crate::{ - ChainLimit, Collection, CollectionById, Config, FungibleTransferBasket, NftTransferBasket, + Collection, CollectionById, Config, FungibleTransferBasket, NftTransferBasket, eth::{account::EvmBackwardsAddressMapping, map_eth_to_id}, }; use evm_coder::{Call, abi::AbiReader}; use frame_support::{ - storage::{StorageMap, StorageDoubleMap, StorageValue}, + storage::{StorageMap, StorageDoubleMap}, }; use sp_core::H160; use sp_std::prelude::*; @@ -17,6 +17,7 @@ }; use core::convert::TryInto; use core::marker::PhantomData; +use nft_data_structs::{NFT_SPONSOR_TRANSFER_TIMEOUT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT}; struct AnyError; @@ -43,7 +44,7 @@ let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { collection_limits.sponsor_transfer_timeout } else { - ChainLimit::get().nft_sponsor_transfer_timeout + NFT_SPONSOR_TRANSFER_TIMEOUT }; let mut sponsor = true; @@ -74,7 +75,7 @@ let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { collection_limits.sponsor_transfer_timeout } else { - ChainLimit::get().fungible_sponsor_transfer_timeout + FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT }; let block_number = >::block_number() as T::BlockNumber; --- a/pallets/nft/src/lib.rs +++ b/pallets/nft/src/lib.rs @@ -31,14 +31,16 @@ StorageValue, transactional, }; -use frame_system::{self as system, ensure_signed, ensure_root}; +use frame_system::{self as system, ensure_signed}; use sp_core::H160; use sp_std::vec; use sp_runtime::sp_std::prelude::Vec; use core::ops::{Deref, DerefMut}; use nft_data_structs::{ MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, MAX_REFUNGIBLE_PIECES, - AccessMode, ChainLimits, Collection, CreateItemData, CollectionLimits, CollectionId, + CUSTOM_DATA_LIMIT, COLLECTION_NUMBER_LIMIT, ACCOUNT_TOKEN_OWNERSHIP_LIMIT, + VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, COLLECTION_ADMINS_LIMIT, + OFFCHAIN_SCHEMA_LIMIT, AccessMode, Collection, CreateItemData, CollectionLimits, CollectionId, CollectionMode, TokenId, SchemaVersion, SponsorshipState, Ownership, NftItemType, FungibleItemType, ReFungibleItemType, }; @@ -86,7 +88,6 @@ fn set_variable_meta_data() -> Weight; fn enable_contract_sponsoring() -> Weight; fn set_schema_version() -> Weight; - fn set_chain_limits() -> Weight; fn set_contract_sponsoring_rate_limit() -> Weight; fn set_variable_meta_data_sponsoring_rate_limit() -> Weight; fn toggle_contract_white_list() -> Weight; @@ -278,10 +279,6 @@ /// Id of last collection token /// Collection id (controlled?1) ItemListIndex: map hasher(blake2_128_concat) CollectionId => TokenId; - //#endregion - - //#region Chain limits struct - pub ChainLimit get(fn chain_limit) config(): ChainLimits; //#endregion //#region Bound counters @@ -435,6 +432,7 @@ origin: T::Origin { fn deposit_event() = default; + const CollectionAdminsLimit: u64 = COLLECTION_ADMINS_LIMIT; type Error = Error; fn on_initialize(_now: T::BlockNumber) -> Weight { @@ -485,14 +483,12 @@ CollectionMode::Fungible(points) => points, _ => 0 }; - - let chain_limit = ChainLimit::get(); let created_count = CreatedCollectionCount::get(); let destroyed_count = DestroyedCollectionCount::get(); // bound Total number of collections - ensure!(created_count - destroyed_count < chain_limit.collection_numbers_limit, Error::::TotalCollectionsLimitExceeded); + ensure!(created_count - destroyed_count < COLLECTION_NUMBER_LIMIT, Error::::TotalCollectionsLimitExceeded); // check params ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::::CollectionDecimalPointLimitExceeded); @@ -508,7 +504,7 @@ CreatedCollectionCount::put(next_id); let limits = CollectionLimits { - sponsored_data_size: chain_limit.custom_data_limit, + sponsored_data_size: CUSTOM_DATA_LIMIT, ..Default::default() }; @@ -737,8 +733,7 @@ match admin_arr.binary_search(&new_admin_id) { Ok(_) => {}, Err(idx) => { - let limits = ChainLimit::get(); - ensure!(admin_arr.len() < limits.collections_admins_limit as usize, Error::::CollectionAdminsLimitExceeded); + ensure!(admin_arr.len() < COLLECTION_ADMINS_LIMIT as usize, Error::::CollectionAdminsLimitExceeded); admin_arr.insert(idx, new_admin_id); >::insert(collection_id, admin_arr); } @@ -1138,7 +1133,7 @@ Self::check_owner_or_admin_permissions(&target_collection, &sender)?; // check schema limit - ensure!(schema.len() as u32 <= ChainLimit::get().offchain_schema_limit, ""); + ensure!(schema.len() as u32 <= OFFCHAIN_SCHEMA_LIMIT, ""); target_collection.offchain_schema = schema; target_collection.save() @@ -1168,7 +1163,7 @@ Self::check_owner_or_admin_permissions(&target_collection, &sender)?; // check schema limit - ensure!(schema.len() as u32 <= ChainLimit::get().const_on_chain_schema_limit, ""); + ensure!(schema.len() as u32 <= CONST_ON_CHAIN_SCHEMA_LIMIT, ""); target_collection.const_on_chain_schema = schema; target_collection.save() @@ -1198,25 +1193,10 @@ Self::check_owner_or_admin_permissions(&target_collection, &sender)?; // check schema limit - ensure!(schema.len() as u32 <= ChainLimit::get().variable_on_chain_schema_limit, ""); + ensure!(schema.len() as u32 <= VARIABLE_ON_CHAIN_SCHEMA_LIMIT, ""); target_collection.variable_on_chain_schema = schema; target_collection.save() - } - - // Sudo permissions function - #[weight = ::WeightInfo::set_chain_limits()] - #[transactional] - pub fn set_chain_limits( - origin, - limits: ChainLimits - ) -> DispatchResult { - - #[cfg(not(feature = "runtime-benchmarks"))] - ensure_root(origin)?; - - ::put(limits); - Ok(()) } #[weight = ::WeightInfo::set_collection_limits()] @@ -1230,12 +1210,11 @@ let mut target_collection = Self::get_collection(collection_id)?; Self::check_owner_permissions(&target_collection, sender.as_sub())?; let old_limits = &target_collection.limits; - let chain_limits = ChainLimit::get(); // collection bounds ensure!(new_limits.sponsor_transfer_timeout <= MAX_SPONSOR_TIMEOUT && new_limits.account_token_ownership_limit <= MAX_TOKEN_OWNERSHIP && - new_limits.sponsored_data_size <= chain_limits.custom_data_limit, + new_limits.sponsored_data_size <= CUSTOM_DATA_LIMIT, Error::::CollectionLimitBoundsExceeded); // token_limit check prev @@ -1471,7 +1450,7 @@ Self::token_exists(collection, item_id)?; ensure!( - ChainLimit::get().custom_data_limit >= data.len() as u32, + CUSTOM_DATA_LIMIT >= data.len() as u32, Error::::TokenVariableDataLimitExceeded ); @@ -1616,38 +1595,17 @@ ) -> DispatchResult { match target_collection.mode { CollectionMode::NFT => { - if let CreateItemData::NFT(data) = data { - // check sizes - ensure!( - ChainLimit::get().custom_data_limit >= data.const_data.len() as u32, - Error::::TokenConstDataLimitExceeded - ); - ensure!( - ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32, - Error::::TokenVariableDataLimitExceeded - ); - } else { + if !matches!(data, CreateItemData::NFT(_)) { fail!(Error::::NotNftDataUsedToMintNftCollectionToken); } } CollectionMode::Fungible(_) => { - if let CreateItemData::Fungible(_) = data { - } else { + if !matches!(data, CreateItemData::Fungible(_)) { fail!(Error::::NotFungibleDataUsedToMintFungibleCollectionToken); } } CollectionMode::ReFungible => { if let CreateItemData::ReFungible(data) = data { - // check sizes - ensure!( - ChainLimit::get().custom_data_limit >= data.const_data.len() as u32, - Error::::TokenConstDataLimitExceeded - ); - ensure!( - ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32, - Error::::TokenVariableDataLimitExceeded - ); - // Check refungibility limits ensure!( data.pieces <= MAX_REFUNGIBLE_PIECES, @@ -1675,8 +1633,8 @@ CreateItemData::NFT(data) => { let item = NftItemType { owner: owner.clone(), - const_data: data.const_data, - variable_data: data.variable_data, + const_data: data.const_data.into_inner(), + variable_data: data.variable_data.into_inner(), }; Self::add_nft_item(collection, item)?; @@ -1692,8 +1650,8 @@ let item = ReFungibleItemType { owner: owner_list, - const_data: data.const_data, - variable_data: data.variable_data, + const_data: data.const_data.into_inner(), + variable_data: data.variable_data.into_inner(), }; Self::add_refungible_item(collection, item)?; @@ -2292,7 +2250,7 @@ // bound Owned tokens by a single address let count = >::get(owner.as_sub()); ensure!( - count < ChainLimit::get().account_token_ownership_limit, + count < ACCOUNT_TOKEN_OWNERSHIP_LIMIT, Error::::AddressOwnershipLimitExceeded ); --- a/pallets/nft/src/sponsorship.rs +++ b/pallets/nft/src/sponsorship.rs @@ -1,15 +1,18 @@ use crate::{ Config, Call, CollectionById, CreateItemBasket, VariableMetaDataBasket, - ReFungibleTransferBasket, FungibleTransferBasket, NftTransferBasket, ChainLimit, - CreateItemData, CollectionMode, + ReFungibleTransferBasket, FungibleTransferBasket, NftTransferBasket, CreateItemData, + CollectionMode, }; use core::marker::PhantomData; use up_sponsorship::SponsorshipHandler; use frame_support::{ - traits::IsSubType, - storage::{StorageMap, StorageDoubleMap, StorageValue}, + traits::{IsSubType}, + storage::{StorageMap, StorageDoubleMap}, +}; +use nft_data_structs::{ + TokenId, CollectionId, NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, + FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, }; -use nft_data_structs::{TokenId, CollectionId}; pub struct NftSponsorshipHandler(PhantomData); impl NftSponsorshipHandler { @@ -47,7 +50,6 @@ item_id: &TokenId, ) -> Option { let collection = CollectionById::::get(collection_id)?; - let limits = ChainLimit::get(); let mut sponsor_transfer = false; if collection.sponsorship.confirmed() { @@ -62,7 +64,7 @@ let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { collection_limits.sponsor_transfer_timeout } else { - limits.nft_sponsor_transfer_timeout + NFT_SPONSOR_TRANSFER_TIMEOUT }; let mut sponsored = true; @@ -84,7 +86,7 @@ let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { collection_limits.sponsor_transfer_timeout } else { - limits.fungible_sponsor_transfer_timeout + FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT }; let block_number = >::block_number() as T::BlockNumber; @@ -107,7 +109,7 @@ let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { collection_limits.sponsor_transfer_timeout } else { - limits.refungible_sponsor_transfer_timeout + REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT }; let mut sponsored = true; --- a/pallets/nft/src/tests.rs +++ b/pallets/nft/src/tests.rs @@ -1,40 +1,18 @@ // Tests to be written here use super::*; use crate::mock::*; -use crate::{AccessMode, CollectionMode, Ownership, ChainLimits, CreateItemData}; +use crate::{AccessMode, CollectionMode, Ownership, CreateItemData}; use nft_data_structs::{ CreateNftData, CreateFungibleData, CreateReFungibleData, CollectionId, TokenId, MAX_DECIMAL_POINTS, }; use frame_support::{assert_noop, assert_ok}; -use frame_system::{RawOrigin}; - -fn default_collection_numbers_limit() -> u32 { - 10 -} - -fn default_limits() { - assert_ok!(TemplateModule::set_chain_limits( - RawOrigin::Root.into(), - ChainLimits { - collection_numbers_limit: default_collection_numbers_limit(), - 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, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); -} +use sp_std::convert::TryInto; fn default_nft_data() -> CreateNftData { CreateNftData { - const_data: vec![1, 2, 3], - variable_data: vec![3, 2, 1], + const_data: vec![1, 2, 3].try_into().unwrap(), + variable_data: vec![3, 2, 1].try_into().unwrap(), } } @@ -44,8 +22,8 @@ fn default_re_fungible_data() -> CreateReFungibleData { CreateReFungibleData { - const_data: vec![1, 2, 3], - variable_data: vec![3, 2, 1], + const_data: vec![1, 2, 3].try_into().unwrap(), + variable_data: vec![3, 2, 1].try_into().unwrap(), pieces: 1023, } } @@ -112,7 +90,6 @@ #[test] fn set_version_schema() { new_test_ext().execute_with(|| { - default_limits(); let origin1 = Origin::signed(1); let collection_id = create_test_collection(&CollectionMode::NFT, 1); @@ -133,8 +110,6 @@ #[test] fn create_fungible_collection_fails_with_large_decimal_numbers() { new_test_ext().execute_with(|| { - default_limits(); - let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); let token_prefix1: Vec = b"token_prefix1\0".to_vec(); @@ -156,14 +131,13 @@ #[test] fn create_nft_item() { new_test_ext().execute_with(|| { - default_limits(); let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); create_test_item(collection_id, &data.clone().into()); let item = TemplateModule::nft_item_id(collection_id, 1).unwrap(); - assert_eq!(item.const_data, data.const_data); - assert_eq!(item.variable_data, data.variable_data); + assert_eq!(item.const_data, data.const_data.into_inner()); + assert_eq!(item.variable_data, data.variable_data.into_inner()); }); } @@ -172,8 +146,6 @@ #[test] fn create_nft_multiple_items() { new_test_ext().execute_with(|| { - default_limits(); - create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -190,10 +162,10 @@ .map(|d| { d.into() }) .collect() )); - for (index, data) in items_data.iter().enumerate() { + for (index, data) in items_data.into_iter().enumerate() { let item = TemplateModule::nft_item_id(1, (index + 1) as TokenId).unwrap(); - assert_eq!(item.const_data.to_vec(), data.const_data); - assert_eq!(item.variable_data.to_vec(), data.variable_data); + assert_eq!(item.const_data.to_vec(), data.const_data.into_inner()); + assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner()); } }); } @@ -201,14 +173,13 @@ #[test] fn create_refungible_item() { new_test_ext().execute_with(|| { - default_limits(); let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let data = default_re_fungible_data(); create_test_item(collection_id, &data.clone().into()); let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap(); - assert_eq!(item.const_data, data.const_data); - assert_eq!(item.variable_data, data.variable_data); + assert_eq!(item.const_data, data.const_data.into_inner()); + assert_eq!(item.variable_data, data.variable_data.into_inner()); assert_eq!( item.owner[0], Ownership { @@ -222,8 +193,6 @@ #[test] fn create_multiple_refungible_items() { new_test_ext().execute_with(|| { - default_limits(); - create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); @@ -244,10 +213,10 @@ .map(|d| { d.into() }) .collect() )); - for (index, data) in items_data.iter().enumerate() { + for (index, data) in items_data.into_iter().enumerate() { let item = TemplateModule::refungible_item_id(1, (index + 1) as TokenId).unwrap(); - assert_eq!(item.const_data.to_vec(), data.const_data); - assert_eq!(item.variable_data.to_vec(), data.variable_data); + assert_eq!(item.const_data.to_vec(), data.const_data.into_inner()); + assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner()); assert_eq!( item.owner[0], Ownership { @@ -262,8 +231,6 @@ #[test] fn create_fungible_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1); let data = default_fungible_data(); @@ -302,8 +269,6 @@ #[test] fn transfer_fungible_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1); let origin1 = Origin::signed(1); @@ -344,8 +309,6 @@ #[test] fn transfer_refungible_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let data = default_re_fungible_data(); @@ -355,8 +318,8 @@ let origin2 = Origin::signed(2); { let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap(); - assert_eq!(item.const_data, data.const_data); - assert_eq!(item.variable_data, data.variable_data); + assert_eq!(item.const_data, data.const_data.into_inner()); + assert_eq!(item.variable_data, data.variable_data.into_inner()); assert_eq!( item.owner[0], Ownership { @@ -441,8 +404,6 @@ #[test] fn transfer_nft_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); @@ -464,8 +425,6 @@ #[test] fn nft_approve_and_transfer_from() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); @@ -503,8 +462,6 @@ #[test] fn nft_approve_and_transfer_from_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -514,8 +471,8 @@ create_test_item(collection_id, &data.clone().into()); assert_eq!( - TemplateModule::nft_item_id(1, 1).unwrap().const_data, - data.const_data + &TemplateModule::nft_item_id(1, 1).unwrap().const_data, + &data.const_data.into_inner() ); assert_eq!(TemplateModule::balance_count(1, 1), 1); assert_eq!(TemplateModule::address_tokens(1, 1), [1]); @@ -573,8 +530,6 @@ #[test] fn refungible_approve_and_transfer_from() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); @@ -636,8 +591,6 @@ #[test] fn fungible_approve_and_transfer_from() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1); let data = default_fungible_data(); @@ -710,8 +663,6 @@ #[test] fn change_collection_owner() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -730,8 +681,6 @@ #[test] fn destroy_collection() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -742,8 +691,6 @@ #[test] fn burn_nft_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -773,8 +720,6 @@ #[test] fn burn_fungible_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1); let origin1 = Origin::signed(1); @@ -804,8 +749,6 @@ #[test] fn burn_refungible_item() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); @@ -851,8 +794,6 @@ #[test] fn add_collection_admin() { new_test_ext().execute_with(|| { - default_limits(); - let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1); create_test_collection_for_owner(&CollectionMode::NFT, 2, 2); create_test_collection_for_owner(&CollectionMode::NFT, 3, 3); @@ -879,8 +820,6 @@ #[test] fn remove_collection_admin() { new_test_ext().execute_with(|| { - default_limits(); - let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1); create_test_collection_for_owner(&CollectionMode::NFT, 2, 2); create_test_collection_for_owner(&CollectionMode::NFT, 3, 3); @@ -916,8 +855,6 @@ #[test] fn balance_of() { new_test_ext().execute_with(|| { - default_limits(); - let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1); let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2); let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible, 3); @@ -969,8 +906,6 @@ #[test] fn approve() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); @@ -987,8 +922,6 @@ #[test] fn transfer_from() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); @@ -1051,8 +984,6 @@ #[test] fn owner_can_add_address_to_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1068,8 +999,6 @@ #[test] fn admin_can_add_address_to_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); @@ -1091,8 +1020,6 @@ #[test] fn nonprivileged_user_cannot_add_address_to_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin2 = Origin::signed(2); @@ -1106,8 +1033,6 @@ #[test] fn nobody_can_add_address_to_white_list_of_nonexisting_collection() { new_test_ext().execute_with(|| { - default_limits(); - let origin1 = Origin::signed(1); assert_noop!( @@ -1120,8 +1045,6 @@ #[test] fn nobody_can_add_address_to_white_list_of_deleted_collection() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1140,8 +1063,6 @@ #[test] fn address_is_already_added_to_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1162,8 +1083,6 @@ #[test] fn owner_can_remove_address_from_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1184,8 +1103,6 @@ #[test] fn admin_can_remove_address_from_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); @@ -1213,8 +1130,6 @@ #[test] fn nonprivileged_user_cannot_remove_address_from_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); @@ -1235,7 +1150,6 @@ #[test] fn nobody_can_remove_address_from_white_list_of_nonexisting_collection() { new_test_ext().execute_with(|| { - default_limits(); let origin1 = Origin::signed(1); assert_noop!( @@ -1248,8 +1162,6 @@ #[test] fn nobody_can_remove_address_from_white_list_of_deleted_collection() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); @@ -1272,8 +1184,6 @@ #[test] fn address_is_already_removed_from_white_list() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1300,8 +1210,6 @@ #[test] fn white_list_test_1() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1330,8 +1238,6 @@ #[test] fn white_list_test_2() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1381,8 +1287,6 @@ #[test] fn white_list_test_3() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1411,8 +1315,6 @@ #[test] fn white_list_test_4() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1463,8 +1365,6 @@ #[test] fn white_list_test_5() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1488,8 +1388,6 @@ #[test] fn white_list_test_6() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1516,8 +1414,6 @@ #[test] fn white_list_test_7() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); @@ -1548,8 +1444,6 @@ #[test] fn white_list_test_8() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); @@ -1598,8 +1492,6 @@ #[test] fn white_list_test_9() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1623,8 +1515,6 @@ #[test] fn white_list_test_10() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1660,8 +1550,6 @@ #[test] fn white_list_test_11() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1694,8 +1582,6 @@ #[test] fn white_list_test_12() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1723,8 +1609,6 @@ #[test] fn white_list_test_13() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1749,8 +1633,6 @@ #[test] fn white_list_test_14() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1786,8 +1668,6 @@ #[test] fn white_list_test_15() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1815,8 +1695,6 @@ #[test] fn white_list_test_16() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1851,8 +1729,6 @@ #[test] fn total_number_collections_bound() { new_test_ext().execute_with(|| { - default_limits(); - create_test_collection(&CollectionMode::NFT, 1); }); } @@ -1861,11 +1737,9 @@ #[test] fn total_number_collections_bound_neg() { new_test_ext().execute_with(|| { - default_limits(); - let origin1 = Origin::signed(1); - for i in 0..default_collection_numbers_limit() { + for i in 0..COLLECTION_NUMBER_LIMIT { create_test_collection(&CollectionMode::NFT, i + 1); } @@ -1891,8 +1765,6 @@ #[test] fn owned_tokens_bound() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let data = default_nft_data(); @@ -1905,28 +1777,16 @@ #[test] fn owned_tokens_bound_neg() { new_test_ext().execute_with(|| { - 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, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); + + for _ in 0..ACCOUNT_TOKEN_OWNERSHIP_LIMIT { + let data = default_nft_data(); + create_test_item(collection_id, &data.clone().into()); + } + let data = default_nft_data(); - create_test_item(collection_id, &data.clone().into()); - assert_noop!( TemplateModule::create_item(origin1, 1, account(1), data.into()), Error::::AddressOwnershipLimitExceeded @@ -1938,22 +1798,6 @@ #[test] fn collection_admins_bound() { new_test_ext().execute_with(|| { - 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, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -1975,184 +1819,32 @@ #[test] fn collection_admins_bound_neg() { new_test_ext().execute_with(|| { - 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, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); - assert_ok!(TemplateModule::add_collection_admin( - origin1.clone(), - collection_id, - account(2) - )); + for i in 0..COLLECTION_ADMINS_LIMIT { + assert_ok!(TemplateModule::add_collection_admin( + origin1.clone(), + collection_id, + account(2 + i) + )); + } assert_noop!( - TemplateModule::add_collection_admin(origin1, collection_id, account(3)), + TemplateModule::add_collection_admin( + origin1, + collection_id, + account(3 + COLLECTION_ADMINS_LIMIT) + ), Error::::CollectionAdminsLimitExceeded - ); - }); -} - -// NFT custom data size. Negative test const_data. -#[test] -fn custom_data_size_nft_const_data_bound_neg() { - new_test_ext().execute_with(|| { - 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: 2, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - - let collection_id = create_test_collection(&CollectionMode::NFT, 1); - - let origin1 = Origin::signed(1); - let too_big_const_data = CreateItemData::NFT(CreateNftData { - const_data: vec![1, 2, 3, 4], - variable_data: vec![], - }); - - assert_noop!( - TemplateModule::create_item(origin1, collection_id, account(1), too_big_const_data), - Error::::TokenConstDataLimitExceeded - ); - }); -} - -// NFT custom data size. Negative test variable_data. -#[test] -fn custom_data_size_nft_variable_data_bound_neg() { - new_test_ext().execute_with(|| { - 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: 2, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - - let collection_id = create_test_collection(&CollectionMode::NFT, 1); - - let origin1 = Origin::signed(1); - let too_big_const_data = CreateItemData::NFT(CreateNftData { - const_data: vec![], - variable_data: vec![1, 2, 3, 4], - }); - - assert_noop!( - TemplateModule::create_item(origin1, collection_id, account(1), too_big_const_data), - Error::::TokenVariableDataLimitExceeded - ); - }); -} - -// Re fungible custom data size. Negative test const_data. -#[test] -fn custom_data_size_re_fungible_const_data_bound_neg() { - new_test_ext().execute_with(|| { - 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: 2, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - - let collection_id = create_test_collection(&CollectionMode::NFT, 1); - - let origin1 = Origin::signed(1); - let too_big_const_data = CreateItemData::NFT(CreateNftData { - const_data: vec![1, 2, 3, 4], - variable_data: vec![], - }); - - assert_noop!( - TemplateModule::create_item(origin1, collection_id, account(1), too_big_const_data), - Error::::TokenConstDataLimitExceeded ); }); } - -// Re fungible custom data size. Negative test variable_data. -#[test] -fn custom_data_size_re_fungible_variable_data_bound_neg() { - new_test_ext().execute_with(|| { - 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: 2, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - - let collection_id = create_test_collection(&CollectionMode::NFT, 1); - - let origin1 = Origin::signed(1); - let too_big_const_data = CreateItemData::NFT(CreateNftData { - const_data: vec![], - variable_data: vec![1, 2, 3, 4], - }); - - assert_noop!( - TemplateModule::create_item(origin1, collection_id, account(1), too_big_const_data), - Error::::TokenVariableDataLimitExceeded - ); - }); -} // #endregion #[test] fn set_const_on_chain_schema() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -2180,8 +1872,6 @@ #[test] fn set_variable_on_chain_schema() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -2209,8 +1899,6 @@ #[test] fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -2218,7 +1906,7 @@ let data = default_nft_data(); create_test_item(1, &data.into()); - let variable_data = b"test set_variable_meta_data method.".to_vec(); + let variable_data = b"test data".to_vec(); assert_ok!(TemplateModule::set_variable_meta_data( origin1, collection_id, @@ -2238,8 +1926,6 @@ #[test] fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); @@ -2247,7 +1933,7 @@ let data = default_re_fungible_data(); create_test_item(1, &data.into()); - let variable_data = b"test set_variable_meta_data method.".to_vec(); + let variable_data = b"test data".to_vec(); assert_ok!(TemplateModule::set_variable_meta_data( origin1, collection_id, @@ -2267,8 +1953,6 @@ #[test] fn set_variable_meta_data_on_fungible_token_fails() { new_test_ext().execute_with(|| { - default_limits(); - let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1); let origin1 = Origin::signed(1); @@ -2276,7 +1960,7 @@ let data = default_fungible_data(); create_test_item(1, &data.into()); - let variable_data = b"test set_variable_meta_data method.".to_vec(); + let variable_data = b"test data".to_vec(); assert_noop!( TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data), Error::::CantStoreMetadataInFungibleTokens @@ -2287,22 +1971,6 @@ #[test] fn set_variable_meta_data_on_nft_token_fails_for_big_data() { new_test_ext().execute_with(|| { - assert_ok!(TemplateModule::set_chain_limits( - RawOrigin::Root.into(), - ChainLimits { - collection_numbers_limit: default_collection_numbers_limit(), - account_token_ownership_limit: 10, - collections_admins_limit: 5, - custom_data_limit: 10, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - let collection_id = create_test_collection(&CollectionMode::NFT, 1); let origin1 = Origin::signed(1); @@ -2321,22 +1989,6 @@ #[test] fn set_variable_meta_data_on_re_fungible_token_fails_for_big_data() { new_test_ext().execute_with(|| { - assert_ok!(TemplateModule::set_chain_limits( - RawOrigin::Root.into(), - ChainLimits { - collection_numbers_limit: default_collection_numbers_limit(), - account_token_ownership_limit: 10, - collections_admins_limit: 5, - custom_data_limit: 10, - nft_sponsor_transfer_timeout: 15, - fungible_sponsor_transfer_timeout: 15, - refungible_sponsor_transfer_timeout: 15, - const_on_chain_schema_limit: 1024, - offchain_schema_limit: 1024, - variable_on_chain_schema_limit: 1024, - } - )); - let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); @@ -2355,8 +2007,6 @@ #[test] fn collection_transfer_flag_works() { new_test_ext().execute_with(|| { - default_limits(); - let origin1 = Origin::signed(1); let collection_id = create_test_collection(&CollectionMode::NFT, 1); @@ -2382,8 +2032,6 @@ #[test] fn collection_transfer_flag_works_neg() { new_test_ext().execute_with(|| { - default_limits(); - let origin1 = Origin::signed(1); let collection_id = create_test_collection(&CollectionMode::NFT, 1); --- a/primitives/nft/Cargo.toml +++ b/primitives/nft/Cargo.toml @@ -9,20 +9,28 @@ version = '0.9.0' [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ['derive'] } -serde = { version = "1.0.119", features = ['derive'], default-features = false } +codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ['derive'] } +serde = { version = "1.0.119", features = ['derive'], default-features = false, optional = true } +max-encoded-len = { default-features = false, features = ['derive'], version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } sp-core = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } +sp-std = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } sp-runtime = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } +derivative = "2.2.0" [features] default = ["std"] std = [ + "serde1", "serde/std", "codec/std", + "max-encoded-len/std", "frame-system/std", "frame-support/std", "sp-runtime/std", "sp-core/std", -] \ No newline at end of file + "sp-std/std", +] +serde1 = ["serde"] +limit-testing = [] \ No newline at end of file --- a/primitives/nft/src/lib.rs +++ b/primitives/nft/src/lib.rs @@ -1,11 +1,13 @@ #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(feature = "serde")] pub use serde::{Serialize, Deserialize}; use sp_runtime::sp_std::prelude::Vec; use codec::{Decode, Encode}; +use max_encoded_len::MaxEncodedLen; pub use frame_support::{ - construct_runtime, decl_event, decl_module, decl_storage, decl_error, + BoundedVec, construct_runtime, decl_event, decl_module, decl_storage, decl_error, dispatch::DispatchResult, ensure, fail, parameter_types, traits::{ @@ -19,18 +21,54 @@ }, StorageValue, transactional, }; +use derivative::Derivative; pub const MAX_DECIMAL_POINTS: DecimalPoints = 30; pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000; pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000; pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000; +pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) { + 100000 +} else { + 10 +}; +pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) { + 2048 +} else { + 10 +}; +pub const COLLECTION_ADMINS_LIMIT: u64 = 5; +pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) { + 1000000 +} else { + 10 +}; + +// Timeouts for item types in passed blocks +pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5; +pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5; +pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5; + +// Schema limits +pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 1024; +pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 1024; +pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 1024; + +/// How much items can be created per single +/// create_many call +pub const MAX_ITEMS_PER_BATCH: u32 = 200; + +parameter_types! { + pub const CustomDataLimit: u32 = CUSTOM_DATA_LIMIT; +} + pub type CollectionId = u32; pub type TokenId = u32; pub type DecimalPoints = u8; #[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub enum CollectionMode { Invalid, NFT, @@ -61,7 +99,7 @@ } #[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub enum AccessMode { Normal, WhiteList, @@ -73,7 +111,7 @@ } #[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub enum SchemaVersion { ImageURL, Unique, @@ -85,14 +123,14 @@ } #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct Ownership { pub owner: AccountId, pub fraction: u128, } #[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub enum SponsorshipState { /// The fees are applied to the transaction sender Disabled, @@ -128,7 +166,7 @@ } #[derive(Encode, Decode, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct Collection { pub owner: T::AccountId, pub mode: CollectionMode, @@ -148,7 +186,7 @@ } #[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct NftItemType { pub owner: AccountId, pub const_data: Vec, @@ -156,13 +194,13 @@ } #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct FungibleItemType { pub value: u128, } #[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct ReFungibleItemType { pub owner: Vec>, pub const_data: Vec, @@ -170,7 +208,7 @@ } #[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct CollectionLimits { pub account_token_ownership_limit: u32, pub sponsored_data_size: u32, @@ -200,48 +238,72 @@ } } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct ChainLimits { - pub collection_numbers_limit: u32, - pub account_token_ownership_limit: u32, - pub collections_admins_limit: u64, - pub custom_data_limit: u32, +/// BoundedVec doesn't supports serde +#[cfg(feature = "serde1")] +mod bounded_serde { + use core::convert::TryFrom; + use frame_support::{BoundedVec, traits::Get}; + use serde::{ + ser::{self, Serialize}, + de::{self, Deserialize, Error}, + }; + use sp_std::vec::Vec; - // Timeouts for item types in passed blocks - pub nft_sponsor_transfer_timeout: u32, - pub fungible_sponsor_transfer_timeout: u32, - pub refungible_sponsor_transfer_timeout: u32, + pub fn serialize(value: &BoundedVec, serializer: D) -> Result + where + D: ser::Serializer, + V: Serialize, + { + let vec: &Vec<_> = &value; + vec.serialize(serializer) + } - // Schema limits - pub offchain_schema_limit: u32, - pub variable_on_chain_schema_limit: u32, - pub const_on_chain_schema_limit: u32, + pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result, D::Error> + where + D: de::Deserializer<'de>, + V: de::Deserialize<'de>, + S: Get, + { + // TODO: Implement custom visitor, which will limit vec size at parse time? Will serde only be used by chainspec? + let vec = >::deserialize(deserializer)?; + let len = vec.len(); + TryFrom::try_from(vec).map_err(|_| D::Error::invalid_length(len, &"lesser size")) + } } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +#[derivative(Debug)] pub struct CreateNftData { - pub const_data: Vec, - pub variable_data: Vec, + #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] + #[derivative(Debug = "ignore")] + pub const_data: BoundedVec, + #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] + #[derivative(Debug = "ignore")] + pub variable_data: BoundedVec, } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct CreateFungibleData { pub value: u128, } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +#[derivative(Debug)] pub struct CreateReFungibleData { - pub const_data: Vec, - pub variable_data: Vec, + #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] + #[derivative(Debug = "ignore")] + pub const_data: BoundedVec, + #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] + #[derivative(Debug = "ignore")] + pub variable_data: BoundedVec, pub pieces: u128, } -#[derive(Encode, Decode, Debug, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub enum CreateItemData { NFT(CreateNftData), Fungible(CreateFungibleData), --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -31,6 +31,7 @@ ] std = [ 'codec/std', + 'max-encoded-len/std', 'cumulus-pallet-aura-ext/std', 'cumulus-pallet-parachain-system/std', 'cumulus-pallet-xcm/std', @@ -84,6 +85,10 @@ 'xcm-builder/std', 'xcm-executor/std', ] +limit-testing = [ + 'pallet-nft/limit-testing', + 'nft-data-structs/limit-testing', +] ################################################################################ # Substrate Dependencies @@ -378,6 +383,8 @@ # local dependencies [dependencies] +max-encoded-len = { default-features = false, features = ['derive'], version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' } +derivative = "2.2.0" pallet-nft = { path = '../pallets/nft', default-features = false, version = '3.0.0' } pallet-inflation = { path = '../pallets/inflation', default-features = false, version = '3.0.0' } nft-data-structs = { path = '../primitives/nft', default-features = false, version = '0.9.0' } --- a/runtime/src/chain_extension.rs +++ b/runtime/src/chain_extension.rs @@ -6,6 +6,8 @@ // use codec::{Decode, Encode}; +use max_encoded_len::MaxEncodedLen; +use derivative::Derivative; pub use pallet_contracts::chain_extension::RetVal; use pallet_contracts::chain_extension::{ @@ -19,61 +21,63 @@ pub use pallet_nft::*; use pallet_nft::CrossAccountId; use nft_data_structs::*; - -use crate::Vec; /// Create item parameters -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtCreateItem { - pub owner: ::AccountId, +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtCreateItem { + pub owner: AccountId, pub collection_id: u32, pub data: CreateItemData, } /// Transfer parameters -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtTransfer { - pub recipient: ::AccountId, +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtTransfer { + pub recipient: AccountId, pub collection_id: u32, pub token_id: u32, pub amount: u128, } -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtCreateMultipleItems { - pub owner: ::AccountId, +#[derive(Derivative, PartialEq, Encode, Decode, MaxEncodedLen)] +#[derivative(Debug)] +pub struct NFTExtCreateMultipleItems { + pub owner: AccountId, pub collection_id: u32, - pub data: Vec, + #[derivative(Debug = "ignore")] + pub data: BoundedVec, } -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtApprove { - pub spender: ::AccountId, +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtApprove { + pub spender: AccountId, pub collection_id: u32, pub item_id: u32, pub amount: u128, } -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtTransferFrom { - pub owner: ::AccountId, - pub recipient: ::AccountId, +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtTransferFrom { + pub owner: AccountId, + pub recipient: AccountId, pub collection_id: u32, pub item_id: u32, pub amount: u128, } -#[derive(Debug, PartialEq, Encode, Decode)] +#[derive(Derivative, PartialEq, Encode, Decode, MaxEncodedLen)] +#[derivative(Debug)] pub struct NFTExtSetVariableMetaData { pub collection_id: u32, pub item_id: u32, - pub data: Vec, + #[derivative(Debug = "ignore")] + pub data: BoundedVec, } -#[derive(Debug, PartialEq, Encode, Decode)] -pub struct NFTExtToggleWhiteList { +#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)] +pub struct NFTExtToggleWhiteList { pub collection_id: u32, - pub address: ::AccountId, + pub address: AccountId, pub whitelisted: bool, } @@ -82,6 +86,8 @@ pub type NftWeightInfoOf = ::WeightInfo; +pub type AccountIdOf = ::AccountId; + impl ChainExtension for NFTExtension { fn call(func_id: u32, env: Environment) -> Result where @@ -93,7 +99,7 @@ match func_id { 0 => { let mut env = env.buf_in_buf_out(); - let input: NFTExtTransfer = env.read_as()?; + let input: NFTExtTransfer> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::transfer())?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -106,13 +112,13 @@ input.amount, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 1 => { // Create Item let mut env = env.buf_in_buf_out(); - let input: NFTExtCreateItem = env.read_as()?; + let input: NFTExtCreateItem> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::create_item(input.data.data_size()))?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -124,13 +130,13 @@ input.data, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 2 => { // Create multiple items let mut env = env.buf_in_buf_out(); - let input: NFTExtCreateMultipleItems = env.read_as()?; + let input: NFTExtCreateMultipleItems> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::create_item( input.data.iter().map(|i| i.data_size()).sum(), ))?; @@ -141,16 +147,16 @@ &C::CrossAccountId::from_sub(env.ext().address().clone()), &collection, &C::CrossAccountId::from_sub(input.owner), - input.data, + input.data.into_inner(), )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 3 => { // Approve let mut env = env.buf_in_buf_out(); - let input: NFTExtApprove = env.read_as()?; + let input: NFTExtApprove> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::approve())?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -163,13 +169,13 @@ input.amount, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 4 => { // Transfer from let mut env = env.buf_in_buf_out(); - let input: NFTExtTransferFrom = env.read_as()?; + let input: NFTExtTransferFrom> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::transfer_from())?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -183,7 +189,7 @@ input.amount, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 5 => { @@ -198,16 +204,16 @@ &C::CrossAccountId::from_sub(env.ext().address().clone()), &collection, input.item_id, - input.data, + input.data.into_inner(), )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } 6 => { // Toggle whitelist let mut env = env.buf_in_buf_out(); - let input: NFTExtToggleWhiteList = env.read_as()?; + let input: NFTExtToggleWhiteList> = env.read_as()?; env.charge_weight(NftWeightInfoOf::::add_to_white_list())?; let collection = pallet_nft::Module::::get_collection(input.collection_id)?; @@ -219,7 +225,7 @@ input.whitelisted, )?; - pallet_nft::Module::::submit_logs(collection)?; + collection.submit_logs()?; Ok(RetVal::Converging(0)) } _ => Err(DispatchError::Other("unknown chain_extension func_id")), --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -72,7 +72,6 @@ use sp_runtime::{ traits::{Dispatchable}, }; -// use pallet_contracts::chain_extension::UncheckedFrom; // pub use pallet_timestamp::Call as TimestampCall; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -419,7 +418,7 @@ type DepositPerStorageItem = DepositPerStorageItem; type RentFraction = RentFraction; type SurchargeReward = SurchargeReward; - type WeightPrice = pallet_transaction_payment::Module; + type WeightPrice = pallet_transaction_payment::Pallet; type WeightInfo = pallet_contracts::weights::SubstrateWeight; type ChainExtension = NFTExtension; type DeletionQueueDepth = DeletionQueueDepth; --- a/runtime/src/nft_weights.rs +++ b/runtime/src/nft_weights.rs @@ -123,11 +123,6 @@ .saturating_add(DbWeight::get().reads(2_u64)) .saturating_add(DbWeight::get().writes(1_u64)) } - fn set_chain_limits() -> Weight { - 1_300_000_u64 - .saturating_add(DbWeight::get().reads(0_u64)) - .saturating_add(DbWeight::get().writes(1_u64)) - } fn set_contract_sponsoring_rate_limit() -> Weight { 3_500_000_u64 .saturating_add(DbWeight::get().reads(0_u64)) --- a/tests/src/addCollectionAdmin.test.ts +++ b/tests/src/addCollectionAdmin.test.ts @@ -117,8 +117,7 @@ ]; const collectionId = await createCollectionExpectSuccess(); - const chainLimit = await api.query.nft.chainLimit() as unknown as { CollectionAdminsLimit: BN }; - const chainAdminLimit = chainLimit.CollectionAdminsLimit.toNumber(); + const chainAdminLimit = api.consts.nft.collectionAdminsLimit.toNumber(); expect(chainAdminLimit).to.be.equal(5); for (let i = 0; i < chainAdminLimit; i++) { --- a/tests/src/collision-tests/adminLimitsOff.test.ts +++ b/tests/src/collision-tests/adminLimitsOff.test.ts @@ -34,8 +34,7 @@ await usingApi(async (api) => { const collectionId = await createCollectionExpectSuccess(); - const chainLimit = await api.query.nft.chainLimit() as unknown as { CollectionAdminsLimit: BN }; - const chainAdminLimit = chainLimit.CollectionAdminsLimit.toNumber(); + const chainAdminLimit = api.consts.nft.collectionAdminsLimit.toNumber(); expect(chainAdminLimit).to.be.equal(5); const changeAdminTx1 = api.tx.nft.addCollectionAdmin(collectionId, Eve.address); -- gitstuff