diff --git a/programs/4-initialization/insecure/src/lib.rs b/programs/4-initialization/insecure/src/lib.rs index 916b433..d188aa8 100644 --- a/programs/4-initialization/insecure/src/lib.rs +++ b/programs/4-initialization/insecure/src/lib.rs @@ -9,10 +9,13 @@ pub mod initialization_insecure { use super::*; pub fn initialize(ctx: Context) -> ProgramResult { + // Deserialize the user account data let mut user = User::try_from_slice(&ctx.accounts.user.data.borrow()).unwrap(); + // Set the authority of the user user.authority = ctx.accounts.authority.key(); + // Re-serialize the user data back into the account let mut storage = ctx.accounts.user.try_borrow_mut_data()?; user.serialize(storage.deref_mut()).unwrap(); Ok(()) @@ -20,19 +23,20 @@ pub mod initialization_insecure { } /* -- reinitialize -- create and dont initialize -- passing previously initialzed accounts from other programs - (e.g. token program => need to check delegate and authority) +- reinitialize: The program can reinitialize the account, which may be a security risk. +- create and don't initialize: The account could be created without being initialized. +- passing previously initialized accounts from other programs (e.g., token program => need to check delegate and authority). */ #[derive(Accounts)] pub struct Initialize<'info> { + // Unchecked user account, vulnerable to attacks like re-initialization user: AccountInfo<'info>, authority: Signer<'info>, } #[derive(BorshSerialize, BorshDeserialize)] pub struct User { + // Authority key of the user account authority: Pubkey, } diff --git a/programs/4-initialization/recommended/src/lib.rs b/programs/4-initialization/recommended/src/lib.rs index 0c344a0..e5f561f 100644 --- a/programs/4-initialization/recommended/src/lib.rs +++ b/programs/4-initialization/recommended/src/lib.rs @@ -7,22 +7,28 @@ pub mod reinitialization_4 { use super::*; pub fn init(_ctx: Context) -> ProgramResult { + // Placeholder message for program initialization msg!("GM"); Ok(()) } } - #[derive(Accounts)] pub struct Init<'info> { + // Initializes a new user account, allocating 8 bytes for the discriminator and 32 bytes for the Pubkey #[account(init, payer = authority, space = 8+32)] user: Account<'info, User>, + + // Authority is the payer of the transaction and must sign #[account(mut)] authority: Signer<'info>, + + // System program for allocating the account system_program: Program<'info, System>, } #[account] pub struct User { + // Authority key of the user account authority: Pubkey, } diff --git a/programs/4-initialization/secure/src/lib.rs b/programs/4-initialization/secure/src/lib.rs index e9c29e7..1925e7a 100644 --- a/programs/4-initialization/secure/src/lib.rs +++ b/programs/4-initialization/secure/src/lib.rs @@ -9,17 +9,23 @@ pub mod reinitialization_secure_recommended { use super::*; pub fn initialize(ctx: Context) -> ProgramResult { + // Deserialize the user account data let mut user = User::try_from_slice(&ctx.accounts.user.data.borrow()).unwrap(); + + // Check if the account has been initialized by verifying the discriminator if !user.discriminator { return Err(ProgramError::InvalidAccountData); } + // Set the authority and mark the account as initialized by setting discriminator to true user.authority = ctx.accounts.authority.key(); user.discriminator = true; + // Re-serialize the user data back into the account let mut storage = ctx.accounts.user.try_borrow_mut_data()?; user.serialize(storage.deref_mut()).unwrap(); + // Log a message indicating successful initialization msg!("GM"); Ok(()) } @@ -27,12 +33,15 @@ pub mod reinitialization_secure_recommended { #[derive(Accounts)] pub struct Initialize<'info> { + // User account with manual data checks for security user: AccountInfo<'info>, authority: Signer<'info>, } #[derive(BorshSerialize, BorshDeserialize)] pub struct User { + // Discriminator to ensure account has been initialized correctly discriminator: bool, + // Authority key of the user account authority: Pubkey, }