diff --git a/programs/compressed-token/program/src/shared/create_pda_account.rs b/programs/compressed-token/program/src/shared/create_pda_account.rs index f7eeb6ab12..592a0b9e1b 100644 --- a/programs/compressed-token/program/src/shared/create_pda_account.rs +++ b/programs/compressed-token/program/src/shared/create_pda_account.rs @@ -43,6 +43,12 @@ pub fn create_pda_account( // Cold Path: if account already has lamports (e.g., from attacker donation), // use Assign + realloc + Transfer instead of CreateAccount which would fail. if new_account.lamports() > 0 { + // Verify account is owned by system program (uninitialized). + // Prevents overwriting an already-initialized account. + if !new_account.is_owned_by(&[0u8; 32]) { + return Err(ProgramError::AccountAlreadyInitialized); + } + let current_lamports = new_account.lamports(); Assign { diff --git a/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs b/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs index da6afdaa2c..1a19e89a76 100644 --- a/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs +++ b/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs @@ -213,14 +213,13 @@ pub fn initialize_ctoken_account( // Access the token account data as mutable bytes let mut token_account_data = AccountInfoTrait::try_borrow_mut_data(token_account_info)?; - // Zero all base token bytes before initialization to prevent pre-set values - // (e.g., amount field via IDL buffer) from persisting through new_zero_copy, - // which only sets mint, owner, and state without zeroing other fields. - if token_account_data.len() < 165 { - msg!("Token account data too small: {}", token_account_data.len()); - return Err(ProgramError::InvalidAccountData); + // Verify account data is zeroed. System-program-owned accounts from transfers + // have 0-length data, and resize zeros new bytes. Non-zero data indicates + // an unexpected state that should not be silently overwritten. + if token_account_data.iter().any(|&b| b != 0) { + msg!("Token account data is not zeroed"); + return Err(ProgramError::AccountAlreadyInitialized); } - token_account_data[..165].fill(0); // Use new_zero_copy to initialize the token account // This sets mint, owner, state, account_type, and extensions