1use error::CoreError;
2use solana_program::{
3 account_info::AccountInfo,
4 entrypoint::ProgramResult,
5 program::{invoke, invoke_signed},
6 program_error::ProgramError,
7 pubkey::Pubkey,
8 rent::Rent,
9 system_instruction,
10};
11
12pub mod error;
13pub mod loader;
14pub mod slot_toggle;
15
16#[inline(always)]
28pub fn create_account<'a, 'info>(
29 payer: &'a AccountInfo<'info>,
30 new_account: &'a AccountInfo<'info>,
31 system_program: &'a AccountInfo<'info>,
32 program_owner: &Pubkey,
33 rent: &Rent,
34 space: u64,
35 seeds: &[Vec<u8>],
36) -> ProgramResult {
37 let current_lamports = **new_account.try_borrow_lamports()?;
38 if current_lamports == 0 {
39 invoke_signed(
41 &system_instruction::create_account(
42 payer.key,
43 new_account.key,
44 rent.minimum_balance(space as usize),
45 space,
46 program_owner,
47 ),
48 &[payer.clone(), new_account.clone(), system_program.clone()],
49 &[seeds
50 .iter()
51 .map(|seed| seed.as_slice())
52 .collect::<Vec<&[u8]>>()
53 .as_slice()],
54 )
55 } else {
56 let required_lamports = rent
61 .minimum_balance(space as usize)
62 .max(1)
63 .saturating_sub(current_lamports);
64 if required_lamports > 0 {
65 invoke(
66 &system_instruction::transfer(payer.key, new_account.key, required_lamports),
67 &[payer.clone(), new_account.clone(), system_program.clone()],
68 )?;
69 }
70 invoke_signed(
72 &system_instruction::allocate(new_account.key, space),
73 &[new_account.clone(), system_program.clone()],
74 &[seeds
75 .iter()
76 .map(|seed| seed.as_slice())
77 .collect::<Vec<&[u8]>>()
78 .as_slice()],
79 )?;
80 invoke_signed(
82 &system_instruction::assign(new_account.key, program_owner),
83 &[new_account.clone(), system_program.clone()],
84 &[seeds
85 .iter()
86 .map(|seed| seed.as_slice())
87 .collect::<Vec<&[u8]>>()
88 .as_slice()],
89 )
90 }
91}
92
93pub fn close_program_account<'a>(
95 program_id: &Pubkey,
96 account_to_close: &AccountInfo<'a>,
97 destination_account: &AccountInfo<'a>,
98) -> ProgramResult {
99 if account_to_close.owner != program_id {
101 return Err(ProgramError::IllegalOwner);
102 }
103
104 **destination_account.lamports.borrow_mut() = destination_account
105 .lamports()
106 .checked_add(account_to_close.lamports())
107 .ok_or(ProgramError::ArithmeticOverflow)?;
108 **account_to_close.lamports.borrow_mut() = 0;
109
110 account_to_close.assign(&solana_program::system_program::id());
111 account_to_close.realloc(0, false)?;
112
113 Ok(())
114}
115
116pub fn realloc<'a, 'info>(
117 account: &'a AccountInfo<'info>,
118 new_size: usize,
119 payer: &'a AccountInfo<'info>,
120 rent: &Rent,
121) -> ProgramResult {
122 let new_minimum_balance = rent.minimum_balance(new_size);
123
124 let lamports_diff = new_minimum_balance.saturating_sub(account.lamports());
125 invoke(
126 &system_instruction::transfer(payer.key, account.key, lamports_diff),
127 &[payer.clone(), account.clone()],
128 )?;
129 account.realloc(new_size, false)?;
130 Ok(())
131}
132
133pub fn get_epoch(slot: u64, epoch_length: u64) -> Result<u64, CoreError> {
134 let epoch = slot
135 .checked_div(epoch_length)
136 .ok_or(CoreError::BadEpochLength)?;
137
138 Ok(epoch)
139}