All SIMDs
SIMD · 0553

Base Inclusion and Resource-based Fee

DraftCoreStandardJune 3, 2026
by cavey

Summary

We split the present static 5000-lamport per-signature fee (2500 burned, 2500 to the leader) into two components:

  • Base inclusion fee — static 2500 lamports per transaction, paid entirely to the leader (see Base Inclusion Fee).
  • Resource fee — dynamic, 100% burned. Computed from requested_cost_units and the resource fee rate (see Resource Fee Calculation). The rate ramps in three feature-gated steps — 1/10, 1/4, then 1/2 lamports per cost unit — replacing the burned half of today's fee and scaling with scheduler cost.

Priority fees are unchanged (100% to the leader, as per SIMD-0096).

The mechanism is suitable for the network before and after Alpenglow activation.

Originating discussion: [Discussion #547].

Motivation

  1. Negligible SOL burn today. At the current ~3000 TPS the network burns on the order of ~648 SOL/day from signature fees alone — several orders of magnitude below daily inflation (~60,000 SOL/day).
  2. The current base fee does not price resources. Users pay a single static per-signature charge regardless of scheduler cost (compute, write locks, loaded data, etc.). This leaves some users underpaying for compute-heavy transactions.

Alternatives Considered

Uniform increase to the 5000-lamport per-signature fee. Rejected. High-volume senders (market makers, validators pre-Alpenglow) pay mostly the flat charge; a uniform increase disproportionately harms them while leaving resource usage mispriced.

50/50 burn / leader split on the resource fee. Rejected. The resource cost is borne by every node that replays and votes on the transaction, not only the leader. Paying the leader a share would create a much harder economic problem to model with second order effects on validator incentives and market structure (e.g. favoring inefficient programs that pay more resource fee to the leader, favoring compute-heavy swaps over cheap maker updates). Burning 100% keeps validator incentives and economics untouched for the most part.

Dynamic resource fee rate. A controller that adjusts the resource fee rate each epoch from block utilization is a reasonable follow-up but adds predictability complexity. This SIMD specifies three static rates activated via separate feature gates (1/10, 1/4, 1/2 lamports per cost unit); a utilization controller or further adjustments can come later.

SIMD-0110-style hot-account base fee. Operates locally on short timescales from account hotness. This proposal is global, tied to per-transaction requested cost, and intended to move slowly (staged static rates via feature gates; dynamic tuning may follow).

New Terminology

  • Base inclusion fee — static 2500 lamports per transaction to the block leader; renamed from "base fee". Pays for inclusion, not resource consumption. Required so the leader is paid even when the priority fee is zero; otherwise game-theoretic incentives would lead leaders to drop zero-prio txns.
  • Resource fee — lamports burned from requested_cost_units and the resource fee rate (see Resource Fee Calculation).
  • Requested cost units — the pre-execution scheduler cost used for block packing and cost tracking today. It is the sum of five cost-model components (see Resource Fee Calculation). For program execution and loaded-account data, the requested compute-unit limit and requested loaded-accounts data size MUST be used (not consumed values).
  • Resource fee rate — lamports per requested cost unit, expressed as a rational resource_fee_rate_numerator / resource_fee_rate_denominator. Three staged values: 1/10, 1/4, and 1/2. See Feature Gates.

Detailed Design

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Feature Gates

Three feature gates SHALL be introduced:

| Gate | Feature ID | Rate | Numerator | Denominator | | ---- | ---------- | ---- | --------- | ----------- | | resource_fee_burn_1_10 | BurnUeW8qFgJm3Y4uroMvqEQDrYWbhv7p231hHbrq8LV | 1/10 | 1 | 10 | | resource_fee_burn_1_4 | Burn2YJ9k9wTcyQCEMztMsbnBReV3FzXpW1aBB7MhwuY | 1/4 | 1 | 4 | | resource_fee_burn_1_2 | BurnSoLN7d4ASk4zVVxTg4ob3C8z71dN6cr8YsyEnaZ6 | 1/2 | 1 | 2 |

When any of these gates is active for a bank, transaction fees MUST follow Total Fee Calculation below (base inclusion fee split plus resource fee). When multiple gates are active, implementations MUST use the highest effective resource fee rate from the table above.

The gates SHOULD be activated in order (1/10 → 1/4 → 1/2). Activating them out of order is permitted; the effective rate is always the maximum among active gates. The staged rollout lets the network observe wallet, RPC, and application behavior at modest burn before reaching the terminal 1/2 rate.

Activation timing

Each gate follows the standard feature activation mechanism. If a gate is activated between epoch E - 1 and epoch E, the corresponding rate change MUST apply starting at the first slot of epoch E. All earlier slots MUST use the previous effective fee model (pre-activation flat fee, or a lower resource fee rate if an earlier gate is already active).

Transaction simulation and fee estimation at epoch boundaries therefore depend on which feature set the bank uses; clients SHOULD use the same feature activation rules as the runtime when simulating near a boundary.

Total Fee Calculation

total_fee = base_inclusion_fee + priority_fee + resource_fee
ComponentFormulaBurnLeader
Base inclusion fee25000%100%
Priority feeCU price × limit (existing)0%100%
Resource fee (new)see Resource Fee Calculation100%0%

Fee-only transactions. In Agave, a transaction that fails during account loading may still be processed as fee-only (ProcessedTransaction::FeesOnly): the fee payer is debited the full total_fee even though the transaction does not execute. This behavior MUST be preserved after the first gate activates, now also including the resource fee.

Base Inclusion Fee (static component)

The "base fee" / "transaction fee" SHOULD be called base inclusion fee in documentation, RPC fields, and user-facing surfaces.

base_inclusion_fee = 2500

Leaders MUST receive a nonzero reward for including a transaction even when the priority fee is zero. Without it, game-theoretic fee maximization would leave zero-priority transactions unincluded. Present designs for multiple concurrent proposers introduce an inclusion fee; this split does not introduce a new fee category or additional complexity beyond what's to come.

Legacy per-signature base fee. Today's 5000-lamport charge scales with signature count (5000 × num_signatures, split 50/50 burn / leader) because the original fee model priced each signature verification at the transaction level. The scheduler cost model also counts signatures in signature_cost, so signature work is priced twice today: once in the per-signature base fee and again (relatively cheaply) in requested_cost_units.

This SIMD. The base inclusion fee is a flat 2500 lamports per transaction — not 2500 × num_signatures. Signature verification is priced only through signature_cost inside requested_cost_units and therefore the resource fee.

Follow-up path.

  1. This SIMD — flat base inclusion fee; resource fee uses today's (relatively cheap) signature_cost component in the cost model.
  2. Follow-up SIMD — if needed, after some investigation, raise signature pricing in the cost model so multi-signer and precompile-heavy transactions pay an appropriate resource fee after step 1. Specific constants are out of scope here and belong in that proposal.

Multi-signer transactions pay less fees than under today's per-signature model until that follow-up is activated.

Resource Fee Calculation (dynamic component)

resource_fee = ceil_div(
  requested_cost_units × resource_fee_rate_numerator,
  resource_fee_rate_denominator)

Implementations MUST compute resource_fee using integer arithmetic only.

The effective resource_fee_rate_numerator and resource_fee_rate_denominator MUST be taken from Feature Gates for the bank being executed or verified.

requested_cost_units is the transaction's pre-execution scheduler cost — the same total computed for block packing and cost tracking today. Implementations MUST compute it as the saturating sum of:

  1. Signature cost (signature_cost) — cost of signature verification (including precompile signatures accounted by the cost model).
  2. Write-lock cost (write_lock_cost).
  3. Instruction-data cost (data_bytes_cost).
  4. Program-execution cost (programs_execution_cost) — cost from the transaction's requested compute-unit limit (Compute Budget).
  5. Loaded-accounts-data-size cost (loaded_accounts_data_size_cost) — cost from the transaction's requested loaded-accounts data size.
requested_cost_units = signature_cost
                     + write_lock_cost
                     + data_bytes_cost
                     + programs_execution_cost      // requested CUs
                     + loaded_accounts_data_size_cost  // requested bytes

(saturating u64 addition at each step, as in validator cost-model code today.)

The resource fee MUST use this requested total, not post-execution consumed costs, for the same reasons as the priority fee:

  1. Async execution. Future async execution paths require a fee known before execution completes.
  2. Pre-execution validation. The runtime can verify the fee payer can afford the fee without executing the transaction.
  3. Better UX. Users know exactly how much they're paying before sending the transaction.
  4. Scheduling incentives. Users should request accurate compute limits.

Note that the sum of requested cost units across transactions in a block MAY exceed per-block packing limits.

Fee Collection and Burn

Implementations MUST:

  1. Compute base_inclusion_fee, resource_fee, and priority_fee; burn the full resource fee; route inclusion and priority fees to the collector.
  2. Deduct total_fee from the fee payer as today.

Validator Components Affected

Validator ComponentImpact
Transaction Execution (Runtime)Fee calculation, burn accounting
Virtual MachineNone
Block PackingFee payer check uses new total fee
ConsensusBurn totals in bank hash
GossipNone
TurbineNone
TPUVote / Simple Vote fast-path updates
SnapshotsNone
On-Chain Core BPF ProgramsNone
Other (please describe)RPC fee responses, wallets, explorers

RPC and client APIs

Agave today exposes fees almost entirely as a single lamport total computed by Bank::get_fee_for_message / transaction simulation (fee crate → FeeDetails::total_fee()). Under this SIMD that total becomes base_inclusion_fee + resource_fee + priority_fee, but the JSON shape can stay scalar unless an implementation chooses to extend it.

RPC methodFieldChange
getFeeForMessageresultNew total fee
simulateTransactionfeeNew total fee
sendTransaction (preflight)fee in errorAs simulation
getTransactionmeta.feeTotal charged
getRecentPrioritizationFees(priority only)Unchanged

The Banks service (get_fee_for_message_with_commitment_and_context) follows the same bank path as getFeeForMessage.

RPC implementations SHOULD ensure the above totals match Total Fee Calculation. They MAY add optional breakdown fields (baseInclusionFee, resourceFee, priorityFee) in a follow-up; this SIMD does not require a schema change. User-facing docs SHOULD stop treating meta.fee / simulation fee as “base fee only” and label them total fee.

getTransaction already exposes meta.costUnits (requested scheduler cost); clients MAY use it with the resource fee rate to estimate resource fee, but SHOULD prefer getFeeForMessage / simulateTransaction for authoritative totals.

Impact

SOL holders. Empirical network data (May 2026) suggests ~1,500–1,800, ~3,750–4,500, and ~7,500–9,000 SOL/day from resource fees at 1/10, 1/4, and 1/2 lamports per requested cost unit respectively, each replacing the flat 2500-lamport-per-signature burn (~648 SOL/day at current throughput). The terminal 1/2 rate implies a meaningful net increase in total burn and roughly 0.5% deflation against ~3.8% inflation; earlier stages burn less while the network validates the new fee model.

Retail / low-priority users. Example transactions at the terminal resource_fee_rate of 1/2 (vote: 3765 requested cost units). At 1/10 or 1/4, multiply the table's resource-fee column by 1/5 or 1/2 respectively (base inclusion and priority fees are unchanged):

| Activity | Today | After | Δ | | -------- | ----- | ----- | -- | | Vote (w/ CB ixns) | 5000 | 2500 + 1883 | -12.3% | | [High Prio Swap (DFlow)][dflow-tx] | 5000 + 2002500 | 2500 + 197720 + 2002500 | +9.72% | | [Mid Prio Swap (OKX)][okx-tx] | 5000 + 130980 | 2500 + 412160 + 130980 | +301% | | [Zero prio Pumpfun swap][pump-tx] | 5000 + 0 | 2500 + 159910 + 0 | +3150% | | [Zerofi oracle update][zerofi-tx] | 5000 + 2568 | 2500 + 1220 + 2568 | -16.9% |

At resource_fee_rate 1/2, low-resource-usage transactions win: they pay less total fee than under today's flat 5000-lamport charge (see Vote and Zerofi rows). Burn tracks requested cost, rewarding efficient programs that request only the resources they need.

Compute-unit estimation. Resource fee is charged on requested cost units, including the Compute Budget unit limit, not consumed compute. Applications that set a loose SetComputeUnitLimit (or never tighten it after simulation) pay resource fee on the full requested amount—the same basis as priority fees today, but now significant for zero-priority transactions that previously paid only the flat base fee. Over-estimating requested compute units increases resource_fee directly at resource_fee_rate.

Note that legacy vote transactions as sent today request on the order of 54k cost units — far more than the work a vote actually performs. At resource_fee_rate 1/2 that would raise pre-Alpenglow vote cost to nearly today's flat 5000-lamport fee. All client implementations SHOULD send votes with Compute Budget instructions that set requested compute units and loaded-accounts data size to reflect actual vote work (see the Vote row above, 3765 requested units). Omitting those instructions remains valid but is NOT RECOMMENDED under this fee model. [SIMD-0458] is live on mainnet-beta; vote transactions that include Compute Budget instructions no longer classify as Simple Vote, so implementations SHOULD update any TPU vote filter or fast-path logic that assumes the legacy Simple Vote shape.

Alpenglow. Pre Alpenglow, validators submit on-chain vote transactions at high volume (on the order of ~1 SOL/day in vote fees today). The vote guidance above (requested cost, Compute Budget, TPU filters) matters directly for validator operating cost in that phase.

Post Alpenglow, consensus votes are no longer on-chain transactions; they are exchanged directly between validators, and vote economics move to separate mechanisms (e.g. the validator admission ticket). Total Fee Calculation still applies to every on-chain transaction before and after Alpenglow, but the vote-specific impact above is primarily a (pre Alpenglow, migration) concern.

Wallets and SDKs. MUST estimate fees using the same formula as Resource Fee Calculation, with the effective numerator and denominator for the bank epoch being simulated.

Security Considerations

Minimum cost decreases from 5000 lamports once the first gate is active. At the terminal 1/2 rate the floor is 3010 lamports for minimal transactions; at 1/10 and 1/4 the floor is lower still. This lowers the lamport floor compared with today's flat 5000-lamport base fee and reduces the cost of DoS spam at that floor. Note that such spam would consist of transactions that are extremely cheap to execute.

Drawbacks

Modest burn vs inflation. Even at the terminal 1/2 lamports per cost unit, aggregate burn increases meaningfully but remains well below inflation. Higher resource fee rates increase burn further and hit high-compute, low-priority traffic hardest (see Pump.fun row at 1/2). The staged gates mitigate a single-step jump but extend the period during which burn stays below the terminal target. Perhaps the terminal rate plus 100M/200M/uncapped CU blocks will be enough burn to counteract inflation.

Backwards Compatibility

This is a consensus-breaking change gated behind feature activation. Nodes that do not implement the resource fee will diverge when any gate activates. All validator client implementations (Agave, Firedancer, Sig, etc.) MUST support all three feature gates before mainnet-beta activation of the first gate.

Application transactions without Compute Budget instructions. Under the present fee model, many transactions pay only the flat 5000-lamport charge and never set requested compute units or loaded-accounts data size. After activation, those transactions still perform the same on-chain work, but requested_cost_units — and therefore resource_fee — can be much larger because the implicit requested limits are high relative to actual consumption (see Resource Fee Calculation).

If the fee payer was funded for ~5000 lamports (+ priority) but the new total_fee is higher, block packing and pre-execution fee checks MAY reject the transaction for insufficient funds even though it would have landed under the old model. This affects zero-priority and low-priority traffic hardest when requested cost is high. Note that this affects applications like Helium, as well as compute-heavy applications like zk protocols.

Wallets, SDKs, and transaction senders SHOULD set Compute Budget instructions with requested limits that reflect actual transaction work before activation, and SHOULD re-estimate total_fee under Total Fee Calculation rather than assuming the legacy flat fee. Programs SHOULD optimize on-chain compute so callers can request lower compute-unit limits and pay less resource fee. (Vote transactions are covered in Impact above.)

Conformance

Requested cost units are already in protocol; all verifying nodes check whether transactions exceed each of their requested resources (whether explicitly specified or default amount). As such, there is no need for additional conformance testing with requested cost units. Furthermore, the map from requested cost units to resource fee in lamports is linear in the input. As such, implementations only need a simple test suite (to check for edge cases, overflow, ceiling division) for the linear map from requested cost units to resource fee lamports.

[Discussion #547]: ../discussions/547 [SIMD-0458]: 0458-stop-using-static-simplevote-transaction-cost.md

[okx-tx]: https://solscan.io/tx/3cE8Af9vZ7W4iyFPp6CqeMA3YqAisXsXhKyww3oZnpUAikz1j9zsJN2b6ewdPUCs9Gcn5bzCHWUvYUQQeyWL8Udh [pump-tx]: https://solscan.io/tx/5oGd26j5bxWar5PzJRxqYroWCBsqRtLrPbGePG76FRfqTFkQU81Z56LAARWevqKam1g9M2o3HomeMfxky5qnDfY2 [dflow-tx]: https://solscan.io/tx/V7X2RhiTH4oDW7kMJErQx6rZuETzp3tYrR1scTNkikdaW4aNpLgZeQWSkAkczwNLLPpjwN5q5cb61fT2JRpSGs8 [zerofi-tx]: https://solscan.io/tx/66vmDnYS9cujQkNgGXiC6e5GqGGkhRdyzX13j23GPUTA61xG7Kj3FNFqGnrLBtMsxhyxLQe4mZyBa4j9ziE7mMAD