diff --git a/CHANGELOG.md b/CHANGELOG.md index 70b7286a..20ddc6b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,18 @@ All notable changes to this project will be documented in this file. The format ### Added +## Release 1.5.1 + +### Changed + +- Add ACL in types of js_client (#256) +- Fix Wrong error on insertion of duplicated token identifier (#258) +- Fix Failure on migration when EventsMode::CES to EventsMode::CES (#263) + +### Added + +- Optional custom string identifier in mint entrypoint (#255) + ## Release 1.5.0 ### Changed diff --git a/Makefile b/Makefile index 449c5c60..e3b47974 100644 --- a/Makefile +++ b/Makefile @@ -28,13 +28,16 @@ build-contract: wasm-strip test-contracts/minting_contract/target/wasm32-unknown-unknown/release/minting_contract.wasm wasm-strip test-contracts/transfer_filter_contract/target/wasm32-unknown-unknown/release/transfer_filter_contract.wasm +VERSIONS := 1_0_0 1_1_0 1_2_0 1_3_0 1_4_0 1_5_0 + setup-test: build-contract mkdir -p tests/wasm - mkdir -p tests/wasm/1_0_0; curl -L https://github.com/casper-ecosystem/cep-78-enhanced-nft/releases/download/v1.0.0/cep-78-wasm.tar.gz | tar zxv -C tests/wasm/1_0_0/ - mkdir -p tests/wasm/1_1_0; curl -L https://github.com/casper-ecosystem/cep-78-enhanced-nft/releases/download/v1.1.0/cep-78-wasm.tar.gz | tar zxv -C tests/wasm/1_1_0/ - mkdir -p tests/wasm/1_2_0; curl -L https://github.com/casper-ecosystem/cep-78-enhanced-nft/releases/download/v1.2.0/cep-78-wasm.tar.gz | tar zxv -C tests/wasm/1_2_0/ - mkdir -p tests/wasm/1_3_0; curl -L https://github.com/casper-ecosystem/cep-78-enhanced-nft/releases/download/v1.3.0/cep-78-wasm.tar.gz | tar zxv -C tests/wasm/1_3_0/ - mkdir -p tests/wasm/1_4_0; curl -L https://github.com/casper-ecosystem/cep-78-enhanced-nft/releases/download/v1.4.0/cep-78-wasm.tar.gz | tar zxv -C tests/wasm/1_4_0/ + $(foreach version,$(VERSIONS), \ + if [ ! -d "tests/wasm/$(version)" ]; then \ + mkdir -p tests/wasm/$(version); \ + curl -L https://github.com/casper-ecosystem/cep-78-enhanced-nft/releases/download/v$(subst _,.,$(version))/cep-78-wasm.tar.gz | tar zxv -C tests/wasm/$(version)/; \ + fi; \ + ) cp contract/target/wasm32-unknown-unknown/release/contract.wasm tests/wasm cp client/mint_session/target/wasm32-unknown-unknown/release/mint_call.wasm tests/wasm diff --git a/client-js/CHANGELOG.md b/client-js/CHANGELOG.md index 1ae5713f..84654282 100644 --- a/client-js/CHANGELOG.md +++ b/client-js/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.5.1] - 2023-11-20 + +### Fixed + +- Add ACL in types of js_client (#256) + ## [1.5.0] - 2023-10-05 ### Fixed diff --git a/client-js/package.json b/client-js/package.json index d87ad113..d9a326bb 100644 --- a/client-js/package.json +++ b/client-js/package.json @@ -1,6 +1,6 @@ { "name": "casper-cep78-js-client", - "version": "1.5.0", + "version": "1.5.1", "description": "CEP78 Enhanced NFT JS Client", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", diff --git a/client/balance_of_session/Cargo.toml b/client/balance_of_session/Cargo.toml index 9414b10f..b2a775a0 100644 --- a/client/balance_of_session/Cargo.toml +++ b/client/balance_of_session/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "balance_of_session" -version = "1.5.0" +version = "1.5.1" edition = "2018" [dependencies] diff --git a/client/get_approved_session/Cargo.toml b/client/get_approved_session/Cargo.toml index 609195a6..e28f0197 100644 --- a/client/get_approved_session/Cargo.toml +++ b/client/get_approved_session/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "get_approved_session" -version = "1.5.0" +version = "1.5.1" edition = "2018" [dependencies] diff --git a/client/is_approved_for_all_session/Cargo.toml b/client/is_approved_for_all_session/Cargo.toml index 0962a01d..14b98280 100644 --- a/client/is_approved_for_all_session/Cargo.toml +++ b/client/is_approved_for_all_session/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "is_approved_for_all_session" -version = "1.5.0" +version = "1.5.1" edition = "2018" [dependencies] diff --git a/client/mint_session/Cargo.toml b/client/mint_session/Cargo.toml index 73f5a132..cc09ef29 100644 --- a/client/mint_session/Cargo.toml +++ b/client/mint_session/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mint_session" -version = "1.5.0" +version = "1.5.1" edition = "2018" [dependencies] diff --git a/client/owner_of_session/Cargo.toml b/client/owner_of_session/Cargo.toml index cd500639..b2b8f64f 100644 --- a/client/owner_of_session/Cargo.toml +++ b/client/owner_of_session/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "owner_of_session" -version = "1.5.0" +version = "1.5.1" edition = "2018" [dependencies] diff --git a/client/transfer_session/Cargo.toml b/client/transfer_session/Cargo.toml index 317e1391..fa10de71 100644 --- a/client/transfer_session/Cargo.toml +++ b/client/transfer_session/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "transfer_session" -version = "1.5.0" +version = "1.5.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/client/updated_receipts/Cargo.toml b/client/updated_receipts/Cargo.toml index f7b95d8b..398c2a61 100644 --- a/client/updated_receipts/Cargo.toml +++ b/client/updated_receipts/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "updated_receipts" -version = "1.5.0" +version = "1.5.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/contract/Cargo.toml b/contract/Cargo.toml index 998c25b5..3ce3b460 100644 --- a/contract/Cargo.toml +++ b/contract/Cargo.toml @@ -1,18 +1,16 @@ [package] name = "contract" -version = "1.5.0" +version = "1.5.1" edition = "2018" [dependencies] -casper-contract = { version = "3.0.0", default-features = false, features = [ - "test-support", -], optional = true } -casper-types = "3.0.0" +casper-contract = { version = "3.0.0", default-features = false, optional = true } +casper-types = { version = "3.0.0", default-features = false } serde = { version = "1.0.80", default-features = false } serde_json = { version = "1.0.59", default-features = false } serde-json-wasm = { version = "0.5.1", default-features = false } base16 = { version = "0.2.1", default-features = false } -casper-event-standard = { version = "0.4.0", default-features = false } +casper-event-standard = { version = "0.4.1", default-features = false } hex = { version = "0.4.3", default-features = false } [[bin]] diff --git a/contract/src/main.rs b/contract/src/main.rs index 8d9ab635..6a667e5d 100644 --- a/contract/src/main.rs +++ b/contract/src/main.rs @@ -2001,27 +2001,50 @@ pub extern "C" fn migrate() { runtime::put_key(RLO_MFLAG, storage::new_uref(false).into()); - let events_mode: EventsMode = utils::get_optional_named_arg_with_user_errors::( - ARG_EVENTS_MODE, - NFTCoreError::InvalidEventsMode, - ) - .unwrap_or(EventsMode::NoEvents as u8) - .try_into() - .unwrap_or_revert(); - - match events_mode { - EventsMode::NoEvents => {} - EventsMode::CES => { - // Initialize events structures. - utils::init_events(); - // Emit Migration event. - casper_event_standard::emit(Migration::new()); + let optional_events_mode: Option = runtime::get_named_arg::>(ARG_EVENTS_MODE); + let current_events_mode: EventsMode = runtime::get_key(EVENTS_MODE) + .and_then(|_| { + utils::get_stored_value_with_user_errors::( + EVENTS_MODE, + NFTCoreError::MissingEventsMode, + NFTCoreError::InvalidEventsMode, + ) + .try_into() + .ok() + }) + .unwrap_or(EventsMode::NoEvents); + + if let Some(optional_events_mode) = optional_events_mode { + let requested_events_mode: EventsMode = optional_events_mode + .try_into() + .unwrap_or_revert_with(NFTCoreError::InvalidEventsMode); + match (current_events_mode, requested_events_mode) { + (EventsMode::CES, EventsMode::CES) => casper_event_standard::emit(Migration::new()), + (_, EventsMode::CES) => { + // Initialize events structures. + utils::init_events(); + casper_event_standard::emit(Migration::new()); + } + (_, EventsMode::CEP47) => record_cep47_event_dictionary(CEP47Event::Migrate), + (_, _) => {} + } + runtime::put_key(EVENTS_MODE, storage::new_uref(optional_events_mode).into()); + } else { + match current_events_mode { + EventsMode::CEP47 => record_cep47_event_dictionary(CEP47Event::Migrate), + EventsMode::CES => casper_event_standard::emit(Migration::new()), + _ => { + // Store "no events" mode in case it was never stored like version < 1.2 + if !runtime::has_key(EVENTS_MODE) { + runtime::put_key( + EVENTS_MODE, + storage::new_uref(EventsMode::NoEvents as u8).into(), + ) + } + } } - EventsMode::CEP47 => record_cep47_event_dictionary(CEP47Event::Migrate), } - runtime::put_key(EVENTS_MODE, storage::new_uref(events_mode as u8).into()); - let acl_package_mode: bool = utils::get_optional_named_arg_with_user_errors::( ARG_ACL_PACKAGE_MODE, NFTCoreError::InvalidACLPackageMode, @@ -2823,8 +2846,7 @@ fn migrate_contract(access_key_name: String, package_key_name: String) { let events_mode = utils::get_optional_named_arg_with_user_errors::( ARG_EVENTS_MODE, NFTCoreError::InvalidEventsMode, - ) - .unwrap_or(0u8); + ); let acl_package_mode: bool = utils::get_optional_named_arg_with_user_errors( ARG_ACL_PACKAGE_MODE, diff --git a/contract/src/modalities.rs b/contract/src/modalities.rs index 88e89846..a24019f9 100644 --- a/contract/src/modalities.rs +++ b/contract/src/modalities.rs @@ -423,7 +423,7 @@ impl TryFrom for NamedKeyConventionMode { } #[repr(u8)] -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Clone, Copy)] #[allow(clippy::upper_case_acronyms)] pub enum EventsMode { NoEvents = 0, diff --git a/test-contracts/mangle_named_keys/Cargo.toml b/test-contracts/mangle_named_keys/Cargo.toml index 5c29dc89..4d2ce876 100644 --- a/test-contracts/mangle_named_keys/Cargo.toml +++ b/test-contracts/mangle_named_keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mangle_named_keys" -version = "1.5.0" +version = "1.5.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/test-contracts/minting_contract/Cargo.toml b/test-contracts/minting_contract/Cargo.toml index 060372f0..5baf93fa 100644 --- a/test-contracts/minting_contract/Cargo.toml +++ b/test-contracts/minting_contract/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minting_contract" -version = "1.5.0" +version = "1.5.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/test-contracts/transfer_filter_contract/Cargo.toml b/test-contracts/transfer_filter_contract/Cargo.toml index 18511a08..52a8b937 100644 --- a/test-contracts/transfer_filter_contract/Cargo.toml +++ b/test-contracts/transfer_filter_contract/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "transfer_filter_contract" -version = "1.5.0" +version = "1.5.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 28fde6ba..4a09e7af 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -1,14 +1,12 @@ [package] name = "tests" -version = "1.5.0" +version = "1.5.1" edition = "2018" [dependencies] -casper-engine-test-support = { version = "5.0.0", default-features = false, features = [ - "test-support", -] } +casper-engine-test-support = { version = "5.0.0", default-features = false } contract = { path = "../contract", default-features = false } casper-execution-engine = { version = "5.0.0", default-features = false } -casper-types = "3.0.0" +casper-types = { version = "3.0.0", default-features = false } serde = { version = "1.0.80", default-features = false } serde_json = { version = "1.0.59", default-features = false } once_cell = "1" diff --git a/tests/src/upgrade.rs b/tests/src/upgrade.rs index c7ea6652..6b78a5e4 100644 --- a/tests/src/upgrade.rs +++ b/tests/src/upgrade.rs @@ -22,9 +22,10 @@ use crate::utility::{ constants::{ ACCOUNT_USER_1, ARG_IS_HASH_IDENTIFIER_MODE, ARG_NFT_CONTRACT_HASH, ARG_NFT_CONTRACT_PACKAGE_HASH, CONTRACT_1_0_0_WASM, CONTRACT_1_1_0_WASM, - CONTRACT_1_2_0_WASM, CONTRACT_1_3_0_WASM, CONTRACT_1_4_0_WASM, MANGLE_NAMED_KEYS, - MINT_1_0_0_WASM, MINT_SESSION_WASM, NFT_CONTRACT_WASM, NFT_TEST_COLLECTION, - NFT_TEST_SYMBOL, PAGE_SIZE, TRANSFER_SESSION_WASM, UPDATED_RECEIPTS_WASM, + CONTRACT_1_2_0_WASM, CONTRACT_1_3_0_WASM, CONTRACT_1_4_0_WASM, CONTRACT_1_5_0_WASM, + MANGLE_NAMED_KEYS, MINT_1_0_0_WASM, MINT_SESSION_WASM, NFT_CONTRACT_WASM, + NFT_TEST_COLLECTION, NFT_TEST_SYMBOL, PAGE_SIZE, TRANSFER_SESSION_WASM, + UPDATED_RECEIPTS_WASM, }, installer_request_builder::{ InstallerRequestBuilder, MetadataMutability, NFTIdentifierMode, NFTMetadataKind, @@ -719,7 +720,6 @@ fn should_safely_upgrade_from_old_version_to_new_version_with_reporting_mode( .with_metadata_mutability(MetadataMutability::Mutable) .with_identifier_mode(NFTIdentifierMode::Ordinal) .with_nft_metadata_kind(NFTMetadataKind::Raw) - .with_events_mode(EventsMode::CES) .build(); builder.exec(install_request).expect_success().commit(); @@ -765,7 +765,8 @@ fn should_safely_upgrade_from_old_version_to_new_version_with_reporting_mode( ARG_NAMED_KEY_CONVENTION => NamedKeyConventionMode::V1_0Custom as u8, ARG_ACCESS_KEY_NAME_1_0_0 => format!("{PREFIX_ACCESS_KEY_NAME}_{NFT_TEST_COLLECTION}"), ARG_HASH_KEY_NAME_1_0_0 => format!("{PREFIX_HASH_KEY_NAME}_{NFT_TEST_COLLECTION}"), - ARG_TOTAL_TOKEN_SUPPLY => 10u64 + ARG_TOTAL_TOKEN_SUPPLY => 10u64, + ARG_EVENTS_MODE => EventsMode::CES as u8 // Optin for CES on upgrade }, ) .build(); @@ -795,21 +796,13 @@ fn should_safely_upgrade_from_old_version_to_new_version_with_reporting_mode( expected_total_token_supply_post_upgrade ); - // Expect No Migration event after 3 Mint events. - let seed_uref = *builder - .query(None, nft_contract_key, &[]) - .expect("must have nft contract") - .as_contract() - .expect("must convert contract") - .named_keys() - .get(casper_event_standard::EVENTS_DICT) - .expect("must have key") - .as_uref() - .expect("must convert to seed uref"); - - builder - .query_dictionary_item(None, seed_uref, "3") - .expect_err("should not have dictionary value for a third migration event"); + // Expect Migration event after 3 mint events + // Below version 1.5.1 migration event is not recorded as per bug https://github.com/casper-ecosystem/cep-78-enhanced-nft/issues/261 + let expected_event = Migration::new(); + let expected_event_index = 3; + let actual_event: Migration = + support::get_event(&builder, &nft_contract_key, expected_event_index).unwrap(); + assert_eq!(actual_event, expected_event, "Expected Migration event."); } #[test] @@ -1002,56 +995,37 @@ fn should_safely_upgrade_with_operator_burn_mode() { } #[test] -fn should_safely_upgrade_from_1_2_0_to_1_3_0() { - //* starting total_token_supply 100u64 - let expected_total_token_supply_post_upgrade = 10; - should_safely_upgrade_from_old_version_to_new_version_with_reporting_mode( - CONTRACT_1_2_0_WASM, - CONTRACT_1_3_0_WASM, - OwnerReverseLookupMode::NoLookUp, - expected_total_token_supply_post_upgrade, - ); - let expected_total_token_supply_post_upgrade = 100; - should_safely_upgrade_from_old_version_to_new_version_with_reporting_mode( - CONTRACT_1_2_0_WASM, - CONTRACT_1_3_0_WASM, - OwnerReverseLookupMode::Complete, - expected_total_token_supply_post_upgrade, - ); -} - -#[test] -fn should_safely_upgrade_from_1_3_0_to_1_4_0() { +fn should_safely_upgrade_from_1_4_0_to_current_version() { //* starting total_token_supply 100u64 let expected_total_token_supply_post_upgrade = 10; should_safely_upgrade_from_old_version_to_new_version_with_reporting_mode( - CONTRACT_1_3_0_WASM, CONTRACT_1_4_0_WASM, + NFT_CONTRACT_WASM, OwnerReverseLookupMode::NoLookUp, expected_total_token_supply_post_upgrade, ); let expected_total_token_supply_post_upgrade = 100; should_safely_upgrade_from_old_version_to_new_version_with_reporting_mode( - CONTRACT_1_3_0_WASM, CONTRACT_1_4_0_WASM, + NFT_CONTRACT_WASM, OwnerReverseLookupMode::Complete, expected_total_token_supply_post_upgrade, ); } #[test] -fn should_safely_upgrade_from_1_4_0_to_current_version() { +fn should_safely_upgrade_from_1_5_0_to_current_version() { //* starting total_token_supply 100u64 let expected_total_token_supply_post_upgrade = 10; should_safely_upgrade_from_old_version_to_new_version_with_reporting_mode( - CONTRACT_1_4_0_WASM, + CONTRACT_1_5_0_WASM, NFT_CONTRACT_WASM, OwnerReverseLookupMode::NoLookUp, expected_total_token_supply_post_upgrade, ); let expected_total_token_supply_post_upgrade = 100; should_safely_upgrade_from_old_version_to_new_version_with_reporting_mode( - CONTRACT_1_4_0_WASM, + CONTRACT_1_5_0_WASM, NFT_CONTRACT_WASM, OwnerReverseLookupMode::Complete, expected_total_token_supply_post_upgrade, @@ -1136,6 +1110,7 @@ fn should_safely_upgrade_from_1_0_0_to_1_2_0_to_current_version() { ARG_ACCESS_KEY_NAME_1_0_0 => format!("{PREFIX_ACCESS_KEY_NAME}_{NFT_TEST_COLLECTION}"), ARG_HASH_KEY_NAME_1_0_0 => format!("{PREFIX_HASH_KEY_NAME}_{NFT_TEST_COLLECTION}"), ARG_TOTAL_TOKEN_SUPPLY => 10u64, + ARG_EVENTS_MODE => EventsMode::CES as u8 }, ) .build(); @@ -1247,6 +1222,231 @@ fn should_safely_upgrade_from_1_0_0_to_1_3_0_to_current_version() { ARG_ACCESS_KEY_NAME_1_0_0 => format!("{PREFIX_ACCESS_KEY_NAME}_{NFT_TEST_COLLECTION}"), ARG_HASH_KEY_NAME_1_0_0 => format!("{PREFIX_HASH_KEY_NAME}_{NFT_TEST_COLLECTION}"), ARG_TOTAL_TOKEN_SUPPLY => 10u64, + ARG_EVENTS_MODE => EventsMode::CES as u8 + }, + ) + .build(); + + builder.exec(upgrade_request).expect_success().commit(); + + let nft_contract_hash = support::get_nft_contract_hash(&builder); + let nft_contract_key: Key = nft_contract_hash.into(); + + let number_of_tokens_at_upgrade = support::get_stored_value_from_global_state::( + &builder, + nft_contract_key, + vec![NUMBER_OF_MINTED_TOKENS.to_string()], + ) + .expect("must get u64 value"); + + assert_eq!(number_of_tokens_at_upgrade, 3); + + let total_token_supply_post_upgrade = support::get_stored_value_from_global_state::( + &builder, + nft_contract_key, + vec![ARG_TOTAL_TOKEN_SUPPLY.to_string()], + ) + .expect("must get u64 value"); + + assert_eq!(total_token_supply_post_upgrade, 50u64); + + // Expect Migration event. + let expected_event = Migration::new(); + let actual_event: Migration = support::get_event(&builder, &nft_contract_key, 0).unwrap(); + assert_eq!(actual_event, expected_event, "Expected Migration event."); +} + +#[test] +fn should_safely_upgrade_from_1_0_0_to_1_4_0_to_current_version() { + let mut builder = InMemoryWasmTestBuilder::default(); + builder + .run_genesis(&PRODUCTION_RUN_GENESIS_REQUEST) + .commit(); + + let install_request = InstallerRequestBuilder::new(*DEFAULT_ACCOUNT_ADDR, CONTRACT_1_0_0_WASM) + .with_collection_name(NFT_TEST_COLLECTION.to_string()) + .with_collection_symbol(NFT_TEST_SYMBOL.to_string()) + .with_total_token_supply(100u64) + .with_ownership_mode(OwnershipMode::Transferable) + .with_metadata_mutability(MetadataMutability::Mutable) + .with_identifier_mode(NFTIdentifierMode::Ordinal) + .with_nft_metadata_kind(NFTMetadataKind::Raw) + .build(); + + builder.exec(install_request).expect_success().commit(); + + let nft_contract_hash_1_0_0 = support::get_nft_contract_hash_1_0_0(&builder); + let nft_contract_key_1_0_0: Key = nft_contract_hash_1_0_0.into(); + + let upgrade_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + CONTRACT_1_4_0_WASM, + runtime_args! { + ARG_NFT_CONTRACT_HASH => nft_contract_key_1_0_0, + ARG_COLLECTION_NAME => NFT_TEST_COLLECTION.to_string(), + ARG_NAMED_KEY_CONVENTION => NamedKeyConventionMode::V1_0Standard as u8, + ARG_EVENTS_MODE => EventsMode::CES as u8, + ARG_TOTAL_TOKEN_SUPPLY => 50u64 + }, + ) + .build(); + + builder.exec(upgrade_request).expect_success().commit(); + + let total_token_supply_post_upgrade = support::get_stored_value_from_global_state::( + &builder, + nft_contract_key_1_0_0, + vec![ARG_TOTAL_TOKEN_SUPPLY.to_string()], + ) + .expect("must get u64 value"); + + assert_eq!(total_token_supply_post_upgrade, 50u64); + + let nft_contract_hash_1_4_0: ContractHash = support::get_nft_contract_hash(&builder); + let nft_contract_key_1_4_0: Key = nft_contract_hash_1_4_0.into(); + + let number_of_tokens_pre_migration = 3usize; + + // Build of prestate before migration. + for _i in 0..number_of_tokens_pre_migration { + let mint_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + MINT_SESSION_WASM, + runtime_args! { + ARG_NFT_CONTRACT_HASH => nft_contract_key_1_4_0, + ARG_TOKEN_OWNER => Key::Account(*DEFAULT_ACCOUNT_ADDR), + ARG_TOKEN_META_DATA => "", + ARG_COLLECTION_NAME => NFT_TEST_COLLECTION.to_string() + }, + ) + .build(); + + builder.exec(mint_request).expect_success().commit(); + } + + let upgrade_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + NFT_CONTRACT_WASM, + runtime_args! { + ARG_NFT_CONTRACT_HASH => nft_contract_key_1_4_0, + ARG_COLLECTION_NAME => NFT_TEST_COLLECTION.to_string(), + ARG_NAMED_KEY_CONVENTION => NamedKeyConventionMode::V1_0Custom as u8, + ARG_ACCESS_KEY_NAME_1_0_0 => format!("{PREFIX_ACCESS_KEY_NAME}_{NFT_TEST_COLLECTION}"), + ARG_HASH_KEY_NAME_1_0_0 => format!("{PREFIX_HASH_KEY_NAME}_{NFT_TEST_COLLECTION}"), + ARG_TOTAL_TOKEN_SUPPLY => 10u64, + ARG_EVENTS_MODE => EventsMode::CES as u8 + }, + ) + .build(); + + builder.exec(upgrade_request).expect_success().commit(); + + let nft_contract_hash = support::get_nft_contract_hash(&builder); + let nft_contract_key: Key = nft_contract_hash.into(); + + let number_of_tokens_at_upgrade = support::get_stored_value_from_global_state::( + &builder, + nft_contract_key, + vec![NUMBER_OF_MINTED_TOKENS.to_string()], + ) + .expect("must get u64 value"); + + assert_eq!(number_of_tokens_at_upgrade, 3); + + let total_token_supply_post_upgrade = support::get_stored_value_from_global_state::( + &builder, + nft_contract_key, + vec![ARG_TOTAL_TOKEN_SUPPLY.to_string()], + ) + .expect("must get u64 value"); + + assert_eq!(total_token_supply_post_upgrade, 50u64); + + // Expect Migration event. + let expected_event = Migration::new(); + let actual_event: Migration = support::get_event(&builder, &nft_contract_key, 0).unwrap(); + assert_eq!(actual_event, expected_event, "Expected Migration event."); +} + +#[test] +fn should_safely_upgrade_from_1_0_0_to_1_5_0_to_current_version() { + let mut builder = InMemoryWasmTestBuilder::default(); + builder + .run_genesis(&PRODUCTION_RUN_GENESIS_REQUEST) + .commit(); + + let install_request = InstallerRequestBuilder::new(*DEFAULT_ACCOUNT_ADDR, CONTRACT_1_0_0_WASM) + .with_collection_name(NFT_TEST_COLLECTION.to_string()) + .with_collection_symbol(NFT_TEST_SYMBOL.to_string()) + .with_total_token_supply(100u64) + .with_ownership_mode(OwnershipMode::Transferable) + .with_metadata_mutability(MetadataMutability::Mutable) + .with_identifier_mode(NFTIdentifierMode::Ordinal) + .with_nft_metadata_kind(NFTMetadataKind::Raw) + .build(); + + builder.exec(install_request).expect_success().commit(); + + let nft_contract_hash_1_0_0 = support::get_nft_contract_hash_1_0_0(&builder); + let nft_contract_key_1_0_0: Key = nft_contract_hash_1_0_0.into(); + + let upgrade_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + CONTRACT_1_5_0_WASM, + runtime_args! { + ARG_NFT_CONTRACT_HASH => nft_contract_key_1_0_0, + ARG_COLLECTION_NAME => NFT_TEST_COLLECTION.to_string(), + ARG_NAMED_KEY_CONVENTION => NamedKeyConventionMode::V1_0Standard as u8, + ARG_EVENTS_MODE => EventsMode::CES as u8, + ARG_TOTAL_TOKEN_SUPPLY => 50u64 + }, + ) + .build(); + + builder.exec(upgrade_request).expect_success().commit(); + + let total_token_supply_post_upgrade = support::get_stored_value_from_global_state::( + &builder, + nft_contract_key_1_0_0, + vec![ARG_TOTAL_TOKEN_SUPPLY.to_string()], + ) + .expect("must get u64 value"); + + assert_eq!(total_token_supply_post_upgrade, 50u64); + + let nft_contract_hash_1_5_0: ContractHash = support::get_nft_contract_hash(&builder); + let nft_contract_key_1_5_0: Key = nft_contract_hash_1_5_0.into(); + + let number_of_tokens_pre_migration = 3usize; + + // Build of prestate before migration. + for _i in 0..number_of_tokens_pre_migration { + let mint_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + MINT_SESSION_WASM, + runtime_args! { + ARG_NFT_CONTRACT_HASH => nft_contract_key_1_5_0, + ARG_TOKEN_OWNER => Key::Account(*DEFAULT_ACCOUNT_ADDR), + ARG_TOKEN_META_DATA => "", + ARG_COLLECTION_NAME => NFT_TEST_COLLECTION.to_string() + }, + ) + .build(); + + builder.exec(mint_request).expect_success().commit(); + } + + let upgrade_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + NFT_CONTRACT_WASM, + runtime_args! { + ARG_NFT_CONTRACT_HASH => nft_contract_key_1_5_0, + ARG_COLLECTION_NAME => NFT_TEST_COLLECTION.to_string(), + ARG_NAMED_KEY_CONVENTION => NamedKeyConventionMode::V1_0Custom as u8, + ARG_ACCESS_KEY_NAME_1_0_0 => format!("{PREFIX_ACCESS_KEY_NAME}_{NFT_TEST_COLLECTION}"), + ARG_HASH_KEY_NAME_1_0_0 => format!("{PREFIX_HASH_KEY_NAME}_{NFT_TEST_COLLECTION}"), + ARG_TOTAL_TOKEN_SUPPLY => 10u64, + ARG_EVENTS_MODE => EventsMode::CES as u8 }, ) .build(); @@ -1280,6 +1480,190 @@ fn should_safely_upgrade_from_1_0_0_to_1_3_0_to_current_version() { assert_eq!(actual_event, expected_event, "Expected Migration event."); } +#[test] +fn should_safely_upgrade_from_1_5_0_to_current_version_without_supplying_events_mode_to_keep_current_mode( +) { + let mut builder = InMemoryWasmTestBuilder::default(); + builder + .run_genesis(&PRODUCTION_RUN_GENESIS_REQUEST) + .commit(); + + let install_request = InstallerRequestBuilder::new(*DEFAULT_ACCOUNT_ADDR, CONTRACT_1_5_0_WASM) + .with_collection_name(NFT_TEST_COLLECTION.to_string()) + .with_collection_symbol(NFT_TEST_SYMBOL.to_string()) + .with_total_token_supply(100u64) + .with_ownership_mode(OwnershipMode::Transferable) + .with_metadata_mutability(MetadataMutability::Mutable) + .with_identifier_mode(NFTIdentifierMode::Ordinal) + .with_nft_metadata_kind(NFTMetadataKind::Raw) + .build(); + + builder.exec(install_request).expect_success().commit(); + + let nft_contract_hash_1_5_0: ContractHash = support::get_nft_contract_hash(&builder); + let nft_contract_key_1_5_0: Key = nft_contract_hash_1_5_0.into(); + + let total_token_supply_post_install = support::get_stored_value_from_global_state::( + &builder, + nft_contract_key_1_5_0, + vec![ARG_TOTAL_TOKEN_SUPPLY.to_string()], + ) + .expect("must get u64 value"); + + assert_eq!(total_token_supply_post_install, 100u64); + + let number_of_tokens_pre_migration = 3usize; + + // Build of prestate before migration. + for _i in 0..number_of_tokens_pre_migration { + let mint_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + MINT_SESSION_WASM, + runtime_args! { + ARG_NFT_CONTRACT_HASH => nft_contract_key_1_5_0, + ARG_TOKEN_OWNER => Key::Account(*DEFAULT_ACCOUNT_ADDR), + ARG_TOKEN_META_DATA => "", + ARG_COLLECTION_NAME => NFT_TEST_COLLECTION.to_string() + }, + ) + .build(); + + builder.exec(mint_request).expect_success().commit(); + } + + let upgrade_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + NFT_CONTRACT_WASM, + runtime_args! { + ARG_NFT_CONTRACT_HASH => nft_contract_key_1_5_0, + ARG_COLLECTION_NAME => NFT_TEST_COLLECTION.to_string(), + ARG_NAMED_KEY_CONVENTION => NamedKeyConventionMode::V1_0Custom as u8, + ARG_ACCESS_KEY_NAME_1_0_0 => format!("{PREFIX_ACCESS_KEY_NAME}_{NFT_TEST_COLLECTION}"), + ARG_HASH_KEY_NAME_1_0_0 => format!("{PREFIX_HASH_KEY_NAME}_{NFT_TEST_COLLECTION}"), + ARG_TOTAL_TOKEN_SUPPLY => 10u64, + }, + ) + .build(); + + builder.exec(upgrade_request).expect_success().commit(); + + let nft_contract_hash = support::get_nft_contract_hash(&builder); + let nft_contract_key: Key = nft_contract_hash.into(); + + let number_of_tokens_at_upgrade = support::get_stored_value_from_global_state::( + &builder, + nft_contract_key, + vec![NUMBER_OF_MINTED_TOKENS.to_string()], + ) + .expect("must get u64 value"); + + assert_eq!(number_of_tokens_at_upgrade, 3); + + // Expect Migration event. + let expected_event = Migration::new(); + let expected_event_index = 3; + let actual_event: Migration = + support::get_event(&builder, &nft_contract_key, expected_event_index).unwrap(); + assert_eq!(actual_event, expected_event, "Expected Migration event."); +} + +#[test] +fn should_safely_upgrade_from_1_5_0_and_disable_events_mode() { + let mut builder = InMemoryWasmTestBuilder::default(); + builder + .run_genesis(&PRODUCTION_RUN_GENESIS_REQUEST) + .commit(); + + let install_request = InstallerRequestBuilder::new(*DEFAULT_ACCOUNT_ADDR, CONTRACT_1_5_0_WASM) + .with_collection_name(NFT_TEST_COLLECTION.to_string()) + .with_collection_symbol(NFT_TEST_SYMBOL.to_string()) + .with_total_token_supply(100u64) + .with_ownership_mode(OwnershipMode::Transferable) + .with_metadata_mutability(MetadataMutability::Mutable) + .with_identifier_mode(NFTIdentifierMode::Ordinal) + .with_nft_metadata_kind(NFTMetadataKind::Raw) + .with_events_mode(EventsMode::CES) + .build(); + + builder.exec(install_request).expect_success().commit(); + + let nft_contract_hash_1_5_0: ContractHash = support::get_nft_contract_hash(&builder); + let nft_contract_key_1_5_0: Key = nft_contract_hash_1_5_0.into(); + + let total_token_supply_post_install = support::get_stored_value_from_global_state::( + &builder, + nft_contract_key_1_5_0, + vec![ARG_TOTAL_TOKEN_SUPPLY.to_string()], + ) + .expect("must get u64 value"); + + assert_eq!(total_token_supply_post_install, 100u64); + + let number_of_tokens_pre_migration = 3usize; + + // Build of prestate before migration. + for _i in 0..number_of_tokens_pre_migration { + let mint_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + MINT_SESSION_WASM, + runtime_args! { + ARG_NFT_CONTRACT_HASH => nft_contract_key_1_5_0, + ARG_TOKEN_OWNER => Key::Account(*DEFAULT_ACCOUNT_ADDR), + ARG_TOKEN_META_DATA => "", + ARG_COLLECTION_NAME => NFT_TEST_COLLECTION.to_string() + }, + ) + .build(); + + builder.exec(mint_request).expect_success().commit(); + } + + let upgrade_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + NFT_CONTRACT_WASM, + runtime_args! { + ARG_NFT_CONTRACT_HASH => nft_contract_key_1_5_0, + ARG_COLLECTION_NAME => NFT_TEST_COLLECTION.to_string(), + ARG_NAMED_KEY_CONVENTION => NamedKeyConventionMode::V1_0Custom as u8, + ARG_ACCESS_KEY_NAME_1_0_0 => format!("{PREFIX_ACCESS_KEY_NAME}_{NFT_TEST_COLLECTION}"), + ARG_HASH_KEY_NAME_1_0_0 => format!("{PREFIX_HASH_KEY_NAME}_{NFT_TEST_COLLECTION}"), + ARG_TOTAL_TOKEN_SUPPLY => 10u64, + ARG_EVENTS_MODE => EventsMode::NoEvents as u8, + }, + ) + .build(); + + builder.exec(upgrade_request).expect_success().commit(); + + let nft_contract_hash = support::get_nft_contract_hash(&builder); + let nft_contract_key: Key = nft_contract_hash.into(); + + let number_of_tokens_at_upgrade = support::get_stored_value_from_global_state::( + &builder, + nft_contract_key, + vec![NUMBER_OF_MINTED_TOKENS.to_string()], + ) + .expect("must get u64 value"); + + assert_eq!(number_of_tokens_at_upgrade, 3); + + // Expect No Migration event after 3 Mint events. + let seed_uref = *builder + .query(None, nft_contract_key, &[]) + .expect("must have nft contract") + .as_contract() + .expect("must convert contract") + .named_keys() + .get(casper_event_standard::EVENTS_DICT) + .expect("must have key") + .as_uref() + .expect("must convert to seed uref"); + + builder + .query_dictionary_item(None, seed_uref, "3") + .expect_err("should not have dictionary value for a third migration event"); +} + #[test] fn should_safely_upgrade_from_1_0_0_to_current_version() { let mut builder = InMemoryWasmTestBuilder::default(); diff --git a/tests/src/utility/constants.rs b/tests/src/utility/constants.rs index adf4a4b2..0f620cd2 100644 --- a/tests/src/utility/constants.rs +++ b/tests/src/utility/constants.rs @@ -4,6 +4,7 @@ pub const CONTRACT_1_1_0_WASM: &str = "1_1_0/contract.wasm"; pub const CONTRACT_1_2_0_WASM: &str = "1_2_0/contract.wasm"; pub const CONTRACT_1_3_0_WASM: &str = "1_3_0/contract.wasm"; pub const CONTRACT_1_4_0_WASM: &str = "1_4_0/contract.wasm"; +pub const CONTRACT_1_5_0_WASM: &str = "1_5_0/contract.wasm"; pub const GET_APPROVED_WASM: &str = "get_approved_call.wasm"; pub const IS_APPROVED_FOR_ALL_WASM: &str = "is_approved_for_all_call.wasm"; pub const MANGLE_NAMED_KEYS: &str = "mangle_named_keys.wasm";