Summary
Total fee = base fee (5,000 lamports/signature, 50% burned) + priority fee (CU_price * CU_limit / 1M lamports, 100% to validator). Charged whether the transaction succeeds or fails.
Fee calculation algorithm
The total fee for a transaction is computed by
calculate_fee_details:
total_fee = base_fee + prioritization_fee
The inputs are the transaction message, the current lamports_per_signature
(currently 5,000), and the prioritization fee derived from compute budget
instructions. The total fee is deducted from the fee payer before execution
begins. If the transaction fails, the fee is still charged.
Base fee
The base fee covers the cost of Ed25519 signature verification plus any precompile signature verifications. Every signature in the transaction is charged, including signatures verified by the Ed25519, Secp256k1, and Secp256r1 precompile programs.
The
calculate_signature_fee
function computes:
signature_count = num_transaction_signatures+ num_ed25519_signatures+ num_secp256k1_signatures+ num_secp256r1_signatures (if feature enabled)base_fee = signature_count * lamports_per_signature
num_transaction_signatures: the number of Ed25519 signatures on the transaction (typically one per signer).num_ed25519_signatures,num_secp256k1_signatures,num_secp256r1_signatures: signatures verified by the corresponding precompile programs.lamports_per_signature: currently 5,000 lamports.
Fee distribution
The base fee and prioritization fee are distributed differently. The
calculate_reward_and_burn_fee_details
function in the runtime computes:
burn_amount = transaction_fee * 50 / 100validator_share = (transaction_fee - burn_amount) + priority_fee
- Base fee (transaction_fee): 50% is
burned
(removed from circulating supply) and 50% goes to the block-producing
validator. The burn percent is
DEFAULT_BURN_PERCENT = 50. - Prioritization fee: 100% goes to the validator (none is burned), per SIMD-0096.
The validator's total reward for a transaction is:
validator_reward = (base_fee / 2) + prioritization_fee
Prioritization fee
The prioritization fee is an optional fee that increases the scheduling priority of a transaction. A compute unit (CU) is a unit of computation that the runtime meters during transaction execution. Every operation (arithmetic, memory access, syscall) costs a fixed number of CUs. You can set the prioritization fee by including compute budget instructions in your transaction. (See the How to Use Priority Fees guide for details.)
Prioritization fee formula
The
get_prioritization_fee
function computes:
micro_lamport_fee = compute_unit_price * compute_unit_limitprioritization_fee = ceil(micro_lamport_fee / 1,000,000)
| Variable | Description | Default |
|---|---|---|
compute_unit_price | Micro-lamports per CU, set via SetComputeUnitPrice | 0 micro-lamports |
compute_unit_limit | Maximum CUs the transaction may consume, set via SetComputeUnitLimit | Sum of per-instruction defaults |
1,000,000 | Conversion factor from micro-lamports to lamports (MICRO_LAMPORTS_PER_LAMPORT) | -- |
Compute unit limit
The compute unit limit is the maximum number of CUs a transaction may consume.
If no
SetComputeUnitLimit
instruction is included, the default is calculated from the number and type of
instructions (200,000 CUs per non-builtin instruction, 3,000 per builtin). See
Compute Budget for details on the default
calculation.
The priority fee is based on the requested CU limit, not actual CU usage. Setting a higher limit than needed means paying for unused compute units.
Compute unit price
The compute unit price is an optional amount of micro-lamports paid for each
requested CU. The CU price directly determines the prioritization fee. To set
the CU price, include a
SetComputeUnitPrice
instruction in your transaction.
The default CU price is 0, meaning the default prioritization fee is also 0.
For real-time CU price estimates, see the priority fee API providers below.
| Provider | Priority Fee API |
|---|---|
| Helius | Documentation |
| QuickNode | Documentation |
| Triton | Documentation |
Transaction scheduling priority
The scheduler ranks transactions using the
calculate_priority_and_cost
function:
Priority = reward * 1,000,000 / (cost + 1)
- reward: the validator's fee income = prioritization fee + non-burned
portion of the base fee. Computed by
calculate_reward_for_transaction. - cost: the scheduler's estimated CU cost (signature costs + write lock costs + instruction data costs + program execution costs + loaded accounts data size cost). See Compute Budget for details.
- 1,000,000: a multiplier to preserve precision, since cost often exceeds reward in raw lamports.
- +1: prevents division by zero.
The priority determines the order in which transactions are dequeued from the scheduler's buffer for execution.
Example: Setting the CU limit and CU price
The examples below show how to set the CU limit and CU price on a transaction using Solana SDKs.
| SDK | Source Code Reference |
|---|---|
@solana/web3.js (Typescript) | ComputeBudgetProgram |
solana-sdk (Rust) | ComputeBudgetInstruction |
const limitInstruction = ComputeBudgetProgram.setComputeUnitLimit({units: 300_000});const priceInstruction = ComputeBudgetProgram.setComputeUnitPrice({microLamports: 1});
import {LAMPORTS_PER_SOL,SystemProgram,Transaction,Keypair,Connection,ComputeBudgetProgram,sendAndConfirmTransaction} from "@solana/web3.js";const connection = new Connection("http://localhost:8899", "confirmed");const sender = Keypair.generate();const recipient = new Keypair();const airdropSignature = await connection.requestAirdrop(sender.publicKey,LAMPORTS_PER_SOL);await connection.confirmTransaction(airdropSignature, "confirmed");// Create compute budget instructionsconst limitInstruction = ComputeBudgetProgram.setComputeUnitLimit({units: 300_000});const priceInstruction = ComputeBudgetProgram.setComputeUnitPrice({microLamports: 1});const transferInstruction = SystemProgram.transfer({fromPubkey: sender.publicKey,toPubkey: recipient.publicKey,lamports: 0.01 * LAMPORTS_PER_SOL});// Add the compute budget and transfer instructions to a new transactionconst transaction = new Transaction().add(limitInstruction).add(priceInstruction).add(transferInstruction);const signature = await sendAndConfirmTransaction(connection, transaction, [sender]);console.log("Transaction Signature:", signature);
Is this page helpful?