From 71e3eed441174d9391baa7a37de0b3624b0e27ff Mon Sep 17 00:00:00 2001 From: usetech-llc Date: Fri, 11 Dec 2020 11:20:28 +0000 Subject: [PATCH] Merge pull request #31 from usetech-llc/feature/NFTPAR-183 Feature/NFTPAR-183 Storage Refactoring. --- --- a/README.md +++ b/README.md @@ -164,12 +164,13 @@ "WhiteList" ] }, + "DecimalPoints": "u8", "CollectionMode": { "_enum": { "Invalid": null, "NFT": null, - "Fungible": "u32", - "ReFungible": "u32" + "Fungible": "DecimalPoints", + "ReFungible": "DecimalPoints" } }, "Ownership": { @@ -177,17 +178,17 @@ "Fraction": "u128" }, "FungibleItemType": { - "Collection": "u64", + "Collection": "CollectionId", "Owner": "AccountId", "Value": "u128" }, "ReFungibleItemType": { - "Collection": "u64", + "Collection": "CollectionId", "Owner": "Vec", "Data": "Vec" }, "NftItemType": { - "Collection": "u64", + "Collection": "CollectionId", "Owner": "AccountId", "ConstData": "Vec", "VariableData": "Vec" @@ -197,7 +198,7 @@ "fraction": "u128" }, "ReFungibleItemType": { - "Collection": "u64", + "Collection": "CollectionId", "Owner": "Vec>", "ConstData": "Vec", "VariableData": "Vec" @@ -206,7 +207,7 @@ "Owner": "AccountId", "Mode": "CollectionMode", "Access": "AccessMode", - "DecimalPoints": "u32", + "DecimalPoints": "DecimalPoints", "Name": "Vec", "Description": "Vec", "TokenPrefix": "Vec", @@ -219,7 +220,7 @@ }, "ApprovePermissions": { "Approved": "AccountId", - "Amount": "u64" + "Amount": "u128" }, "RawData": "Vec", "Address": "AccountId", @@ -240,7 +241,9 @@ "Fungible": "CreateFungibleData", "ReFungible": "CreateReFungibleData" } - } + }, + "CollectionId": "u32", + "TokenId": "u32" } ``` \ No newline at end of file --- a/pallets/nft/src/lib.rs +++ b/pallets/nft/src/lib.rs @@ -45,18 +45,25 @@ mod default_weights; +pub const MAX_DECIMAL_POINTS: DecimalPoints = 30; + // Structs // #region +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))] pub enum CollectionMode { Invalid, NFT, // decimal points - Fungible(u32), + Fungible(DecimalPoints), // decimal points - ReFungible(u32), + ReFungible(DecimalPoints), } impl Into for CollectionMode { @@ -101,7 +108,7 @@ pub owner: AccountId, pub mode: CollectionMode, pub access: AccessMode, - pub decimal_points: u32, + pub decimal_points: DecimalPoints, pub name: Vec, // 64 include null escape char pub description: Vec, // 256 include null escape char pub token_prefix: Vec, // 16 include null escape char @@ -116,7 +123,7 @@ #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct NftItemType { - pub collection: u64, + pub collection: CollectionId, pub owner: AccountId, pub const_data: Vec, pub variable_data: Vec, @@ -125,7 +132,7 @@ #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct FungibleItemType { - pub collection: u64, + pub collection: CollectionId, pub owner: AccountId, pub value: u128, } @@ -133,7 +140,7 @@ #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct ReFungibleItemType { - pub collection: u64, + pub collection: CollectionId, pub owner: Vec>, pub const_data: Vec, pub variable_data: Vec, @@ -143,7 +150,7 @@ #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct ApprovePermissions { pub approved: AccountId, - pub amount: u64, + pub amount: u128, } #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] @@ -151,8 +158,8 @@ pub struct VestingItem { pub sender: AccountId, pub recipient: AccountId, - pub collection_id: u64, - pub item_id: u64, + pub collection_id: CollectionId, + pub item_id: TokenId, pub amount: u64, pub vesting_date: Moment, } @@ -167,8 +174,8 @@ #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct ChainLimits { - pub collection_numbers_limit: u64, - pub account_token_ownership_limit: u64, + pub collection_numbers_limit: u32, + pub account_token_ownership_limit: u32, pub collections_admins_limit: u64, pub custom_data_limit: u32, @@ -266,7 +273,7 @@ pub enum Error for Module { /// Total collections bound exceeded. TotalCollectionsLimitExceeded, - /// Decimal_points parameter must be lower than 4. + /// Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30. CollectionDecimalPointLimitExceeded, /// Collection name can not be longer than 63 char. CollectionNameLimitExceeded, @@ -341,41 +348,41 @@ trait Store for Module as Nft { // Private members - NextCollectionID: u64; - CreatedCollectionCount: u64; + NextCollectionID: CollectionId; + CreatedCollectionCount: u32; ChainVersion: u64; - ItemListIndex: map hasher(blake2_128_concat) u64 => u64; + ItemListIndex: map hasher(identity) CollectionId => TokenId; // Chain limits struct pub ChainLimit get(fn chain_limit) config(): ChainLimits; // Bound counters - CollectionCount: u64; - pub AccountItemCount get(fn account_item_count): map hasher(identity) T::AccountId => u64; + CollectionCount: u32; + pub AccountItemCount get(fn account_item_count): map hasher(twox_64_concat) T::AccountId => u32; // Basic collections - pub Collection get(fn collection) config(): map hasher(identity) u64 => CollectionType; - pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec; - pub WhiteList get(fn white_list): map hasher(identity) u64 => Vec; + pub Collection get(fn collection) config(): map hasher(identity) CollectionId => CollectionType; + pub AdminList get(fn admin_list_collection): map hasher(identity) CollectionId => Vec; + pub WhiteList get(fn white_list): map hasher(identity) CollectionId => Vec; /// Balance owner per collection map - pub Balance get(fn balance_count): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) T::AccountId => u64; + pub Balance get(fn balance_count): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => u128; /// second parameter: item id + owner account id - pub ApprovedList get(fn approved): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) (u64, T::AccountId) => Vec>; + pub ApprovedList get(fn approved): double_map hasher(identity) CollectionId, hasher(twox_64_concat) (TokenId, T::AccountId) => Vec>; /// Item collections - pub NftItemList get(fn nft_item_id) config(): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => NftItemType; - pub FungibleItemList get(fn fungible_item_id) config(): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => FungibleItemType; - pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => ReFungibleItemType; + pub NftItemList get(fn nft_item_id) config(): double_map hasher(identity) CollectionId, hasher(identity) TokenId => NftItemType; + pub FungibleItemList get(fn fungible_item_id) config(): double_map hasher(identity) CollectionId, hasher(identity) TokenId => FungibleItemType; + pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(identity) CollectionId, hasher(identity) TokenId => ReFungibleItemType; /// Index list - pub AddressTokens get(fn address_tokens): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) T::AccountId => Vec; + pub AddressTokens get(fn address_tokens): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => Vec; /// Tokens transfer baskets - pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => T::BlockNumber; - pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => Vec>; - pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => T::BlockNumber; + pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(identity) CollectionId, hasher(identity) TokenId => T::BlockNumber; + pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(identity) CollectionId, hasher(identity) TokenId => Vec>; + pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(identity) CollectionId, hasher(identity) TokenId => T::BlockNumber; // Contract Sponsorship and Ownership pub ContractOwner get(fn contract_owner): map hasher(twox_64_concat) T::AccountId => T::AccountId; @@ -419,7 +426,7 @@ /// * mode: [CollectionMode] converted into u8. /// /// * account_id: Collection owner. - Created(u64, u8, AccountId), + Created(CollectionId, u8, AccountId), /// New item was created. /// @@ -428,7 +435,7 @@ /// * collection_id: Id of the collection where item was created. /// /// * item_id: Id of an item. Unique within the collection. - ItemCreated(u64, u64), + ItemCreated(CollectionId, TokenId), /// Collection item was burned. /// @@ -437,7 +444,7 @@ /// collection_id. /// /// item_id: Identifier of burned NFT. - ItemDestroyed(u64, u64), + ItemDestroyed(CollectionId, TokenId), } ); @@ -495,7 +502,7 @@ ensure!(CollectionCount::get() < ChainLimit::get().collection_numbers_limit, Error::::TotalCollectionsLimitExceeded); // check params - ensure!(decimal_points <= 4, Error::::CollectionDecimalPointLimitExceeded); + ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::::CollectionDecimalPointLimitExceeded); let mut name = collection_name.to_vec(); name.push(0); @@ -558,7 +565,7 @@ /// /// * collection_id: collection to destroy. #[weight = T::WeightInfo::destroy_collection()] - pub fn destroy_collection(origin, collection_id: u64) -> DispatchResult { + pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult { let sender = ensure_signed(origin)?; Self::check_owner_permissions(collection_id, sender)?; @@ -605,7 +612,7 @@ /// /// * address. #[weight = T::WeightInfo::add_to_white_list()] - pub fn add_to_white_list(origin, collection_id: u64, address: T::AccountId) -> DispatchResult{ + pub fn add_to_white_list(origin, collection_id: CollectionId, address: T::AccountId) -> DispatchResult{ let sender = ensure_signed(origin)?; Self::check_owner_or_admin_permissions(collection_id, sender)?; @@ -640,7 +647,7 @@ /// /// * address. #[weight = T::WeightInfo::remove_from_white_list()] - pub fn remove_from_white_list(origin, collection_id: u64, address: T::AccountId) -> DispatchResult{ + pub fn remove_from_white_list(origin, collection_id: CollectionId, address: T::AccountId) -> DispatchResult{ let sender = ensure_signed(origin)?; Self::check_owner_or_admin_permissions(collection_id, sender)?; @@ -669,7 +676,7 @@ /// /// * mode: [AccessMode] #[weight = T::WeightInfo::set_public_access_mode()] - pub fn set_public_access_mode(origin, collection_id: u64, mode: AccessMode) -> DispatchResult + pub fn set_public_access_mode(origin, collection_id: CollectionId, mode: AccessMode) -> DispatchResult { let sender = ensure_signed(origin)?; @@ -695,7 +702,7 @@ /// /// * mint_permission: Boolean parameter. If True, allows minting to Anyone with conditions above. #[weight = T::WeightInfo::set_mint_permission()] - pub fn set_mint_permission(origin, collection_id: u64, mint_permission: bool) -> DispatchResult + pub fn set_mint_permission(origin, collection_id: CollectionId, mint_permission: bool) -> DispatchResult { let sender = ensure_signed(origin)?; @@ -719,7 +726,7 @@ /// /// * new_owner. #[weight = T::WeightInfo::change_collection_owner()] - pub fn change_collection_owner(origin, collection_id: u64, new_owner: T::AccountId) -> DispatchResult { + pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult { let sender = ensure_signed(origin)?; Self::check_owner_permissions(collection_id, sender)?; @@ -744,7 +751,7 @@ /// /// * new_admin_id: Address of new admin to add. #[weight = T::WeightInfo::add_collection_admin()] - pub fn add_collection_admin(origin, collection_id: u64, new_admin_id: T::AccountId) -> DispatchResult { + pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::AccountId) -> DispatchResult { let sender = ensure_signed(origin)?; Self::check_owner_or_admin_permissions(collection_id, sender)?; @@ -778,7 +785,7 @@ /// /// * account_id: Address of admin to remove. #[weight = T::WeightInfo::remove_collection_admin()] - pub fn remove_collection_admin(origin, collection_id: u64, account_id: T::AccountId) -> DispatchResult { + pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::AccountId) -> DispatchResult { let sender = ensure_signed(origin)?; Self::check_owner_or_admin_permissions(collection_id, sender)?; @@ -803,7 +810,7 @@ /// /// * new_sponsor. #[weight = T::WeightInfo::set_collection_sponsor()] - pub fn set_collection_sponsor(origin, collection_id: u64, new_sponsor: T::AccountId) -> DispatchResult { + pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult { let sender = ensure_signed(origin)?; ensure!(>::contains_key(collection_id), Error::::CollectionNotFound); @@ -825,7 +832,7 @@ /// /// * collection_id. #[weight = T::WeightInfo::confirm_sponsorship()] - pub fn confirm_sponsorship(origin, collection_id: u64) -> DispatchResult { + pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult { let sender = ensure_signed(origin)?; ensure!(>::contains_key(collection_id), Error::::CollectionNotFound); @@ -850,7 +857,7 @@ /// /// * collection_id. #[weight = T::WeightInfo::remove_collection_sponsor()] - pub fn remove_collection_sponsor(origin, collection_id: u64) -> DispatchResult { + pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult { let sender = ensure_signed(origin)?; ensure!(>::contains_key(collection_id), Error::::CollectionNotFound); @@ -889,7 +896,7 @@ // .saturating_add(RocksDbWeight::get().writes(8 as Weight))] #[weight = T::WeightInfo::create_item(data.len())] - pub fn create_item(origin, collection_id: u64, owner: T::AccountId, data: CreateItemData) -> DispatchResult { + pub fn create_item(origin, collection_id: CollectionId, owner: T::AccountId, data: CreateItemData) -> DispatchResult { let sender = ensure_signed(origin)?; @@ -925,7 +932,7 @@ #[weight = T::WeightInfo::create_item(items_data.into_iter() .map(|data| { data.len() }) .sum())] - pub fn create_multiple_items(origin, collection_id: u64, owner: T::AccountId, items_data: Vec) -> DispatchResult { + pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::AccountId, items_data: Vec) -> DispatchResult { ensure!(items_data.len() > 0, Error::::EmptyArgument); let sender = ensure_signed(origin)?; @@ -959,7 +966,7 @@ /// /// * item_id: ID of NFT to burn. #[weight = T::WeightInfo::burn_item()] - pub fn burn_item(origin, collection_id: u64, item_id: u64) -> DispatchResult { + pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId) -> DispatchResult { let sender = ensure_signed(origin)?; Self::collection_exists(collection_id)?; @@ -1012,7 +1019,7 @@ /// * Fungible Mode: Must specify transferred amount /// * Re-Fungible Mode: Must specify transferred portion (between 0 and 1) #[weight = T::WeightInfo::transfer()] - pub fn transfer(origin, recipient: T::AccountId, collection_id: u64, item_id: u64, value: u64) -> DispatchResult { + pub fn transfer(origin, recipient: T::AccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResult { let sender = ensure_signed(origin)?; @@ -1054,7 +1061,7 @@ /// /// * item_id: ID of the item. #[weight = T::WeightInfo::approve()] - pub fn approve(origin, approved: T::AccountId, collection_id: u64, item_id: u64) -> DispatchResult { + pub fn approve(origin, approved: T::AccountId, collection_id: CollectionId, item_id: TokenId) -> DispatchResult { let sender = ensure_signed(origin)?; @@ -1112,7 +1119,7 @@ /// /// * value: Amount to transfer. #[weight = T::WeightInfo::transfer_from()] - pub fn transfer_from(origin, from: T::AccountId, recipient: T::AccountId, collection_id: u64, item_id: u64, value: u64 ) -> DispatchResult { + pub fn transfer_from(origin, from: T::AccountId, recipient: T::AccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResult { let sender = ensure_signed(origin)?; let mut appoved_transfer = false; @@ -1157,7 +1164,7 @@ /// #[weight = 0] - pub fn safe_transfer_from(origin, collection_id: u64, item_id: u64, new_owner: T::AccountId) -> DispatchResult { + pub fn safe_transfer_from(origin, collection_id: CollectionId, item_id: TokenId, new_owner: T::AccountId) -> DispatchResult { // let no_perm_mes = "You do not have permissions to modify this collection"; // ensure!(>::contains_key((collection_id, item_id)), no_perm_mes); @@ -1186,8 +1193,8 @@ #[weight = T::WeightInfo::set_variable_meta_data()] pub fn set_variable_meta_data ( origin, - collection_id: u64, - item_id: u64, + collection_id: CollectionId, + item_id: TokenId, data: Vec ) -> DispatchResult { let sender = ensure_signed(origin)?; @@ -1231,7 +1238,7 @@ #[weight = T::WeightInfo::set_offchain_schema()] pub fn set_offchain_schema( origin, - collection_id: u64, + collection_id: CollectionId, schema: Vec ) -> DispatchResult { let sender = ensure_signed(origin)?; @@ -1259,7 +1266,7 @@ #[weight = T::WeightInfo::set_const_on_chain_schema()] pub fn set_const_on_chain_schema ( origin, - collection_id: u64, + collection_id: CollectionId, schema: Vec ) -> DispatchResult { let sender = ensure_signed(origin)?; @@ -1287,7 +1294,7 @@ #[weight = T::WeightInfo::set_const_on_chain_schema()] pub fn set_variable_on_chain_schema ( origin, - collection_id: u64, + collection_id: CollectionId, schema: Vec ) -> DispatchResult { let sender = ensure_signed(origin)?; @@ -1396,7 +1403,7 @@ impl Module { - fn can_create_items_in_collection(collection_id: u64, collection: &CollectionType, sender: &T::AccountId, owner: &T::AccountId) -> DispatchResult { + fn can_create_items_in_collection(collection_id: CollectionId, collection: &CollectionType, sender: &T::AccountId, owner: &T::AccountId) -> DispatchResult { if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) { ensure!(collection.mint_mode == true, Error::::PublicMintingNotAllowed); @@ -1441,7 +1448,7 @@ Ok(()) } - fn create_item_no_validation(collection_id: u64, collection: &CollectionType, owner: T::AccountId, data: CreateItemData) -> DispatchResult { + fn create_item_no_validation(collection_id: CollectionId, collection: &CollectionType, owner: T::AccountId, data: CreateItemData) -> DispatchResult { match data { CreateItemData::NFT(data) => { @@ -1458,14 +1465,14 @@ let item = FungibleItemType { collection: collection_id, owner, - value: (10 as u128).pow(collection.decimal_points) + value: (10 as u128).pow(collection.decimal_points as u32) }; Self::add_fungible_item(item)?; }, CreateItemData::ReFungible(data) => { let mut owner_list = Vec::new(); - let value = (10 as u128).pow(collection.decimal_points); + let value = (10 as u128).pow(collection.decimal_points as u32); owner_list.push(Ownership {owner: owner.clone(), fraction: value}); let item = ReFungibleItemType { @@ -1492,7 +1499,6 @@ .ok_or(Error::::NumOverflow)?; let itemcopy = item.clone(); let owner = item.owner.clone(); - let value = item.value as u64; Self::add_token_index(item.collection, current_index, owner.clone())?; @@ -1505,7 +1511,7 @@ // Update balance let new_balance = >::get(item.collection, owner.clone()) - .checked_add(value) + .checked_add(item.value) .ok_or(Error::::NumOverflow)?; >::insert(item.collection, owner.clone(), new_balance); @@ -1518,7 +1524,7 @@ .ok_or(Error::::NumOverflow)?; let itemcopy = item.clone(); - let value = item.owner.first().unwrap().fraction as u64; + let value = item.owner.first().unwrap().fraction; let owner = item.owner.first().unwrap().owner.clone(); Self::add_token_index(item.collection, current_index, owner.clone())?; @@ -1565,8 +1571,8 @@ } fn burn_refungible_item( - collection_id: u64, - item_id: u64, + collection_id: CollectionId, + item_id: TokenId, owner: T::AccountId, ) -> DispatchResult { ensure!( @@ -1587,7 +1593,7 @@ // update balance let new_balance = >::get(collection_id, item.owner.clone()) - .checked_sub(item.fraction as u64) + .checked_sub(item.fraction) .ok_or(Error::::NumOverflow)?; >::insert(collection_id, item.owner.clone(), new_balance); @@ -1596,7 +1602,7 @@ Ok(()) } - fn burn_nft_item(collection_id: u64, item_id: u64) -> DispatchResult { + fn burn_nft_item(collection_id: CollectionId, item_id: TokenId) -> DispatchResult { ensure!( >::contains_key(collection_id, item_id), Error::::TokenNotFound @@ -1617,7 +1623,7 @@ Ok(()) } - fn burn_fungible_item(collection_id: u64, item_id: u64) -> DispatchResult { + fn burn_fungible_item(collection_id: CollectionId, item_id: TokenId) -> DispatchResult { ensure!( >::contains_key(collection_id, item_id), Error::::TokenNotFound @@ -1630,7 +1636,7 @@ // update balance let new_balance = >::get(collection_id, item.owner.clone()) - .checked_sub(item.value as u64) + .checked_sub(item.value) .ok_or(Error::::NumOverflow)?; >::insert(collection_id, item.owner.clone(), new_balance); @@ -1639,7 +1645,7 @@ Ok(()) } - fn collection_exists(collection_id: u64) -> DispatchResult { + fn collection_exists(collection_id: CollectionId) -> DispatchResult { ensure!( >::contains_key(collection_id), Error::::CollectionNotFound @@ -1647,7 +1653,7 @@ Ok(()) } - fn check_owner_permissions(collection_id: u64, subject: T::AccountId) -> DispatchResult { + fn check_owner_permissions(collection_id: CollectionId, subject: T::AccountId) -> DispatchResult { Self::collection_exists(collection_id)?; let target_collection = >::get(collection_id); @@ -1659,7 +1665,7 @@ Ok(()) } - fn is_owner_or_admin_permissions(collection_id: u64, subject: T::AccountId) -> bool { + fn is_owner_or_admin_permissions(collection_id: CollectionId, subject: T::AccountId) -> bool { let target_collection = >::get(collection_id); let mut result: bool = subject == target_collection.owner; let exists = >::contains_key(collection_id); @@ -1674,7 +1680,7 @@ } fn check_owner_or_admin_permissions( - collection_id: u64, + collection_id: CollectionId, subject: T::AccountId, ) -> DispatchResult { Self::collection_exists(collection_id)?; @@ -1687,7 +1693,7 @@ Ok(()) } - fn is_item_owner(subject: T::AccountId, collection_id: u64, item_id: u64) -> bool { + fn is_item_owner(subject: T::AccountId, collection_id: CollectionId, item_id: TokenId) -> bool { let target_collection = >::get(collection_id); match target_collection.mode { @@ -1707,7 +1713,7 @@ } } - fn check_white_list(collection_id: u64, address: &T::AccountId) -> DispatchResult { + fn check_white_list(collection_id: CollectionId, address: &T::AccountId) -> DispatchResult { let mes = Error::::AddresNotInWhiteList; ensure!(>::contains_key(collection_id), mes); let wl = >::get(collection_id); @@ -1717,9 +1723,9 @@ } fn transfer_fungible( - collection_id: u64, - item_id: u64, - value: u64, + collection_id: CollectionId, + item_id: TokenId, + value: u128, owner: T::AccountId, new_owner: T::AccountId, ) -> DispatchResult { @@ -1731,7 +1737,7 @@ let full_item = >::get(collection_id, item_id); let amount = full_item.value; - ensure!(amount >= value.into(), Error::::TokenValueTooLow); + ensure!(amount >= value, Error::::TokenValueTooLow); // update balance let balance_old_owner = >::get(collection_id, owner.clone()) @@ -1745,10 +1751,8 @@ new_owner_account_id = new_owner_items[0]; } - let val64 = value.into(); - // transfer - if amount == val64 && new_owner_account_id == 0 { + if amount == value && new_owner_account_id == 0 { // change owner // new owner do not have account let mut new_full_item = full_item.clone(); @@ -1765,13 +1769,13 @@ Self::move_token_index(collection_id, item_id, owner.clone(), new_owner.clone())?; } else { let mut new_full_item = full_item.clone(); - new_full_item.value -= val64; + new_full_item.value -= value; // separate amount if new_owner_account_id > 0 { // new owner has account let mut item = >::get(collection_id, new_owner_account_id); - item.value += val64; + item.value += value; // update balance let balance_new_owner = >::get(collection_id, new_owner.clone()) @@ -1785,13 +1789,13 @@ let item = FungibleItemType { collection: collection_id, owner: new_owner.clone(), - value: val64, + value }; Self::add_fungible_item(item)?; } - if amount == val64 { + if amount == value { Self::remove_token_index(collection_id, item_id, full_item.owner.clone())?; // remove approve list @@ -1806,9 +1810,9 @@ } fn transfer_refungible( - collection_id: u64, - item_id: u64, - value: u64, + collection_id: CollectionId, + item_id: TokenId, + value: u128, owner: T::AccountId, new_owner: T::AccountId, ) -> DispatchResult { @@ -1826,7 +1830,7 @@ .ok_or(Error::::NumOverflow)?; let amount = item.fraction; - ensure!(amount >= value.into(), Error::::TokenValueTooLow); + ensure!(amount >= value, Error::::TokenValueTooLow); // update balance let balance_old_owner = >::get(collection_id, item.owner.clone()) @@ -1841,10 +1845,9 @@ let old_owner = item.owner.clone(); let new_owner_has_account = full_item.owner.iter().any(|i| i.owner == new_owner); - let val64 = value.into(); // transfer - if amount == val64 && !new_owner_has_account { + if amount == value && !new_owner_has_account { // change owner // new owner do not have account let mut new_full_item = full_item.clone(); @@ -1865,7 +1868,7 @@ .iter_mut() .find(|i| i.owner == owner) .unwrap() - .fraction -= val64; + .fraction -= value; // separate amount if new_owner_has_account { @@ -1875,12 +1878,12 @@ .iter_mut() .find(|i| i.owner == new_owner) .unwrap() - .fraction += val64; + .fraction += value; } else { // new owner do not have account new_full_item.owner.push(Ownership { owner: new_owner.clone(), - fraction: val64, + fraction: value, }); Self::add_token_index(collection_id, item_id, new_owner.clone())?; } @@ -1892,8 +1895,8 @@ } fn transfer_nft( - collection_id: u64, - item_id: u64, + collection_id: CollectionId, + item_id: TokenId, sender: T::AccountId, new_owner: T::AccountId, ) -> DispatchResult { @@ -1934,8 +1937,8 @@ } fn item_exists( - collection_id: u64, - item_id: u64, + collection_id: CollectionId, + item_id: TokenId, mode: &CollectionMode ) -> DispatchResult { match mode { @@ -1949,8 +1952,8 @@ } fn set_re_fungible_variable_data( - collection_id: u64, - item_id: u64, + collection_id: CollectionId, + item_id: TokenId, data: Vec ) -> DispatchResult { let mut item = >::get(collection_id, item_id); @@ -1963,8 +1966,8 @@ } fn set_nft_variable_data( - collection_id: u64, - item_id: u64, + collection_id: CollectionId, + item_id: TokenId, data: Vec ) -> DispatchResult { let mut item = >::get(collection_id, item_id); @@ -1979,8 +1982,8 @@ fn init_collection(item: &CollectionType) { // check params assert!( - item.decimal_points <= 4, - "decimal_points parameter must be lower than 4" + item.decimal_points <= MAX_DECIMAL_POINTS, + "decimal_points parameter must be lower than MAX_DECIMAL_POINTS" ); assert!( item.name.len() <= 64, @@ -2026,7 +2029,6 @@ .checked_add(1) .unwrap(); let owner = item.owner.clone(); - let value = item.value as u64; Self::add_token_index(item.collection, current_index, owner.clone()).unwrap(); @@ -2034,7 +2036,7 @@ // Update balance let new_balance = >::get(item.collection, owner.clone()) - .checked_add(value) + .checked_add(item.value) .unwrap(); >::insert(item.collection, owner.clone(), new_balance); } @@ -2044,7 +2046,7 @@ .checked_add(1) .unwrap(); - let value = item.owner.first().unwrap().fraction as u64; + let value = item.owner.first().unwrap().fraction; let owner = item.owner.first().unwrap().owner.clone(); Self::add_token_index(item.collection, current_index, owner.clone()).unwrap(); @@ -2058,7 +2060,7 @@ >::insert(item.collection, owner.clone(), new_balance); } - fn add_token_index(collection_id: u64, item_index: u64, owner: T::AccountId) -> DispatchResult { + fn add_token_index(collection_id: CollectionId, item_index: TokenId, owner: T::AccountId) -> DispatchResult { // add to account limit if >::contains_key(owner.clone()) { @@ -2096,8 +2098,8 @@ } fn remove_token_index( - collection_id: u64, - item_index: u64, + collection_id: CollectionId, + item_index: TokenId, owner: T::AccountId, ) -> DispatchResult { @@ -2123,8 +2125,8 @@ } fn move_token_index( - collection_id: u64, - item_index: u64, + collection_id: CollectionId, + item_index: TokenId, old_owner: T::AccountId, new_owner: T::AccountId, ) -> DispatchResult { --- a/pallets/nft/src/tests.rs +++ b/pallets/nft/src/tests.rs @@ -2,11 +2,12 @@ use super::*; use crate::mock::*; use crate::{AccessMode, ApprovePermissions, CollectionMode, - Ownership, ChainLimits, CreateItemData, CreateNftData, CreateFungibleData, CreateReFungibleData}; //Err + Ownership, ChainLimits, CreateItemData, CreateNftData, CreateFungibleData, CreateReFungibleData, + CollectionId, TokenId, MAX_DECIMAL_POINTS}; //Err use frame_support::{assert_noop, assert_ok}; use frame_system::{ RawOrigin }; -fn default_collection_numbers_limit() -> u64 { +fn default_collection_numbers_limit() -> u32 { 10 } @@ -34,7 +35,7 @@ CreateReFungibleData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] } } -fn create_test_collection_for_owner(mode: &CollectionMode, owner: u64, id: u64) -> u64 { +fn create_test_collection_for_owner(mode: &CollectionMode, owner: u64, id: CollectionId) -> CollectionId { 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(); @@ -59,11 +60,11 @@ id } -fn create_test_collection(mode: &CollectionMode, id: u64) -> u64 { +fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId { create_test_collection_for_owner(&mode, 1, id) } -fn create_test_item(collection_id: u64, data: &CreateItemData) { +fn create_test_item(collection_id: CollectionId, data: &CreateItemData) { let origin1 = Origin::signed(1); assert_ok!(TemplateModule::create_item( origin1.clone(), @@ -77,6 +78,46 @@ // Use cases tests region // #region #[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(); + + let origin1 = Origin::signed(1); + assert_noop!(TemplateModule::create_collection( + origin1, + col_name1, + col_desc1, + token_prefix1, + CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1) + ), Error::::CollectionDecimalPointLimitExceeded); + }); +} + +#[test] +fn create_re_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(); + + let origin1 = Origin::signed(1); + assert_noop!(TemplateModule::create_collection( + origin1, + col_name1, + col_desc1, + token_prefix1, + CollectionMode::ReFungible(MAX_DECIMAL_POINTS + 1) + ), Error::::CollectionDecimalPointLimitExceeded); + }); +} + +#[test] fn create_nft_item() { new_test_ext().execute_with(|| { default_limits(); @@ -109,8 +150,8 @@ items_data.clone().into_iter().map(|d| { d.into() }).collect() )); for (index, data) in items_data.iter().enumerate() { - assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as u64).const_data.to_vec(), data.const_data); - assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as u64).variable_data.to_vec(), data.variable_data); + assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as TokenId).const_data.to_vec(), data.const_data); + assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as TokenId).variable_data.to_vec(), data.variable_data); } }); } @@ -160,7 +201,7 @@ )); for (index, data) in items_data.iter().enumerate() { - let item = TemplateModule::refungible_item_id(1, (index + 1) as u64); + let item = TemplateModule::refungible_item_id(1, (index + 1) as TokenId); assert_eq!(item.const_data.to_vec(), data.const_data); assert_eq!(item.variable_data.to_vec(), data.variable_data); assert_eq!( @@ -207,7 +248,7 @@ )); for (index, _) in items_data.iter().enumerate() { - assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as u64).owner, 1); + assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as TokenId).owner, 1); } assert_eq!(TemplateModule::balance_count(1, 1), 3000); assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]); -- gitstuff