From c8b2fd69113b458cea9a059f4ce474c0198530b0 Mon Sep 17 00:00:00 2001 From: ananas-block Date: Sun, 15 Jun 2025 15:30:17 +0100 Subject: [PATCH 1/3] fix: system program add signer mut account check --- program-libs/account-checks/src/checks.rs | 7 +++ program-libs/account-checks/tests/tests.rs | 43 +++++++++++++++++++ .../system/src/accounts/account_checks.rs | 5 ++- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/program-libs/account-checks/src/checks.rs b/program-libs/account-checks/src/checks.rs index f5aff8d5de..68e5671ecf 100644 --- a/program-libs/account-checks/src/checks.rs +++ b/program-libs/account-checks/src/checks.rs @@ -121,6 +121,13 @@ pub fn check_signer(account_info: &A) -> Result<(), Account Ok(()) } +pub fn check_mut(account_info: &A) -> Result<(), AccountError> { + if !account_info.is_writable() { + return Err(AccountError::AccountNotMutable); + } + Ok(()) +} + pub fn check_owner( owner: &[u8; 32], account_info: &A, diff --git a/program-libs/account-checks/tests/tests.rs b/program-libs/account-checks/tests/tests.rs index c1e3df88ba..d2570cdea1 100644 --- a/program-libs/account-checks/tests/tests.rs +++ b/program-libs/account-checks/tests/tests.rs @@ -298,6 +298,49 @@ fn test_check_non_mut() { } } +// 4.5. check_mut tests - 4 tests total +#[test] +fn test_check_mut() { + // Solana success case + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, true); + assert!(check_mut(&account.get_account_info()).is_ok()); + } + + // Solana failure case (not writable) + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, false); + assert_eq!( + check_mut(&account.get_account_info()), + Err(AccountError::AccountNotMutable) + ); + } + + // Pinocchio success case + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, true, false, false); + assert!(check_mut(&account).is_ok()); + } + + // Pinocchio failure case (not writable) + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, false, false, false); + assert_eq!(check_mut(&account), Err(AccountError::AccountNotMutable)); + } +} + // 5. check_account_info tests - 6 tests total #[test] fn test_check_account_info() { diff --git a/programs/system/src/accounts/account_checks.rs b/programs/system/src/accounts/account_checks.rs index 569c6b6eef..624bc43f3f 100644 --- a/programs/system/src/accounts/account_checks.rs +++ b/programs/system/src/accounts/account_checks.rs @@ -1,6 +1,6 @@ use light_account_checks::checks::{ - check_discriminator, check_non_mut, check_owner, check_pda_seeds, check_pda_seeds_with_bump, - check_program, check_signer, + check_account_info_mut, check_discriminator, check_mut, check_non_mut, check_owner, + check_pda_seeds, check_pda_seeds_with_bump, check_program, check_signer, }; use light_compressed_account::{ constants::ACCOUNT_COMPRESSION_PROGRAM_ID, instruction_data::traits::AccountOptions, @@ -14,6 +14,7 @@ use crate::{ pub fn check_fee_payer(fee_payer: Option<&AccountInfo>) -> Result<&AccountInfo> { let fee_payer = fee_payer.ok_or(ProgramError::NotEnoughAccountKeys)?; check_signer(fee_payer).map_err(ProgramError::from)?; + check_mut(fee_payer).map_err(ProgramError::from)?; Ok(fee_payer) } From 6f6af0cbd41e40fe601746ec18d5137b2ac5e8e4 Mon Sep 17 00:00:00 2001 From: ananas-block Date: Sun, 15 Jun 2025 15:41:52 +0100 Subject: [PATCH 2/3] chore: simplify check_account_info_mut --- program-libs/account-checks/src/checks.rs | 5 +---- programs/system/src/accounts/account_checks.rs | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/program-libs/account-checks/src/checks.rs b/program-libs/account-checks/src/checks.rs index 68e5671ecf..fdbc043afa 100644 --- a/program-libs/account-checks/src/checks.rs +++ b/program-libs/account-checks/src/checks.rs @@ -24,9 +24,7 @@ pub fn check_account_info_mut( program_id: &[u8; 32], account_info: &A, ) -> Result<(), AccountError> { - if !account_info.is_writable() { - return Err(AccountError::AccountMutable); - } + check_mut(account_info)?; check_account_info::(program_id, account_info) } @@ -39,7 +37,6 @@ pub fn check_account_info_non_mut( account_info: &A, ) -> Result<(), AccountError> { check_non_mut(account_info)?; - check_account_info::(program_id, account_info) } diff --git a/programs/system/src/accounts/account_checks.rs b/programs/system/src/accounts/account_checks.rs index 624bc43f3f..70ab3b3915 100644 --- a/programs/system/src/accounts/account_checks.rs +++ b/programs/system/src/accounts/account_checks.rs @@ -1,6 +1,6 @@ use light_account_checks::checks::{ - check_account_info_mut, check_discriminator, check_mut, check_non_mut, check_owner, - check_pda_seeds, check_pda_seeds_with_bump, check_program, check_signer, + check_discriminator, check_mut, check_non_mut, check_owner, check_pda_seeds, + check_pda_seeds_with_bump, check_program, check_signer, }; use light_compressed_account::{ constants::ACCOUNT_COMPRESSION_PROGRAM_ID, instruction_data::traits::AccountOptions, From 5bc72d580ed06a1bccf78ade2fefa5a1e193da2f Mon Sep 17 00:00:00 2001 From: ananas-block Date: Sun, 15 Jun 2025 16:53:26 +0100 Subject: [PATCH 3/3] fix tests --- program-libs/account-checks/tests/tests.rs | 4 ++-- programs/system/src/invoke/instruction.rs | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/program-libs/account-checks/tests/tests.rs b/program-libs/account-checks/tests/tests.rs index d2570cdea1..d7b45bc366 100644 --- a/program-libs/account-checks/tests/tests.rs +++ b/program-libs/account-checks/tests/tests.rs @@ -170,7 +170,7 @@ fn test_check_account_info_mut() { set_discriminator::(&mut account.data).unwrap(); assert_eq!( check_account_info_mut::(&owner.to_bytes(), &account.get_account_info()), - Err(AccountError::AccountMutable) + Err(AccountError::AccountNotMutable) ); } @@ -193,7 +193,7 @@ fn test_check_account_info_mut() { account_info_init::(&account).unwrap(); assert_eq!( check_account_info_mut::(&owner, &account), - Err(AccountError::AccountMutable) + Err(AccountError::AccountNotMutable) ); } } diff --git a/programs/system/src/invoke/instruction.rs b/programs/system/src/invoke/instruction.rs index be0b7c8a6d..1241ecd05e 100644 --- a/programs/system/src/invoke/instruction.rs +++ b/programs/system/src/invoke/instruction.rs @@ -1,3 +1,4 @@ +use light_account_checks::checks::check_signer; use pinocchio::{account_info::AccountInfo, program_error::ProgramError}; use crate::{ @@ -46,7 +47,8 @@ impl<'info> InvokeInstruction<'info> { let fee_payer = check_fee_payer(accounts.next())?; // Fee payer and authority can be the same account in case of invoke. - let authority = check_fee_payer(accounts.next())?; + let authority = accounts.next().ok_or(ProgramError::NotEnoughAccountKeys)?; + check_signer(authority).map_err(ProgramError::from)?; let registered_program_pda = check_non_mut_account_info(accounts.next())?;