use crate::account_view::AccountView;
use crate::address::Address;
use crate::error::ProgramError;
use crate::ProgramResult;
#[inline]
pub fn close_and_transfer(
source: &AccountView<'_>,
destination: &AccountView<'_>,
) -> ProgramResult {
let lamports = source.lamports();
if lamports == 0 {
source.close()?;
return Ok(());
}
destination.set_lamports(
destination
.lamports()
.checked_add(lamports)
.ok_or(ProgramError::ArithmeticOverflow)?,
);
source.close()
}
#[inline]
pub fn transfer_lamports(
from: &AccountView<'_>,
to: &AccountView<'_>,
amount: u64,
) -> ProgramResult {
let from_lamports = from.lamports();
if from_lamports < amount {
return Err(ProgramError::InsufficientFunds);
}
let to_lamports = to.lamports();
let new_to = to_lamports
.checked_add(amount)
.ok_or(ProgramError::ArithmeticOverflow)?;
from.set_lamports(from_lamports - amount);
to.set_lamports(new_to);
Ok(())
}
#[inline]
pub fn require_rent_exempt(account: &AccountView<'_>) -> ProgramResult {
let min = crate::sysvar::rent_exempt_minimum(account.data_len());
if account.lamports() >= min {
Ok(())
} else {
Err(ProgramError::AccountNotRentExempt)
}
}
#[inline]
pub fn require_rent_exempt_with(
rent: &crate::sysvar::Rent,
account: &AccountView<'_>,
) -> ProgramResult {
let min = rent.minimum_balance(account.data_len());
if account.lamports() >= min {
Ok(())
} else {
Err(ProgramError::AccountNotRentExempt)
}
}
#[inline]
pub fn require_same_address(a: &AccountView<'_>, b: &AccountView<'_>) -> ProgramResult {
if crate::address::address_eq(a.address(), b.address()) {
Ok(())
} else {
Err(ProgramError::InvalidArgument)
}
}
#[inline]
pub fn require_address(account: &AccountView<'_>, expected: &Address) -> ProgramResult {
if crate::address::address_eq(account.address(), expected) {
Ok(())
} else {
Err(ProgramError::InvalidArgument)
}
}
#[inline]
pub fn require_account_type(
account: &AccountView<'_>,
expected_disc: u8,
expected_owner: &Address,
) -> ProgramResult {
if account.disc() != expected_disc {
return Err(ProgramError::InvalidAccountData);
}
account.require_owned_by(expected_owner)
}
#[inline]
pub fn zero_data(account: &AccountView<'_>) -> ProgramResult {
crate::mem::zero_account_data(account)
}
#[inline]
pub fn realloc_checked(
account: &AccountView<'_>,
new_len: usize,
payer: Option<&AccountView<'_>>,
) -> ProgramResult {
account.check_resize(new_len)?;
let min = crate::sysvar::rent_exempt_minimum(new_len);
let current = account.lamports();
if current < min {
if let Some(payer) = payer {
let deficit = min - current;
transfer_lamports(payer, account, deficit)?;
} else {
return Err(ProgramError::AccountNotRentExempt);
}
}
account.resize(new_len)
}
#[inline]
pub fn realloc_checked_with(
rent: &crate::sysvar::Rent,
account: &AccountView<'_>,
new_len: usize,
payer: Option<&AccountView<'_>>,
) -> ProgramResult {
account.check_resize(new_len)?;
let min = rent.minimum_balance(new_len);
let current = account.lamports();
if current < min {
if let Some(payer) = payer {
let deficit = min - current;
transfer_lamports(payer, account, deficit)?;
} else {
return Err(ProgramError::AccountNotRentExempt);
}
}
account.resize(new_len)
}