XRP Ledger Standards

XLS-0077
Final
  xls: 77
  title: Deep Freeze
  description: Enhancement to prevent token misuse by frozen account holders and improve regulatory compliance
  author: Shawn Xie 
  discussion-from: https://github.com/XRPLF/XRPL-Standards/discussions/220
  status: Final
  category: Amendment
  created: 2024-07-08

Deep-freeze

Abstract

This amendment empowers token issuers on the XRP Ledger to prevent token misuse by frozen account holders. The document outlines enhancements to the interactions between frozen assets and payments, ensuring that frozen token holders cannot receive funds until or unless their trustline is unfrozen. These changes will enable token issuers to more easily comply with regulations on the XRPL. For example, prevent tokens from flowing to wallets identified on sanctions lists, thereby enhancing regulatory compliance for use cases such as regulated stablecoins and real-world assets (RWA).

1. Overview

This proposal introduces a new deep-freeze feature for the trustlines that interacts with payment, offers, DEX and AMM. In essence, issuers can block sending and receiving of funds for holders who have been deep-frozen.

2. Specification

2.1. Deep-freeze Mechanism

The Deep-freeze feature is a setting on a trust line and requires that the issuer must have "regularly frozen" the trust line before they can enact a deep-freeze. The issuer cannot enact a deep-freeze if they have enabled No Freeze on their account.

When an issuer enacts Deep-freeze, the following rules apply to the tokens in that trust line:

  • Payments can still occur directly between the two parties of the deep-frozen trust line.
  • The counterparty of that trust line can no longer increase or decrease its balance on the deep-frozen trust line, except in direct payments to the issuer. The counterparty can only send the deep-frozen currencies directly to the issuer.
  • The counterparty can neither send nor receive from others on the deep-frozen trustline
  • The counterparty's offers to buy or sell the tokens in the deep-frozen trustline are considered unfunded

An individual address can deep-freeze its trust line to an issuer or financial institution. This has no effect on transactions between the institution and other users. However it does the following:

  • It prevents other addresses from sending that financial institution's tokens to the individual address.
  • It also prevents the individual address from sending the token to other non-issuer addresses.

2.1.1. RippleState Object

Two new flags lsfLowDeepFreeze and lsfHighDeepFreeze are introduced in the RippleState (trustline) object.

Flag Name Flag Value Description
lsfLowDeepFreeze 0x02000000 The low account has deep-frozen the trust line, preventing the high account from sending and receiving the asset.
lsfHighDeepFreeze 0x04000000 The high account has deep-frozen the trust line, preventing the low account from sending and receiving the asset.

2.1.2. TrustSet Transaction

Two new flags tfSetDeepFreeze and tfClearDeepFreeze are introduced in the TrustSet transaction.

Flag Name Flag Value Description
tfSetDeepFreeze 0x00400000 Deep freeze the trust line.
tfClearDeepFreeze 0x00800000 Clear the deep-freeze on the trust line.

The TrustSet transaction trying to set tfSetDeepFreeze will succeed if and only if one of the following is true:

  • The holder is already frozen, indicated by lsfLowFreeze/lsfHighFreeze on the trust line.
  • tfSetFreeze is also set in the same TrustSet transaction.

The TrustSet also introduces an additional restriction:

  • If the trust line is deep-frozen by the issuer (indicated by lsfLowDeepFreeze/lsfHighDeepFreeze), the TrustSet transaction fails if the issuer sets the tfClearFreeze flag without also setting the tfClearDeepFreeze flag. In other words, the issuer cannot clear the regular freeze on a trust line unless they also clear the deep-freeze.

2.2. Payment Engine

Payment engine executes paths that is made of steps to connect the sender to the receiver. In general, funds can be deposited into a trustline through one of two steps:

  • Rippling
  • Order book or AMM

This proposal proposes changes to both steps above to ensure a deep-frozen trustline cannot increase its balance.

2.2.1. Rippling

This proposal suggests an update: the receipt of funds in a deep-frozen trust line as a result of a rippling step will fail.

Example

Let's take a look at an example of how deep-freeze impacts rippling:

