diff --git a/Dev_Docs/audit/Solana-audit-by-Claude-File5-9июня2026.md b/Dev_Docs/audit/Solana-audit-by-Claude-File5-9июня2026.md new file mode 100644 index 0000000..473a0f4 diff --git a/shine-solana/shine/programs/shine_users/src/lib.rs b/shine-solana/shine/programs/shine_users/src/lib.rs index 11d7ad1..a4907f8 100644 --- a/shine-solana/shine/programs/shine_users/src/lib.rs +++ b/shine-solana/shine/programs/shine_users/src/lib.rs @@ -444,6 +444,7 @@ fn process_create_user_pda(program_id: &Pubkey, accounts: &[AccountInfo], args: require!(args.additional_limit % settings::LIMIT_STEP == 0, ShineUsersError::InvalidLimitIncrement); require_keys_eq!(*login_guard_program.key, Pubkey::from_str(settings::SHINE_LOGIN_GUARD_PROGRAM_ID).map_err(|_| ProgramError::from(ShineUsersError::InvalidLoginGuardResponse))?, ShineUsersError::InvalidLoginGuardResponse); classify_login_or_fail(login_guard_program, &args.login)?; + validate_users_economy_config_pda(program_id, users_economy_config_pda)?; let economy = read_users_economy_config(users_economy_config_pda)?; let login_seed = login_seed_normalized(&args.login); @@ -522,6 +523,7 @@ fn process_update_user_pda(program_id: &Pubkey, accounts: &[AccountInfo], args: validate_fields(&args.fields)?; validate_inflow_vault(inflow_vault)?; require!(args.additional_limit % settings::LIMIT_STEP == 0, ShineUsersError::InvalidLimitIncrement); + validate_users_economy_config_pda(program_id, users_economy_config_pda)?; let economy = read_users_economy_config(users_economy_config_pda)?; let normalized_login = login_seed_normalized(&args.login); @@ -630,6 +632,13 @@ fn serialize_users_economy_config(state: &UsersEconomyConfigState) -> Vec { out } +fn validate_users_economy_config_pda(program_id: &Pubkey, pda: &AccountInfo) -> ProgramResult { + let (expected_pda, _) = find_users_economy_config_pda(program_id); + require_keys_eq!(expected_pda, *pda.key, ShineUsersError::InvalidPdaAddress); + require!(pda.owner == program_id, ShineUsersError::InvalidPdaAddress); + Ok(()) +} + fn read_users_economy_config(pda: &AccountInfo) -> Result { let raw = read_pda_all(pda)?; require!(!raw.is_empty(), ShineUsersError::EmptyPdaData);