diff --git a/contracts/nft-reward/src/errors.rs b/contracts/nft-reward/src/errors.rs index c4c72f3..4dfbc53 100644 --- a/contracts/nft-reward/src/errors.rs +++ b/contracts/nft-reward/src/errors.rs @@ -17,8 +17,5 @@ pub enum NftErrorCode { NftNotTransferable = 11, NftLocked = 12, InvalidMetadata = 13, - InvalidTitle = 14, - InvalidDescription = 15, - InvalidImageUri = 16, - InvalidHuntTitle = 17, + MetadataFrozen = 14, } diff --git a/contracts/nft-reward/src/lib.rs b/contracts/nft-reward/src/lib.rs index 9acaa39..bf360ed 100644 --- a/contracts/nft-reward/src/lib.rs +++ b/contracts/nft-reward/src/lib.rs @@ -102,6 +102,7 @@ pub struct NftData { pub transferable: bool, pub minted_at: u64, pub locked: bool, + pub metadata_frozen: bool, } /// Event emitted when an NFT is minted. @@ -143,6 +144,14 @@ pub struct NftMetadataUpdatedEvent { pub updater: Address, } +/// Event emitted when an NFT's metadata is permanently frozen. +#[contracttype] +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct NftMetadataFrozenEvent { + pub nft_id: u64, + pub owner: Address, +} + /// Event emitted when admin batch-updates image URIs across NFTs. #[contracttype] #[derive(Clone, Debug, PartialEq, Eq)] @@ -600,6 +609,7 @@ impl NftReward { transferable, minted_at, locked: false, + metadata_frozen: false, }; Storage::save_nft(&env, &nft_data); @@ -731,7 +741,11 @@ impl NftReward { return Err(crate::errors::NftErrorCode::NotOwner); } - let new_description = Self::validate_metadata_field( + if nft.metadata_frozen { + return Err(crate::errors::NftErrorCode::MetadataFrozen); + } + + let new_description = Self::sanitize_metadata_field( &env, &new_description, MAX_NFT_DESCRIPTION_BYTES, @@ -752,6 +766,36 @@ impl NftReward { Ok(()) } + /// Permanently freezes the NFT's metadata, preventing future updates. Owner only. + pub fn freeze_nft_metadata( + env: Env, + nft_id: u64, + owner: Address, + ) -> Result<(), crate::errors::NftErrorCode> { + owner.require_auth(); + + let mut nft = + Storage::get_nft(&env, nft_id).ok_or(crate::errors::NftErrorCode::NftNotFound)?; + + if nft.owner != owner { + return Err(crate::errors::NftErrorCode::NotOwner); + } + + if nft.metadata_frozen { + return Err(crate::errors::NftErrorCode::MetadataFrozen); + } + + nft.metadata_frozen = true; + Storage::save_nft(&env, &nft); + + env.events().publish( + (Symbol::new(&env, "NftMetadataFrozen"), nft_id), + NftMetadataFrozenEvent { nft_id, owner }, + ); + + Ok(()) + } + /// Returns the total number of NFTs minted so far. pub fn total_supply(env: Env) -> u64 { Storage::get_nft_counter(&env)