Fees

The information below applies to the upcoming Babylon release, and does not apply for the current Olympia mainnet. You can find information on the Olympia fee model here.

Fees are the XRD required to be paid to run a transaction. Fees reflect the burden each transaction puts on the network, most notably in the areas of how work-intensive it is to compute the result, and how much permanent storage it requires. On the Radix Public Network, fees are also where royalties are accounted for. Royalties are set by developers who deploy code or run applications on the network, and allow them to collect a “use fee” every time their work gets used in a transaction.

We suggest reading this article about the overall model before continuing.

Current state of implementation

As of Scrypto v0.5, an early implementation of fees is present, and all transactions on your local simulator and test networks will consume XRD.

In the current implementation, all fee table amounts should be considered as nonsensical placeholders, and are in no way representative of the values which will ultimately ship with Babylon.

The royalty system described in the article linked above is not yet implemented.

Calculating costs

Fees are calculated using a fee table, which describes the CostUnits associated with a given operation, and a fiat value multiplier, which is used to compute a cost in XRD for a given amount of CostUnits.

For each section of code to be run, the system determines a price for that section, taking the following steps:

  1. Apply the fee table to each operation in the section, and sum up the total CostUnits required to run it.

  2. Multiply by the fiat value multiplier to compute the base network XRD cost.

  3. Multiply by the user’s tip multiplier, if one was specified.

  4. Add any royalties incurred.

This gives the total XRD cost to run a section of code. If the transaction’s fee reserve has sufficient balance to pay this, this cost is deducted from the reserve and the transaction continues execution. If not, the transaction fails at this point, and any already-spent fees are forfeited.

Paying fees

Fees can be paid from any vault containing XRD. Remember that, on Radix, tokens (including XRD) aren’t directly “held” by a keypair - they’re always stored in vaults owned by components. In order to identify where a fee is being paid from, the transaction needs to call some component which will lock some XRD with which to pay the fee, establishing the fee reserve to begin paying from. Most commonly, this will be an Account component under the signer’s control.

It isn’t necessary to pay the entire fee from a single source…additional XRD may be locked for fee payment throughout the course of the transaction. This allows for a model where profit-generating applications can “chip in” for some amount of the fee without necessarily having to cover the entire cost.

At this point you may be wondering how your transaction pays the cost of the operations which lead up to that first locking of a fee. The answer is that the network automatically grants a small loan to all transactions, establishing a fixed amount of CostUnits which can be consumed before the fee reserve is initially established, at which point the loan must be fully repaid in order for execution to continue. If the transaction exceeds the loan amount without locking a sufficient amount to proceed, then the transaction is simply rejected and no record of it is kept.

Transactions which successfully repay their loan, but then fail to complete (either due to a logical abort or running out of fee reserve during execution) are marked as failed. Failed transactions still spend whatever fees (and royalties, if any) were consumed up until the point they failed. If a transaction completes successfully without spending all its fee reserve, the unspent amount is returned to the vault it was locked from.

Syntax

If you’re only interested in "how can I lock a fee so my test transaction can proceed" then simply call the lock_fee method on an Account using CALL_METHOD in the transaction manifest. If you want to understand the mechanics of doing this in Scrypto, read on.

Vaults now have two methods which can be used to commit XRD to paying fees, lock_fee() and lock_contingent_fee(). Calling them on a Vault which holds anything other than XRD will produce a runtime error.

lock_fee() will immediately add the associated amount of XRD to the fee reserve. This XRD can be used to pay for ongoing processing during the transaction’s execution, and can be spent even if the transaction ultimately fails in its execution.

lock_contingent_fee() does not directly impact the fee reserve, but will have spending priority "after the fact" if the transaction processes successfully. This method is appropriate to use for applications which want to pay for part or all of their consumer’s fees, without exposing them to risk from malicious actors who will build transactions which get this fee committed and then purposely fail, draining the XRD of the application without benefit.

Fees are paid in a LIFO manner, with contingent-locked fees always being fully spent first (if the transaction executes successfully). This is most easily explained by example.

Fee consumption examples

Example 1

  1. Account Alpha calls lock_fee for 10 XRD.

  2. Radiswap calls lock_contingent_fee for 2 XRD.

  3. Transaction completes successfully having spent 8 XRD.

Radiswap spends 2 XRD.

Account Alpha spends 6 XRD.

Example 2

  1. Radiswap calls lock_contingent_fee for 100 XRD.

  2. Account Alpha calls lock_fee for 10 XRD.

  3. Transaction cost exceeds 10 XRD during some section.

Transaction fails.

Radiswap spends nothing.

Account Alpha spends 10 XRD.

Example 3

  1. Account Alpha calls lock_fee for 10 XRD.

  2. Radiswap calls lock_contingent_fee for 100 XRD.

  3. Transaction completes successfully having spent 6 XRD.

Radiswap spends 6 XRD.

Account Alpha spends nothing.

Example 4

  1. Account Alpha calls lock_fee for 10 XRD.

  2. Stuff happens which eats up 5 XRD of fee.

  3. Account Bravo calls lock_fee for 10 XRD.

  4. Radiswap calls lock_contingent_fee for 1 XRD.

Transaction completes successfully having spent 12 XRD.

Radiswap spends 1 XRD.

Account Alpha spends 1 XRD.

Account Bravo spends 10 XRD.

Example 5

  1. Account Alpha calls lock_fee for 10 XRD.

  2. Radiswap calls lock_contingent_fee for 5 XRD.

  3. Loanify calls lock_contingent_fee for 5 XRD.

Transaction completes successfully having spent 8 XRD.

Radiswap spends 3 XRD.

Loanify spends 5 XRD.

Account Alpha spends nothing.

Example 6

  1. Account Alpha calls lock_fee for 10 XRD.

  2. Radiswap calls lock_contingent_fee for 10 XRD.

  3. Transaction panics having spent 8 XRD.

Radiswap spends nothing.

Account Alpha spends 8 XRD.