Fee and Sequence Handling

← Back to Transactors: Understanding the Lifecycle of a Transaction


Introduction

Transaction fees and sequence numbers are fundamental mechanisms that ensure the XRP Ledger operates securely and efficiently. Fees prevent spam and compensate the network for processing transactions, while sequence numbers prevent replay attacks and ensure transaction ordering.

Understanding how these mechanisms work is essential for implementing transactors correctly and for building applications that submit transactions reliably.


Transaction Fees

Every transaction on the XRP Ledger requires a fee, paid in XRP. This fee is destroyed (burned), permanently removing it from circulation.

Base Fee

The base fee is the minimum fee for a standard transaction:

static XRPAmount
Transactor::calculateBaseFee(ReadView const& view, STTx const& tx)
{
    // Get the reference fee from the ledger
    return view.fees().base;
}

The current reference base fee is 10 drops (0.00001 XRP).

Fee Calculation

Different transaction types may have different fee multipliers:

Fee Escalation (Transaction Queue)

When the network is busy, the required fee increases:

Fee Checking in Preclaim

The base Transactor class checks fees during preclaim:

Fee Payment

Fees are paid at the start of doApply:


Account Reserves

Accounts must maintain a minimum XRP balance called the reserve. The reserve has two components:

  1. Base Reserve: Fixed amount every account must hold (currently 1 XRP)

  2. Owner Reserve: Additional amount per owned object (currently 0.2 XRP per object)

Reserve Calculation

Checking Reserves Before Creating Objects

Before creating a new object that will increase the owner count, verify the account can afford it:

Why mPriorBalance?

Using the balance before fee deduction allows accounts to use reserve XRP to pay transaction fees. This is important for:

  • Deleting objects when an account is low on funds

  • Sending the last XRP out of an account


Sequence Numbers

Each account has a sequence number that starts at 1 and increments with each transaction. This prevents:

  • Replay attacks: A transaction can only be applied once

  • Transaction ordering issues: Transactions are applied in sequence order

Sequence Number Checking

Sequence Number Consumption

After a successful transaction (or tec failure), the sequence number is incremented:


Tickets

Tickets provide an alternative to strict sequence ordering. A ticket is a pre-reserved sequence number that can be used later.

Creating Tickets

The TicketCreate transaction reserves a range of sequence numbers:

Using Tickets

Instead of Sequence, use TicketSequence:

Ticket Handling in Transactors


LastLedgerSequence

Transactions can specify a maximum ledger sequence for inclusion:

If the transaction is not included by this ledger, it becomes invalid:

Best Practice: Always set LastLedgerSequence to prevent transactions from being stuck indefinitely. A common value is current_ledger + 4.


mPriorBalance and mSourceBalance

The Transactor base class tracks two balance values:

These are set during the reset() method before doApply() runs:

Usage:

  • Use mPriorBalance for reserve checks (allows fee payment from reserves)

  • Use mSourceBalance for balance-dependent operations (actual available funds)


Code
Meaning
When Returned

temBAD_FEE

Fee is malformed

Negative fee

telINSUF_FEE_P

Fee too low

Below minimum for network load

terINSUF_FEE_B

Can't afford fee

Balance < fee

tecINSUFFICIENT_RESERVE

Reserve not met

Creating object without enough XRP


Code
Meaning
When Returned

tefPAST_SEQ

Sequence already used

Transaction replayed or sequence too low

terPRE_SEQ

Sequence too high

Earlier transaction not yet applied

tefMAX_LEDGER

Transaction expired

LastLedgerSequence exceeded

tefNO_TICKET

Ticket not found

TicketSequence doesn't exist


Best Practices

  1. Always set LastLedgerSequence: Prevent stuck transactions

  2. Check reserves before creating objects: Use mPriorBalance

  3. Handle sequence gaps: Use tickets for out-of-order transactions

  4. Account for fee escalation: During high load, fees increase

  5. Don't hardcode fees: Query the current fee level

  6. Consider ticket usage: For systems that need flexible ordering


Codebase References

File
Description

src/xrpld/app/tx/detail/Transactor.cpp

Fee and sequence handling implementation

src/xrpld/app/misc/TxQ.cpp

Transaction queue and fee escalation

include/xrpl/protocol/Fees.h

Fee structure definitions

Last updated