use hopper_runtime::{error::ProgramError, AccountView, ProgramResult};
pub const CLOSE_SENTINEL: u8 = 0xFF;
#[inline(always)]
pub fn zero_init(data: &mut [u8]) {
for byte in data.iter_mut() {
*byte = 0;
}
}
#[inline]
pub fn safe_close(account: &AccountView, destination: &AccountView) -> ProgramResult {
let lamports = account.lamports();
if lamports == 0 {
return Ok(());
}
let new_dest = destination
.lamports()
.checked_add(lamports)
.ok_or(ProgramError::ArithmeticOverflow)?;
destination.set_lamports(new_dest);
account.set_lamports(0);
let mut data = account.try_borrow_mut()?;
zero_init(&mut data);
Ok(())
}
#[inline]
pub fn safe_close_with_sentinel(account: &AccountView, destination: &AccountView) -> ProgramResult {
safe_close(account, destination)?;
let mut data = account.try_borrow_mut()?;
if !data.is_empty() {
data[0] = CLOSE_SENTINEL;
}
Ok(())
}
#[inline]
pub fn safe_realloc(account: &AccountView, new_size: usize, payer: &AccountView) -> ProgramResult {
account.resize(new_size)?;
let rent_needed = rent_exempt_min_internal(new_size);
let current_lamports = account.lamports();
if rent_needed > current_lamports {
let deficit = rent_needed - current_lamports;
let payer_lamports = payer
.lamports()
.checked_sub(deficit)
.ok_or(ProgramError::InsufficientFunds)?;
payer.set_lamports(payer_lamports);
let acct_lamports = account
.lamports()
.checked_add(deficit)
.ok_or(ProgramError::ArithmeticOverflow)?;
account.set_lamports(acct_lamports);
}
Ok(())
}
pub(crate) fn rent_exempt_min_internal(data_len: usize) -> u64 {
((128 + data_len) as u64) * 6960
}