#![no_std]
pub mod account;
pub mod check;
pub mod event;
pub mod field;
pub mod instruction;
pub mod math;
pub mod packed;
pub mod prelude;
pub mod state;
pub mod state_utils;
pub mod sysvar;
pub mod time;
#[cfg(feature = "log")]
pub mod log;
#[cfg(feature = "programs")]
pub mod programs;
pub mod abi;
pub mod compat;
pub mod interface;
pub use field::*;
pub use packed::*;
pub use state_utils::*;
pub use hopper_runtime;
pub use hopper_runtime::{ProgramError, AccountView, Address, ProgramResult};
#[doc(hidden)]
pub const fn __sha256_const(data: &[u8]) -> [u8; 32] {
sha2_const_stable::Sha256::new().update(data).finalize()
}
#[macro_export]
macro_rules! require {
($cond:expr, $err:expr $(,)?) => {
if !($cond) {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_keys_eq {
($a:expr, $b:expr, $err:expr $(,)?) => {
let __jiminy_a: &$crate::Address = &$a;
let __jiminy_b: &$crate::Address = &$b;
if __jiminy_a != __jiminy_b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_keys_neq {
($a:expr, $b:expr, $err:expr $(,)?) => {
let __jiminy_a: &$crate::Address = &$a;
let __jiminy_b: &$crate::Address = &$b;
if __jiminy_a == __jiminy_b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_accounts_ne {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a.address() == $b.address() {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_gte {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a < $b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_gt {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a <= $b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_lt {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a >= $b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_lte {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a > $b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_eq {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a != $b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_neq {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a == $b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_flag {
($byte:expr, $n:expr, $err:expr $(,)?) => {
if ($byte >> $n) & 1 == 0 {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! check_accounts_unique {
($a:expr, $b:expr) => {
if $a.address() == $b.address() {
return Err($crate::ProgramError::InvalidArgument);
}
};
($head:expr, $($tail:expr),+ $(,)?) => {
$( if $head.address() == $tail.address() {
return Err($crate::ProgramError::InvalidArgument);
} )+
$crate::check_accounts_unique!($($tail),+);
};
}
#[macro_export]
macro_rules! error_codes {
(
base = $base:expr;
$( $(#[$meta:meta])* $name:ident ),+ $(,)?
) => {
#[allow(non_upper_case_globals)]
pub mod errors {
$crate::error_codes!(@count $base; $( $(#[$meta])* $name ),+ );
}
$(
impl From<errors::$name> for $crate::ProgramError {
#[inline(always)]
fn from(_: errors::$name) -> Self {
$crate::ProgramError::Custom(errors::$name::CODE)
}
}
)+
};
(@count $code:expr; $(#[$meta:meta])* $name:ident) => {
$(#[$meta])*
pub struct $name;
impl $name {
pub const CODE: u32 = $code;
}
};
(@count $code:expr; $(#[$meta:meta])* $name:ident, $( $(#[$rmeta:meta])* $rest:ident ),+ ) => {
$(#[$meta])*
pub struct $name;
impl $name {
pub const CODE: u32 = $code;
}
$crate::error_codes!(@count $code + 1; $( $(#[$rmeta])* $rest ),+ );
};
}
#[macro_export]
macro_rules! instruction_dispatch {
(
$pid:expr, $accs:expr, $data:expr;
$( $tag:expr => $handler:expr ),+ $(,)?
) => {{
let mut ix = $crate::account::SliceCursor::new($data);
let tag = ix.read_u8()?;
match tag {
$( $tag => { let _ = &ix; $handler } )+
_ => Err($crate::ProgramError::InvalidInstructionData),
}
}};
}
#[macro_export]
macro_rules! init_account {
($payer:expr, $account:expr, $program_id:expr, $Layout:ty) => {{
let space = <$Layout>::LEN as u64;
let lamports = $crate::check::rent_exempt_min(<$Layout>::LEN);
$crate::hopper_runtime::system::instructions::CreateAccount {
from: $payer,
to: $account,
lamports,
space,
owner: $program_id,
}
.invoke()?;
let mut data = $account.try_borrow_mut()?;
$crate::account::zero_init(&mut data);
$crate::account::write_header(
&mut data,
<$Layout>::DISC,
<$Layout>::VERSION,
&<$Layout>::LAYOUT_ID,
)?;
Ok::<(), $crate::ProgramError>(())
}};
}
#[macro_export]
macro_rules! close_account {
($account:expr, $destination:expr) => {
$crate::account::safe_close_with_sentinel($account, $destination)
};
}
#[macro_export]
macro_rules! check_account {
($account:expr, $($constraint:tt)*) => {{
$crate::__check_account_inner!($account, $($constraint)*)
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __check_account_inner {
($account:expr, ) => { Ok::<(), $crate::ProgramError>(()) };
($account:expr $(,)?) => { Ok::<(), $crate::ProgramError>(()) };
($account:expr, owner = $id:expr $(, $($rest:tt)*)?) => {{
$crate::check::check_owner($account, $id)?;
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
($account:expr, writable $(, $($rest:tt)*)?) => {{
$crate::check::check_writable($account)?;
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
($account:expr, signer $(, $($rest:tt)*)?) => {{
$crate::check::check_signer($account)?;
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
($account:expr, disc = $d:expr $(, $($rest:tt)*)?) => {{
{
let data = $account.try_borrow()?;
$crate::check::check_discriminator(&data, $d)?;
}
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
($account:expr, version >= $v:expr $(, $($rest:tt)*)?) => {{
{
let data = $account.try_borrow()?;
$crate::check::check_version(&data, $v)?;
}
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
($account:expr, layout_id = $id:expr $(, $($rest:tt)*)?) => {{
{
let data = $account.try_borrow()?;
$crate::account::check_layout_id(&data, $id)?;
}
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
($account:expr, size >= $n:expr $(, $($rest:tt)*)?) => {{
{
let data = $account.try_borrow()?;
$crate::check::check_size(&data, $n)?;
}
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
}
#[macro_export]
macro_rules! check_account_strict {
($account:expr, owner = $owner:expr, disc = $disc:expr, layout_id = $lid:expr
$(, $($rest:tt)*)?) => {{
$crate::check::check_owner($account, $owner)?;
{
let data = $account.try_borrow()?;
$crate::check::check_discriminator(&data, $disc)?;
$crate::account::check_layout_id(&data, $lid)?;
}
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
}