From 8e72b74515adf3eba6952d3d287b08ba16dacfdf Mon Sep 17 00:00:00 2001 From: febo Date: Tue, 18 Nov 2025 13:59:47 +0000 Subject: [PATCH 1/4] Add create account helper --- programs/system/src/lib.rs | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/programs/system/src/lib.rs b/programs/system/src/lib.rs index 35268bc1..cff3f6c0 100644 --- a/programs/system/src/lib.rs +++ b/programs/system/src/lib.rs @@ -1,5 +1,69 @@ #![no_std] +use pinocchio::{ + account_info::AccountInfo, + instruction::Signer, + pubkey::Pubkey, + sysvars::{rent::Rent, Sysvar}, + ProgramResult, +}; + +use crate::instructions::{Assign, CreateAccount, Transfer}; + pub mod instructions; pinocchio_pubkey::declare_id!("11111111111111111111111111111111"); + +/// Create an account with a minimal balance to be rent-exempt. +/// +/// The account will be funded by the `payer` if its current lamports +/// are insufficient for rent-exemption. +#[inline(always)] +pub fn create_account_with_minimal_balance( + account: &AccountInfo, + space: usize, + owner: &Pubkey, + payer: &AccountInfo, + signers: &[Signer], + rent_sysvar: Option<&AccountInfo>, +) -> ProgramResult { + let lamports = if let Some(rent_sysvar) = rent_sysvar { + let rent = Rent::from_account_info(rent_sysvar)?; + rent.minimum_balance(space) + } else { + Rent::get()?.minimum_balance(space) + }; + + if account.lamports() == 0 { + CreateAccount { + from: payer, + to: account, + lamports, + space: space as u64, + owner, + } + .invoke_signed(signers) + } else { + let required_lamports = lamports.saturating_sub(account.lamports()); + + // Transfer lamports from `payer` to `account` if needed. + if required_lamports > 0 { + Transfer { + from: payer, + to: account, + lamports: required_lamports, + } + .invoke()?; + } + + Assign { account, owner }.invoke_signed(signers)?; + + // Allocates the required space for the account. + // + // SAFETY: There are no active borrows of the `account`. + // This was checked by the `Assign` CPI above. + unsafe { account.resize_unchecked(space)? }; + + Ok(()) + } +} From e04e5990d748309925d95c3fc05e5b0a4b377512 Mon Sep 17 00:00:00 2001 From: febo Date: Tue, 18 Nov 2025 14:09:34 +0000 Subject: [PATCH 2/4] More comments --- programs/system/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/programs/system/src/lib.rs b/programs/system/src/lib.rs index cff3f6c0..117aaa3c 100644 --- a/programs/system/src/lib.rs +++ b/programs/system/src/lib.rs @@ -35,6 +35,7 @@ pub fn create_account_with_minimal_balance( }; if account.lamports() == 0 { + // Create the account if it does not exist. CreateAccount { from: payer, to: account, @@ -56,9 +57,10 @@ pub fn create_account_with_minimal_balance( .invoke()?; } + // Assign the account to the specified owner. Assign { account, owner }.invoke_signed(signers)?; - // Allocates the required space for the account. + // Allocate the required space for the account. // // SAFETY: There are no active borrows of the `account`. // This was checked by the `Assign` CPI above. From 1466edae6f381eb436c1c6e2b350a6fa2f16a95e Mon Sep 17 00:00:00 2001 From: febo Date: Wed, 19 Nov 2025 11:15:27 +0000 Subject: [PATCH 3/4] Use signer seeds on transfer --- programs/system/src/lib.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/programs/system/src/lib.rs b/programs/system/src/lib.rs index 117aaa3c..8f4198d7 100644 --- a/programs/system/src/lib.rs +++ b/programs/system/src/lib.rs @@ -14,12 +14,17 @@ pub mod instructions; pinocchio_pubkey::declare_id!("11111111111111111111111111111111"); -/// Create an account with a minimal balance to be rent-exempt. +/// Create an account with a minimum balance to be rent-exempt. +/// +/// When creating a PDA `account`, the PDA signer seeds must be provided +/// via the `signers`. /// /// The account will be funded by the `payer` if its current lamports -/// are insufficient for rent-exemption. +/// are insufficient for rent-exemption. The payer can be a PDA signer +/// owned by the system program and its signer seeds can be provided +/// via the `signers`. #[inline(always)] -pub fn create_account_with_minimal_balance( +pub fn create_account_with_minimum_balance( account: &AccountInfo, space: usize, owner: &Pubkey, @@ -54,7 +59,7 @@ pub fn create_account_with_minimal_balance( to: account, lamports: required_lamports, } - .invoke()?; + .invoke_signed(signers)?; } // Assign the account to the specified owner. From 31c337c0358db3f6876bf98ecc0f70a7598d4716 Mon Sep 17 00:00:00 2001 From: febo Date: Wed, 19 Nov 2025 11:45:35 +0000 Subject: [PATCH 4/4] Cosmetics --- programs/system/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/programs/system/src/lib.rs b/programs/system/src/lib.rs index 8f4198d7..c326c6df 100644 --- a/programs/system/src/lib.rs +++ b/programs/system/src/lib.rs @@ -69,8 +69,6 @@ pub fn create_account_with_minimum_balance( // // SAFETY: There are no active borrows of the `account`. // This was checked by the `Assign` CPI above. - unsafe { account.resize_unchecked(space)? }; - - Ok(()) + unsafe { account.resize_unchecked(space) } } }