hopper_core/account/
lifecycle.rs1use hopper_runtime::{error::ProgramError, AccountView, ProgramResult};
4
5pub const CLOSE_SENTINEL: u8 = 0xFF;
8
9#[inline(always)]
14pub fn zero_init(data: &mut [u8]) {
15 for byte in data.iter_mut() {
18 *byte = 0;
19 }
20}
21
22#[inline]
26pub fn safe_close(account: &AccountView, destination: &AccountView) -> ProgramResult {
27 let lamports = account.lamports();
28 if lamports == 0 {
29 return Ok(());
30 }
31
32 let new_dest = destination
34 .lamports()
35 .checked_add(lamports)
36 .ok_or(ProgramError::ArithmeticOverflow)?;
37 destination.set_lamports(new_dest);
38
39 account.set_lamports(0);
41
42 let mut data = account.try_borrow_mut()?;
44 zero_init(&mut data);
45
46 Ok(())
47}
48
49#[inline]
51pub fn safe_close_with_sentinel(account: &AccountView, destination: &AccountView) -> ProgramResult {
52 safe_close(account, destination)?;
53
54 let mut data = account.try_borrow_mut()?;
56 if !data.is_empty() {
57 data[0] = CLOSE_SENTINEL;
58 }
59
60 Ok(())
61}
62
63#[inline]
67pub fn safe_realloc(account: &AccountView, new_size: usize, payer: &AccountView) -> ProgramResult {
68 account.resize(new_size)?;
69
70 let rent_needed = rent_exempt_min_internal(new_size);
72 let current_lamports = account.lamports();
73
74 if rent_needed > current_lamports {
75 let deficit = rent_needed - current_lamports;
76 let payer_lamports = payer
78 .lamports()
79 .checked_sub(deficit)
80 .ok_or(ProgramError::InsufficientFunds)?;
81 payer.set_lamports(payer_lamports);
82 let acct_lamports = account
83 .lamports()
84 .checked_add(deficit)
85 .ok_or(ProgramError::ArithmeticOverflow)?;
86 account.set_lamports(acct_lamports);
87 }
88
89 Ok(())
90}
91
92pub(crate) fn rent_exempt_min_internal(data_len: usize) -> u64 {
94 ((128 + data_len) as u64) * 6960
97}