From 5981d3f87111d384300b759a45d361cf40ffe5fa5404a2301af0c66205ae2060 Mon Sep 17 00:00:00 2001 From: AidarKC Date: Tue, 9 Jun 2026 23:10:20 +0400 Subject: [PATCH] =?UTF-8?q?solana:=20=D0=BF=D1=80=D0=B8=D0=B2=D1=8F=D0=B7?= =?UTF-8?q?=D0=B0=D1=82=D1=8C=20singleton=20pda=20=D0=B2=20shine=5Fpayment?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shine/programs/shine_payments/src/lib.rs | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/shine-solana/shine/programs/shine_payments/src/lib.rs b/shine-solana/shine/programs/shine_payments/src/lib.rs index bfbb121..da1532f 100644 --- a/shine-solana/shine/programs/shine_payments/src/lib.rs +++ b/shine-solana/shine/programs/shine_payments/src/lib.rs @@ -596,7 +596,7 @@ fn process_init(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult } fn process_update_coef_limit( - _program_id: &Pubkey, + program_id: &Pubkey, accounts: &[AccountInfo], args: UpdateCoefLimitArgs, ) -> ProgramResult { @@ -606,6 +606,8 @@ fn process_update_coef_limit( let coef_limit_pda = next_account_info(account_iter)?; require!(account_iter.next().is_none(), PaymentsError::InvalidInstruction); + validate_singleton_state_pda(program_id, config_pda, settings::CONFIG_SEED)?; + validate_singleton_state_pda(program_id, coef_limit_pda, settings::COEF_LIMIT_SEED)?; let config = read_state::(config_pda)?; require_keys_eq!(config.dao_wallet, *signer.key, PaymentsError::UnauthorizedDao); require!(args.coef_ppm > 0, PaymentsError::InvalidCoefficient); @@ -635,6 +637,7 @@ fn process_grant_manager_limits( require!(account_iter.next().is_none(), PaymentsError::InvalidInstruction); require_system_program(system_program_ai)?; + validate_singleton_state_pda(program_id, config_pda, settings::CONFIG_SEED)?; let config = read_state::(config_pda)?; require_keys_eq!(config.dao_wallet, *signer.key, PaymentsError::UnauthorizedDao); require!( @@ -738,6 +741,7 @@ fn process_manager_add_ticket( let (expected_manager_pda, _) = find_manager_allowance_pda(program_id, signer.key); require_keys_eq!(expected_manager_pda, *manager_allowance_pda.key, PaymentsError::InvalidPdaAddress); + validate_singleton_state_pda(program_id, queues_pda, settings::QUEUES_SEED)?; let mut allowance = read_state::(manager_allowance_pda)?; require_keys_eq!(allowance.manager_wallet, *signer.key, PaymentsError::InvalidManagerWallet); @@ -793,6 +797,10 @@ fn process_step_payout(program_id: &Pubkey, accounts: &[AccountInfo]) -> Program let sol_usd_price_update = next_account_info(account_iter)?; require!(account_iter.next().is_none(), PaymentsError::InvalidInstruction); + validate_singleton_state_pda(program_id, config_pda, settings::CONFIG_SEED)?; + validate_singleton_state_pda(program_id, coef_limit_pda, settings::COEF_LIMIT_SEED)?; + validate_singleton_state_pda(program_id, queues_pda, settings::QUEUES_SEED)?; + validate_singleton_state_pda(program_id, inflow_vault_pda, settings::INFLOW_VAULT_SEED)?; let config = read_state::(config_pda)?; let coef_limit = read_state::(coef_limit_pda)?; let mut queues = read_state::(queues_pda)?; @@ -856,6 +864,7 @@ fn process_change_ticket_recipient( let ticket_pda = next_account_info(account_iter)?; require!(account_iter.next().is_none(), PaymentsError::InvalidInstruction); + validate_singleton_state_pda(program_id, queues_pda, settings::QUEUES_SEED)?; let queues = read_state::(queues_pda)?; let mut ticket = read_state::(ticket_pda)?; require!(!ticket.is_paid, PaymentsError::TicketAlreadyPaid); @@ -944,6 +953,17 @@ fn ensure_expected_pdas( Ok(()) } +fn validate_singleton_state_pda( + program_id: &Pubkey, + pda: &AccountInfo, + seed: &[u8], +) -> ProgramResult { + let (expected_pda, _) = find_single_pda(program_id, seed); + require_keys_eq!(expected_pda, *pda.key, PaymentsError::InvalidPdaAddress); + require_keys_eq!(*pda.owner, id(), PaymentsError::InvalidPdaAddress); + Ok(()) +} + fn find_single_pda(program_id: &Pubkey, seed: &[u8]) -> (Pubkey, u8) { Pubkey::find_program_address(&[seed], program_id) } @@ -979,6 +999,9 @@ fn buy_ticket_by_purchase_usd( transfer_lamports: u64, recipient_wallet: Pubkey, ) -> ProgramResult { + validate_singleton_state_pda(program_id, ctx.config_pda, settings::CONFIG_SEED)?; + validate_singleton_state_pda(program_id, ctx.coef_limit_pda, settings::COEF_LIMIT_SEED)?; + validate_singleton_state_pda(program_id, ctx.queues_pda, settings::QUEUES_SEED)?; let config = read_state::(ctx.config_pda)?; let coef_limit = read_state::(ctx.coef_limit_pda)?; let mut queues = read_state::(ctx.queues_pda)?;