diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index d58fc33870..86b9d04134 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -1455,10 +1455,14 @@ mod tests { }, assert_matches::assert_matches, solana_address_lookup_table_program::state::LookupTableMeta, - solana_program_runtime::executor_cache::TransactionExecutorCache, + solana_program_runtime::{ + executor_cache::TransactionExecutorCache, + prioritization_fee::{PrioritizationFeeDetails, PrioritizationFeeType}, + }, solana_sdk::{ account::{AccountSharedData, WritableAccount}, bpf_loader_upgradeable::UpgradeableLoaderState, + compute_budget::ComputeBudgetInstruction, epoch_schedule::EpochSchedule, genesis_config::ClusterType, hash::Hash, @@ -4257,4 +4261,64 @@ mod tests { test(tx_set_limit_99, &feature_set, &result_requested_limit); test(tx_set_limit_0, &feature_set, &result_invalid_limit); } + + #[test] + fn test_load_accounts_too_high_prioritization_fee() { + solana_logger::setup(); + let lamports_per_signature = 5000_u64; + let request_units = 1_000_000_u32; + let request_unit_price = 2_000_000_000_u64; + let prioritization_fee_details = PrioritizationFeeDetails::new( + PrioritizationFeeType::ComputeUnitPrice(request_unit_price), + request_units as u64, + ); + let prioritization_fee = prioritization_fee_details.get_fee(); + + let keypair = Keypair::new(); + let key0 = keypair.pubkey(); + // set up account with balance of `prioritization_fee` + let account = AccountSharedData::new(prioritization_fee, 0, &Pubkey::default()); + let accounts = vec![(key0, account)]; + + let instructions = &[ + ComputeBudgetInstruction::set_compute_unit_limit(request_units), + ComputeBudgetInstruction::set_compute_unit_price(request_unit_price), + ]; + let tx = Transaction::new( + &[&keypair], + Message::new(instructions, Some(&key0)), + Hash::default(), + ); + + let fee = Bank::calculate_fee( + &SanitizedMessage::try_from(tx.message().clone()).unwrap(), + lamports_per_signature, + &FeeStructure::default(), + true, + false, + true, + true, + true, + false, + ); + assert_eq!(fee, lamports_per_signature + prioritization_fee); + + // assert fail to load account with 2B lamport balance for transaction asking for 2B + // lamports as prioritization fee. + let mut error_counters = TransactionErrorMetrics::default(); + let loaded_accounts = load_accounts_with_fee( + tx, + &accounts, + lamports_per_signature, + &mut error_counters, + None, + ); + + assert_eq!(error_counters.insufficient_funds, 1); + assert_eq!(loaded_accounts.len(), 1); + assert_eq!( + loaded_accounts[0].clone(), + (Err(TransactionError::InsufficientFundsForFee), None), + ); + } } diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 89e84049ec..dc87a729c6 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -10813,6 +10813,47 @@ fn test_calculate_fee_compute_units() { } } +#[test] +fn test_calculate_prioritization_fee() { + let fee_structure = FeeStructure { + lamports_per_signature: 1, + ..FeeStructure::default() + }; + + let request_units = 1_000_000_u32; + let request_unit_price = 2_000_000_000_u64; + let prioritization_fee_details = PrioritizationFeeDetails::new( + PrioritizationFeeType::ComputeUnitPrice(request_unit_price), + request_units as u64, + ); + let prioritization_fee = prioritization_fee_details.get_fee(); + + let message = SanitizedMessage::try_from(Message::new( + &[ + ComputeBudgetInstruction::set_compute_unit_limit(request_units), + ComputeBudgetInstruction::set_compute_unit_price(request_unit_price), + ], + Some(&Pubkey::new_unique()), + )) + .unwrap(); + + let fee = Bank::calculate_fee( + &message, + fee_structure.lamports_per_signature, + &fee_structure, + true, // use_default_units_per_instruction + false, // not support_request_units_deprecated + true, // remove_congestion_multiplier + true, // enable_request_heap_frame_ix + true, // support_set_accounts_data_size_limit_ix, + false, // include_loaded_account_data_size_in_fee + ); + assert_eq!( + fee, + fee_structure.lamports_per_signature + prioritization_fee + ); +} + #[test] fn test_calculate_fee_secp256k1() { let fee_structure = FeeStructure {