use hopper_runtime::error::ProgramError;
use hopper_runtime::{AccountAudit, AccountView, Address, ProgramResult};
#[inline(always)]
pub fn require_payer(account: &AccountView) -> ProgramResult {
if !account.is_signer() {
return Err(ProgramError::MissingRequiredSignature);
}
if !account.is_writable() {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
#[inline(always)]
pub fn require_authority(account: &AccountView, stored_authority: &[u8; 32]) -> ProgramResult {
if !account.is_signer() {
return Err(ProgramError::MissingRequiredSignature);
}
let addr: &[u8; 32] = unsafe {
&*(account.address() as *const Address as *const [u8; 32])
};
if !crate::check::keys_eq_fast(addr, stored_authority) {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
#[inline(always)]
pub fn require_owned_writable(account: &AccountView, program_id: &Address) -> ProgramResult {
if !account.owned_by(program_id) {
return Err(ProgramError::IncorrectProgramId);
}
if !account.is_writable() {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
#[inline]
pub fn require_all_unique(accounts: &[AccountView]) -> ProgramResult {
AccountAudit::new(accounts).require_all_unique()
}
#[inline]
pub fn require_unique_writable(accounts: &[AccountView]) -> ProgramResult {
AccountAudit::new(accounts).require_unique_writable()
}
#[inline]
pub fn require_unique_signers(accounts: &[AccountView]) -> ProgramResult {
AccountAudit::new(accounts).require_unique_signers()
}
#[inline]
pub fn check_lamport_conservation(accounts: &[AccountView], pre_lamports: &[u64]) -> ProgramResult {
if accounts.len() != pre_lamports.len() {
return Err(ProgramError::InvalidArgument);
}
let mut pre_total: u64 = 0;
let mut post_total: u64 = 0;
let mut i = 0;
while i < accounts.len() {
pre_total = pre_total
.checked_add(pre_lamports[i])
.ok_or(ProgramError::ArithmeticOverflow)?;
post_total = post_total
.checked_add(accounts[i].lamports())
.ok_or(ProgramError::ArithmeticOverflow)?;
i += 1;
}
if pre_total != post_total {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
#[inline]
pub fn snapshot_lamports<const N: usize>(
accounts: &[AccountView],
) -> Result<[u64; N], ProgramError> {
if accounts.len() < N {
return Err(ProgramError::NotEnoughAccountKeys);
}
let mut snapshot = [0u64; N];
let mut i = 0;
while i < N {
snapshot[i] = accounts[i].lamports();
i += 1;
}
Ok(snapshot)
}
#[inline]
pub fn check_writable_coherence(accounts: &[AccountView], program_id: &Address) -> ProgramResult {
let mut i = 0;
while i < accounts.len() {
if accounts[i].is_writable()
&& !accounts[i].is_signer()
&& !accounts[i].owned_by(program_id)
{
return Err(ProgramError::InvalidAccountData);
}
i += 1;
}
Ok(())
}