Skip to content

Commit e9c6594

Browse files
authored
fix: system program add signer mut account check (#1808)
* fix: system program add signer mut account check * chore: simplify check_account_info_mut * fix tests
1 parent 1c90f3e commit e9c6594

File tree

4 files changed

+59
-9
lines changed

4 files changed

+59
-9
lines changed

program-libs/account-checks/src/checks.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ pub fn check_account_info_mut<T: Discriminator, A: AccountInfoTrait>(
2424
program_id: &[u8; 32],
2525
account_info: &A,
2626
) -> Result<(), AccountError> {
27-
if !account_info.is_writable() {
28-
return Err(AccountError::AccountMutable);
29-
}
27+
check_mut(account_info)?;
3028
check_account_info::<T, A>(program_id, account_info)
3129
}
3230

@@ -39,7 +37,6 @@ pub fn check_account_info_non_mut<T: Discriminator, A: AccountInfoTrait>(
3937
account_info: &A,
4038
) -> Result<(), AccountError> {
4139
check_non_mut(account_info)?;
42-
4340
check_account_info::<T, A>(program_id, account_info)
4441
}
4542

@@ -121,6 +118,13 @@ pub fn check_signer<A: AccountInfoTrait>(account_info: &A) -> Result<(), Account
121118
Ok(())
122119
}
123120

121+
pub fn check_mut<A: AccountInfoTrait>(account_info: &A) -> Result<(), AccountError> {
122+
if !account_info.is_writable() {
123+
return Err(AccountError::AccountNotMutable);
124+
}
125+
Ok(())
126+
}
127+
124128
pub fn check_owner<A: AccountInfoTrait>(
125129
owner: &[u8; 32],
126130
account_info: &A,

program-libs/account-checks/tests/tests.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ fn test_check_account_info_mut() {
170170
set_discriminator::<TestStruct>(&mut account.data).unwrap();
171171
assert_eq!(
172172
check_account_info_mut::<TestStruct, _>(&owner.to_bytes(), &account.get_account_info()),
173-
Err(AccountError::AccountMutable)
173+
Err(AccountError::AccountNotMutable)
174174
);
175175
}
176176

@@ -193,7 +193,7 @@ fn test_check_account_info_mut() {
193193
account_info_init::<TestStruct, _>(&account).unwrap();
194194
assert_eq!(
195195
check_account_info_mut::<TestStruct, _>(&owner, &account),
196-
Err(AccountError::AccountMutable)
196+
Err(AccountError::AccountNotMutable)
197197
);
198198
}
199199
}
@@ -298,6 +298,49 @@ fn test_check_non_mut() {
298298
}
299299
}
300300

301+
// 4.5. check_mut tests - 4 tests total
302+
#[test]
303+
fn test_check_mut() {
304+
// Solana success case
305+
#[cfg(feature = "solana")]
306+
{
307+
let key = create_pubkey();
308+
let owner = create_pubkey();
309+
let mut account = create_test_account_solana(key, owner, 16, true);
310+
assert!(check_mut(&account.get_account_info()).is_ok());
311+
}
312+
313+
// Solana failure case (not writable)
314+
#[cfg(feature = "solana")]
315+
{
316+
let key = create_pubkey();
317+
let owner = create_pubkey();
318+
let mut account = create_test_account_solana(key, owner, 16, false);
319+
assert_eq!(
320+
check_mut(&account.get_account_info()),
321+
Err(AccountError::AccountNotMutable)
322+
);
323+
}
324+
325+
// Pinocchio success case
326+
#[cfg(feature = "pinocchio")]
327+
{
328+
let key = [1u8; 32];
329+
let owner = [2u8; 32];
330+
let account = create_test_account_pinocchio(key, owner, 16, true, false, false);
331+
assert!(check_mut(&account).is_ok());
332+
}
333+
334+
// Pinocchio failure case (not writable)
335+
#[cfg(feature = "pinocchio")]
336+
{
337+
let key = [1u8; 32];
338+
let owner = [2u8; 32];
339+
let account = create_test_account_pinocchio(key, owner, 16, false, false, false);
340+
assert_eq!(check_mut(&account), Err(AccountError::AccountNotMutable));
341+
}
342+
}
343+
301344
// 5. check_account_info tests - 6 tests total
302345
#[test]
303346
fn test_check_account_info() {

programs/system/src/accounts/account_checks.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use light_account_checks::checks::{
2-
check_discriminator, check_non_mut, check_owner, check_pda_seeds, check_pda_seeds_with_bump,
3-
check_program, check_signer,
2+
check_discriminator, check_mut, check_non_mut, check_owner, check_pda_seeds,
3+
check_pda_seeds_with_bump, check_program, check_signer,
44
};
55
use light_compressed_account::{
66
constants::ACCOUNT_COMPRESSION_PROGRAM_ID, instruction_data::traits::AccountOptions,
@@ -16,6 +16,7 @@ use crate::{
1616
pub fn check_fee_payer(fee_payer: Option<&AccountInfo>) -> Result<&AccountInfo> {
1717
let fee_payer = fee_payer.ok_or(ProgramError::NotEnoughAccountKeys)?;
1818
check_signer(fee_payer).map_err(ProgramError::from)?;
19+
check_mut(fee_payer).map_err(ProgramError::from)?;
1920
Ok(fee_payer)
2021
}
2122

programs/system/src/invoke/instruction.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use light_account_checks::checks::check_signer;
12
use pinocchio::{account_info::AccountInfo, program_error::ProgramError};
23

34
use crate::{
@@ -46,7 +47,8 @@ impl<'info> InvokeInstruction<'info> {
4647
let fee_payer = check_fee_payer(accounts.next())?;
4748

4849
// Fee payer and authority can be the same account in case of invoke.
49-
let authority = check_fee_payer(accounts.next())?;
50+
let authority = accounts.next().ok_or(ProgramError::NotEnoughAccountKeys)?;
51+
check_signer(authority).map_err(ProgramError::from)?;
5052

5153
let registered_program_pda = check_non_mut_account_info(accounts.next())?;
5254

0 commit comments

Comments
 (0)