A transaction fee is required to process a transactions. Transaction processing fees are always charged for transactions which are distributed to the network, even if the transaction should apparently fail.
When the network is under excessive load, transaction fees are raised to protect the network. The network may be under excessive load due to attack or simply popularity or some mass event.
Default schedule (subject to change without notice):
- Default fee
- 0.00001 XRP
The current fee schedule can be found by subscribing to ledger close messages or with the RPC server_info.
Transaction fees are adjusted based on two factors: base fee and load fee
base fee: long term fee adjustments
Since transaction fees are paid in XRP and the price of XRP may change overtime, to keep the price of transactions affordable, Ripple uses an adjustable "base fee" to specify the cost of transactions.
load fee: short term fee adjustments
The "load fee" can rise quickly to protect the network from attacks and keep the network functional under heavy load.
Fees are set in "fee units". This sets the relative fees for various transactions, reserve amounts, and so on. The fees are adjusted to keep transactions affordable by adusting a single "base fee". Changing the base fee changes the cost of a fee unit and thus scales all fees.
Calculating the Transaction Fee
The server reports three variables: base_fee_xrp, load_base, and load_factor which are used to calculate the transaction_fee. These values can be retrieved by querying the server directly. See: server_info and server_state. Then can also be monitored thought the server stream and ledger stream
- Is the fee if there's no excessive load. It currently set to 10 drops.
- Is the reference load level that indicates the normal fee. It is currently 256.
- Is the current load measurement.
If load_factor is equal to load_base, then
transaction_fee = base_fee
transaction_fee = base_fee * load_factor / load_base
So for example: If the base_fee is 10, the load_base is 256, and the load_factor is 382. The transaction fee becomes:
14.9 drops = 10 drops * 382 / 256
See also: Calculating the Transaction Fee
If you trust the server, you can submit a transaction without fees, the server will fill in the fee. A transaction that includes a fee which is less than what a particular server requires will not be forwarded by that server; Typically, there is no point in submitting such a transaction to that server (with some exceptions: if the fee changes before submitting, or if the transaction is submitted by a trusted entity for example).
When submitting a transaction to an untrusted server, the server may tell you a fee and then drop your transactions regardless of the fee you set. For this reason you should not limit the servers you submit your transaction to to the servers with the lowest fees. Additionally, you should submit your transaction to multiple servers. If you transaction is not processed, you should connect to more trust worthy IPs and submit your transaction again.
Terminology should be consistent. The terms are as follows:
- Reference Transaction
- A basic account to account transfer of XRPs.
- Base Fee (fee_base)
- The cost, in XRP, of the reference transaction assuming no load on the network. This is the knob that gets turned to adjust transaction fees based on the scarcity of XRPs.
- Fee Units
- A measure of the relative cost of different things such as transactions, reserves, and so on. If one transaction costs twice as many fee units as another, it will cost twice as much to process under the same conditions. The conversion of fee units to XRP needed to perform a transaction depends on the base fee, the reference fee, and load.
- Reference Fee (fee_ref)
- The cost, in fee units, of the reference transaction.
- Reserve Base (reserve_base)
- The amount needed to create an account, in fee units.
- Reserve Increment (reserve_inc)
- The amount of additional reserve required for each counted owner entry, in fee units.
- Load Base (load_base)
- The value of the load fee that indicates that there is no additional fee imposed due to load.
- Local Load Fee
- The multiplicative adjustment to fees based on load on a particular server. A value equal to the load base indicates only normal fees apply.
- Network Load Fee
- The multiplicative adjustment to fees based on load to the network as a whole.
- Load Fee (load_fee)
- The greater of the local load fee and the network load fee. This is the actual factor used by a server when deciding whether a transaction has an adequate fee.
- Load Factor (load_factor)
- The amount a fee has to be multiplied by to convert from the fee required under no load to the transaction fee required under current load.
Base fees are set in integer fee units and based on a reference transaction. The reference transaction is the cheapest, useful transaction -- typically sending Ripples directly from one account to another. The cost of the reference transaction in fee units is called the "base reference".
Currently this is set to 10. That is, the reference transaction costs 10 fee units. There should never be any need to change this value. This value is essentially arbitrary. However, too small a value would make fee settings too coarse and too large a value would limit the maximum fee. Any number from 10 to 1,000 is reasonable.
To adjust fees to keep them in a sensible range should the scarcity of Ripples change, a "base fee" is used. This is the cost of the reference transaction in system base currency units (millionths of a Ripple).
If the reference transaction should cost 10 millionths of a ripple, the "base fee" should be set to 10. This is the current value. This makes it very simple to adjust fees to keep them sensible -- just figure out how many millionths of a Ripple the reference transaction should cost and set that as the base fee.
Other fees are set in terms of fee units. These are tenths of the reference transaction (because the "base reference" is 10). So if some operation should cost twice as much as the reference transaction, it should be set to 20 fee units.
For example, if the base account reserve should be 5,000 times the cost of the reference transaction, it should be set to 50,000 fee units. This is the current value.
There are two multipliers. One is the load multiplier and the other is the base multiplier. The equation is:
The 'Load Multiplier' is set by each node according to the load it is experiencing and the load it detects on the network. The 'Base Multiplier' is adjusted based on the value of the credits to keep the normal cost of a transaction in line with the actual cost of processing that transaction.
Each node will decide whether or not to process a transaction based on the fee. The node will compute the two base fees, multiply the execution fee by a load factor, sum those two fees, and then multiply by the base fee. This is the required transaction fee for that node. If the transaction holds the necessary fee, the node will process and forward the transaction. If not, it will just store it.
If some nodes think a transaction's fee is adequate and some don't, then some will process it and some won't. Since the network is heavily redundant, it won't take more than small percentage of nodes to think a transaction fee is adequate for the vast majority of nodes to receive the transaction. If a bit more than half of the network accepts the transaction, it will wind up in the candidate set for the consensus ledger during avalanche. If less than half of the network accepts the transaction, it will not.
So, in a sense, a majority of validators sets the effective network fee based on load. If a transaction does make it into the candidate set, a node must apply the transaction (if possible) regardless of fee. Otherwise, consensus will break.
Reserve rates are always controlled by consensus and are in the ledger. Thus nodes can rely on the reserve rates being consistent during transaction processing. This is necessary to make the exchange logic respect the reserve.
Fee Changes and Fee Discovery
When we want to change the base fee or multiplier, we just release a new version of the software with a new base fee (or publish a new fee schedule). People can tweak that, but they probably won't. People might not upgrade, but they probably will. As soon as more than half the network is running the new software, a transaction setting the new fee scheduled will get in the ledger. Then clients can start dropping their fees paid.
If a node gets heavily loaded, it can start raising the multiplier on the execution fee, increasing the fees it demands to process transactions. If only a few nodes get loaded, in practise it will have no effect. They'll either have to get the transactions and process them anyway or stop validating. (If you can't keep up with the network's consensus ledgers, you must stop validating.) When they catch up, they can start validating again.
We also give nodes a way to "weak sign" the consensus ledger. In this case, the node is just saying that it wasn't split off from the network, its UNL converged on that ledger, but that it could not validate it because it could not keep up with the transactions. Essentially, the network will gracefully degrade under load into only those nodes powerful enough to process all transactions.
It is important that the fee schedule increase rapidly enough that an attacker can't easily reduce the set of validating nodes to a small set. I don't see this as being difficult. There will also be a safety to detect if too many trusted validators are overloaded and to treat that as equivalent to local load.
This requires the "fail to agree = agree to fail" logic. That is, if a node does not have a transaction or does not recognize a transaction, it simply never votes "yes" on that transaction. If nodes on your UNL are present but ignoring a transaction, you treat that as a "no" vote. This renders the network highly resistant to DoS attacks. DoS attacks will, at worst, raise some nodes fee schedules or cause some nodes to bow out. The attacker will have to spend more and more to maintain the attack and legitimate users can just increase their fees if they are in a hurry. Nodes that ignore the transactions will barely be effected as nodes stop propagating the transactions and they can be ignored at ledger close (unless they garner a majority).
Communicating Fees to Clients
If the base fee differs from the network default, it is included in the ledger. The fee schedule is always communicated to the client when it subscribes to the ledger stream.
For base fees, four values are included in the JSON, all integers:
- The number of fee units the reference transaction costs.
- The XRP cost of the reference transaction.
- The reserve amount in fee units.
- The amount added to the reserve per counted owner entry in fee units.
The fee_ref will normally be 10, the reserve_base will be 50,000,000 fee units, and the reserve_inc will be 12,500,000 fee units. This is not expected to change. The fee_base is currently 10.
To compute the cost, in XRP, of a fee unit, divide the fee_base by the fee_ref.
cost of fee unit in XRP = fee_base / fee_ref
required reserve in XRP = (reserve_base + (count * reserve_inc)) * fee_base / fee_ref
cost of transaction in XRP = transaction fee units * fee_base / fee_ref
Note: The above formulas compute base fees, not adjusted for load. The reserve is never adjusted for load, so the formulas above are correct for reserves.
For load fees, two values are included in the server state JSON, both integers:
- The value of the load fee that represents no load.
- The current load fee.
The load_base will normally be 256. This is not expected to change.
If the load_fee is also 256, then there is no load fee. If the load_fee is 512, then fees are doubled due to load. Normal fees can be converted to fees adjusted for load by multiplying by the load_fee and dividing by the load_base.
If the load_base and the load_fee are unequal, it is advisable to add a cushion in case the load increases or the server's view of the load fee is unusually low. The load fee includes both local server measures of load and network-wide measures of load.
load adjusted transaction fee in XRP = normal fee in XRP * load_fee / load_base
Do not adjust reserve fees for load! Only transaction fees are adjusted.
Some effort will be needed to ensure transaction fees can rise fast enough to prevent network destabilization. Also, fees will need to rise fast enough to prevent the network from contracting into a too-small group of ultra-fast nodes as this makes the network more vulnerable to a takeover.