Skip to content

Commit

Permalink
add collection metadata verification
Browse files Browse the repository at this point in the history
  • Loading branch information
JeremyLi28 committed Nov 7, 2024
1 parent 6e06918 commit c58fdc8
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 72 deletions.
63 changes: 63 additions & 0 deletions programs/mmm/src/instructions/cnft/metadata_args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use anchor_lang::{prelude::*, AnchorDeserialize, AnchorSerialize};

// Define the TokenStandard enum
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash)]
pub enum TokenStandard {
NonFungible,
FungibleAsset,
Fungible,
NonFungibleEdition,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Eq, PartialEq)]
pub struct Collection {
pub verified: bool,
pub key: Pubkey,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash)]
pub enum UseMethod {
Burn,
Multiple,
Single,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Eq, PartialEq)]
pub struct Uses {
pub use_method: UseMethod,
pub remaining: u64,
pub total: u64,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash)]
pub enum TokenProgramVersion {
Original,
Token2022,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Eq, PartialEq)]
pub struct Creator {
pub address: Pubkey,
pub verified: bool,
/// The percentage share.
///
/// The value is a percentage, not basis points.
pub share: u8,
}

// Define the MetadataArgs struct
#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct MetadataArgs {
pub name: String,
pub symbol: String, // Changed from Option<String> to String
pub uri: String,
pub seller_fee_basis_points: u16,
pub primary_sale_happened: bool, // Changed from Option<bool> to bool
pub is_mutable: bool, // Changed from Option<bool> to bool
pub edition_nonce: Option<u8>,
pub token_standard: Option<TokenStandard>, // Changed from Option<u8> to Option<TokenStandard>
pub collection: Option<Collection>,
pub uses: Option<Uses>,
pub token_program_version: TokenProgramVersion, // Assuming TokenProgramVersion is a simple u8
pub creators: Vec<Creator>,
}
4 changes: 3 additions & 1 deletion programs/mmm/src/instructions/cnft/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod sol_cnft_fulfill_buy;
pub mod metadata_args;

pub use sol_cnft_fulfill_buy::*;
pub use sol_cnft_fulfill_buy::*;
pub use metadata_args::*;
68 changes: 5 additions & 63 deletions programs/mmm/src/instructions/cnft/sol_cnft_fulfill_buy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,71 +6,11 @@ use crate::{
constants::*,
errors::MMMErrorCode,
state::{BubblegumProgram, Pool, SellState, TreeConfigAnchor},
util::{log_pool, transfer_compressed_nft, try_close_pool},
util::{hash_metadata, log_pool, transfer_compressed_nft, try_close_pool},
verify_referral::verify_referral,
};

// Define the TokenStandard enum
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash)]
pub enum TokenStandard {
NonFungible,
FungibleAsset,
Fungible,
NonFungibleEdition,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Eq, PartialEq)]
pub struct Collection {
pub verified: bool,
pub key: Pubkey,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash)]
pub enum UseMethod {
Burn,
Multiple,
Single,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Eq, PartialEq)]
pub struct Uses {
pub use_method: UseMethod,
pub remaining: u64,
pub total: u64,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash)]
pub enum TokenProgramVersion {
Original,
Token2022,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Eq, PartialEq)]
pub struct Creator {
pub address: Pubkey,
pub verified: bool,
/// The percentage share.
///
/// The value is a percentage, not basis points.
pub share: u8,
}

// Define the MetadataArgs struct
#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct MetadataArgs {
pub name: String,
pub symbol: String, // Changed from Option<String> to String
pub uri: String,
pub seller_fee_basis_points: u16,
pub primary_sale_happened: bool, // Changed from Option<bool> to bool
pub is_mutable: bool, // Changed from Option<bool> to bool
pub edition_nonce: Option<u8>,
pub token_standard: Option<TokenStandard>, // Changed from Option<u8> to Option<TokenStandard>
pub collection: Option<Collection>,
pub uses: Option<Uses>,
pub token_program_version: TokenProgramVersion, // Assuming TokenProgramVersion is a simple u8
pub creators: Vec<Creator>,
}
use super::MetadataArgs;

#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct SolCnftFulfillBuyArgs {
Expand Down Expand Up @@ -210,6 +150,8 @@ pub fn handler<'info>(
return Err(MMMErrorCode::InvalidAccountState.into());
}

let data_hash = hash_metadata(&args.metadata_args)?;

msg!("seller fee basis points: {}", args.seller_fee_basis_points);
// Create data_hash from metadata_hash + seller_fee_basis_points (secures creator royalties)
// let data_hash = hash_metadata_data(args.metadata_hash, args.seller_fee_basis_points)?;
Expand All @@ -228,7 +170,7 @@ pub fn handler<'info>(
proof_path,
ctx.accounts.bubblegum_program.key(),
args.root,
args.metadata_hash,
data_hash,
args.creator_hash,
args.nonce,
args.index,
Expand Down
21 changes: 13 additions & 8 deletions programs/mmm/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
errors::MMMErrorCode,
get_creators_from_royalties,
state::*,
IndexableAsset,
IndexableAsset, MetadataArgs,
};
use anchor_lang::{prelude::*, solana_program::log::sol_log_data};
use anchor_spl::token_interface::Mint;
Expand Down Expand Up @@ -1214,13 +1214,18 @@ pub fn transfer_compressed_nft<'info>(
Ok(())
}

// Taken from Bubblegum's hash_metadata: hashes seller_fee_basis_points to the final data_hash that Bubblegum expects.
// This way we can use the seller_fee_basis_points while still guaranteeing validity.
pub fn hash_metadata_data(
metadata_args_hash: [u8; 32],
seller_fee_basis_points: u16,
) -> Result<[u8; 32]> {
Ok(keccak::hashv(&[&metadata_args_hash, &seller_fee_basis_points.to_le_bytes()]).to_bytes())
/// Computes the hash of the metadata.
///
/// The hash is computed as the keccak256 hash of the metadata bytes, which is
/// then hashed with the `seller_fee_basis_points`.
pub fn hash_metadata(metadata: &MetadataArgs) -> Result<[u8; 32]> {
let hash = keccak::hashv(&[metadata.try_to_vec()?.as_slice()]);
// Calculate new data hash.
Ok(keccak::hashv(&[
&hash.to_bytes(),
&metadata.seller_fee_basis_points.to_le_bytes(),
])
.to_bytes())
}

#[cfg(test)]
Expand Down

0 comments on commit c58fdc8

Please sign in to comment.