difftreelog
Merge pull request #197 from UniqueNetwork/feature/CORE-167
in: master
Limits logic fixed. Tests added
5 files changed
pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -306,9 +306,6 @@
/// Amount of collections destroyed, used for total amount tracking with
/// CreatedCollectionCount
DestroyedCollectionCount: u32;
- /// Total amount of account owned tokens (NFTs + RFTs + unique fungibles)
- /// Account id (real)
- pub AccountItemCount get(fn account_item_count): map hasher(twox_64_concat) T::AccountId => u32;
//#endregion
//#region Basic collections
@@ -1125,6 +1122,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let collection = Self::get_collection(collection_id)?;
+ Self::meta_update_check(&sender, &collection, item_id)?;
Self::set_variable_meta_data_internal(&sender, &collection, item_id, data)?;
@@ -1647,11 +1645,19 @@
collection.consume_sload()?;
let account_items: u32 =
<AddressTokens<T>>::get(collection_id, recipient.as_sub()).len() as u32;
- ensure!(
- collection.limits.account_token_ownership_limit > account_items,
- Error::<T>::AccountTokenLimitExceeded
- );
+ // zero limit means collection limit is disabled
+ // otherwise get lower value
+ let limit = if collection.limits.account_token_ownership_limit == 0
+ || collection.limits.account_token_ownership_limit > ACCOUNT_TOKEN_OWNERSHIP_LIMIT
+ {
+ ACCOUNT_TOKEN_OWNERSHIP_LIMIT
+ } else {
+ collection.limits.account_token_ownership_limit
+ };
+
+ ensure!(limit > account_items, Error::<T>::AccountTokenLimitExceeded);
+
// preliminary transfer check
ensure!(collection.transfers_enabled, Error::<T>::TransferNotAllowed);
@@ -1674,12 +1680,23 @@
as u32)
.checked_add(amount)
.ok_or(Error::<T>::AccountTokenLimitExceeded)?;
+
+ // zero limit means collection limit is disabled
+ // otherwise get lower value
+ let account_token_limit = if collection.limits.account_token_ownership_limit == 0
+ || collection.limits.account_token_ownership_limit > ACCOUNT_TOKEN_OWNERSHIP_LIMIT
+ {
+ ACCOUNT_TOKEN_OWNERSHIP_LIMIT
+ } else {
+ collection.limits.account_token_ownership_limit
+ };
+
ensure!(
collection.limits.token_limit >= total_items,
Error::<T>::CollectionTokenLimitExceeded
);
ensure!(
- collection.limits.account_token_ownership_limit >= account_items,
+ account_token_limit >= account_items,
Error::<T>::AccountTokenLimitExceeded
);
@@ -2409,32 +2426,19 @@
item_index: TokenId,
owner: &T::CrossAccountId,
) -> DispatchResult {
- // add to account limit
collection.consume_sload()?;
- if <AccountItemCount<T>>::contains_key(owner.as_sub()) {
- // bound Owned tokens by a single address
+ let list_exists = <AddressTokens<T>>::contains_key(collection.id, owner.as_sub());
+ if list_exists {
collection.consume_sload()?;
- let count = <AccountItemCount<T>>::get(owner.as_sub());
+ let mut list = <AddressTokens<T>>::get(collection.id, owner.as_sub());
+
+ // bound Owned tokens by a single address in collection
+ let account_items: u32 = list.len() as u32;
ensure!(
- count < ACCOUNT_TOKEN_OWNERSHIP_LIMIT,
+ account_items < ACCOUNT_TOKEN_OWNERSHIP_LIMIT,
Error::<T>::AddressOwnershipLimitExceeded
);
- collection.consume_sstore()?;
- <AccountItemCount<T>>::insert(
- owner.as_sub(),
- count.checked_add(1).ok_or(Error::<T>::NumOverflow)?,
- );
- } else {
- collection.consume_sstore()?;
- <AccountItemCount<T>>::insert(owner.as_sub(), 1);
- }
-
- collection.consume_sload()?;
- let list_exists = <AddressTokens<T>>::contains_key(collection.id, owner.as_sub());
- if list_exists {
- collection.consume_sload()?;
- let mut list = <AddressTokens<T>>::get(collection.id, owner.as_sub());
let item_contains = list.contains(&item_index.clone());
if !item_contains {
@@ -2457,16 +2461,6 @@
item_index: TokenId,
owner: &T::CrossAccountId,
) -> DispatchResult {
- // update counter
- collection.consume_sload()?;
- collection.consume_sstore()?;
- <AccountItemCount<T>>::insert(
- owner.as_sub(),
- <AccountItemCount<T>>::get(owner.as_sub())
- .checked_sub(1)
- .ok_or(Error::<T>::NumOverflow)?,
- );
-
collection.consume_sload()?;
let list_exists = <AddressTokens<T>>::contains_key(collection.id, owner.as_sub());
if list_exists {
pallets/nft/src/sponsorship.rsdiffbeforeafterboth--- a/pallets/nft/src/sponsorship.rs
+++ b/pallets/nft/src/sponsorship.rs
@@ -61,10 +61,15 @@
sponsor_transfer = match collection_mode {
CollectionMode::NFT => {
// get correct limit
- let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
- collection_limits.sponsor_transfer_timeout
+ let limit: u32 = if collection_limits.sponsor_transfer_timeout != 0 {
+ if collection_limits.sponsor_transfer_timeout > NFT_SPONSOR_TRANSFER_TIMEOUT
+ {
+ collection_limits.sponsor_transfer_timeout
+ } else {
+ NFT_SPONSOR_TRANSFER_TIMEOUT
+ }
} else {
- NFT_SPONSOR_TRANSFER_TIMEOUT
+ 0
};
let mut sponsored = true;
@@ -83,13 +88,18 @@
}
CollectionMode::Fungible(_) => {
// get correct limit
- let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
- collection_limits.sponsor_transfer_timeout
+ let limit: u32 = if collection_limits.sponsor_transfer_timeout != 0 {
+ if collection_limits.sponsor_transfer_timeout
+ > FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
+ {
+ collection_limits.sponsor_transfer_timeout
+ } else {
+ FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
+ }
} else {
- FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
+ 0
};
- let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
let mut sponsored = true;
if FungibleTransferBasket::<T>::contains_key(collection_id, who) {
let last_tx_block = FungibleTransferBasket::<T>::get(collection_id, who);
@@ -106,10 +116,16 @@
}
CollectionMode::ReFungible => {
// get correct limit
- let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
- collection_limits.sponsor_transfer_timeout
+ let limit: u32 = if collection_limits.sponsor_transfer_timeout != 0 {
+ if collection_limits.sponsor_transfer_timeout
+ > REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
+ {
+ collection_limits.sponsor_transfer_timeout
+ } else {
+ REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
+ }
} else {
- REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
+ 0
};
let mut sponsored = true;
pallets/nft/src/tests.rsdiffbeforeafterboth1// Tests to be written here2use super::*;3use crate::mock::*;4use crate::{AccessMode, CollectionMode, Ownership, CreateItemData};5use nft_data_structs::{6 CreateNftData, CreateFungibleData, CreateReFungibleData, CollectionId, TokenId,7 MAX_DECIMAL_POINTS,8};9use frame_support::{assert_noop, assert_ok};10use sp_std::convert::TryInto;1112fn default_nft_data() -> CreateNftData {13 CreateNftData {14 const_data: vec![1, 2, 3].try_into().unwrap(),15 variable_data: vec![3, 2, 1].try_into().unwrap(),16 }17}1819fn default_fungible_data() -> CreateFungibleData {20 CreateFungibleData { value: 5 }21}2223fn default_re_fungible_data() -> CreateReFungibleData {24 CreateReFungibleData {25 const_data: vec![1, 2, 3].try_into().unwrap(),26 variable_data: vec![3, 2, 1].try_into().unwrap(),27 pieces: 1023,28 }29}3031fn create_test_collection_for_owner(32 mode: &CollectionMode,33 owner: u64,34 id: CollectionId,35) -> CollectionId {36 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();37 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();38 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();3940 let origin1 = Origin::signed(owner);41 assert_ok!(TemplateModule::create_collection(42 origin1,43 col_name1,44 col_desc1,45 token_prefix1,46 mode.clone()47 ));4849 let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();50 let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();51 let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();52 assert_eq!(TemplateModule::collection_id(id).unwrap().owner, owner);53 assert_eq!(54 TemplateModule::collection_id(id).unwrap().name,55 saved_col_name56 );57 assert_eq!(TemplateModule::collection_id(id).unwrap().mode, *mode);58 assert_eq!(59 TemplateModule::collection_id(id).unwrap().description,60 saved_description61 );62 assert_eq!(63 TemplateModule::collection_id(id).unwrap().token_prefix,64 saved_prefix65 );66 id67}6869fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {70 create_test_collection_for_owner(&mode, 1, id)71}7273fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {74 let origin1 = Origin::signed(1);75 assert_ok!(TemplateModule::create_item(76 origin1,77 collection_id,78 account(1),79 data.clone()80 ));81}8283fn account(sub: u64) -> TestCrossAccountId {84 TestCrossAccountId::from_sub(sub)85}8687// Use cases tests region88// #region8990#[test]91fn set_version_schema() {92 new_test_ext().execute_with(|| {93 let origin1 = Origin::signed(1);94 let collection_id = create_test_collection(&CollectionMode::NFT, 1);9596 assert_ok!(TemplateModule::set_schema_version(97 origin1,98 collection_id,99 SchemaVersion::Unique100 ));101 assert_eq!(102 TemplateModule::collection_id(collection_id)103 .unwrap()104 .schema_version,105 SchemaVersion::Unique106 );107 });108}109110#[test]111fn create_fungible_collection_fails_with_large_decimal_numbers() {112 new_test_ext().execute_with(|| {113 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();114 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();115 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();116117 let origin1 = Origin::signed(1);118 assert_noop!(119 TemplateModule::create_collection(120 origin1,121 col_name1,122 col_desc1,123 token_prefix1,124 CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1)125 ),126 Error::<Test>::CollectionDecimalPointLimitExceeded127 );128 });129}130131#[test]132fn create_nft_item() {133 new_test_ext().execute_with(|| {134 let collection_id = create_test_collection(&CollectionMode::NFT, 1);135136 let data = default_nft_data();137 create_test_item(collection_id, &data.clone().into());138 let item = TemplateModule::nft_item_id(collection_id, 1).unwrap();139 assert_eq!(item.const_data, data.const_data.into_inner());140 assert_eq!(item.variable_data, data.variable_data.into_inner());141 });142}143144// Use cases tests region145// #region146#[test]147fn create_nft_multiple_items() {148 new_test_ext().execute_with(|| {149 create_test_collection(&CollectionMode::NFT, 1);150151 let origin1 = Origin::signed(1);152153 let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];154155 assert_ok!(TemplateModule::create_multiple_items(156 origin1,157 1,158 account(1),159 items_data160 .clone()161 .into_iter()162 .map(|d| { d.into() })163 .collect()164 ));165 for (index, data) in items_data.into_iter().enumerate() {166 let item = TemplateModule::nft_item_id(1, (index + 1) as TokenId).unwrap();167 assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());168 assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());169 }170 });171}172173#[test]174fn create_refungible_item() {175 new_test_ext().execute_with(|| {176 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);177178 let data = default_re_fungible_data();179 create_test_item(collection_id, &data.clone().into());180 let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap();181 assert_eq!(item.const_data, data.const_data.into_inner());182 assert_eq!(item.variable_data, data.variable_data.into_inner());183 assert_eq!(184 item.owner[0],185 Ownership {186 owner: account(1),187 fraction: 1023188 }189 );190 });191}192193#[test]194fn create_multiple_refungible_items() {195 new_test_ext().execute_with(|| {196 create_test_collection(&CollectionMode::ReFungible, 1);197198 let origin1 = Origin::signed(1);199200 let items_data = vec![201 default_re_fungible_data(),202 default_re_fungible_data(),203 default_re_fungible_data(),204 ];205206 assert_ok!(TemplateModule::create_multiple_items(207 origin1,208 1,209 account(1),210 items_data211 .clone()212 .into_iter()213 .map(|d| { d.into() })214 .collect()215 ));216 for (index, data) in items_data.into_iter().enumerate() {217 let item = TemplateModule::refungible_item_id(1, (index + 1) as TokenId).unwrap();218 assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());219 assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());220 assert_eq!(221 item.owner[0],222 Ownership {223 owner: account(1),224 fraction: 1023225 }226 );227 }228 });229}230231#[test]232fn create_fungible_item() {233 new_test_ext().execute_with(|| {234 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);235236 let data = default_fungible_data();237 create_test_item(collection_id, &data.into());238239 assert_eq!(TemplateModule::fungible_item_id(collection_id, 1).value, 5);240 });241}242243//#[test]244// fn create_multiple_fungible_items() {245// new_test_ext().execute_with(|| {246// default_limits();247248// create_test_collection(&CollectionMode::Fungible(3), 1);249250// let origin1 = Origin::signed(1);251252// let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];253254// assert_ok!(TemplateModule::create_multiple_items(255// origin1.clone(),256// 1,257// 1,258// items_data.clone().into_iter().map(|d| { d.into() }).collect()259// ));260261// for (index, _) in items_data.iter().enumerate() {262// assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as TokenId).value, 5);263// }264// assert_eq!(TemplateModule::balance_count(1, 1), 3000);265// assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]);266// });267// }268269#[test]270fn transfer_fungible_item() {271 new_test_ext().execute_with(|| {272 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);273274 let origin1 = Origin::signed(1);275 let origin2 = Origin::signed(2);276277 let data = default_fungible_data();278 create_test_item(collection_id, &data.into());279280 assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 5);281 assert_eq!(TemplateModule::balance_count(1, 1), 5);282283 // change owner scenario284 assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 5));285 assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 0);286 assert_eq!(TemplateModule::balance_count(1, 1), 0);287 assert_eq!(TemplateModule::balance_count(1, 2), 5);288289 // split item scenario290 assert_ok!(TemplateModule::transfer(291 origin2.clone(),292 account(3),293 1,294 1,295 3296 ));297 assert_eq!(TemplateModule::balance_count(1, 2), 2);298 assert_eq!(TemplateModule::balance_count(1, 3), 3);299300 // split item and new owner has account scenario301 assert_ok!(TemplateModule::transfer(origin2, account(3), 1, 1, 1));302 assert_eq!(TemplateModule::fungible_item_id(1, 2).value, 1);303 assert_eq!(TemplateModule::fungible_item_id(1, 3).value, 4);304 assert_eq!(TemplateModule::balance_count(1, 2), 1);305 assert_eq!(TemplateModule::balance_count(1, 3), 4);306 });307}308309#[test]310fn transfer_refungible_item() {311 new_test_ext().execute_with(|| {312 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);313314 let data = default_re_fungible_data();315 create_test_item(collection_id, &data.clone().into());316317 let origin1 = Origin::signed(1);318 let origin2 = Origin::signed(2);319 {320 let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap();321 assert_eq!(item.const_data, data.const_data.into_inner());322 assert_eq!(item.variable_data, data.variable_data.into_inner());323 assert_eq!(324 item.owner[0],325 Ownership {326 owner: account(1),327 fraction: 1023328 }329 );330 }331 assert_eq!(TemplateModule::balance_count(1, 1), 1023);332 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);333334 // change owner scenario335 assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1023));336 assert_eq!(337 TemplateModule::refungible_item_id(1, 1).unwrap().owner[0],338 Ownership {339 owner: account(2),340 fraction: 1023341 }342 );343 assert_eq!(TemplateModule::balance_count(1, 1), 0);344 assert_eq!(TemplateModule::balance_count(1, 2), 1023);345 // assert_eq!(TemplateModule::address_tokens(1, 1), []);346 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);347348 // split item scenario349 assert_ok!(TemplateModule::transfer(350 origin2.clone(),351 account(3),352 1,353 1,354 500355 ));356 {357 let item = TemplateModule::refungible_item_id(1, 1).unwrap();358 assert_eq!(359 item.owner[0],360 Ownership {361 owner: account(2),362 fraction: 523363 }364 );365 assert_eq!(366 item.owner[1],367 Ownership {368 owner: account(3),369 fraction: 500370 }371 );372 }373 assert_eq!(TemplateModule::balance_count(1, 2), 523);374 assert_eq!(TemplateModule::balance_count(1, 3), 500);375 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);376 assert_eq!(TemplateModule::address_tokens(1, 3), [1]);377378 // split item and new owner has account scenario379 assert_ok!(TemplateModule::transfer(origin2, account(3), 1, 1, 200));380 {381 let item = TemplateModule::refungible_item_id(1, 1).unwrap();382 assert_eq!(383 item.owner[0],384 Ownership {385 owner: account(2),386 fraction: 323387 }388 );389 assert_eq!(390 item.owner[1],391 Ownership {392 owner: account(3),393 fraction: 700394 }395 );396 }397 assert_eq!(TemplateModule::balance_count(1, 2), 323);398 assert_eq!(TemplateModule::balance_count(1, 3), 700);399 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);400 assert_eq!(TemplateModule::address_tokens(1, 3), [1]);401 });402}403404#[test]405fn transfer_nft_item() {406 new_test_ext().execute_with(|| {407 let collection_id = create_test_collection(&CollectionMode::NFT, 1);408409 let data = default_nft_data();410 create_test_item(collection_id, &data.into());411 assert_eq!(TemplateModule::balance_count(1, 1), 1);412 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);413414 let origin1 = Origin::signed(1);415 // default scenario416 assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1000));417 assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(2));418 assert_eq!(TemplateModule::balance_count(1, 1), 0);419 assert_eq!(TemplateModule::balance_count(1, 2), 1);420 // assert_eq!(TemplateModule::address_tokens(1, 1), []);421 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);422 });423}424425#[test]426fn nft_approve_and_transfer_from() {427 new_test_ext().execute_with(|| {428 let collection_id = create_test_collection(&CollectionMode::NFT, 1);429430 let data = default_nft_data();431 create_test_item(collection_id, &data.into());432433 let origin1 = Origin::signed(1);434 let origin2 = Origin::signed(2);435436 assert_eq!(TemplateModule::balance_count(1, 1), 1);437 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);438439 // neg transfer440 assert_noop!(441 TemplateModule::transfer_from(origin2.clone(), account(1), account(2), 1, 1, 1),442 Error::<Test>::NoPermission443 );444445 // do approve446 assert_ok!(TemplateModule::approve(origin1, account(2), 1, 1, 5));447 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);448 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);449450 assert_ok!(TemplateModule::transfer_from(451 origin2,452 account(1),453 account(3),454 1,455 1,456 1457 ));458 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 4);459 });460}461462#[test]463fn nft_approve_and_transfer_from_white_list() {464 new_test_ext().execute_with(|| {465 let collection_id = create_test_collection(&CollectionMode::NFT, 1);466467 let origin1 = Origin::signed(1);468 let origin2 = Origin::signed(2);469470 let data = default_nft_data();471 create_test_item(collection_id, &data.clone().into());472473 assert_eq!(474 &TemplateModule::nft_item_id(1, 1).unwrap().const_data,475 &data.const_data.into_inner()476 );477 assert_eq!(TemplateModule::balance_count(1, 1), 1);478 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);479480 assert_ok!(TemplateModule::set_mint_permission(481 origin1.clone(),482 1,483 true484 ));485 assert_ok!(TemplateModule::set_public_access_mode(486 origin1.clone(),487 1,488 AccessMode::WhiteList489 ));490 assert_ok!(TemplateModule::add_to_white_list(491 origin1.clone(),492 1,493 account(1)494 ));495 assert_ok!(TemplateModule::add_to_white_list(496 origin1.clone(),497 1,498 account(2)499 ));500 assert_ok!(TemplateModule::add_to_white_list(501 origin1.clone(),502 1,503 account(3)504 ));505506 // do approve507 assert_ok!(TemplateModule::approve(508 origin1.clone(),509 account(2),510 1,511 1,512 5513 ));514 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);515 assert_ok!(TemplateModule::approve(origin1, account(3), 1, 1, 5));516 assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);517518 assert_ok!(TemplateModule::transfer_from(519 origin2,520 account(1),521 account(3),522 1,523 1,524 1525 ));526 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 4);527 });528}529530#[test]531fn refungible_approve_and_transfer_from() {532 new_test_ext().execute_with(|| {533 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);534535 let origin1 = Origin::signed(1);536 let origin2 = Origin::signed(2);537538 let data = default_re_fungible_data();539 create_test_item(collection_id, &data.into());540541 assert_eq!(TemplateModule::balance_count(1, 1), 1023);542 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);543544 assert_ok!(TemplateModule::set_mint_permission(545 origin1.clone(),546 1,547 true548 ));549 assert_ok!(TemplateModule::set_public_access_mode(550 origin1.clone(),551 1,552 AccessMode::WhiteList553 ));554 assert_ok!(TemplateModule::add_to_white_list(555 origin1.clone(),556 1,557 account(1)558 ));559 assert_ok!(TemplateModule::add_to_white_list(560 origin1.clone(),561 1,562 account(2)563 ));564 assert_ok!(TemplateModule::add_to_white_list(565 origin1.clone(),566 1,567 account(3)568 ));569570 // do approve571 assert_ok!(TemplateModule::approve(origin1, account(2), 1, 1, 1023));572 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1023);573574 assert_ok!(TemplateModule::transfer_from(575 origin2,576 account(1),577 account(3),578 1,579 1,580 100581 ));582 assert_eq!(TemplateModule::balance_count(1, 1), 923);583 assert_eq!(TemplateModule::balance_count(1, 3), 100);584 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);585 assert_eq!(TemplateModule::address_tokens(1, 3), [1]);586587 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 923);588 });589}590591#[test]592fn fungible_approve_and_transfer_from() {593 new_test_ext().execute_with(|| {594 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);595596 let data = default_fungible_data();597 create_test_item(collection_id, &data.into());598599 let origin1 = Origin::signed(1);600 let origin2 = Origin::signed(2);601602 assert_eq!(TemplateModule::balance_count(1, 1), 5);603604 assert_ok!(TemplateModule::set_mint_permission(605 origin1.clone(),606 1,607 true608 ));609 assert_ok!(TemplateModule::set_public_access_mode(610 origin1.clone(),611 1,612 AccessMode::WhiteList613 ));614 assert_ok!(TemplateModule::add_to_white_list(615 origin1.clone(),616 1,617 account(1)618 ));619 assert_ok!(TemplateModule::add_to_white_list(620 origin1.clone(),621 1,622 account(2)623 ));624 assert_ok!(TemplateModule::add_to_white_list(625 origin1.clone(),626 1,627 account(3)628 ));629630 // do approve631 assert_ok!(TemplateModule::approve(632 origin1.clone(),633 account(2),634 1,635 1,636 5637 ));638 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);639 assert_ok!(TemplateModule::approve(origin1, account(3), 1, 1, 5));640 assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);641 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);642643 assert_ok!(TemplateModule::transfer_from(644 origin2.clone(),645 account(1),646 account(3),647 1,648 1,649 4650 ));651 assert_eq!(TemplateModule::balance_count(1, 1), 1);652 assert_eq!(TemplateModule::balance_count(1, 3), 4);653654 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);655656 assert_noop!(657 TemplateModule::transfer_from(origin2, account(1), account(3), 1, 1, 4),658 Error::<Test>::NoPermission659 );660 });661}662663#[test]664fn change_collection_owner() {665 new_test_ext().execute_with(|| {666 let collection_id = create_test_collection(&CollectionMode::NFT, 1);667668 let origin1 = Origin::signed(1);669 assert_ok!(TemplateModule::change_collection_owner(670 origin1,671 collection_id,672 2673 ));674 assert_eq!(675 TemplateModule::collection_id(collection_id).unwrap().owner,676 2677 );678 });679}680681#[test]682fn destroy_collection() {683 new_test_ext().execute_with(|| {684 let collection_id = create_test_collection(&CollectionMode::NFT, 1);685686 let origin1 = Origin::signed(1);687 assert_ok!(TemplateModule::destroy_collection(origin1, collection_id));688 });689}690691#[test]692fn burn_nft_item() {693 new_test_ext().execute_with(|| {694 let collection_id = create_test_collection(&CollectionMode::NFT, 1);695696 let origin1 = Origin::signed(1);697 assert_ok!(TemplateModule::add_collection_admin(698 origin1.clone(),699 collection_id,700 account(2)701 ));702703 let data = default_nft_data();704 create_test_item(collection_id, &data.into());705706 // check balance (collection with id = 1, user id = 1)707 assert_eq!(TemplateModule::balance_count(1, 1), 1);708709 // burn item710 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 5));711 assert_noop!(712 TemplateModule::burn_item(origin1, 1, 1, 5),713 Error::<Test>::TokenNotFound714 );715716 assert_eq!(TemplateModule::balance_count(1, 1), 0);717 });718}719720#[test]721fn burn_fungible_item() {722 new_test_ext().execute_with(|| {723 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);724725 let origin1 = Origin::signed(1);726 assert_ok!(TemplateModule::add_collection_admin(727 origin1.clone(),728 collection_id,729 account(2)730 ));731732 let data = default_fungible_data();733 create_test_item(collection_id, &data.into());734735 // check balance (collection with id = 1, user id = 1)736 assert_eq!(TemplateModule::balance_count(1, 1), 5);737738 // burn item739 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 5));740 assert_noop!(741 TemplateModule::burn_item(origin1, 1, 1, 5),742 Error::<Test>::TokenValueNotEnough743 );744745 assert_eq!(TemplateModule::balance_count(1, 1), 0);746 });747}748749#[test]750fn burn_refungible_item() {751 new_test_ext().execute_with(|| {752 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);753 let origin1 = Origin::signed(1);754755 assert_ok!(TemplateModule::set_mint_permission(756 origin1.clone(),757 collection_id,758 true759 ));760 assert_ok!(TemplateModule::set_public_access_mode(761 origin1.clone(),762 collection_id,763 AccessMode::WhiteList764 ));765 assert_ok!(TemplateModule::add_to_white_list(766 origin1.clone(),767 1,768 account(1)769 ));770771 assert_ok!(TemplateModule::add_collection_admin(772 origin1.clone(),773 1,774 account(2)775 ));776777 let data = default_re_fungible_data();778 create_test_item(collection_id, &data.into());779780 // check balance (collection with id = 1, user id = 2)781 assert_eq!(TemplateModule::balance_count(1, 1), 1023);782783 // burn item784 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 1023));785 assert_noop!(786 TemplateModule::burn_item(origin1, 1, 1, 1023),787 Error::<Test>::TokenNotFound788 );789790 assert_eq!(TemplateModule::balance_count(1, 1), 0);791 });792}793794#[test]795fn add_collection_admin() {796 new_test_ext().execute_with(|| {797 let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);798 create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);799 create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);800801 let origin1 = Origin::signed(1);802803 // collection admin804 assert_ok!(TemplateModule::add_collection_admin(805 origin1.clone(),806 collection1_id,807 account(2)808 ));809 assert_ok!(TemplateModule::add_collection_admin(810 origin1,811 collection1_id,812 account(3)813 ));814815 assert!(TemplateModule::admin_list_collection(collection1_id).contains(&account(2)),);816 assert!(TemplateModule::admin_list_collection(collection1_id).contains(&account(3)),);817 });818}819820#[test]821fn remove_collection_admin() {822 new_test_ext().execute_with(|| {823 let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);824 create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);825 create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);826827 let origin1 = Origin::signed(1);828 let origin2 = Origin::signed(2);829830 // collection admin831 assert_ok!(TemplateModule::add_collection_admin(832 origin1.clone(),833 collection1_id,834 account(2)835 ));836 assert_ok!(TemplateModule::add_collection_admin(837 origin1,838 collection1_id,839 account(3)840 ));841842 assert!(TemplateModule::admin_list_collection(1).contains(&account(2)),);843 assert!(TemplateModule::admin_list_collection(1).contains(&account(3)),);844845 // remove admin846 assert_ok!(TemplateModule::remove_collection_admin(847 origin2,848 1,849 account(3)850 ));851 assert!(!TemplateModule::admin_list_collection(1).contains(&account(3)),);852 });853}854855#[test]856fn balance_of() {857 new_test_ext().execute_with(|| {858 let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1);859 let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2);860 let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible, 3);861862 // check balance before863 assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 0);864 assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 0);865 assert_eq!(866 TemplateModule::balance_count(re_fungible_collection_id, 1),867 0868 );869870 let nft_data = default_nft_data();871 create_test_item(nft_collection_id, &nft_data.into());872873 let fungible_data = default_fungible_data();874 create_test_item(fungible_collection_id, &fungible_data.into());875876 let re_fungible_data = default_re_fungible_data();877 create_test_item(re_fungible_collection_id, &re_fungible_data.into());878879 // check balance (collection with id = 1, user id = 1)880 assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 1);881 assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 5);882 assert_eq!(883 TemplateModule::balance_count(re_fungible_collection_id, 1),884 1023885 );886 assert_eq!(887 TemplateModule::nft_item_id(nft_collection_id, 1)888 .unwrap()889 .owner,890 account(1)891 );892 assert_eq!(893 TemplateModule::fungible_item_id(fungible_collection_id, 1).value,894 5895 );896 assert_eq!(897 TemplateModule::refungible_item_id(re_fungible_collection_id, 1)898 .unwrap()899 .owner[0]900 .owner,901 account(1)902 );903 });904}905906#[test]907fn approve() {908 new_test_ext().execute_with(|| {909 let collection_id = create_test_collection(&CollectionMode::NFT, 1);910911 let data = default_nft_data();912 create_test_item(collection_id, &data.into());913914 let origin1 = Origin::signed(1);915916 // approve917 assert_ok!(TemplateModule::approve(origin1, account(2), 1, 1, 1));918 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);919 });920}921922#[test]923fn transfer_from() {924 new_test_ext().execute_with(|| {925 let collection_id = create_test_collection(&CollectionMode::NFT, 1);926 let origin1 = Origin::signed(1);927 let origin2 = Origin::signed(2);928929 let data = default_nft_data();930 create_test_item(collection_id, &data.into());931932 // approve933 assert_ok!(TemplateModule::approve(934 origin1.clone(),935 account(2),936 1,937 1,938 1939 ));940 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);941942 assert_ok!(TemplateModule::set_mint_permission(943 origin1.clone(),944 1,945 true946 ));947 assert_ok!(TemplateModule::set_public_access_mode(948 origin1.clone(),949 1,950 AccessMode::WhiteList951 ));952 assert_ok!(TemplateModule::add_to_white_list(953 origin1.clone(),954 1,955 account(1)956 ));957 assert_ok!(TemplateModule::add_to_white_list(958 origin1.clone(),959 1,960 account(2)961 ));962 assert_ok!(TemplateModule::add_to_white_list(origin1, 1, account(3)));963964 assert_ok!(TemplateModule::transfer_from(965 origin2,966 account(1),967 account(2),968 1,969 1,970 1971 ));972973 // after transfer974 assert_eq!(TemplateModule::balance_count(1, 1), 0);975 assert_eq!(TemplateModule::balance_count(1, 2), 1);976 });977}978979// #endregion980981// Coverage tests region982// #region983984#[test]985fn owner_can_add_address_to_white_list() {986 new_test_ext().execute_with(|| {987 let collection_id = create_test_collection(&CollectionMode::NFT, 1);988989 let origin1 = Origin::signed(1);990 assert_ok!(TemplateModule::add_to_white_list(991 origin1,992 collection_id,993 account(2)994 ));995 assert!(TemplateModule::white_list(collection_id, 2));996 });997}998999#[test]1000fn admin_can_add_address_to_white_list() {1001 new_test_ext().execute_with(|| {1002 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1003 let origin1 = Origin::signed(1);1004 let origin2 = Origin::signed(2);10051006 assert_ok!(TemplateModule::add_collection_admin(1007 origin1,1008 collection_id,1009 account(2)1010 ));1011 assert_ok!(TemplateModule::add_to_white_list(1012 origin2,1013 collection_id,1014 account(3)1015 ));1016 assert!(TemplateModule::white_list(collection_id, 3));1017 });1018}10191020#[test]1021fn nonprivileged_user_cannot_add_address_to_white_list() {1022 new_test_ext().execute_with(|| {1023 let collection_id = create_test_collection(&CollectionMode::NFT, 1);10241025 let origin2 = Origin::signed(2);1026 assert_noop!(1027 TemplateModule::add_to_white_list(origin2, collection_id, account(3)),1028 Error::<Test>::NoPermission1029 );1030 });1031}10321033#[test]1034fn nobody_can_add_address_to_white_list_of_nonexisting_collection() {1035 new_test_ext().execute_with(|| {1036 let origin1 = Origin::signed(1);10371038 assert_noop!(1039 TemplateModule::add_to_white_list(origin1, 1, account(2)),1040 Error::<Test>::CollectionNotFound1041 );1042 });1043}10441045#[test]1046fn nobody_can_add_address_to_white_list_of_deleted_collection() {1047 new_test_ext().execute_with(|| {1048 let collection_id = create_test_collection(&CollectionMode::NFT, 1);10491050 let origin1 = Origin::signed(1);1051 assert_ok!(TemplateModule::destroy_collection(1052 origin1.clone(),1053 collection_id1054 ));1055 assert_noop!(1056 TemplateModule::add_to_white_list(origin1, collection_id, account(2)),1057 Error::<Test>::CollectionNotFound1058 );1059 });1060}10611062// If address is already added to white list, nothing happens1063#[test]1064fn address_is_already_added_to_white_list() {1065 new_test_ext().execute_with(|| {1066 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1067 let origin1 = Origin::signed(1);10681069 assert_ok!(TemplateModule::add_to_white_list(1070 origin1.clone(),1071 collection_id,1072 account(2)1073 ));1074 assert_ok!(TemplateModule::add_to_white_list(1075 origin1,1076 collection_id,1077 account(2)1078 ));1079 assert!(TemplateModule::white_list(collection_id, 2));1080 });1081}10821083#[test]1084fn owner_can_remove_address_from_white_list() {1085 new_test_ext().execute_with(|| {1086 let collection_id = create_test_collection(&CollectionMode::NFT, 1);10871088 let origin1 = Origin::signed(1);1089 assert_ok!(TemplateModule::add_to_white_list(1090 origin1.clone(),1091 collection_id,1092 account(2)1093 ));1094 assert_ok!(TemplateModule::remove_from_white_list(1095 origin1,1096 collection_id,1097 account(2)1098 ));1099 assert!(!TemplateModule::white_list(collection_id, 2));1100 });1101}11021103#[test]1104fn admin_can_remove_address_from_white_list() {1105 new_test_ext().execute_with(|| {1106 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1107 let origin1 = Origin::signed(1);1108 let origin2 = Origin::signed(2);11091110 assert_ok!(TemplateModule::add_collection_admin(1111 origin1.clone(),1112 collection_id,1113 account(2)1114 ));11151116 assert_ok!(TemplateModule::add_to_white_list(1117 origin1,1118 collection_id,1119 account(3)1120 ));1121 assert_ok!(TemplateModule::remove_from_white_list(1122 origin2,1123 collection_id,1124 account(3)1125 ));1126 assert!(!TemplateModule::white_list(collection_id, 3));1127 });1128}11291130#[test]1131fn nonprivileged_user_cannot_remove_address_from_white_list() {1132 new_test_ext().execute_with(|| {1133 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1134 let origin1 = Origin::signed(1);1135 let origin2 = Origin::signed(2);11361137 assert_ok!(TemplateModule::add_to_white_list(1138 origin1,1139 collection_id,1140 account(2)1141 ));1142 assert_noop!(1143 TemplateModule::remove_from_white_list(origin2, collection_id, account(2)),1144 Error::<Test>::NoPermission1145 );1146 assert!(TemplateModule::white_list(collection_id, 2));1147 });1148}11491150#[test]1151fn nobody_can_remove_address_from_white_list_of_nonexisting_collection() {1152 new_test_ext().execute_with(|| {1153 let origin1 = Origin::signed(1);11541155 assert_noop!(1156 TemplateModule::remove_from_white_list(origin1, 1, account(2)),1157 Error::<Test>::CollectionNotFound1158 );1159 });1160}11611162#[test]1163fn nobody_can_remove_address_from_white_list_of_deleted_collection() {1164 new_test_ext().execute_with(|| {1165 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1166 let origin1 = Origin::signed(1);1167 let origin2 = Origin::signed(2);11681169 assert_ok!(TemplateModule::add_to_white_list(1170 origin1.clone(),1171 collection_id,1172 account(2)1173 ));1174 assert_ok!(TemplateModule::destroy_collection(origin1, collection_id));1175 assert_noop!(1176 TemplateModule::remove_from_white_list(origin2, collection_id, account(2)),1177 Error::<Test>::CollectionNotFound1178 );1179 assert!(!TemplateModule::white_list(collection_id, 2));1180 });1181}11821183// If address is already removed from white list, nothing happens1184#[test]1185fn address_is_already_removed_from_white_list() {1186 new_test_ext().execute_with(|| {1187 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1188 let origin1 = Origin::signed(1);11891190 assert_ok!(TemplateModule::add_to_white_list(1191 origin1.clone(),1192 collection_id,1193 account(2)1194 ));1195 assert_ok!(TemplateModule::remove_from_white_list(1196 origin1.clone(),1197 collection_id,1198 account(2)1199 ));1200 assert_ok!(TemplateModule::remove_from_white_list(1201 origin1,1202 collection_id,1203 account(2)1204 ));1205 assert!(!TemplateModule::white_list(collection_id, 2));1206 });1207}12081209// If Public Access mode is set to WhiteList, tokens can’t be transferred from a non-whitelisted address with transfer or transferFrom (2 tests)1210#[test]1211fn white_list_test_1() {1212 new_test_ext().execute_with(|| {1213 let collection_id = create_test_collection(&CollectionMode::NFT, 1);12141215 let origin1 = Origin::signed(1);12161217 let data = default_nft_data();1218 create_test_item(collection_id, &data.into());12191220 assert_ok!(TemplateModule::set_public_access_mode(1221 origin1.clone(),1222 collection_id,1223 AccessMode::WhiteList1224 ));1225 assert_ok!(TemplateModule::add_to_white_list(1226 origin1.clone(),1227 collection_id,1228 account(2)1229 ));12301231 assert_noop!(1232 TemplateModule::transfer(origin1, account(3), 1, 1, 1),1233 Error::<Test>::AddresNotInWhiteList1234 );1235 });1236}12371238#[test]1239fn white_list_test_2() {1240 new_test_ext().execute_with(|| {1241 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1242 let origin1 = Origin::signed(1);12431244 let data = default_nft_data();1245 create_test_item(collection_id, &data.into());12461247 assert_ok!(TemplateModule::set_public_access_mode(1248 origin1.clone(),1249 collection_id,1250 AccessMode::WhiteList1251 ));1252 assert_ok!(TemplateModule::add_to_white_list(1253 origin1.clone(),1254 1,1255 account(1)1256 ));1257 assert_ok!(TemplateModule::add_to_white_list(1258 origin1.clone(),1259 1,1260 account(2)1261 ));12621263 // do approve1264 assert_ok!(TemplateModule::approve(1265 origin1.clone(),1266 account(1),1267 1,1268 1,1269 11270 ));1271 assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);12721273 assert_ok!(TemplateModule::remove_from_white_list(1274 origin1.clone(),1275 1,1276 account(1)1277 ));12781279 assert_noop!(1280 TemplateModule::transfer_from(origin1, account(1), account(3), 1, 1, 1),1281 Error::<Test>::AddresNotInWhiteList1282 );1283 });1284}12851286// If Public Access mode is set to WhiteList, tokens can’t be transferred to a non-whitelisted address with transfer or transferFrom (2 tests)1287#[test]1288fn white_list_test_3() {1289 new_test_ext().execute_with(|| {1290 let collection_id = create_test_collection(&CollectionMode::NFT, 1);12911292 let origin1 = Origin::signed(1);12931294 let data = default_nft_data();1295 create_test_item(collection_id, &data.into());12961297 assert_ok!(TemplateModule::set_public_access_mode(1298 origin1.clone(),1299 collection_id,1300 AccessMode::WhiteList1301 ));1302 assert_ok!(TemplateModule::add_to_white_list(1303 origin1.clone(),1304 1,1305 account(1)1306 ));13071308 assert_noop!(1309 TemplateModule::transfer(origin1, account(3), 1, 1, 1),1310 Error::<Test>::AddresNotInWhiteList1311 );1312 });1313}13141315#[test]1316fn white_list_test_4() {1317 new_test_ext().execute_with(|| {1318 let collection_id = create_test_collection(&CollectionMode::NFT, 1);13191320 let origin1 = Origin::signed(1);13211322 let data = default_nft_data();1323 create_test_item(collection_id, &data.into());13241325 assert_ok!(TemplateModule::set_public_access_mode(1326 origin1.clone(),1327 collection_id,1328 AccessMode::WhiteList1329 ));1330 assert_ok!(TemplateModule::add_to_white_list(1331 origin1.clone(),1332 collection_id,1333 account(1)1334 ));1335 assert_ok!(TemplateModule::add_to_white_list(1336 origin1.clone(),1337 collection_id,1338 account(2)1339 ));13401341 // do approve1342 assert_ok!(TemplateModule::approve(1343 origin1.clone(),1344 account(1),1345 1,1346 1,1347 11348 ));1349 assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);13501351 assert_ok!(TemplateModule::remove_from_white_list(1352 origin1.clone(),1353 collection_id,1354 account(2)1355 ));13561357 assert_noop!(1358 TemplateModule::transfer_from(origin1, account(1), account(3), 1, 1, 1),1359 Error::<Test>::AddresNotInWhiteList1360 );1361 });1362}13631364// If Public Access mode is set to WhiteList, tokens can’t be destroyed by a non-whitelisted address (even if it owned them before enabling WhiteList mode)1365#[test]1366fn white_list_test_5() {1367 new_test_ext().execute_with(|| {1368 let collection_id = create_test_collection(&CollectionMode::NFT, 1);13691370 let origin1 = Origin::signed(1);13711372 let data = default_nft_data();1373 create_test_item(collection_id, &data.into());13741375 assert_ok!(TemplateModule::set_public_access_mode(1376 origin1.clone(),1377 collection_id,1378 AccessMode::WhiteList1379 ));1380 assert_noop!(1381 TemplateModule::burn_item(origin1, 1, 1, 5),1382 Error::<Test>::AddresNotInWhiteList1383 );1384 });1385}13861387// If Public Access mode is set to WhiteList, token transfers can’t be Approved by a non-whitelisted address (see Approve method).1388#[test]1389fn white_list_test_6() {1390 new_test_ext().execute_with(|| {1391 let collection_id = create_test_collection(&CollectionMode::NFT, 1);13921393 let origin1 = Origin::signed(1);13941395 let data = default_nft_data();1396 create_test_item(collection_id, &data.into());13971398 assert_ok!(TemplateModule::set_public_access_mode(1399 origin1.clone(),1400 collection_id,1401 AccessMode::WhiteList1402 ));14031404 // do approve1405 assert_noop!(1406 TemplateModule::approve(origin1, account(1), 1, 1, 5),1407 Error::<Test>::AddresNotInWhiteList1408 );1409 });1410}14111412// If Public Access mode is set to WhiteList, tokens can be transferred from a whitelisted address with transfer or transferFrom (2 tests) and1413// tokens can be transferred from a whitelisted address with transfer or transferFrom (2 tests)1414#[test]1415fn white_list_test_7() {1416 new_test_ext().execute_with(|| {1417 let collection_id = create_test_collection(&CollectionMode::NFT, 1);14181419 let data = default_nft_data();1420 create_test_item(collection_id, &data.into());14211422 let origin1 = Origin::signed(1);14231424 assert_ok!(TemplateModule::set_public_access_mode(1425 origin1.clone(),1426 collection_id,1427 AccessMode::WhiteList1428 ));1429 assert_ok!(TemplateModule::add_to_white_list(1430 origin1.clone(),1431 collection_id,1432 account(1)1433 ));1434 assert_ok!(TemplateModule::add_to_white_list(1435 origin1.clone(),1436 collection_id,1437 account(2)1438 ));14391440 assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1));1441 });1442}14431444#[test]1445fn white_list_test_8() {1446 new_test_ext().execute_with(|| {1447 let collection_id = create_test_collection(&CollectionMode::NFT, 1);14481449 let data = default_nft_data();1450 create_test_item(collection_id, &data.into());14511452 let origin1 = Origin::signed(1);14531454 assert_ok!(TemplateModule::set_public_access_mode(1455 origin1.clone(),1456 collection_id,1457 AccessMode::WhiteList1458 ));1459 assert_ok!(TemplateModule::add_to_white_list(1460 origin1.clone(),1461 collection_id,1462 account(1)1463 ));1464 assert_ok!(TemplateModule::add_to_white_list(1465 origin1.clone(),1466 collection_id,1467 account(2)1468 ));14691470 // do approve1471 assert_ok!(TemplateModule::approve(1472 origin1.clone(),1473 account(1),1474 1,1475 1,1476 51477 ));1478 assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 5);14791480 assert_ok!(TemplateModule::transfer_from(1481 origin1,1482 account(1),1483 account(2),1484 1,1485 1,1486 11487 ));1488 });1489}14901491// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens can be created by owner.1492#[test]1493fn white_list_test_9() {1494 new_test_ext().execute_with(|| {1495 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1496 let origin1 = Origin::signed(1);14971498 assert_ok!(TemplateModule::set_public_access_mode(1499 origin1.clone(),1500 collection_id,1501 AccessMode::WhiteList1502 ));1503 assert_ok!(TemplateModule::set_mint_permission(1504 origin1,1505 collection_id,1506 false1507 ));15081509 let data = default_nft_data();1510 create_test_item(collection_id, &data.into());1511 });1512}15131514// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens can be created by admin.1515#[test]1516fn white_list_test_10() {1517 new_test_ext().execute_with(|| {1518 let collection_id = create_test_collection(&CollectionMode::NFT, 1);15191520 let origin1 = Origin::signed(1);1521 let origin2 = Origin::signed(2);15221523 assert_ok!(TemplateModule::set_public_access_mode(1524 origin1.clone(),1525 collection_id,1526 AccessMode::WhiteList1527 ));1528 assert_ok!(TemplateModule::set_mint_permission(1529 origin1.clone(),1530 collection_id,1531 false1532 ));15331534 assert_ok!(TemplateModule::add_collection_admin(1535 origin1,1536 collection_id,1537 account(2)1538 ));15391540 assert_ok!(TemplateModule::create_item(1541 origin2,1542 collection_id,1543 account(2),1544 default_nft_data().into()1545 ));1546 });1547}15481549// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens cannot be created by non-privileged and white listed address.1550#[test]1551fn white_list_test_11() {1552 new_test_ext().execute_with(|| {1553 let collection_id = create_test_collection(&CollectionMode::NFT, 1);15541555 let origin1 = Origin::signed(1);1556 let origin2 = Origin::signed(2);15571558 assert_ok!(TemplateModule::set_public_access_mode(1559 origin1.clone(),1560 collection_id,1561 AccessMode::WhiteList1562 ));1563 assert_ok!(TemplateModule::set_mint_permission(1564 origin1.clone(),1565 collection_id,1566 false1567 ));1568 assert_ok!(TemplateModule::add_to_white_list(1569 origin1,1570 collection_id,1571 account(2)1572 ));15731574 assert_noop!(1575 TemplateModule::create_item(origin2, 1, account(2), default_nft_data().into()),1576 Error::<Test>::PublicMintingNotAllowed1577 );1578 });1579}15801581// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens cannot be created by non-privileged and non-white listed address.1582#[test]1583fn white_list_test_12() {1584 new_test_ext().execute_with(|| {1585 let collection_id = create_test_collection(&CollectionMode::NFT, 1);15861587 let origin1 = Origin::signed(1);1588 let origin2 = Origin::signed(2);15891590 assert_ok!(TemplateModule::set_public_access_mode(1591 origin1.clone(),1592 collection_id,1593 AccessMode::WhiteList1594 ));1595 assert_ok!(TemplateModule::set_mint_permission(1596 origin1,1597 collection_id,1598 false1599 ));16001601 assert_noop!(1602 TemplateModule::create_item(origin2, 1, account(2), default_nft_data().into()),1603 Error::<Test>::PublicMintingNotAllowed1604 );1605 });1606}16071608// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by owner.1609#[test]1610fn white_list_test_13() {1611 new_test_ext().execute_with(|| {1612 let collection_id = create_test_collection(&CollectionMode::NFT, 1);16131614 let origin1 = Origin::signed(1);16151616 assert_ok!(TemplateModule::set_public_access_mode(1617 origin1.clone(),1618 collection_id,1619 AccessMode::WhiteList1620 ));1621 assert_ok!(TemplateModule::set_mint_permission(1622 origin1,1623 collection_id,1624 true1625 ));16261627 let data = default_nft_data();1628 create_test_item(collection_id, &data.into());1629 });1630}16311632// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by admin.1633#[test]1634fn white_list_test_14() {1635 new_test_ext().execute_with(|| {1636 let collection_id = create_test_collection(&CollectionMode::NFT, 1);16371638 let origin1 = Origin::signed(1);1639 let origin2 = Origin::signed(2);16401641 assert_ok!(TemplateModule::set_public_access_mode(1642 origin1.clone(),1643 collection_id,1644 AccessMode::WhiteList1645 ));1646 assert_ok!(TemplateModule::set_mint_permission(1647 origin1.clone(),1648 collection_id,1649 true1650 ));16511652 assert_ok!(TemplateModule::add_collection_admin(1653 origin1,1654 collection_id,1655 account(2)1656 ));16571658 assert_ok!(TemplateModule::create_item(1659 origin2,1660 1,1661 account(2),1662 default_nft_data().into()1663 ));1664 });1665}16661667// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens cannot be created by non-privileged and non-white listed address.1668#[test]1669fn white_list_test_15() {1670 new_test_ext().execute_with(|| {1671 let collection_id = create_test_collection(&CollectionMode::NFT, 1);16721673 let origin1 = Origin::signed(1);1674 let origin2 = Origin::signed(2);16751676 assert_ok!(TemplateModule::set_public_access_mode(1677 origin1.clone(),1678 collection_id,1679 AccessMode::WhiteList1680 ));1681 assert_ok!(TemplateModule::set_mint_permission(1682 origin1,1683 collection_id,1684 true1685 ));16861687 assert_noop!(1688 TemplateModule::create_item(origin2, 1, account(2), default_nft_data().into()),1689 Error::<Test>::AddresNotInWhiteList1690 );1691 });1692}16931694// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by non-privileged and white listed address.1695#[test]1696fn white_list_test_16() {1697 new_test_ext().execute_with(|| {1698 let collection_id = create_test_collection(&CollectionMode::NFT, 1);16991700 let origin1 = Origin::signed(1);1701 let origin2 = Origin::signed(2);17021703 assert_ok!(TemplateModule::set_public_access_mode(1704 origin1.clone(),1705 collection_id,1706 AccessMode::WhiteList1707 ));1708 assert_ok!(TemplateModule::set_mint_permission(1709 origin1.clone(),1710 collection_id,1711 true1712 ));1713 assert_ok!(TemplateModule::add_to_white_list(1714 origin1,1715 collection_id,1716 account(2)1717 ));17181719 assert_ok!(TemplateModule::create_item(1720 origin2,1721 1,1722 account(2),1723 default_nft_data().into()1724 ));1725 });1726}17271728// Total number of collections. Positive test1729#[test]1730fn total_number_collections_bound() {1731 new_test_ext().execute_with(|| {1732 create_test_collection(&CollectionMode::NFT, 1);1733 });1734}17351736// Total number of collections. Negotive test1737#[test]1738fn total_number_collections_bound_neg() {1739 new_test_ext().execute_with(|| {1740 let origin1 = Origin::signed(1);17411742 for i in 0..COLLECTION_NUMBER_LIMIT {1743 create_test_collection(&CollectionMode::NFT, i + 1);1744 }17451746 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();1747 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();1748 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();17491750 // 11-th collection in chain. Expects error1751 assert_noop!(1752 TemplateModule::create_collection(1753 origin1,1754 col_name1,1755 col_desc1,1756 token_prefix1,1757 CollectionMode::NFT1758 ),1759 Error::<Test>::TotalCollectionsLimitExceeded1760 );1761 });1762}17631764// Owned tokens by a single address. Positive test1765#[test]1766fn owned_tokens_bound() {1767 new_test_ext().execute_with(|| {1768 let collection_id = create_test_collection(&CollectionMode::NFT, 1);17691770 let data = default_nft_data();1771 create_test_item(collection_id, &data.clone().into());1772 create_test_item(collection_id, &data.into());1773 });1774}17751776// Owned tokens by a single address. Negotive test1777#[test]1778fn owned_tokens_bound_neg() {1779 new_test_ext().execute_with(|| {1780 let collection_id = create_test_collection(&CollectionMode::NFT, 1);17811782 let origin1 = Origin::signed(1);17831784 for _ in 0..ACCOUNT_TOKEN_OWNERSHIP_LIMIT {1785 let data = default_nft_data();1786 create_test_item(collection_id, &data.clone().into());1787 }17881789 let data = default_nft_data();1790 assert_noop!(1791 TemplateModule::create_item(origin1, 1, account(1), data.into()),1792 Error::<Test>::AddressOwnershipLimitExceeded1793 );1794 });1795}17961797// Number of collection admins. Positive test1798#[test]1799fn collection_admins_bound() {1800 new_test_ext().execute_with(|| {1801 let collection_id = create_test_collection(&CollectionMode::NFT, 1);18021803 let origin1 = Origin::signed(1);18041805 assert_ok!(TemplateModule::add_collection_admin(1806 origin1.clone(),1807 collection_id,1808 account(2)1809 ));1810 assert_ok!(TemplateModule::add_collection_admin(1811 origin1,1812 collection_id,1813 account(3)1814 ));1815 });1816}18171818// Number of collection admins. Negotive test1819#[test]1820fn collection_admins_bound_neg() {1821 new_test_ext().execute_with(|| {1822 let collection_id = create_test_collection(&CollectionMode::NFT, 1);18231824 let origin1 = Origin::signed(1);18251826 for i in 0..COLLECTION_ADMINS_LIMIT {1827 assert_ok!(TemplateModule::add_collection_admin(1828 origin1.clone(),1829 collection_id,1830 account(2 + i)1831 ));1832 }1833 assert_noop!(1834 TemplateModule::add_collection_admin(1835 origin1,1836 collection_id,1837 account(3 + COLLECTION_ADMINS_LIMIT)1838 ),1839 Error::<Test>::CollectionAdminsLimitExceeded1840 );1841 });1842}1843// #endregion18441845#[test]1846fn set_const_on_chain_schema() {1847 new_test_ext().execute_with(|| {1848 let collection_id = create_test_collection(&CollectionMode::NFT, 1);18491850 let origin1 = Origin::signed(1);1851 assert_ok!(TemplateModule::set_const_on_chain_schema(1852 origin1,1853 collection_id,1854 b"test const on chain schema".to_vec()1855 ));18561857 assert_eq!(1858 TemplateModule::collection_id(collection_id)1859 .unwrap()1860 .const_on_chain_schema,1861 b"test const on chain schema".to_vec()1862 );1863 assert_eq!(1864 TemplateModule::collection_id(collection_id)1865 .unwrap()1866 .variable_on_chain_schema,1867 b"".to_vec()1868 );1869 });1870}18711872#[test]1873fn set_variable_on_chain_schema() {1874 new_test_ext().execute_with(|| {1875 let collection_id = create_test_collection(&CollectionMode::NFT, 1);18761877 let origin1 = Origin::signed(1);1878 assert_ok!(TemplateModule::set_variable_on_chain_schema(1879 origin1,1880 collection_id,1881 b"test variable on chain schema".to_vec()1882 ));18831884 assert_eq!(1885 TemplateModule::collection_id(collection_id)1886 .unwrap()1887 .const_on_chain_schema,1888 b"".to_vec()1889 );1890 assert_eq!(1891 TemplateModule::collection_id(collection_id)1892 .unwrap()1893 .variable_on_chain_schema,1894 b"test variable on chain schema".to_vec()1895 );1896 });1897}18981899#[test]1900fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {1901 new_test_ext().execute_with(|| {1902 let collection_id = create_test_collection(&CollectionMode::NFT, 1);19031904 let origin1 = Origin::signed(1);19051906 let data = default_nft_data();1907 create_test_item(1, &data.into());19081909 let variable_data = b"test data".to_vec();1910 assert_ok!(TemplateModule::set_variable_meta_data(1911 origin1,1912 collection_id,1913 1,1914 variable_data.clone()1915 ));19161917 assert_eq!(1918 TemplateModule::nft_item_id(collection_id, 1)1919 .unwrap()1920 .variable_data,1921 variable_data1922 );1923 });1924}19251926#[test]1927fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {1928 new_test_ext().execute_with(|| {1929 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);19301931 let origin1 = Origin::signed(1);19321933 let data = default_re_fungible_data();1934 create_test_item(1, &data.into());19351936 let variable_data = b"test data".to_vec();1937 assert_ok!(TemplateModule::set_variable_meta_data(1938 origin1,1939 collection_id,1940 1,1941 variable_data.clone()1942 ));19431944 assert_eq!(1945 TemplateModule::refungible_item_id(collection_id, 1)1946 .unwrap()1947 .variable_data,1948 variable_data1949 );1950 });1951}19521953#[test]1954fn set_variable_meta_data_on_fungible_token_fails() {1955 new_test_ext().execute_with(|| {1956 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);19571958 let origin1 = Origin::signed(1);19591960 let data = default_fungible_data();1961 create_test_item(1, &data.into());19621963 let variable_data = b"test data".to_vec();1964 assert_noop!(1965 TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),1966 Error::<Test>::CantStoreMetadataInFungibleTokens1967 );1968 });1969}19701971#[test]1972fn set_variable_meta_data_on_nft_token_fails_for_big_data() {1973 new_test_ext().execute_with(|| {1974 let collection_id = create_test_collection(&CollectionMode::NFT, 1);19751976 let origin1 = Origin::signed(1);19771978 let data = default_nft_data();1979 create_test_item(1, &data.into());19801981 let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();1982 assert_noop!(1983 TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),1984 Error::<Test>::TokenVariableDataLimitExceeded1985 );1986 });1987}19881989#[test]1990fn set_variable_meta_data_on_re_fungible_token_fails_for_big_data() {1991 new_test_ext().execute_with(|| {1992 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);19931994 let origin1 = Origin::signed(1);19951996 let data = default_re_fungible_data();1997 create_test_item(1, &data.into());19981999 let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();2000 assert_noop!(2001 TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),2002 Error::<Test>::TokenVariableDataLimitExceeded2003 );2004 });2005}20062007#[test]2008fn set_variable_meta_data_on_nft_with_item_owner_permission_flag() {2009 new_test_ext().execute_with(|| {2010 //default_limits();20112012 let collection_id = create_test_collection(&CollectionMode::NFT, 1);20132014 let origin1 = Origin::signed(1);20152016 let data = default_nft_data();2017 create_test_item(1, &data.into());20182019 TemplateModule::set_meta_update_permission_flag(2020 origin1.clone(),2021 collection_id,2022 MetaUpdatePermission::ItemOwner,2023 );20242025 let variable_data = b"ten chars.".to_vec();2026 assert_ok!(TemplateModule::set_variable_meta_data(2027 origin1,2028 collection_id,2029 1,2030 variable_data.clone()2031 ));20322033 assert_eq!(2034 TemplateModule::nft_item_id(collection_id, 1)2035 .unwrap()2036 .variable_data,2037 variable_data2038 );2039 });2040}20412042#[test]2043fn set_variable_meta_data_on_nft_with_item_owner_permission_flag_neg() {2044 new_test_ext().execute_with(|| {2045 // default_limits();20462047 let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);20482049 let origin1 = Origin::signed(1);2050 let origin2 = Origin::signed(2);20512052 assert_ok!(TemplateModule::set_mint_permission(2053 origin2.clone(),2054 collection_id,2055 true2056 ));2057 assert_ok!(TemplateModule::add_to_white_list(2058 origin2.clone(),2059 collection_id,2060 account(1)2061 ));20622063 let data = default_nft_data();2064 create_test_item(1, &data.into());20652066 assert_ok!(TemplateModule::set_meta_update_permission_flag(2067 origin2.clone(),2068 collection_id,2069 MetaUpdatePermission::ItemOwner,2070 ));20712072 let variable_data = b"ten chars.++".to_vec();2073 assert_noop!(2074 TemplateModule::set_variable_meta_data(2075 origin2,2076 collection_id,2077 1,2078 variable_data.clone()2079 ),2080 Error::<Test>::TokenVariableDataLimitExceeded2081 );20822083 #[test]2084 fn collection_transfer_flag_works() {2085 new_test_ext().execute_with(|| {2086 let origin1 = Origin::signed(1);20872088 let collection_id = create_test_collection(&CollectionMode::NFT, 1);2089 assert_ok!(TemplateModule::set_transfers_enabled_flag(origin1, 1, true));20902091 let data = default_nft_data();2092 create_test_item(collection_id, &data.into());2093 assert_eq!(TemplateModule::balance_count(1, 1), 1);2094 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);20952096 let origin1 = Origin::signed(1);20972098 // default scenario2099 assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1000));2100 assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(2));2101 assert_eq!(TemplateModule::balance_count(1, 1), 0);2102 assert_eq!(TemplateModule::balance_count(1, 2), 1);21032104 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);2105 });2106 }21072108 #[test]2109 fn set_variable_meta_data_on_nft_with_admin_flag() {2110 new_test_ext().execute_with(|| {2111 // default_limits();21122113 let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);21142115 let origin1 = Origin::signed(1);2116 let origin2 = Origin::signed(2);21172118 assert_ok!(TemplateModule::set_mint_permission(2119 origin2.clone(),2120 collection_id,2121 true2122 ));2123 assert_ok!(TemplateModule::add_to_white_list(2124 origin2.clone(),2125 collection_id,2126 account(1)2127 ));21282129 assert_ok!(TemplateModule::add_collection_admin(2130 origin2.clone(),2131 collection_id,2132 account(1)2133 ));21342135 let data = default_nft_data();2136 create_test_item(1, &data.into());21372138 assert_ok!(TemplateModule::set_meta_update_permission_flag(2139 origin2.clone(),2140 collection_id,2141 MetaUpdatePermission::Admin,2142 ));21432144 let variable_data = b"test set_variable_meta_data method.".to_vec();2145 assert_ok!(TemplateModule::set_variable_meta_data(2146 origin1,2147 collection_id,2148 1,2149 variable_data.clone()2150 ));21512152 assert_eq!(2153 TemplateModule::nft_item_id(collection_id, 1)2154 .unwrap()2155 .variable_data,2156 variable_data2157 );2158 });2159 }21602161 #[test]2162 fn set_variable_meta_data_on_nft_with_admin_flag_neg() {2163 new_test_ext().execute_with(|| {2164 // default_limits();21652166 let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);21672168 let origin1 = Origin::signed(1);2169 let origin2 = Origin::signed(2);21702171 assert_ok!(TemplateModule::set_mint_permission(2172 origin2.clone(),2173 collection_id,2174 true2175 ));2176 assert_ok!(TemplateModule::add_to_white_list(2177 origin2.clone(),2178 collection_id,2179 account(1)2180 ));21812182 let data = default_nft_data();2183 create_test_item(1, &data.into());21842185 assert_ok!(TemplateModule::set_meta_update_permission_flag(2186 origin2.clone(),2187 collection_id,2188 MetaUpdatePermission::Admin,2189 ));21902191 let variable_data = b"test set_variable_meta_data method.".to_vec();2192 assert_noop!(2193 TemplateModule::set_variable_meta_data(2194 origin1,2195 collection_id,2196 1,2197 variable_data.clone()2198 ),2199 Error::<Test>::NoPermission2200 );2201 });2202 }22032204 #[test]2205 fn set_variable_meta_flag_after_freeze() {2206 new_test_ext().execute_with(|| {2207 // default_limits();22082209 let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);22102211 let origin2 = Origin::signed(2);22122213 assert_ok!(TemplateModule::set_meta_update_permission_flag(2214 origin2.clone(),2215 collection_id,2216 MetaUpdatePermission::None,2217 ));2218 assert_noop!(2219 TemplateModule::set_meta_update_permission_flag(2220 origin2.clone(),2221 collection_id,2222 MetaUpdatePermission::Admin2223 ),2224 Error::<Test>::MetadataFlagFrozen2225 );2226 });2227 }22282229 #[test]2230 fn set_variable_meta_data_on_nft_with_none_flag_neg() {2231 new_test_ext().execute_with(|| {2232 // default_limits();22332234 let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);2235 let origin1 = Origin::signed(1);22362237 let data = default_nft_data();2238 create_test_item(1, &data.into());22392240 assert_ok!(TemplateModule::set_meta_update_permission_flag(2241 origin1.clone(),2242 collection_id,2243 MetaUpdatePermission::None,2244 ));22452246 let variable_data = b"test set_variable_meta_data method.".to_vec();2247 assert_noop!(2248 TemplateModule::set_variable_meta_data(2249 origin1.clone(),2250 collection_id,2251 1,2252 variable_data.clone()2253 ),2254 Error::<Test>::MetadataUpdateDenied2255 );2256 });2257 }22582259 #[test]2260 fn collection_transfer_flag_works_neg() {2261 new_test_ext().execute_with(|| {2262 let origin1 = Origin::signed(1);22632264 let collection_id = create_test_collection(&CollectionMode::NFT, 1);2265 assert_ok!(TemplateModule::set_transfers_enabled_flag(2266 origin1, 1, false2267 ));22682269 let data = default_nft_data();2270 create_test_item(collection_id, &data.into());2271 assert_eq!(TemplateModule::balance_count(1, 1), 1);2272 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);22732274 let origin1 = Origin::signed(1);22752276 // default scenario2277 assert_noop!(2278 TemplateModule::transfer(origin1, account(2), 1, 1, 1000),2279 Error::<Test>::TransferNotAllowed2280 );2281 assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(1));2282 assert_eq!(TemplateModule::balance_count(1, 1), 1);2283 assert_eq!(TemplateModule::balance_count(1, 2), 0);22842285 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);2286 });2287 }2288 });2289}tests/src/limits.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/limits.test.ts
@@ -0,0 +1,378 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { IKeyringPair } from '@polkadot/types/types';
+import privateKey from './substrate/privateKey';
+import usingApi from './substrate/substrate-api';
+import {
+ createCollectionExpectSuccess,
+ destroyCollectionExpectSuccess,
+ setCollectionLimitsExpectSuccess,
+ setCollectionSponsorExpectSuccess,
+ confirmSponsorshipExpectSuccess,
+ createItemExpectSuccess,
+ createItemExpectFailure,
+ transferExpectSuccess,
+ getFreeBalance,
+ waitNewBlocks,
+} from './util/helpers';
+import { expect } from 'chai';
+
+describe('Number of tokens per address (NFT)', () => {
+ let Alice: IKeyringPair;
+
+ before(async () => {
+ await usingApi(async () => {
+ Alice = privateKey('//Alice');
+ });
+ });
+
+ it('Collection limits allow greater number than chain limits, chain limits are enforced', async () => {
+
+ const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { AccountTokenOwnershipLimit: 20 });
+ for(let i = 0; i < 10; i++){
+ await createItemExpectSuccess(Alice, collectionId, 'NFT');
+ }
+ await createItemExpectFailure(Alice, collectionId, 'NFT');
+ await destroyCollectionExpectSuccess(collectionId);
+ });
+
+ it('Collection limits allow lower number than chain limits, collection limits are enforced', async () => {
+
+ const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { AccountTokenOwnershipLimit: 1 });
+ await createItemExpectSuccess(Alice, collectionId, 'NFT');
+ await createItemExpectFailure(Alice, collectionId, 'NFT');
+ await destroyCollectionExpectSuccess(collectionId);
+ });
+});
+
+describe('Number of tokens per address (ReFungible)', () => {
+ let Alice: IKeyringPair;
+
+ before(async () => {
+ await usingApi(async () => {
+ Alice = privateKey('//Alice');
+ });
+ });
+
+ it('Collection limits allow greater number than chain limits, chain limits are enforced', async () => {
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible' }});
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { AccountTokenOwnershipLimit: 20 });
+ for(let i = 0; i < 10; i++){
+ await createItemExpectSuccess(Alice, collectionId, 'ReFungible');
+ }
+ await createItemExpectFailure(Alice, collectionId, 'ReFungible');
+ await destroyCollectionExpectSuccess(collectionId);
+ });
+
+ it('Collection limits allow lower number than chain limits, collection limits are enforced', async () => {
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible' }});
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { AccountTokenOwnershipLimit: 1 });
+ await createItemExpectSuccess(Alice, collectionId, 'ReFungible');
+ await createItemExpectFailure(Alice, collectionId, 'ReFungible');
+ await destroyCollectionExpectSuccess(collectionId);
+ });
+});
+
+describe('Sponsor timeout (NFT)', () => {
+ let Alice: IKeyringPair;
+ let Bob: IKeyringPair;
+ let Charlie: IKeyringPair;
+
+ before(async () => {
+ await usingApi(async () => {
+ Alice = privateKey('//Alice');
+ Bob = privateKey('//Bob');
+ Charlie = privateKey('//Charlie');
+ });
+ });
+
+ it('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {
+ const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { SponsorTimeout: 7 });
+ const tokenId = await createItemExpectSuccess(Alice, collectionId, 'NFT');
+ await setCollectionSponsorExpectSuccess(collectionId, Alice.address);
+ await confirmSponsorshipExpectSuccess(collectionId, '//Alice');
+ await transferExpectSuccess(collectionId, tokenId, Alice, Bob);
+ const aliceBalanceBefore = (await getFreeBalance(Alice)).toNumber();
+
+ // check setting SponsorTimeout = 5, fail
+ await waitNewBlocks(5);
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie);
+ const aliceBalanceAfterUnsponsoredTransaction = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);
+
+ // check setting SponsorTimeout = 7, success
+ await waitNewBlocks(2); // 5 + 2
+ await transferExpectSuccess(collectionId, tokenId, Charlie, Bob);
+ const aliceBalanceAfterSponsoredTransaction = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);
+ await destroyCollectionExpectSuccess(collectionId);
+ });
+
+ it('Collection limits have lower timeout value than chain limits, chain limits are enforced', async () => {
+
+ const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { SponsorTimeout: 1 });
+ const tokenId = await createItemExpectSuccess(Alice, collectionId, 'NFT');
+ await setCollectionSponsorExpectSuccess(collectionId, Alice.address);
+ await confirmSponsorshipExpectSuccess(collectionId, '//Alice');
+ await transferExpectSuccess(collectionId, tokenId, Alice, Bob);
+ const aliceBalanceBefore = (await getFreeBalance(Alice)).toNumber();
+
+ // check setting SponsorTimeout = 1, fail
+ await waitNewBlocks(1);
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie);
+ const aliceBalanceAfterUnsponsoredTransaction = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);
+
+ // check setting SponsorTimeout = 5, success
+ await waitNewBlocks(4);
+ await transferExpectSuccess(collectionId, tokenId, Charlie, Bob);
+ const aliceBalanceAfterSponsoredTransaction = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);
+ await destroyCollectionExpectSuccess(collectionId);
+ });
+});
+
+describe('Sponsor timeout (Fungible)', () => {
+ let Alice: IKeyringPair;
+ let Bob: IKeyringPair;
+ let Charlie: IKeyringPair;
+
+ before(async () => {
+ await usingApi(async () => {
+ Alice = privateKey('//Alice');
+ Bob = privateKey('//Bob');
+ Charlie = privateKey('//Charlie');
+ });
+ });
+
+ it('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { SponsorTimeout: 7 });
+ const tokenId = await createItemExpectSuccess(Alice, collectionId, 'Fungible');
+ await setCollectionSponsorExpectSuccess(collectionId, Alice.address);
+ await confirmSponsorshipExpectSuccess(collectionId, '//Alice');
+ await transferExpectSuccess(collectionId, tokenId, Alice, Bob, 10, 'Fungible');
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie, 2, 'Fungible');
+ const aliceBalanceBefore = (await getFreeBalance(Alice)).toNumber();
+
+ // check setting SponsorTimeout = 5, fail
+ await waitNewBlocks(5);
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie, 2, 'Fungible');
+ const aliceBalanceAfterUnsponsoredTransaction = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);
+
+ // check setting SponsorTimeout = 7, success
+ await waitNewBlocks(2); // 5 + 2
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie, 2, 'Fungible');
+ const aliceBalanceAfterSponsoredTransaction = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);
+
+ await destroyCollectionExpectSuccess(collectionId);
+ });
+
+ it('Collection limits have lower timeout value than chain limits, chain limits are enforced', async () => {
+
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { SponsorTimeout: 1 });
+ const tokenId = await createItemExpectSuccess(Alice, collectionId, 'Fungible');
+ await setCollectionSponsorExpectSuccess(collectionId, Alice.address);
+ await confirmSponsorshipExpectSuccess(collectionId, '//Alice');
+ await transferExpectSuccess(collectionId, tokenId, Alice, Bob, 10, 'Fungible');
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie, 2, 'Fungible');
+ const aliceBalanceBefore = (await getFreeBalance(Alice)).toNumber();
+
+ // check setting SponsorTimeout = 1, fail
+ await waitNewBlocks(1);
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie, 2, 'Fungible');
+ const aliceBalanceAfterUnsponsoredTransaction = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);
+
+ // check setting SponsorTimeout = 5, success
+ await waitNewBlocks(4);
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie, 2, 'Fungible');
+ const aliceBalanceAfterSponsoredTransaction = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);
+
+ await destroyCollectionExpectSuccess(collectionId);
+ });
+});
+
+describe('Sponsor timeout (ReFungible)', () => {
+ let Alice: IKeyringPair;
+ let Bob: IKeyringPair;
+ let Charlie: IKeyringPair;
+
+ before(async () => {
+ await usingApi(async () => {
+ Alice = privateKey('//Alice');
+ Bob = privateKey('//Bob');
+ Charlie = privateKey('//Charlie');
+ });
+ });
+
+ it('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible' }});
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { SponsorTimeout: 7 });
+ const tokenId = await createItemExpectSuccess(Alice, collectionId, 'ReFungible');
+ await setCollectionSponsorExpectSuccess(collectionId, Alice.address);
+ await confirmSponsorshipExpectSuccess(collectionId, '//Alice');
+ await transferExpectSuccess(collectionId, tokenId, Alice, Bob, 100, 'ReFungible');
+ const aliceBalanceBefore = (await getFreeBalance(Alice)).toNumber();
+
+ // check setting SponsorTimeout = 5, fail
+ await waitNewBlocks(5);
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie, 20, 'ReFungible');
+ const aliceBalanceAfterUnsponsoredTransaction = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);
+
+ // check setting SponsorTimeout = 7, success
+ await waitNewBlocks(2); // 5 + 2
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie, 20, 'ReFungible');
+ const aliceBalanceAfterSponsoredTransaction = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);
+ await destroyCollectionExpectSuccess(collectionId);
+ });
+
+ it('Collection limits have lower timeout value than chain limits, chain limits are enforced', async () => {
+
+ const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { SponsorTimeout: 1 });
+ const tokenId = await createItemExpectSuccess(Alice, collectionId, 'NFT');
+ await setCollectionSponsorExpectSuccess(collectionId, Alice.address);
+ await confirmSponsorshipExpectSuccess(collectionId, '//Alice');
+ await transferExpectSuccess(collectionId, tokenId, Alice, Bob);
+ const aliceBalanceBefore = (await getFreeBalance(Alice)).toNumber();
+
+ // check setting SponsorTimeout = 1, fail
+ await waitNewBlocks(1);
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie);
+ const aliceBalanceAfterUnsponsoredTransaction = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);
+
+ // check setting SponsorTimeout = 5, success
+ await waitNewBlocks(4);
+ await transferExpectSuccess(collectionId, tokenId, Charlie, Bob);
+ const aliceBalanceAfterSponsoredTransaction = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);
+ await destroyCollectionExpectSuccess(collectionId);
+ });
+});
+
+describe('Collection zero limits (NFT)', () => {
+ let Alice: IKeyringPair;
+ let Bob: IKeyringPair;
+ let Charlie: IKeyringPair;
+
+ before(async () => {
+ await usingApi(async () => {
+ Alice = privateKey('//Alice');
+ Bob = privateKey('//Bob');
+ Charlie = privateKey('//Charlie');
+ });
+ });
+
+ it('Limits have 0 in tokens per address field, the chain limits are applied', async () => {
+ const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { AccountTokenOwnershipLimit: 0 });
+ for(let i = 0; i < 10; i++){
+ await createItemExpectSuccess(Alice, collectionId, 'NFT');
+ }
+ await createItemExpectFailure(Alice, collectionId, 'NFT');
+ });
+
+ it('Limits have 0 in sponsor timeout, no limits are applied', async () => {
+
+ const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { SponsorTimeout: 0 });
+ const tokenId = await createItemExpectSuccess(Alice, collectionId, 'NFT');
+ await setCollectionSponsorExpectSuccess(collectionId, Alice.address);
+ await confirmSponsorshipExpectSuccess(collectionId, '//Alice');
+ await transferExpectSuccess(collectionId, tokenId, Alice, Bob);
+ const aliceBalanceBefore = (await getFreeBalance(Alice)).toNumber();
+
+ // check setting SponsorTimeout = 0, success with next block
+ await waitNewBlocks(1);
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie);
+ const aliceBalanceAfterSponsoredTransaction1 = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterSponsoredTransaction1).to.be.lessThan(aliceBalanceBefore);
+ });
+});
+
+describe.only('Collection zero limits (Fungible)', () => {
+ let Alice: IKeyringPair;
+ let Bob: IKeyringPair;
+ let Charlie: IKeyringPair;
+
+ before(async () => {
+ await usingApi(async () => {
+ Alice = privateKey('//Alice');
+ Bob = privateKey('//Bob');
+ Charlie = privateKey('//Charlie');
+ });
+ });
+
+ it('Limits have 0 in sponsor timeout, no limits are applied', async () => {
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { SponsorTimeout: 0 });
+ const tokenId = await createItemExpectSuccess(Alice, collectionId, 'Fungible');
+ await setCollectionSponsorExpectSuccess(collectionId, Alice.address);
+ await confirmSponsorshipExpectSuccess(collectionId, '//Alice');
+ await transferExpectSuccess(collectionId, tokenId, Alice, Bob, 10, 'Fungible');
+ const aliceBalanceBefore = (await getFreeBalance(Alice)).toNumber();
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie, 2, 'Fungible');
+
+ // check setting SponsorTimeout = 0, success with next block
+ await waitNewBlocks(1);
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie, 2, 'Fungible');
+ const aliceBalanceAfterSponsoredTransaction1 = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterSponsoredTransaction1).to.be.lessThan(aliceBalanceBefore);
+ });
+});
+
+describe.only('Collection zero limits (ReFungible)', () => {
+ let Alice: IKeyringPair;
+ let Bob: IKeyringPair;
+ let Charlie: IKeyringPair;
+
+ before(async () => {
+ await usingApi(async () => {
+ Alice = privateKey('//Alice');
+ Bob = privateKey('//Bob');
+ Charlie = privateKey('//Charlie');
+ });
+ });
+
+ it('Limits have 0 in tokens per address field, the chain limits are applied', async () => {
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible' }});
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { AccountTokenOwnershipLimit: 0 });
+ for(let i = 0; i < 10; i++){
+ await createItemExpectSuccess(Alice, collectionId, 'ReFungible');
+ }
+ await createItemExpectFailure(Alice, collectionId, 'ReFungible');
+ });
+
+ it('Limits have 0 in sponsor timeout, no limits are applied', async () => {
+
+ const collectionId = await createCollectionExpectSuccess({ mode: { type: 'ReFungible' } });
+ await setCollectionLimitsExpectSuccess(Alice, collectionId, { SponsorTimeout: 0 });
+ const tokenId = await createItemExpectSuccess(Alice, collectionId, 'ReFungible');
+ await setCollectionSponsorExpectSuccess(collectionId, Alice.address);
+ await confirmSponsorshipExpectSuccess(collectionId, '//Alice');
+ await transferExpectSuccess(collectionId, tokenId, Alice, Bob, 100, 'ReFungible');
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie, 20, 'ReFungible');
+ const aliceBalanceBefore = (await getFreeBalance(Alice)).toNumber();
+
+ // check setting SponsorTimeout = 0, success with next block
+ await waitNewBlocks(1);
+ await transferExpectSuccess(collectionId, tokenId, Bob, Charlie, 20, 'ReFungible');
+ const aliceBalanceAfterSponsoredTransaction1 = (await getFreeBalance(Alice)).toNumber();
+ expect(aliceBalanceAfterSponsoredTransaction1).to.be.lessThan(aliceBalanceBefore);
+ });
+});
tests/src/util/helpers.tsdiffbeforeafterboth--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -811,6 +811,17 @@
}
export async function
+getFreeBalance(account: IKeyringPair) : Promise<BigNumber>
+{
+ let balance = new BigNumber(0) ;
+ await usingApi(async (api) => {
+ balance = new BigNumber((await api.query.system.account(account.address)).data.free.toString());
+ });
+
+ return balance;
+}
+
+export async function
scheduleTransferExpectSuccess(
collectionId: number,
tokenId: number,
@@ -884,8 +895,11 @@
if (type === 'ReFungible') {
const nftItemData =
(await api.query.nft.reFungibleItemList(collectionId, tokenId)).toJSON() as unknown as IReFungibleTokenDataType;
- expect(nftItemData.Owner[0].Owner).to.be.deep.equal(to);
- expect(nftItemData.Owner[0].Fraction.toString()).to.be.equal(value.toString());
+ const expectedOwner = toSubstrateAddress(to);
+ const ownerIndex = nftItemData.Owner.findIndex(v => toSubstrateAddress(v.Owner as any as string) == expectedOwner);
+ expect(ownerIndex).to.not.equal(-1);
+ expect(nftItemData.Owner[ownerIndex].Owner).to.be.deep.equal(normalizeAccountId(to));
+ expect(nftItemData.Owner[ownerIndex].Fraction).to.be.greaterThanOrEqual(value as number);
}
});
}
@@ -1190,7 +1204,6 @@
export async function waitNewBlocks(blocksCount = 1): Promise<void> {
await usingApi(async (api) => {
const promise = new Promise<void>(async (resolve) => {
-
const unsubscribe = await api.rpc.chain.subscribeNewHeads(() => {
if (blocksCount > 0) {
blocksCount--;