diff --git a/.github/workflows/build-programs.yml b/.github/workflows/build-programs.yml index f84ca8dd..dc82a1c1 100644 --- a/.github/workflows/build-programs.yml +++ b/.github/workflows/build-programs.yml @@ -64,4 +64,5 @@ jobs: name: program-builds # First wildcard ensures exported paths are consistently under the programs folder. path: ./program*/.bin/*.so + include-hidden-files: true if-no-files-found: error diff --git a/programs/token-metadata/program/src/state/fee.rs b/programs/token-metadata/program/src/state/fee.rs index ad9123b3..ea4f911e 100644 --- a/programs/token-metadata/program/src/state/fee.rs +++ b/programs/token-metadata/program/src/state/fee.rs @@ -1,9 +1,18 @@ use super::*; +use solana_program::{rent::Rent, sysvar::Sysvar}; pub(crate) const FEE_AUTHORITY: Pubkey = pubkey!("Levytx9LLPzAtDJJD7q813Zsm8zg9e1pb53mGxTKpD7"); +const CREATE_FEE_SCALAR: usize = 1308; +const CREATE_FEE_OFFSET: u64 = 5440; // create_metadata_accounts_v3, create, print edition commands -pub const CREATE_FEE: u64 = 10_000_000; +pub fn get_create_fee() -> Result { + let rent = Rent::get()?.minimum_balance(CREATE_FEE_SCALAR); + + Ok(rent + .checked_add(CREATE_FEE_OFFSET) + .ok_or(MetadataError::NumericalOverflowError)?) +} pub const FEE_FLAG_SET: u8 = 1; pub const FEE_FLAG_CLEARED: u8 = 0; diff --git a/programs/token-metadata/program/src/utils/fee.rs b/programs/token-metadata/program/src/utils/fee.rs index 79cd662f..c7b2d8f7 100644 --- a/programs/token-metadata/program/src/utils/fee.rs +++ b/programs/token-metadata/program/src/utils/fee.rs @@ -5,7 +5,7 @@ use solana_program::{ use crate::{ error::MetadataError, - state::{fee::CREATE_FEE, MAX_METADATA_LEN, METADATA_FEE_FLAG_OFFSET}, + state::{get_create_fee, MAX_METADATA_LEN, METADATA_FEE_FLAG_OFFSET}, }; #[repr(C)] @@ -26,7 +26,7 @@ pub(crate) fn levy(args: LevyArgs) -> ProgramResult { if account_data_len > 0 { return Err(MetadataError::ExpectedUninitializedAccount.into()); } - let fee = CREATE_FEE + rent.minimum_balance(MAX_METADATA_LEN); + let fee = get_create_fee()? + rent.minimum_balance(MAX_METADATA_LEN); invoke( &solana_program::system_instruction::transfer( diff --git a/programs/token-metadata/program/tests/fees.rs b/programs/token-metadata/program/tests/fees.rs index ac0a89a0..a9aefdd9 100644 --- a/programs/token-metadata/program/tests/fees.rs +++ b/programs/token-metadata/program/tests/fees.rs @@ -13,7 +13,7 @@ mod fees { }; use token_metadata::{ instruction::{collect_fees, BurnArgs, UpdateArgs}, - state::{CREATE_FEE, FEE_FLAG_CLEARED, METADATA_FEE_FLAG_OFFSET}, + state::{FEE_FLAG_CLEARED, METADATA_FEE_FLAG_OFFSET}, }; use super::*; @@ -132,7 +132,7 @@ mod fees { println!("Transaction size: {:?}", tx.message().serialize().len()); context.banks_client.process_transaction(tx).await.unwrap(); - let expected_balance = num_accounts * CREATE_FEE; + let expected_balance = num_accounts * SOLANA_CREATE_FEE; let recipient_balance = get_account(&mut context, &recipient.pubkey()) .await @@ -206,7 +206,7 @@ mod fees { ); context.banks_client.process_transaction(tx).await.unwrap(); - let expected_balance = CREATE_FEE; + let expected_balance = SOLANA_CREATE_FEE; let recipient_balance = get_account(&mut context, &recipient.pubkey()) .await diff --git a/programs/token-metadata/program/tests/utils/digital_asset.rs b/programs/token-metadata/program/tests/utils/digital_asset.rs index fcee77a6..26247e11 100644 --- a/programs/token-metadata/program/tests/utils/digital_asset.rs +++ b/programs/token-metadata/program/tests/utils/digital_asset.rs @@ -31,14 +31,13 @@ use token_metadata::{ state::{ AssetData, Collection, CollectionDetails, Creator, MasterEditionV2, Metadata, PrintSupply, ProgrammableConfig, TokenDelegateRole, TokenMetadataAccount, TokenRecord, TokenStandard, - CREATE_FEE, EDITION, EDITION_MARKER_BIT_SIZE, FEE_FLAG_SET, METADATA_FEE_FLAG_OFFSET, - PREFIX, + EDITION, EDITION_MARKER_BIT_SIZE, FEE_FLAG_SET, METADATA_FEE_FLAG_OFFSET, PREFIX, }, utils::unpack, ID, }; -use crate::upsize_edition; +use crate::{upsize_edition, SOLANA_CREATE_FEE}; use super::{ airdrop, create_mint, create_token_account, get_account, mint_tokens, upsize_master_edition, @@ -1494,7 +1493,7 @@ impl DigitalAsset { let rent = context.banks_client.get_rent().await.unwrap(); let rent_exempt = rent.minimum_balance(account.data.len()); - let expected_lamports = rent_exempt + CREATE_FEE; + let expected_lamports = rent_exempt + SOLANA_CREATE_FEE; assert_eq!(account.lamports, expected_lamports); let last_byte = account.data.len() - METADATA_FEE_FLAG_OFFSET; diff --git a/programs/token-metadata/program/tests/utils/metadata.rs b/programs/token-metadata/program/tests/utils/metadata.rs index 89d5728d..bc99f8cb 100644 --- a/programs/token-metadata/program/tests/utils/metadata.rs +++ b/programs/token-metadata/program/tests/utils/metadata.rs @@ -6,8 +6,7 @@ use token_metadata::{ instruction, state::{ Collection, CollectionDetails, Creator, DataV2, Metadata as TmMetadata, - TokenMetadataAccount, TokenStandard, Uses, CREATE_FEE, FEE_FLAG_SET, - METADATA_FEE_FLAG_OFFSET, PREFIX, + TokenMetadataAccount, TokenStandard, Uses, FEE_FLAG_SET, METADATA_FEE_FLAG_OFFSET, PREFIX, }, ID, }; @@ -696,7 +695,7 @@ impl Metadata { let rent = context.banks_client.get_rent().await.unwrap(); let rent_exempt = rent.minimum_balance(account.data.len()); - let expected_lamports = rent_exempt + CREATE_FEE; + let expected_lamports = rent_exempt + SOLANA_CREATE_FEE; assert_eq!(account.lamports, expected_lamports); let last_byte = account.data.len() - METADATA_FEE_FLAG_OFFSET; diff --git a/programs/token-metadata/program/tests/utils/mod.rs b/programs/token-metadata/program/tests/utils/mod.rs index e2918d56..26c53e79 100644 --- a/programs/token-metadata/program/tests/utils/mod.rs +++ b/programs/token-metadata/program/tests/utils/mod.rs @@ -34,6 +34,8 @@ pub const DEFAULT_COLLECTION_DETAILS: Option = { Some(CollectionDetails::V1 { size: 0 }) }; +pub const SOLANA_CREATE_FEE: u64 = 10_000_000; + pub fn program_test() -> ProgramTest { let mut program_test = ProgramTest::new("token_metadata", token_metadata::ID, None); program_test.add_program("spl_token_2022", spl_token_2022::ID, None);