Introduction
Every transaction on Radix pays a fee in XRD, and every manifest you write has to say where that XRD comes from. That is what the lock_fee call at the top of most manifests is doing. Two things about the Radix model differ from what you may expect coming from an EVM chain, and both change how you design a dApp.
First, the fee is not attached to the signer. XRD is held in vaults owned by components, so a fee is paid by whichever component locks it – which may be the user's Smart Account, your dApp's component, or both. Second, the total fee is not a single gas number: it is a network cost, an optional user tip, and any royalties the code you called charges, each with different destinations.
What Makes Up a Fee
The fee model prices each transaction in three parts, and the first of those is itself three separately-metered quantities:
- Network fee – the cost of running the transaction and of the state it leaves behind. It is the sum of an execution cost, a finalization cost and a storage cost. The first two are metered in cost units against a fee table; the third is charged per byte written to state and to archive.
- Tip – an optional percentage the submitter adds when demand exceeds capacity. It amplifies only the network portion, never royalties, and goes straight to the validator proposing the round.
- Royalties – amounts set by a package publisher or component instantiator, charged whenever a transaction calls that code. Royalties are part of the fee the user pays, but they are not burnt or shared with validators; see Events, Metadata, and Royalties for how to configure them.
Because royalties are counted inside the fee, a transaction that touches an expensive component costs more than an identical transaction that does not – and the user sees the total before signing, in the wallet's transaction summary.
The Prices, and the Fiat Peg Behind Them
The prices are protocol constants, declared in radix-common/src/constants/transaction_execution.rs and assembled into a CostingParameters struct by the engine. Every figure below is checkable against any committed transaction's receipt.fee_summary through the Gateway API.
| Parameter | Value | What it controls |
EXECUTION_COST_UNIT_PRICE_IN_XRD | 0.00000005 XRD | Price of one execution cost unit |
FINALIZATION_COST_UNIT_PRICE_IN_XRD | 0.00000005 XRD | Price of one finalization cost unit |
STATE_STORAGE_PRICE_IN_XRD | 0.00009536743 XRD | Price of one byte of state storage |
ARCHIVE_STORAGE_PRICE_IN_XRD | 0.00009536743 XRD | Price of one byte of archive storage (payload, events, logs) |
EXECUTION_COST_UNIT_LIMIT | 100,000,000 | Ceiling on execution cost units in one transaction |
FINALIZATION_COST_UNIT_LIMIT | 50,000,000 | Ceiling on finalization cost units in one transaction |
EXECUTION_COST_UNIT_LOAN | 4,000,000 | Cost units advanced before the first lock_fee |
USD_PRICE_IN_XRD | 16.666… XRD | The fiat multiplier — the rate at which USD-denominated royalties convert to XRD |
Working the mainnet transaction above back through them: 7,286,902 execution cost units at 0.00000005 XRD is 0.3643451 XRD, 820,152 finalization cost units is 0.0410076 XRD, and 0.09574889972 XRD of storage is exactly 1,004 bytes at 0.00009536743 XRD each. The three constants are not documentation — they are what the ledger charged.
The last row is the one worth reading twice. USD_PRICE_IN_XRD is the "fiat value multiplier": it fixes what the protocol believes a dollar is worth in XRD, and at 16.666… it values 1 XRD at $0.06. That figure is not read from an oracle and does not track the market — it is a compiled-in constant, and CostingParameters::latest() in transaction_executor.rs still returns babylon_genesis(), so no protocol update since Babylon has moved it. XRD traded at about $0.00093 on 23 August 2026, roughly sixty-four times below the rate the fee model assumes.
For a developer that cuts two ways. Transaction costs are set in XRD and are therefore stable in XRD and cheap in fiat — the half-XRD transaction above cost about $0.0005. But anything the protocol prices in dollars is converted at $0.06 per XRD, so a royalty declared in USD, and the 166.666… XRD per-function royalty ceiling nominally described as $10, are worth far less than their labels suggest at today's price. Preview credit is generous for the same reason: PREVIEW_CREDIT_IN_XRD advances 1,000,000 XRD, commented in the source as $60,000.
Locking a Fee
A transaction pays from a fee reserve, which is established by calling lock_fee on a component that owns an XRD vault. In practice this is the first instruction in most manifests:
CALL_METHOD
Address("account_rdx...")
"lock_fee"
Decimal("5")
;The amount is a ceiling, not a charge. Whatever the transaction does not spend is returned to the vault it was locked from. Locking too little is the failure mode to guard against: if the reserve runs dry mid-execution the transaction fails, and the fees already consumed are not refunded.
Multiple Payers
More than one vault can lock a fee in the same transaction, and later locks are used preferentially. That is what makes fee sponsorship straightforward on Radix: a dApp component can lock part or all of the fee so the user does not need XRD to interact with it, and a profit-taking application can chip in a share of each trade. Nothing about this requires a meta-transaction relayer – it is a normal manifest instruction.
The Bootstrap Loan
The instructions that run before the first lock_fee still cost something. The network covers them with a small automatic loan of cost units, which must be repaid the moment the reserve is established. A transaction that burns through the loan without locking enough is rejected outright and leaves no ledger record. One that repays the loan and then fails is committed as failed: the state changes roll back, but the fees spent up to the failure are kept.
Where Fees Go
Spent fees are split by type, and the shares are protocol constants rather than a validator setting:
- Network fee – 25% goes to the validator that proposed the round and 25% to the validator set, shared at the end of the epoch in the same shape as network emissions. The remaining 50% is burnt. The two shares are
NETWORK_FEES_PROPOSER_SHARE_PERCENTAGEandNETWORK_FEES_VALIDATOR_SET_SHARE_PERCENTAGEin transaction_execution.rs, both set to 25, and the burn is whatever is left after them:to_burn_amount()subtracts both shares from the total rather than computing a share of its own. - Tips – paid immediately and entirely to the round proposer. The corresponding constants are
TIPS_PROPOSER_SHARE_PERCENTAGE = 100andTIPS_VALIDATOR_SET_SHARE_PERCENTAGE = 0, so a tip is never burnt and never shared. - Royalties – deposited into a system-generated vault owned by the component (or, for package royalties, by the package). The instantiator or deployer claims them with a badge the system creates automatically at instantiation or deployment. A single function's royalty is capped at
MAX_PER_FUNCTION_ROYALTY_IN_XRD, 166.666… XRD.
A live example. The Gateway returns this breakdown for any committed transaction under receipt.fee_destination; for mainnet transaction txid_rdx15gl7urc8kn36mjeq0hwru4mhn9t6uknkh7c7vsnw7tkh6t85zh9q6t3jzn at state version 553,951,096 (23 August 2026), against network fees of 0.50110159972 XRD:
| Destination | XRD | Share |
| Burnt | 0.25055079986 | 50% |
| Round proposer | 0.12527539993 | 25% |
| Validator set (epoch pool) | 0.12527539993 | 25% |
The burn is why fee revenue is deflationary for XRD supply, and the epoch pool is why validator income tracks participation rather than luck of the round.
Practical Guidance
- Lock generously. The unspent portion comes back, so a reserve that is too high costs nothing and a reserve that is too low burns fees for a failed transaction.
- Estimate before you submit. Preview the transaction through the Gateway API to get a fee estimate rather than guessing, especially for manifests whose cost varies with input size.
- Sponsor deliberately. If your component locks the fee, anyone who can call it can spend your XRD – gate the sponsoring method with a badge or a business rule, not just goodwill.
- Price royalties as user cost. A royalty is invisible in your own testing but appears in every user's fee summary.
Next Steps
- Radix Engine Toolkit – build and sign transactions from your own code, with no wallet in the loop