+-------+           USD           +---------+           USD           +-------+
| Alice | ----------------------> | Gateway | ----------------------> |  Bob  |
+-------+                         +---------+ (Bob is deep-frozen)    +-------+

Consider the following scenario:

  1. Issuer account issues USD to both Alice and Bob, each of which has a trustline.
  2. Issuer deep-freezes Bob's trustline by submitting a TrustSet with tfSetFreeze and tfSetDeepFreeze flags.
  3. Alice attempts to send a USD Payment to Bob. The transaction fails because Bob's USD trustline has been deep-frozen and can no longer receive funds.

2.2.2. Order Book and AMM

In the payment engine, offers and AMM pools can be consumed in the path when a cross-currency payment is involved, resulting in a change to the trustline balance. This proposal introduces behavior changes to the order book step when trustlines have been deep-frozen.

2.2.2.1. Order Book

This proposal introduces a change to the order book step: if the offer owner has been deep-frozen for the TakerPays token (buy amount), the offer is considered to be unfunded and the step fails.

Example

Let's take a look at an example of how deep-freeze impacts order book:

                                                                 Bob's Offer
+-------+         USD            +---------+        USD       +--------------+      XRP     +-------+
| Alice | ---------------------> | Gateway | ---------------> | Sell: 100 XRP| -----------> | Carol |
+-------+     SendMax: 100 USD   +---------+                  +--------------+              +-------+
              Amount: 100 XRP                                 | Buy: 100 USD |
                                                              +--------------+
                                                            (Bob is deep-frozen)

Consider the following scenario:

  1. Issuer account issues USD to both Alice and Bob, each of which has a trustline.
  2. Issuer deep-freezes Bob's trustline by submitting a TrustSet with tfSetFreeze and tfSetDeepFreeze flags.
  3. Alice attempts to send XRP to Carol through a Payment transaction using Bob's offer to exchange USD for XRP. Alice fails to send XRP to Carol because Bob's offer is unfunded due to the deep-frozen trustline.
2.2.2.2. AMM

The AMM step does not require any changes because, currently, an AMM step fails if the AMM account is frozen for any involved asset. Since a deep-frozen asset would already be regularly frozen, no additional checks are needed when an asset is deep-frozen.

2.3. OfferCreate transaction

This proposal introduces a new change to the OfferCreate transaction:

  • OfferCreate returns tecFROZEN if the TakerPays (buy amount) token has been deep-frozen by the issuer

Moreover, any existing offers where the owner has been deep-frozen on the TakerPays token can no longer be consumed and will be considered as an unfunded offer that will be implicitly cancelled by new Offers that cross it.

2.4. AMMWithdraw transaction

This proposal does not need to change the AMMWithdraw transaction due to the deep-freeze, as all deep-frozen tokens have already been regularly frozen, preventing the withdrawal of either regularly frozen or deep-frozen tokens.

3. Invariants

Possible invariants:

  • Disallowing any increase in the balance of an deep-frozen trustline as a result of any type of transaction.
  • A trust line cannot have the lsfLowDeepFreeze flag set without also having the lsfLowFreeze flag set, and the same applies to the lsfHighDeepFreeze flag.

4. FAQ

Why can't we embed the disallow-receiving into the existing freeze without introducing a new flag?

Altering the existing freeze functionality to disallow receiving would be a significant breaking change, potentially disrupting the workflows of current users. Instead, it is preferable to introduce a configurable flag, offering additional flexibility without affecting the existing behavior.

Why can't this be a separate feature named "block-receiving"?

The block-receiving feature shares similarities with the existing freeze functionality, as both aim to prevent unauthorized or blacklisted parties from transferring funds. Creating it as a separate feature would introduce unnecessary complexities, such as the need to add a new account-level flag to toggle the feature. Integrating it into the existing framework avoids these complications while maintaining consistency.

How does MPT freeze/lock behavior differ from IOU?

The MPT freeze/lock functionality differs somewhat from how IOUs work today. When an MPT holder is locked, they cannot send or receive MPT payments, so a single flag is sufficient. In contrast, for IOUs, the regular freeze only disallows sending. If the issuer wants to block receiving as well, they must apply a deep-freeze.

Originally posted by @shawnxie999 in https://github.com/XRPLF/XRPL-Standards/discussions/220