diff --git a/Cargo.lock b/Cargo.lock index de7049f..3ffc70d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1294,11 +1294,11 @@ dependencies = [ "drillx", "mpl-token-metadata", "num_enum", - "ore-utils", "solana-program", "spl-associated-token-account", "spl-token", "static_assertions", + "steel", "thiserror", ] @@ -1309,21 +1309,11 @@ dependencies = [ "drillx", "mpl-token-metadata", "ore-api", - "ore-utils", "rand 0.8.5", "solana-program", "spl-associated-token-account", "spl-token", -] - -[[package]] -name = "ore-utils" -version = "2.1.9" -dependencies = [ - "bytemuck", - "solana-program", - "spl-associated-token-account", - "spl-token", + "steel", ] [[package]] @@ -2219,6 +2209,18 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "steel" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b09eae425248a8afcef3cf3300dfa548791194fa9fe519dadd5c57d7964dbc" +dependencies = [ + "bytemuck", + "solana-program", + "spl-associated-token-account", + "spl-token", +] + [[package]] name = "strsim" version = "0.11.1" diff --git a/Cargo.toml b/Cargo.toml index 6d4b8d8..3bb3b18 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "2" -members = ["api", "program", "utils"] +members = ["api", "program"] [workspace.package] version = "2.1.9" @@ -20,11 +20,11 @@ drillx = { version = "2.0.0", features = ["solana"] } mpl-token-metadata = "4.1.2" num_enum = "0.7.2" ore-api = { path = "api", version = "2.1.9" } -ore-utils = { path = "utils", features = ["spl"], version = "2.1.9" } solana-program = "^1.18" spl-token = { version = "^4", features = ["no-entrypoint"] } spl-associated-token-account = { version = "^2.3", features = [ "no-entrypoint" ] } static_assertions = "1.1.0" +steel = { features = ["spl"], version = "0.1.0" } thiserror = "1.0.57" diff --git a/api/Cargo.toml b/api/Cargo.toml index aad2498..d11cc5a 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -16,9 +16,9 @@ const-crypto.workspace = true drillx.workspace = true mpl-token-metadata.workspace = true num_enum.workspace = true -ore-utils.workspace = true solana-program.workspace = true spl-token.workspace = true spl-associated-token-account.workspace = true static_assertions.workspace = true +steel.workspace = true thiserror.workspace = true diff --git a/api/src/error.rs b/api/src/error.rs index b0653ba..408681d 100644 --- a/api/src/error.rs +++ b/api/src/error.rs @@ -1,5 +1,5 @@ use num_enum::IntoPrimitive; -use ore_utils::*; +use steel::*; use thiserror::Error; #[derive(Debug, Error, Clone, Copy, PartialEq, Eq, IntoPrimitive)] diff --git a/api/src/event.rs b/api/src/event.rs index 9f41f25..b7068b3 100644 --- a/api/src/event.rs +++ b/api/src/event.rs @@ -1,5 +1,5 @@ use bytemuck::{Pod, Zeroable}; -use ore_utils::*; +use steel::*; #[repr(C)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] diff --git a/api/src/instruction.rs b/api/src/instruction.rs index 7010646..923b2c5 100644 --- a/api/src/instruction.rs +++ b/api/src/instruction.rs @@ -1,6 +1,6 @@ use bytemuck::{Pod, Zeroable}; use num_enum::TryFromPrimitive; -use ore_utils::*; +use steel::*; #[repr(u8)] #[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)] diff --git a/api/src/loaders.rs b/api/src/loaders.rs index 881ca5d..925335d 100644 --- a/api/src/loaders.rs +++ b/api/src/loaders.rs @@ -1,5 +1,5 @@ -use ore_utils::*; use solana_program::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey}; +use steel::*; use crate::{ consts::*, diff --git a/api/src/state/bus.rs b/api/src/state/bus.rs index 0d07296..2c12776 100644 --- a/api/src/state/bus.rs +++ b/api/src/state/bus.rs @@ -1,6 +1,6 @@ use bytemuck::{Pod, Zeroable}; -use ore_utils::*; use solana_program::pubkey::Pubkey; +use steel::*; use crate::consts::BUS; diff --git a/api/src/state/config.rs b/api/src/state/config.rs index 35dded5..e35216c 100644 --- a/api/src/state/config.rs +++ b/api/src/state/config.rs @@ -1,6 +1,6 @@ use bytemuck::{Pod, Zeroable}; -use ore_utils::*; use solana_program::pubkey::Pubkey; +use steel::*; use crate::consts::CONFIG; diff --git a/api/src/state/proof.rs b/api/src/state/proof.rs index ba68660..33c0f4a 100644 --- a/api/src/state/proof.rs +++ b/api/src/state/proof.rs @@ -1,6 +1,6 @@ use bytemuck::{Pod, Zeroable}; -use ore_utils::*; use solana_program::pubkey::Pubkey; +use steel::*; use crate::consts::PROOF; diff --git a/api/src/state/treasury.rs b/api/src/state/treasury.rs index 20c34fc..289fc35 100644 --- a/api/src/state/treasury.rs +++ b/api/src/state/treasury.rs @@ -1,6 +1,6 @@ use bytemuck::{Pod, Zeroable}; -use ore_utils::*; use solana_program::pubkey::Pubkey; +use steel::*; use crate::consts::TREASURY; diff --git a/program/Cargo.toml b/program/Cargo.toml index 70af79c..1bf4718 100644 --- a/program/Cargo.toml +++ b/program/Cargo.toml @@ -21,10 +21,10 @@ default = [] drillx.workspace = true mpl-token-metadata.workspace = true ore-api.workspace = true -ore-utils.workspace = true solana-program.workspace = true spl-token.workspace = true spl-associated-token-account.workspace = true +steel.workspace = true [dev-dependencies] rand = "0.8.5" diff --git a/program/src/claim.rs b/program/src/claim.rs index aedf620..7cf33cc 100644 --- a/program/src/claim.rs +++ b/program/src/claim.rs @@ -1,8 +1,8 @@ use ore_api::{consts::*, error::OreError, instruction::*, loaders::*, state::Proof}; -use ore_utils::*; use solana_program::{ account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, }; +use steel::*; /// Claim distributes claimable ORE from the treasury to a miner. pub fn process_claim(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { diff --git a/program/src/close.rs b/program/src/close.rs index c12150c..4529e39 100644 --- a/program/src/close.rs +++ b/program/src/close.rs @@ -1,9 +1,9 @@ use ore_api::{loaders::*, state::Proof}; -use ore_utils::*; use solana_program::{ account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, system_program, }; +use steel::*; /// Close closes a proof account and returns the rent to the owner. pub fn process_close(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { diff --git a/program/src/initialize.rs b/program/src/initialize.rs index 6759876..b4255d0 100644 --- a/program/src/initialize.rs +++ b/program/src/initialize.rs @@ -5,12 +5,12 @@ use ore_api::{ instruction::*, state::{Bus, Config, Treasury}, }; -use ore_utils::*; use solana_program::{ self, account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, program_pack::Pack, system_program, sysvar, }; use spl_token::state::Mint; +use steel::*; /// Initialize sets up the ORE program to begin mining. pub fn process_initialize(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { diff --git a/program/src/mine.rs b/program/src/mine.rs index 9efd3dc..40aa1ee 100644 --- a/program/src/mine.rs +++ b/program/src/mine.rs @@ -9,7 +9,6 @@ use ore_api::{ loaders::*, state::{Bus, Config, Proof}, }; -use ore_utils::*; use solana_program::program::set_return_data; #[allow(deprecated)] use solana_program::{ @@ -24,6 +23,7 @@ use solana_program::{ slot_hashes::SlotHash, sysvar::{self, Sysvar}, }; +use steel::*; /// Mine validates hashes and increments a miner's collectable balance. pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { diff --git a/program/src/open.rs b/program/src/open.rs index 4ded87c..f914af8 100644 --- a/program/src/open.rs +++ b/program/src/open.rs @@ -1,7 +1,6 @@ use std::mem::size_of; use ore_api::{consts::*, instruction::Open, state::Proof}; -use ore_utils::*; use solana_program::{ account_info::AccountInfo, clock::Clock, @@ -12,6 +11,7 @@ use solana_program::{ system_program, sysvar::{self, Sysvar}, }; +use steel::*; /// Open creates a new proof account to track a miner's state. pub fn process_open(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { diff --git a/program/src/reset.rs b/program/src/reset.rs index eda9489..a3abcfa 100644 --- a/program/src/reset.rs +++ b/program/src/reset.rs @@ -4,12 +4,12 @@ use ore_api::{ loaders::*, state::{Bus, Config}, }; -use ore_utils::*; use solana_program::{ account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, program_error::ProgramError, program_pack::Pack, sysvar::Sysvar, }; use spl_token::state::Mint; +use steel::*; /// Reset tops up the bus balances, updates the base reward rate, and sets up the ORE program for the next epoch. pub fn process_reset(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { diff --git a/program/src/stake.rs b/program/src/stake.rs index e64f5b3..08f33b5 100644 --- a/program/src/stake.rs +++ b/program/src/stake.rs @@ -1,9 +1,9 @@ use ore_api::{consts::*, instruction::Stake, loaders::*, state::Proof}; -use ore_utils::*; use solana_program::{ account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, program_error::ProgramError, sysvar::Sysvar, }; +use steel::*; /// Stake deposits ORE into a proof account to earn multiplier. pub fn process_stake(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { diff --git a/program/src/update.rs b/program/src/update.rs index c5a21e7..6ffdf3b 100644 --- a/program/src/update.rs +++ b/program/src/update.rs @@ -1,8 +1,8 @@ use ore_api::{loaders::*, state::Proof}; -use ore_utils::*; use solana_program::{ account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, }; +use steel::*; /// Update changes the miner authority on a proof account. pub fn process_update(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { diff --git a/program/src/upgrade.rs b/program/src/upgrade.rs index a167872..7530117 100644 --- a/program/src/upgrade.rs +++ b/program/src/upgrade.rs @@ -1,10 +1,10 @@ use ore_api::{consts::*, error::OreError, instruction::Stake}; -use ore_utils::*; use solana_program::{ account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, program_pack::Pack, }; use spl_token::state::Mint; +use steel::*; /// Upgrade allows a user to migrate a v1 token to a v2 token at a 1:1 exchange rate. pub fn process_upgrade(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult { diff --git a/utils/Cargo.toml b/utils/Cargo.toml deleted file mode 100644 index 2af4092..0000000 --- a/utils/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "ore-utils" -description = "Utils for building ORE programs" -version.workspace = true -edition.workspace = true -license.workspace = true -homepage.workspace = true -documentation.workspace = true -repository.workspace = true -keywords.workspace = true - -[features] -deafult = [] -spl = ["spl-token", "spl-associated-token-account"] - -[dependencies] -bytemuck.workspace = true -solana-program.workspace = true -spl-token = { workspace = true, optional = true } -spl-associated-token-account = { workspace = true, optional = true } diff --git a/utils/src/cpi.rs b/utils/src/cpi.rs deleted file mode 100644 index bce2c8e..0000000 --- a/utils/src/cpi.rs +++ /dev/null @@ -1,214 +0,0 @@ -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey, rent::Rent, - sysvar::Sysvar, -}; - -/// Creates a new pda. -#[inline(always)] -pub fn create_pda<'a, 'info>( - target_account: &'a AccountInfo<'info>, - owner: &Pubkey, - space: usize, - pda_seeds: &[&[u8]], - system_program: &'a AccountInfo<'info>, - payer: &'a AccountInfo<'info>, -) -> ProgramResult { - let rent = Rent::get()?; - if target_account.lamports().eq(&0) { - // If balance is zero, create account - solana_program::program::invoke_signed( - &solana_program::system_instruction::create_account( - payer.key, - target_account.key, - rent.minimum_balance(space), - space as u64, - owner, - ), - &[ - payer.clone(), - target_account.clone(), - system_program.clone(), - ], - &[pda_seeds], - )?; - } else { - // Otherwise, if balance is nonzero: - - // 1) transfer sufficient lamports for rent exemption - let rent_exempt_balance = rent - .minimum_balance(space) - .saturating_sub(target_account.lamports()); - if rent_exempt_balance.gt(&0) { - solana_program::program::invoke( - &solana_program::system_instruction::transfer( - payer.key, - target_account.key, - rent_exempt_balance, - ), - &[ - payer.clone(), - target_account.clone(), - system_program.clone(), - ], - )?; - } - - // 2) allocate space for the account - solana_program::program::invoke_signed( - &solana_program::system_instruction::allocate(target_account.key, space as u64), - &[target_account.clone(), system_program.clone()], - &[pda_seeds], - )?; - - // 3) assign our program as the owner - solana_program::program::invoke_signed( - &solana_program::system_instruction::assign(target_account.key, owner), - &[target_account.clone(), system_program.clone()], - &[pda_seeds], - )?; - } - - Ok(()) -} - -#[cfg(feature = "spl")] -#[inline(always)] -pub fn create_ata<'info>( - funder_info: &AccountInfo<'info>, - owner_info: &AccountInfo<'info>, - token_account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - system_program: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - associated_token_program: &AccountInfo<'info>, -) -> ProgramResult { - solana_program::program::invoke( - &spl_associated_token_account::instruction::create_associated_token_account( - funder_info.key, - owner_info.key, - mint_info.key, - &spl_token::id(), - ), - &[ - funder_info.clone(), - token_account_info.clone(), - owner_info.clone(), - mint_info.clone(), - system_program.clone(), - token_program.clone(), - associated_token_program.clone(), - ], - ) -} - -#[cfg(feature = "spl")] -#[inline(always)] -pub fn transfer<'info>( - authority_info: &AccountInfo<'info>, - from_info: &AccountInfo<'info>, - to_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - amount: u64, -) -> ProgramResult { - solana_program::program::invoke( - &spl_token::instruction::transfer( - &spl_token::id(), - from_info.key, - to_info.key, - authority_info.key, - &[authority_info.key], - amount, - )?, - &[ - token_program.clone(), - from_info.clone(), - to_info.clone(), - authority_info.clone(), - ], - ) -} - -#[cfg(feature = "spl")] -#[inline(always)] -pub fn transfer_signed<'info>( - authority_info: &AccountInfo<'info>, - from_info: &AccountInfo<'info>, - to_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - amount: u64, - signer_seeds: &[&[&[u8]]], -) -> ProgramResult { - solana_program::program::invoke_signed( - &spl_token::instruction::transfer( - &spl_token::id(), - from_info.key, - to_info.key, - authority_info.key, - &[authority_info.key], - amount, - )?, - &[ - token_program.clone(), - from_info.clone(), - to_info.clone(), - authority_info.clone(), - ], - signer_seeds, - ) -} - -#[cfg(feature = "spl")] -#[inline(always)] -pub fn mint_to_signed<'info>( - mint_info: &AccountInfo<'info>, - to_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - amount: u64, - signer_seeds: &[&[&[u8]]], -) -> ProgramResult { - solana_program::program::invoke_signed( - &spl_token::instruction::mint_to( - &spl_token::id(), - mint_info.key, - to_info.key, - authority_info.key, - &[authority_info.key], - amount, - )?, - &[ - token_program.clone(), - mint_info.clone(), - to_info.clone(), - authority_info.clone(), - ], - signer_seeds, - ) -} - -#[cfg(feature = "spl")] -#[inline(always)] -pub fn burn<'info>( - token_account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - amount: u64, -) -> ProgramResult { - solana_program::program::invoke( - &spl_token::instruction::burn( - &spl_token::id(), - token_account_info.key, - mint_info.key, - authority_info.key, - &[authority_info.key], - amount, - )?, - &[ - token_program.clone(), - token_account_info.clone(), - mint_info.clone(), - authority_info.clone(), - ], - ) -} diff --git a/utils/src/lib.rs b/utils/src/lib.rs deleted file mode 100644 index d4c963a..0000000 --- a/utils/src/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod cpi; -mod loaders; -pub mod macros; -mod traits; - -pub use cpi::*; -pub use loaders::*; -pub use traits::*; diff --git a/utils/src/loaders.rs b/utils/src/loaders.rs deleted file mode 100644 index 72681fe..0000000 --- a/utils/src/loaders.rs +++ /dev/null @@ -1,249 +0,0 @@ -#[cfg(feature = "spl")] -use solana_program::program_pack::Pack; -use solana_program::{ - account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, system_program, sysvar, -}; -#[cfg(feature = "spl")] -use spl_token::state::Mint; - -/// Errors if: -/// - Account is not a signer. -pub fn load_signer(info: &AccountInfo<'_>) -> Result<(), ProgramError> { - if !info.is_signer { - return Err(ProgramError::MissingRequiredSignature); - } - - Ok(()) -} - -/// Errors if: -/// - Address does not match PDA derived from provided seeds. -/// - Cannot load as an uninitialized account. -pub fn load_uninitialized_pda( - info: &AccountInfo<'_>, - seeds: &[&[u8]], - bump: u8, - program_id: &Pubkey, -) -> Result<(), ProgramError> { - let pda = Pubkey::find_program_address(seeds, program_id); - - if info.key.ne(&pda.0) { - return Err(ProgramError::InvalidSeeds); - } - - if bump.ne(&pda.1) { - return Err(ProgramError::InvalidSeeds); - } - - load_system_account(info, true) -} - -/// Errors if: -/// - Owner is not the system program. -/// - Data is not empty. -/// - Account is not writable. -pub fn load_system_account(info: &AccountInfo<'_>, is_writable: bool) -> Result<(), ProgramError> { - if info.owner.ne(&system_program::id()) { - return Err(ProgramError::InvalidAccountOwner); - } - - if !info.data_is_empty() { - return Err(ProgramError::AccountAlreadyInitialized); - } - - if is_writable && !info.is_writable { - return Err(ProgramError::InvalidAccountData); - } - - Ok(()) -} - -/// Errors if: -/// - Owner is not the sysvar address. -/// - Account cannot load with the expected address. -pub fn load_sysvar(info: &AccountInfo<'_>, key: Pubkey) -> Result<(), ProgramError> { - if info.owner.ne(&sysvar::id()) { - return Err(ProgramError::InvalidAccountOwner); - } - - load_account(info, key, false) -} - -/// Errors if: -/// - Address does not match the expected value. -/// - Expected to be writable, but is not. -pub fn load_account( - info: &AccountInfo<'_>, - key: Pubkey, - is_writable: bool, -) -> Result<(), ProgramError> { - if info.key.ne(&key) { - return Err(ProgramError::InvalidAccountData); - } - - if is_writable && !info.is_writable { - return Err(ProgramError::InvalidAccountData); - } - - Ok(()) -} - -/// Errors if: -/// - Address does not match the expected value. -/// - Account is not executable. -pub fn load_program(info: &AccountInfo<'_>, key: Pubkey) -> Result<(), ProgramError> { - if info.key.ne(&key) { - return Err(ProgramError::IncorrectProgramId); - } - - if !info.executable { - return Err(ProgramError::InvalidAccountData); - } - - Ok(()) -} - -/// Errors if: -/// - Account is not writable. -pub fn load_any(info: &AccountInfo<'_>, is_writable: bool) -> Result<(), ProgramError> { - if is_writable && !info.is_writable { - return Err(ProgramError::InvalidAccountData); - } - - Ok(()) -} - -/// Errors if: -/// - Owner is not SPL token program. -/// - Address does not match the expected mint address. -/// - Data is empty. -/// - Data cannot deserialize into a mint account. -/// - Expected to be writable, but is not. -#[cfg(feature = "spl")] -pub fn load_mint( - info: &AccountInfo<'_>, - address: Pubkey, - is_writable: bool, -) -> Result<(), ProgramError> { - if info.owner.ne(&spl_token::id()) { - return Err(ProgramError::InvalidAccountOwner); - } - - if info.key.ne(&address) { - return Err(ProgramError::InvalidSeeds); - } - - if info.data_is_empty() { - return Err(ProgramError::UninitializedAccount); - } - - Mint::unpack(&info.data.borrow())?; - - if is_writable && !info.is_writable { - return Err(ProgramError::InvalidAccountData); - } - - Ok(()) -} - -/// Errors if: -/// - Owner is not SPL token program. -/// - Data is empty. -/// - Data cannot deserialize into a mint account. -/// - Expected to be writable, but is not. -#[cfg(feature = "spl")] -pub fn load_any_mint(info: &AccountInfo<'_>, is_writable: bool) -> Result<(), ProgramError> { - if info.owner.ne(&spl_token::id()) { - return Err(ProgramError::InvalidAccountOwner); - } - - if info.data_is_empty() { - return Err(ProgramError::UninitializedAccount); - } - - Mint::unpack(&info.data.borrow())?; - - if is_writable && !info.is_writable { - return Err(ProgramError::InvalidAccountData); - } - - Ok(()) -} - -/// Errors if: -/// - Owner is not SPL token program. -/// - Data is empty. -/// - Data cannot deserialize into a token account. -/// - Token account owner does not match the expected owner address. -/// - Token account mint does not match the expected mint address. -/// - Expected to be writable, but is not. -#[cfg(feature = "spl")] -pub fn load_token_account( - info: &AccountInfo<'_>, - owner: Option<&Pubkey>, - mint: &Pubkey, - is_writable: bool, -) -> Result<(), ProgramError> { - if info.owner.ne(&spl_token::id()) { - return Err(ProgramError::InvalidAccountOwner); - } - - if info.data_is_empty() { - return Err(ProgramError::UninitializedAccount); - } - - let account_data = info.data.borrow(); - let account = spl_token::state::Account::unpack(&account_data)?; - - if account.mint.ne(&mint) { - return Err(ProgramError::InvalidAccountData); - } - - if let Some(owner) = owner { - if account.owner.ne(owner) { - return Err(ProgramError::InvalidAccountData); - } - } - - if is_writable && !info.is_writable { - return Err(ProgramError::InvalidAccountData); - } - - Ok(()) -} - -/// Errors if: -/// - Owner is not SPL token program. -/// - Data is empty. -/// - Data cannot deserialize into a token account. -/// - Address does not match the expected associated token address. -/// - Expected to be writable, but is not. -#[cfg(feature = "spl")] -pub fn load_associated_token_account( - info: &AccountInfo<'_>, - owner: &Pubkey, - mint: &Pubkey, - is_writable: bool, -) -> Result<(), ProgramError> { - if info.owner.ne(&spl_token::id()) { - return Err(ProgramError::InvalidAccountOwner); - } - - if info.data_is_empty() { - return Err(ProgramError::UninitializedAccount); - } - - let account_data = info.data.borrow(); - let _ = spl_token::state::Account::unpack(&account_data)?; - - let address = spl_associated_token_account::get_associated_token_address(owner, mint); - if info.key.ne(&address) { - return Err(ProgramError::InvalidSeeds); - } - - if is_writable && !info.is_writable { - return Err(ProgramError::InvalidAccountData); - } - - Ok(()) -} diff --git a/utils/src/macros.rs b/utils/src/macros.rs deleted file mode 100644 index 1bda272..0000000 --- a/utils/src/macros.rs +++ /dev/null @@ -1,120 +0,0 @@ -#[macro_export] -macro_rules! impl_to_bytes { - ($struct_name:ident) => { - impl $struct_name { - pub fn to_bytes(&self) -> &[u8] { - bytemuck::bytes_of(self) - } - } - }; -} - -#[macro_export] -macro_rules! impl_from_bytes { - ($struct_name:ident) => { - impl $struct_name { - pub fn from_bytes(data: &[u8]) -> &Self { - bytemuck::from_bytes::(data) - } - } - }; -} - -#[macro_export] -macro_rules! impl_account_from_bytes { - ($struct_name:ident) => { - impl $crate::AccountDeserialize for $struct_name { - fn try_from_bytes( - data: &[u8], - ) -> Result<&Self, solana_program::program_error::ProgramError> { - if Self::discriminator().ne(&data[0]) { - return Err(solana_program::program_error::ProgramError::InvalidAccountData); - } - bytemuck::try_from_bytes::(&data[8..]).or(Err( - solana_program::program_error::ProgramError::InvalidAccountData, - )) - } - fn try_from_bytes_mut( - data: &mut [u8], - ) -> Result<&mut Self, solana_program::program_error::ProgramError> { - if Self::discriminator().ne(&data[0]) { - return Err(solana_program::program_error::ProgramError::InvalidAccountData); - } - bytemuck::try_from_bytes_mut::(&mut data[8..]).or(Err( - solana_program::program_error::ProgramError::InvalidAccountData, - )) - } - } - }; -} - -#[macro_export] -macro_rules! impl_instruction_from_bytes { - ($struct_name:ident) => { - impl $struct_name { - pub fn try_from_bytes( - data: &[u8], - ) -> Result<&Self, solana_program::program_error::ProgramError> { - bytemuck::try_from_bytes::(data).or(Err( - solana_program::program_error::ProgramError::InvalidInstructionData, - )) - } - } - }; -} - -#[macro_export] -macro_rules! account { - ($discriminator_name:ident, $struct_name:ident) => { - $crate::impl_to_bytes!($struct_name); - $crate::impl_account_from_bytes!($struct_name); - - impl $crate::Discriminator for $struct_name { - fn discriminator() -> u8 { - $discriminator_name::$struct_name.into() - } - } - }; -} - -#[macro_export] -macro_rules! error { - ($struct_name:ident) => { - impl From<$struct_name> for solana_program::program_error::ProgramError { - fn from(e: $struct_name) -> Self { - solana_program::program_error::ProgramError::Custom(e as u32) - } - } - }; -} - -#[macro_export] -macro_rules! event { - ($struct_name:ident) => { - $crate::impl_to_bytes!($struct_name); - $crate::impl_from_bytes!($struct_name); - }; -} - -#[macro_export] -macro_rules! instruction { - ($discriminator_name:ident, $struct_name:ident) => { - $crate::impl_instruction_from_bytes!($struct_name); - - impl $crate::Discriminator for $struct_name { - fn discriminator() -> u8 { - $discriminator_name::$struct_name as u8 - } - } - - impl $struct_name { - pub fn to_bytes(&self) -> Vec { - [ - [$discriminator_name::$struct_name as u8].to_vec(), - bytemuck::bytes_of(self).to_vec(), - ] - .concat() - } - } - }; -} diff --git a/utils/src/traits.rs b/utils/src/traits.rs deleted file mode 100644 index 755a5fe..0000000 --- a/utils/src/traits.rs +++ /dev/null @@ -1,10 +0,0 @@ -use solana_program::program_error::ProgramError; - -pub trait AccountDeserialize { - fn try_from_bytes(data: &[u8]) -> Result<&Self, ProgramError>; - fn try_from_bytes_mut(data: &mut [u8]) -> Result<&mut Self, ProgramError>; -} - -pub trait Discriminator { - fn discriminator() -> u8; -}