#![no_std]
#[cfg(any(feature = "account-resize", feature = "unsafe-account-resize"))]
use pinocchio::{error::ProgramError, hint::unlikely};
use {
crate::instructions::{Allocate, Assign, CreateAccount, Transfer},
pinocchio::{
address::declare_id,
cpi::Signer,
sysvars::{rent::Rent, Sysvar},
AccountView, Address, ProgramResult,
},
};
pub mod instructions;
declare_id!("11111111111111111111111111111111");
#[inline(always)]
pub fn create_account_with_minimum_balance(
account: &mut AccountView,
space: usize,
owner: &Address,
payer: &AccountView,
rent_sysvar: Option<&AccountView>,
) -> ProgramResult {
create_account_with_minimum_balance_signed(account, space, owner, payer, rent_sysvar, &[])
}
#[inline(always)]
pub fn create_account_with_minimum_balance_signed(
account: &mut AccountView,
space: usize,
owner: &Address,
payer: &AccountView,
rent_sysvar: Option<&AccountView>,
signers: &[Signer],
) -> ProgramResult {
let lamports = if let Some(rent_sysvar) = rent_sysvar {
let rent = Rent::from_account_view(rent_sysvar)?;
rent.try_minimum_balance(space)?
} else {
Rent::get()?.try_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());
if required_lamports > 0 {
Transfer {
from: payer,
to: account,
lamports: required_lamports,
}
.invoke_signed(signers)?;
}
Allocate {
account,
space: space as u64,
}
.invoke_signed(signers)?;
Assign { account, owner }.invoke_signed(signers)
}
}
#[cfg(any(feature = "account-resize", feature = "unsafe-account-resize"))]
#[inline(always)]
pub fn create_program_account_with_minimum_balance(
account: &mut AccountView,
space: usize,
owner: &Address,
payer: &AccountView,
rent_sysvar: Option<&AccountView>,
) -> ProgramResult {
create_program_account_with_minimum_balance_signed(
account,
space,
owner,
payer,
rent_sysvar,
&[],
)
}
#[cfg(any(feature = "account-resize", feature = "unsafe-account-resize"))]
#[inline(always)]
pub fn create_program_account_with_minimum_balance_signed(
account: &mut AccountView,
space: usize,
owner: &Address,
payer: &AccountView,
rent_sysvar: Option<&AccountView>,
signers: &[Signer],
) -> ProgramResult {
let lamports = if let Some(rent_sysvar) = rent_sysvar {
let rent = Rent::from_account_view(rent_sysvar)?;
rent.try_minimum_balance(space)?
} else {
Rent::get()?.try_minimum_balance(space)?
};
if account.lamports() == 0 {
CreateAccount {
from: payer,
to: account,
lamports,
space: space as u64,
owner,
}
.invoke_signed(signers)
} else {
if unlikely(account.data_len() > 0) {
return Err(ProgramError::AccountAlreadyInitialized);
}
let required_lamports = lamports.saturating_sub(account.lamports());
if required_lamports > 0 {
Transfer {
from: payer,
to: account,
lamports: required_lamports,
}
.invoke_signed(signers)?;
}
Assign { account, owner }.invoke_signed(signers)?;
unsafe {
#[cfg(feature = "account-resize")]
<AccountView as pinocchio::Resize>::resize_unchecked(account, space)?;
#[cfg(all(feature = "unsafe-account-resize", not(feature = "account-resize")))]
<AccountView as pinocchio::UnsafeResize>::resize(account, space);
}
Ok(())
}
}