Skip to content
2 changes: 1 addition & 1 deletion @theme/components/Amendments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ export function AmendmentDisclaimer(props: {
) : (
<>
{translate("component.amendment-status.updates.1", "The ")}{link()}
{translate("component.amendment-status.updates.2", "updates this.")}
{translate("component.amendment-status.updates.2", " updates this.")}
{" "}
<AmendmentBadge amendment={amendmentStatus} />
</>
Expand Down
46 changes: 34 additions & 12 deletions docs/concepts/payment-types/escrow.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
---
html: escrow.html
parent: payment-types.html
seo:
description: Escrow holds funds until specified conditions are met.
labels:
Expand All @@ -10,29 +8,48 @@ labels:

Traditionally, an escrow is a contract between two parties to facilitate financial transactions. An impartial third party receives and holds funds, and only releases them to the intended recipient when conditions specified by the contract are met. This method ensures both parties meet their obligations.

The XRP Ledger takes escrow a step further, replacing the third party with an automated system built into the ledger. An escrow locks up XRP or fungible tokens, which can't be used or destroyed until conditions are met.
The XRP Ledger takes escrow a step further, replacing the third party with an automated system built into the ledger. An escrow locks up XRP or fungible tokens ([see Token Escrow](#token-escrow)), which can't be used or destroyed until conditions are met.

{% amendment-disclaimer name="Escrow" /%}
{% amendment-disclaimer name="TokenEscrow" mode="updated" /%}

## Token Escrow

The [TokenEscrow amendment][] extends escrow functionality to fungible tokens, which means [Trust Line Tokens](../../concepts/tokens/fungible-tokens/trust-line-tokens.md) and [Multi-Purpose Tokens (MPTs)](../../concepts/tokens/fungible-tokens/multi-purpose-tokens.md#transferability-controls) can be held in escrow.

For Trust Line Tokens to be held in escrow, the issuing account must have the **Allow Trust Line Locking** flag enabled, which allows tokens issued by the account to be held in escrow. For MPTs, the issuer needs to enable the **Can Escrow** and **Can Transfer** flags when creating the token issuance, so that the tokens can be held in escrow and transferred.

While issuers can't create escrows with their own issued tokens, they can serve as recipients. When an issuer receives escrowed tokens, the process works the same way as a direct payment.

If a token requires authorization, the sender must be pre-authorized by the issuer before creating an escrow and must also be authorized to receive the tokens back when an expired escrow is canceled, regardless of who submits the cancellation transaction. The recipient must be pre-authorized before the escrow can be finished.

## Types of Escrow

The XRP Ledger supports three types of escrow:

- **Time-based Escrow:** Funds only become available after a certain amount of time passes.
- **Conditional Escrow:** This escrow is created with a corresponding condition and fulfillment. The condition serves as a lock on the funds and won't release until the correct fulfillment key is provided.
- **Combination Escrow:** This escrow combines the features of time-based and conditional escrow. The escrow is completely inaccessible until the specified time passes, after which the funds can be release by providing the correct fulfillment.
- **Combination Escrow:** This escrow combines the features of time-based and conditional escrow. The escrow is completely inaccessible until the specified time passes, after which the funds can be released by providing the correct fulfillment.

## Escrow Lifecycle

The lifecycle of an escrow is as follows:

1. The sender creates an escrow using the `EscrowCreate` transaction. This transaction defines:

- An number of XRP or fungible tokens to lock up.
- The conditions to release the XRP or fungible tokens.
- The recipient of the XRP or fungible tokens.
- An amount of XRP or fungible tokens to lock up.
- The conditions to release the funds.
- For **XRP escrows** this can include a time when the escrow can complete, a cryptographic condition that must be fulfilled, and optionally a time when the escrow expires.
- For **token escrows** similar conditions apply, but an expiration time is _mandatory_.
- The recipient of the funds. Any applicable transfer rates or fees are captured at creation time and will apply when the escrow completes, ensuring predictability for the recipient.

2. When the transaction is processed, the XRP Ledger creates an `Escrow` object that holds the escrowed XRP or fungible token.
2. When the transaction is processed successfully, the XRP Ledger creates an `Escrow` object that holds the escrowed funds.

3. The recipient sends an `EscrowFinish` transaction to deliver the XRP or fungible tokens. If the conditions have been met, this destroys the `Escrow` object and delivers the XRP or fungible tokens to the recipient.
3. The recipient sends an `EscrowFinish` transaction to deliver the funds. If the conditions are met, this destroys the `Escrow` object and delivers the funds to the recipient. Additionally, any missing trust lines or MPT entries may be auto-created for recipients if authorization isn't required.

{% admonition type="info" name="Note" %}If the escrow has an expiration time and isn't successfully finished before then, the escrow becomes expired. An expired escrow remains in the ledger until an `EscrowCancel` transaction cancels it, destroying the `Escrow` object and returning the escrowed XRP or fungible tokens to the sender.{% /admonition %}
{% admonition type="info" name="Note" %}
If the escrow has an expiration time and isn't successfully finished before then, the escrow becomes expired. An expired escrow remains in the ledger until an `EscrowCancel` transaction cancels it, returning the escrowed funds to the sender.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can an EscrowCancel transaction come from anybody?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I understand yes, any account can submit an EscrowCancel transaction.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, EscrowFinish and EscrowCancel transactions can both be sent by anyone as long as the conditions are met (to finish or cancel the escrow, respectively)

Copy link
Collaborator

@oeggert oeggert Oct 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I missed it elsewhere in the doc, it might be worth mentioning that either party can finish the escrow. Not a blocker, though.

{% /admonition %}

## Escrow States

Expand All @@ -42,13 +59,16 @@ The following diagram shows the states an Escrow can progress through:

The diagram shows three different cases for three possible combinations of the escrow's "finish-after" time (`FinishAfter` field), crypto-condition (`Condition` field), and expiration time (`CancelAfter` field):

{% admonition type="info" name="Note" %}
While XRP escrows can sometimes exist without an expiration time, token escrows must **always** have an expiration time (`CancelAfter` field).
{% /admonition %}

- **Time-based Escrow (left):** With only a finish-after time, the escrow is created in the **Held** state. After the specified time has passed, it becomes **Ready** and anyone can finish it. If the escrow has an expiration time and no one finishes it before that time passes, then the escrow becomes **Expired**. In the expired state, an escrow cannot be finished, and anyone can cancel it. If the escrow does not have a `CancelAfter` field, it never expires and cannot be canceled.

- **Combination Escrow (center):** If the escrow specifies both a crypto-condition (`Condition` field) _and_ a "finish-after" time (`FinishAfter` field), the escrow is **Held** until its finish-after time has passed. Then it becomes **Conditionally Ready**, and can finish it if they supply the correct fulfillment to the crypto-condition. If the escrow has an expiration time (`CancelAfter` field), and no one finishes it before that time passes, then the escrow becomes **Expired**. In the expired state, an escrow cannot be finished, and anyone can cancel it. If the escrow does not have a `CancelAfter` field, it never expires and cannot be canceled.

- **Conditional Escrow (right):** If the escrow specifies a crypto-condition (`Condition` field) and not a finish-after time, the escrow becomes **Conditionally Ready** immediately when it is created. During this time, anyone can finish the escrow, but only if they supply the correct fulfillment to the crypto-condition. If no one finishes the escrow before its expiration time (`CancelAfter` field), the escrow becomes **Expired**. (An escrow without a finish-after time _must_ have an expiration time.) In the expired state, the escrow can no longer be finished, and anyone can cancel it.


## Limitations

- The costs can make it infeasible for small amounts.
Expand All @@ -57,15 +77,17 @@ The diagram shows three different cases for three possible combinations of the e
- You can't create an escrow with past time values.
- Timed releases and expirations resolve according to [ledger close times](../ledgers/ledger-close-times.md). In practice, actual release and expiration times can vary by about five seconds as ledgers close.
- The only supported crypto-condition type is PREIMAGE-SHA-256.
- If a token holder is deep frozen (Trust Line Tokens) or locked (MPTs), they cannot finish an escrow to receive tokens, but they can still cancel an escrow to return tokens to the sender. Individual or global freezes for Trust Line Tokens don't prevent escrow completion.

- For tokens requiring authorization, both sender and recipient must be pre-authorized by the issuer before creating or finishing the escrow, respectively. Authorization cannot be granted during the escrow completion process.

## EscrowFinish Transaction Cost

When using crypto-conditions, the EscrowFinish transaction must pay a [higher transaction cost](../transactions/transaction-cost.md#special-transaction-costs) because of the higher processing load involved in verifying the crypto-condition fulfillment.

The additional transaction cost required is proportional to the size of the fulfillment. If the transaction is [multi-signed](../accounts/multi-signing.md), the cost of multi-signing is added to the cost of the fulfillment.

Currently, an EscrowFinish with a fulfillment requires a minimum transaction cost of **330 [drops of XRP](../../references/protocol/data-types/basic-data-types.md#specifying-currency-amounts)** plus 10 drops per 16 bytes in the size of the fulfillment**.
Currently, an EscrowFinish with a fulfillment requires a minimum transaction cost of **330 [drops of XRP](../../references/protocol/data-types/basic-data-types.md#specifying-currency-amounts)** plus 10 drops per 16 bytes in the size of the fulfillment.

{% admonition type="info" name="Note" %}The above formula is based on the assumption that the reference cost of a transaction is 10 drops of XRP.{% /admonition %}

Expand Down
8 changes: 4 additions & 4 deletions docs/concepts/payment-types/payment-channels.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
---
seo:
description: Payment Channels enable fast, asynchronous payments that can be divided into very small increments and settled later.
description: Payment Channels enable fast, asynchronous XRP payments that can be divided into very small increments and settled later.
labels:
- Payment Channels
- Smart Contracts
---
# Payment Channels

Payment Channels are an advanced feature for sending "asynchronous" payments that can be divided into very small increments and settled later.
Payment Channels are an advanced feature for sending "asynchronous" XRP payments that can be divided into very small increments and settled later.

The XRP or fungible tokens for a payment channel are set aside temporarily. The sender creates _Claims_ against the channel, which the recipient verifies without sending an XRP Ledger transaction or waiting for a new ledger version to be approved by [consensus](../consensus-protocol/index.md). (This is an _asynchronous_ process because it happens separate from the usual pattern of getting transactions approved by consensus.) At any time, the recipient can _redeem_ a Claim to receive an amount of XRP or fungible tokens authorized by that Claim. Settling a Claim like this uses a standard XRP Ledger transaction, as part of the usual consensus process. This single transaction can encompass any number of transactions guaranteed by smaller Claims.
The XRP for a payment channel is set aside temporarily. The sender creates _Claims_ against the channel, which the recipient verifies without sending an XRP Ledger transaction or waiting for a new ledger version to be approved by [consensus](../consensus-protocol/index.md). (This is an _asynchronous_ process because it happens separate from the usual pattern of getting transactions approved by consensus.) At any time, the recipient can _redeem_ a Claim to receive an amount of XRP authorized by that Claim. Settling a Claim like this uses a standard XRP Ledger transaction, as part of the usual consensus process. This single transaction can encompass any number of transactions guaranteed by smaller Claims.

Because Claims can be verified individually but settled in bulk later, payment channels make it possible to conduct transactions at a rate only limited by the participants' ability to create and verify the digital signatures of those Claims. This limit is primarily based on the speed of the participants' hardware and the complexity of the signature algorithms. For maximum speed, use Ed25519 signatures, which are faster than the XRP Ledger's default secp256k1 ECDSA signatures. Research has [demonstrated the ability to create over Ed25519 100,000 signatures per second and to verify over 70,000 per second](https://ed25519.cr.yp.to/ed25519-20110926.pdf) on commodity hardware in 2011.


## Why Use Payment Channels

The process of using a payment channel always involves two parties, a payer and a payee. The payer is an individual person or institution using the XRP Ledger who is a customer of the payee. The payee is a person or business who receives XRP or fungible tokens as payment for goods or services.
The process of using a payment channel always involves two parties, a payer and a payee. The payer is an individual person or institution using the XRP Ledger who is a customer of the payee. The payee is a person or business who receives XRP as payment for goods or services.

Payment Channels do not intrinsically specify anything about what you can buy and sell with them. However, the types of goods and services that are a good fit for payment channels are:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ labels:
- Payment Channels
---
# account_channels
[[Source]](https://github.com/XRPLF/rippled/blob/master/src/ripple/rpc/handlers/AccountChannels.cpp "Source")
[[Source]](https://github.com/XRPLF/rippled/blob/master/src/xrpld/rpc/handlers/AccountChannels.cpp "Source")

The `account_channels` method returns information about an account's Payment Channels. This includes only channels where the specified account is the channel's source, not the destination. (A channel's "source" and "owner" are the same.) All information retrieved is relative to a particular version of the ledger.

Expand Down Expand Up @@ -57,14 +57,11 @@ The request includes the following parameters:
| Field | Type | Required? | Description |
|:----------------------|:---------------------|:----------|-------------|
| `account` | String - [Address][] | Yes | Look up channels where this account is the channel's owner/source. |
| `amount` | Object or String | No | The total amount allocated to this channel. |
| `balance` | Object or String | No | The total amount paid out from this channel, as of the ledger version used. (You can calculate the amount left in the channel by subtracting `balance` from `amount`). |
| `destination_account` | String - [Address][] | No | A second account; if provided, filter results to payment channels whose destination is this account. |
| `ledger_hash` | String | No | The unique hash of the ledger version to use. (See [Specifying Ledgers][]) |
| `ledger_index` | Number or String | No | The [ledger index][] of the ledger to use, or a shortcut string to choose a ledger automatically. (See [Specifying Ledgers][]) |
| `limit` | Number | No | Limit the number of transactions to retrieve. Cannot be less than 10 or more than 400. Positive values outside this range are replaced with the closest valid option. The default is 200. |
| `marker` | [Marker][] | No | Value from a previous paginated response. Resume retrieving data where that response left off. |
| `transfer_rate` | Number | No | The fee to charge when users make claims on a payment channel, initially set on the creation of a payment channel and updated on subsequent funding or claim transactions. |

## Response Format

Expand Down Expand Up @@ -175,8 +172,8 @@ Each Channel Object has the following fields:
| Field | Type | Description |
|:----------------------|:-----------------|:----------------------------------|
| `account` | String | The owner of the channel, as an [Address][]. |
| `amount` | Object or String | The total amount of [XRP, in drops][] or fungible tokens allocated to this channel. |
| `balance` | String | The total amount of [XRP, in drops][] or fungible tokens paid out from this channel, as of the ledger version used. (You can calculate the amount left in the channel by subtracting `balance` from `amount`.) |
| `amount` | String - Number | The total amount of [XRP, in drops][] allocated to this channel. |
| `balance` | String - Number | The total amount of [XRP, in drops][] paid out from this channel, as of the ledger version used. (You can calculate the amount left in the channel by subtracting `balance` from `amount`.) |
| `channel_id` | String | A unique ID for this channel, as a 64-character hexadecimal string. This is also the [ID of the channel object](../../../protocol/ledger-data/ledger-entry-types/paychannel.md#paychannel-id-format) in the ledger's state data. |
| `destination_account` | String | The destination account of the channel, as an [Address][]. Only this account can receive the `amount` in the channel while it is open. |
| `settle_delay` | Unsigned Integer | The number of seconds the payment channel must stay open after the owner of the channel requests to close it. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ The request accepts the following parameters:
| `limit` | Number | No | Limit the number of trust lines to retrieve. The server may return less than the specified limit, even if there are more pages of results. Must be within the inclusive range 10 to 400. Positive values outside this range are replaced with the closest valid option. The default is 200. |
| `marker` | [Marker][] | No | Value from a previous paginated response. Resume retrieving data where that response left off. |
| `peer` | String - [Address][] | No | A second account; if provided, filter results to trust lines connecting the two accounts. |
| `locked_balance` | Object | No | The total amount locked in payment channels or escrow. |
| `lock_count` | Number | No | the total number of lock balances on a RippleState ledger object. |

The following parameters are deprecated and may be removed without further notice: `ledger` and `peer_index`.

Expand Down
Loading