From a6f52a1aa94b92ca1a562925fc33f4ccdc142d03 Mon Sep 17 00:00:00 2001 From: Samuel Vanderwaal Date: Wed, 1 Jan 2025 15:37:02 -0900 Subject: [PATCH 1/3] handle possible error --- toolbox/src/metaplex_core.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/toolbox/src/metaplex_core.rs b/toolbox/src/metaplex_core.rs index 719da5b..29c8685 100644 --- a/toolbox/src/metaplex_core.rs +++ b/toolbox/src/metaplex_core.rs @@ -50,9 +50,9 @@ pub fn validate_core_asset( assert_ownership(asset_info, Key::AssetV1)?; // validates the collection is owned by the MPL Core program - maybe_collection_info - .as_ref() - .map(|c| assert_ownership(c, Key::CollectionV1)); + if let Some(collection_info) = maybe_collection_info { + assert_ownership(collection_info, Key::CollectionV1)?; + } let asset = BaseAssetV1::try_from(asset_info)?; From e67255334a2de82af74bb14d3d8dbf3532a37c13 Mon Sep 17 00:00:00 2001 From: Samuel Vanderwaal Date: Wed, 1 Jan 2025 19:58:19 -0900 Subject: [PATCH 2/3] add edition decoders --- Cargo.lock | 2 +- toolbox/Cargo.toml | 2 +- toolbox/src/token_metadata.rs | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a9e759..a1cd9b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2594,7 +2594,7 @@ dependencies = [ [[package]] name = "tensor-toolbox" -version = "0.7.1" +version = "0.8.0" dependencies = [ "anchor-lang", "anchor-spl", diff --git a/toolbox/Cargo.toml b/toolbox/Cargo.toml index 6117c9f..a367c3e 100644 --- a/toolbox/Cargo.toml +++ b/toolbox/Cargo.toml @@ -3,7 +3,7 @@ name = "tensor-toolbox" description = "Toolbox of useful Rust utilities for Tensor Foundation's Solana programs" repository = "https://github.com/tensor-foundation/toolbox" homepage = "https://github.com/tensor-foundation/toolbox" -version = "0.7.1" +version = "0.8.0" edition = "2021" readme = "../README.md" license = "Apache-2.0" diff --git a/toolbox/src/token_metadata.rs b/toolbox/src/token_metadata.rs index 3819194..e99dfb3 100644 --- a/toolbox/src/token_metadata.rs +++ b/toolbox/src/token_metadata.rs @@ -7,9 +7,9 @@ use anchor_spl::{ token_interface::{self, Mint, TokenAccount, TokenInterface, TransferChecked}, }; use mpl_token_metadata::{ - accounts::Metadata, + accounts::{Edition, MasterEdition, Metadata}, instructions::{DelegateTransferV1CpiBuilder, TransferV1CpiBuilder}, - types::{AuthorizationData, TokenStandard}, + types::{AuthorizationData, Key as MplKey, TokenStandard}, }; use tensor_vipers::{throw_err, unwrap_opt}; @@ -36,6 +36,36 @@ pub fn assert_decode_metadata(mint: &Pubkey, metadata: &AccountInfo) -> Result Result { + if *edition.owner != mpl_token_metadata::ID { + throw_err!(TensorError::BadMetadata); + } + + let edition = MasterEdition::safe_deserialize(&edition.try_borrow_data()?) + .map_err(|_error| TensorError::BadMetadata)?; + + Ok(edition) +} + +#[inline(never)] +pub fn assert_decode_edition(edition: &AccountInfo) -> Result { + if *edition.owner != mpl_token_metadata::ID { + throw_err!(TensorError::BadMetadata); + } + + let data = edition.try_borrow_data()?; + + if data.is_empty() || data[0] != MplKey::EditionV1 as u8 { + throw_err!(TensorError::BadMetadata); + } + + let edition = Edition::from_bytes(&edition.try_borrow_data()?) + .map_err(|_error| TensorError::BadMetadata)?; + + Ok(edition) +} + /// Transfer Args using AccountInfo types to be more generic. pub struct TransferArgsAi<'a, 'info> { /// Account that will pay for any associated fees. From 0e9246010790411ab4d2b9af9a836dc62c406a3e Mon Sep 17 00:00:00 2001 From: Samuel Vanderwaal Date: Thu, 2 Jan 2025 09:36:26 -0900 Subject: [PATCH 3/3] improve returned errors --- toolbox/src/error.rs | 6 ++++++ toolbox/src/token_metadata.rs | 12 ++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/toolbox/src/error.rs b/toolbox/src/error.rs index 83ed71f..d54fa97 100644 --- a/toolbox/src/error.rs +++ b/toolbox/src/error.rs @@ -31,4 +31,10 @@ pub enum TensorError { #[msg("invalid whitelist")] InvalidWhitelist = 9010, + + #[msg("invalid program owner")] + InvalidProgramOwner = 9011, + + #[msg("invalid edition")] + InvalidEdition = 9012, } diff --git a/toolbox/src/token_metadata.rs b/toolbox/src/token_metadata.rs index e99dfb3..3e30824 100644 --- a/toolbox/src/token_metadata.rs +++ b/toolbox/src/token_metadata.rs @@ -20,7 +20,7 @@ pub use mpl_token_metadata::ID; #[inline(never)] pub fn assert_decode_metadata(mint: &Pubkey, metadata: &AccountInfo) -> Result { if *metadata.owner != mpl_token_metadata::ID { - throw_err!(TensorError::BadMetadata); + throw_err!(TensorError::InvalidProgramOwner); } // We must use `safe_deserialize` since there are variations on the metadata struct @@ -39,11 +39,11 @@ pub fn assert_decode_metadata(mint: &Pubkey, metadata: &AccountInfo) -> Result Result { if *edition.owner != mpl_token_metadata::ID { - throw_err!(TensorError::BadMetadata); + throw_err!(TensorError::InvalidProgramOwner); } let edition = MasterEdition::safe_deserialize(&edition.try_borrow_data()?) - .map_err(|_error| TensorError::BadMetadata)?; + .map_err(|_error| TensorError::InvalidEdition)?; Ok(edition) } @@ -51,17 +51,17 @@ pub fn assert_decode_master_edition(edition: &AccountInfo) -> Result Result { if *edition.owner != mpl_token_metadata::ID { - throw_err!(TensorError::BadMetadata); + throw_err!(TensorError::InvalidProgramOwner); } let data = edition.try_borrow_data()?; if data.is_empty() || data[0] != MplKey::EditionV1 as u8 { - throw_err!(TensorError::BadMetadata); + throw_err!(TensorError::InvalidEdition); } let edition = Edition::from_bytes(&edition.try_borrow_data()?) - .map_err(|_error| TensorError::BadMetadata)?; + .map_err(|_error| TensorError::InvalidEdition)?; Ok(edition) }