hopper_core/check/
guards.rs1use hopper_runtime::error::ProgramError;
10use hopper_runtime::{AccountAudit, AccountView, Address, ProgramResult};
11
12#[inline(always)]
16pub fn require_payer(account: &AccountView) -> ProgramResult {
17 if !account.is_signer() {
18 return Err(ProgramError::MissingRequiredSignature);
19 }
20 if !account.is_writable() {
21 return Err(ProgramError::InvalidAccountData);
22 }
23 Ok(())
24}
25
26#[inline(always)]
28pub fn require_authority(account: &AccountView, stored_authority: &[u8; 32]) -> ProgramResult {
29 if !account.is_signer() {
30 return Err(ProgramError::MissingRequiredSignature);
31 }
32 let addr: &[u8; 32] = unsafe {
34 &*(account.address() as *const Address as *const [u8; 32])
36 };
37 if !crate::check::keys_eq_fast(addr, stored_authority) {
38 return Err(ProgramError::InvalidAccountData);
39 }
40 Ok(())
41}
42
43#[inline(always)]
45pub fn require_owned_writable(account: &AccountView, program_id: &Address) -> ProgramResult {
46 if !account.owned_by(program_id) {
47 return Err(ProgramError::IncorrectProgramId);
48 }
49 if !account.is_writable() {
50 return Err(ProgramError::InvalidAccountData);
51 }
52 Ok(())
53}
54
55#[inline]
62pub fn require_all_unique(accounts: &[AccountView]) -> ProgramResult {
63 AccountAudit::new(accounts).require_all_unique()
64}
65
66#[inline]
68pub fn require_unique_writable(accounts: &[AccountView]) -> ProgramResult {
69 AccountAudit::new(accounts).require_unique_writable()
70}
71
72#[inline]
74pub fn require_unique_signers(accounts: &[AccountView]) -> ProgramResult {
75 AccountAudit::new(accounts).require_unique_signers()
76}
77
78#[inline]
85pub fn check_lamport_conservation(accounts: &[AccountView], pre_lamports: &[u64]) -> ProgramResult {
86 if accounts.len() != pre_lamports.len() {
87 return Err(ProgramError::InvalidArgument);
88 }
89 let mut pre_total: u64 = 0;
90 let mut post_total: u64 = 0;
91 let mut i = 0;
92 while i < accounts.len() {
93 pre_total = pre_total
94 .checked_add(pre_lamports[i])
95 .ok_or(ProgramError::ArithmeticOverflow)?;
96 post_total = post_total
97 .checked_add(accounts[i].lamports())
98 .ok_or(ProgramError::ArithmeticOverflow)?;
99 i += 1;
100 }
101 if pre_total != post_total {
102 return Err(ProgramError::InvalidAccountData);
103 }
104 Ok(())
105}
106
107#[inline]
112pub fn snapshot_lamports<const N: usize>(
113 accounts: &[AccountView],
114) -> Result<[u64; N], ProgramError> {
115 if accounts.len() < N {
116 return Err(ProgramError::NotEnoughAccountKeys);
117 }
118 let mut snapshot = [0u64; N];
119 let mut i = 0;
120 while i < N {
121 snapshot[i] = accounts[i].lamports();
122 i += 1;
123 }
124 Ok(snapshot)
125}
126
127#[inline]
135pub fn check_writable_coherence(accounts: &[AccountView], program_id: &Address) -> ProgramResult {
136 let mut i = 0;
137 while i < accounts.len() {
138 if accounts[i].is_writable()
139 && !accounts[i].is_signer()
140 && !accounts[i].owned_by(program_id)
141 {
142 return Err(ProgramError::InvalidAccountData);
143 }
144 i += 1;
145 }
146 Ok(())
147}