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 rent = crate::sysvar::get_rent()?;
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 {
let len = account.data_len();
if len == 0 {
return Ok(());
}
let data_ptr = account.data_ptr_unchecked();
unsafe {
core::ptr::write_bytes(data_ptr, 0, len);
}
Ok(())
}
#[inline]
pub fn realloc_checked(
account: &AccountView,
new_len: usize,
payer: Option<&AccountView>,
) -> ProgramResult {
let rent = crate::sysvar::get_rent()?;
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)
}