|
1 | | -<pre> |
2 | | -Title: <b>Pseudo-Account</b> |
3 | | -Type: <b>draft</b> |
4 | | -Revision: <b>1</b> (2025-03-04) |
| 1 | +<pre> |
| 2 | +xls: 64 |
| 3 | +title: Pseudo-Account |
| 4 | +description: A standard for a "pseudo-account" AccountRoot object to be associated with one or more ledger entries. |
| 5 | +author: Vito Tumas (@Tapanito) |
| 6 | +status: Draft |
| 7 | +category: Ammendment |
| 8 | +created: 2025-03-04 |
| 9 | +updated: 2025-08-29 |
| 10 | +</pre> |
5 | 11 |
|
6 | | -<hr> Authors: |
7 | | - <a href="mailto:vtumas@ripple.com">Vytautas Vito Tumas</a> |
| 12 | +### Abstract |
8 | 13 |
|
9 | | -Affiliation: |
10 | | - <a href="https://ripple.com">Ripple</a> |
11 | | -</pre> |
| 14 | +This document proposes a standard for a *pseudo-account*, an `AccountRoot` ledger entry that can be associated with one or more other ledger entries. A pseudo-account is designed to hold and/or issue assets on behalf of its associated entries, enabling protocol-level functionality that requires an on-ledger entity to manage funds. |
| 15 | + |
| 16 | +### Motivation |
| 17 | + |
| 18 | +The XRP Ledger is an account-based system where assets (XRP, IOUs, etc.) can only be held by an `AccountRoot` entry. However, several advanced protocols, such as Automated Market Makers (AMMs), lending pools, and vaults, require a ledger *object* itself to hold and manage assets. |
| 19 | + |
| 20 | +The [XLS-30 (AMM)](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0030-automated-market-maker#readme) specification pioneered this concept by introducing a pseudo-account linked to each `AMM` instance. This allows the AMM to track its token balances and issue Liquidity Provider Tokens (`LPTokens`). |
| 21 | + |
| 22 | +This specification formalizes and standardizes the requirements for an `AccountRoot` when it functions as a pseudo-account, ensuring a consistent and secure implementation across different protocols. It defines mandatory flags, a naming convention for linking fields, and the core invariants that any protocol using a pseudo-account must enforce. |
| 23 | + |
| 24 | +### Specification |
| 25 | + |
| 26 | +#### Ledger Entries |
12 | 27 |
|
13 | | -# Pseudo-Account |
| 28 | +This specification defines a set of mandatory properties and fields for an `AccountRoot` ledger entry when it is used as a pseudo-account. |
14 | 29 |
|
15 | | -## _Abstract_ |
| 30 | +##### **`AccountRoot`** |
16 | 31 |
|
17 | | -In this document, we propose a standard for a _pseudo-account_, an `AccountRoot` object that can be associated with one or more other ledger entries to hold and/or issue assets on behalf of the associated entries. |
| 32 | +###### **Object Identifier** |
18 | 33 |
|
19 | | -## 1. Introduction |
| 34 | +The address of the pseudo-account's `AccountRoot` must be derived deterministically and be difficult to predict before creation. This prevents malicious actors from front-running the creation transaction by pre-funding the address. The protocol creating the `AccountRoot` must ensure the derived address is unoccupied. |
20 | 35 |
|
21 | | -The XRP Ledger is an account-based blockchain in which assets—such as XRP, IOUs, or MPT—can only be held by an account represented by an `AccountRoot` ledger entry. However, certain use cases, such as Automated Market Makers (AMM), Single Asset Vaults, and the Lending Protocol—require assets to be transferable to and from an object. |
| 36 | +A nonce-based approach is used to generate the unique `AccountRoot` ID: |
22 | 37 |
|
23 | | -The [XLS-30](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0030-automated-market-maker#readme) specification introduced the `AMMID` field in the `AccountRoot` ledger entry. This field associates a _pseudo-account_ with an `AMM` instance, allowing it to track XRP and token balances in the pool and issue `LPTokens` on behalf of the `AMM` instance. |
| 38 | +1. Initialize a nonce, $i$, to $0$. |
| 39 | +2. Compute a candidate ID: `AccountID` = `SHA512-Half`($i$ || `ParentLedgerHash` || `<ObjectID>`). |
| 40 | +3. Check if an `AccountRoot` with this `AccountID` already exists on the ledger. |
| 41 | +4. If it exists, increment the nonce $i$ and repeat from step 2. |
| 42 | +5. If it does not exist, the computed `AccountID` is used for the new pseudo-account. |
24 | 43 |
|
25 | | -This specification formalises the requirements for an `AccountRoot` when used as a _pseudo-account_. Specifically, it defines: |
| 44 | +###### **Fields** |
26 | 45 |
|
27 | | -- A set of flags that must be enabled. |
28 | | -- A naming convention for the field identifying the object the `AccountRoot` is associated with. |
29 | | -- Minimum requirements for any protocol implementing a _pseudo-account_. |
| 46 | +| Field Name | Constant | Required | Internal Type | Default Value | Description | |
| 47 | +| :--- | :---: | :---: | :---: | :---: | :--- | |
| 48 | +| `<Object>ID` | Yes | Yes | `HASH256` | N/A | The unique identifier of the ledger object this pseudo-account is associated with. | |
| 49 | +| `Flags` | Yes | Yes | `UINT32` | N/A | A set of flags that must be set for a pseudo-account. | |
| 50 | +| `Sequence` | Yes | Yes | `UINT32` | `0` | The sequence number, which must be `0`. | |
| 51 | +| `RegularKey` | Yes | No | `ACCOUNT` | N/A | A regular key, which must not be set for a pseudo-account. | |
30 | 52 |
|
31 | | -## 2. Ledger Entries |
| 53 | +A detailed description of these fields follows: |
32 | 54 |
|
33 | | -### 2.1. `AccountRoot` Ledger Entry |
| 55 | +**`<Object>ID`** |
34 | 56 |
|
35 | | -#### 2.1.1. Object Identifier |
| 57 | +This field links the pseudo-account to its parent ledger object. Any protocol introducing a pseudo-account must define a new, optional field on the `AccountRoot` object to store this ID. The field name must follow this convention: |
36 | 58 |
|
37 | | -The address of the `AccountRoot` must be randomised to prevent users from identifying and funding the address before its creation. The protocol that creates an `AccountRoot` must ensure the account address is unoccupied. |
| 59 | +* `<Object>` is the name of the associated ledger object (e.g., `AMM`, `Vault`). Names that are acronyms should be fully capitalized (`AMMID`). Otherwise, use PascalCase (`VaultID`). |
| 60 | +* The suffix `ID` must always be appended. |
38 | 61 |
|
39 | | -The unique ID of the **`AccountRoot`** object, a.k.a. **`AccountRootID`** is computed as follows: |
| 62 | +**`Flags`** |
40 | 63 |
|
41 | | -- for (i = 0; i <= 256; i--) |
42 | | - - Compute `AccountRootID` = `SHA512-Half`(i || [Parent Ledger Hash](https://xrpl.org/ledgerhashes.html) || `<Object>ID>`) |
43 | | - - If the computed `AccountRootID` exists, repeat |
44 | | - - else, return `AccountRootID` |
| 64 | +The following flags must be set on a pseudo-account's `AccountRoot` and must be immutable: |
45 | 65 |
|
46 | | -#### 2.1.2. Fields |
| 66 | +| Flag Name | Hex Value | Description | |
| 67 | +| :--- | :---: | :--- | |
| 68 | +| `lsfDisableMaster` | `0x00040000` | Disables the master key pair, ensuring no entity can sign transactions directly for this account. Control is ceded entirely to protocol rules. | |
| 69 | +| `lsfDepositAuth` | `0x01000000` | Requires authorization for deposits, typically meaning that funds can only be sent to this account via specific protocol transactions rather than standard `Payment` transactions. | |
47 | 70 |
|
48 | | -| Field Name | Modifiable? | Required? | JSON Type | Internal Type | Default Value | Description | |
49 | | -| ------------ | :---------: | :-------: | :-------: | :-----------: | :-----------: | :---------------------------------------------------------------------------------------------------------- | |
50 | | -| `<Object>ID` | `N/A` | `no` | `string` | `HASH256` | `N/A` | The object identifier the `pseudo-account` is associated with. | |
51 | | -| `Flags` | `no` | `yes` | `number` | `UINT32` | `N/A` | A set of flags that must be set for a `pseudo-account`. | |
52 | | -| `Sequence` | `no` | `yes` | `number` | `UINT32` | `0` | The sequence number of the `pseudo-account`. | |
53 | | -| `RegularKey` | `no` | `yes` | `string` | `ACCOUNTID` | `N/A` | The address of a key pair that can be used to sign transactions for this account instead of the master key. | |
| 71 | +**`Sequence`** |
54 | 72 |
|
55 | | -##### 2.1.2.1. `<Object>ID` |
| 73 | +The `Sequence` number of a pseudo-account must be initialized to `0` and must not be changed. This, combined with the disabled master key, prevents the account from ever submitting a transaction on its own behalf. |
56 | 74 |
|
57 | | -The `<Object>ID` field uniquely identifies the ledger entry associated with an account. Any protocol introducing a `pseudo-account` must include a new, optional `<Object>ID` field. |
| 75 | +**`RegularKey`** |
58 | 76 |
|
59 | | -The naming convention for this field follows these rules: |
| 77 | +A `RegularKey` must not be set on a pseudo-account. |
60 | 78 |
|
61 | | -- `<Object>` represents the name of the related object: |
62 | | - - All letters must be capitalised if the name is an acronym (e.g., `AMM`). |
63 | | - - Otherwise, capitalise the first letter of each noun (e.g., `Vault` or `LoanBroker`). |
64 | | -- `ID` must always be appended as a suffix. |
| 79 | +###### **Reserves** |
65 | 80 |
|
66 | | -##### 2.1.2.2. `Flags` |
| 81 | +The cost of creating a pseudo-account depends on whether it is owned and controlled by another account. |
67 | 82 |
|
68 | | -The following flags must be set for a `pseudo-account`: |
| 83 | +* **Owned Pseudo-Accounts:** For objects like a `Vault` where a single account owns and controls the associated pseudo-account, the transaction must increase the owner's XRP reserve by one increment. This is in addition to any other reserve requirements of the transaction (e.g., for the `Vault` object itself). The transaction fee is the standard network fee. |
69 | 84 |
|
70 | | -| Flag Name | Flag Value | Modifiable? | Description | |
71 | | -| ------------------ | :--------: | :---------: | :---------------------------------------------------------------------------------------: | |
72 | | -| `lsfDisableMaster` | `0x01` | `No` | Ensure that no one can control the account directly and send transactions on its behalf. | |
73 | | -| `lsfDepositAuth` | `0x001` | `No` | Ensure that the only way to add funds to the account is by using a `deposit` transaction. | |
| 85 | +* **Unowned Pseudo-Accounts:** For objects like an `AMM` that are not owned by any account, the creation transaction must charge a special, higher-than-normal transaction fee. This fee must be at least the value of one incremental owner reserve (currently **2 XRP**, subject to change via Fee Voting). This amount is burned, compensating for the permanent ledger space without tying the reserve to a specific owner. |
74 | 86 |
|
| 87 | +###### **Deletion** |
75 | 88 |
|
| 89 | +A pseudo-account must be deleted together with the associated object. |
76 | 90 |
|
77 | | -##### 2.1.2.3. `Sequence` |
78 | | -The `Sequence` number of a` _pseudo-account_` **must** be `0`. A _pseudo-account_ cannot submit valid transactions. |
| 91 | +###### **Invariants** |
79 | 92 |
|
80 | | -##### 2.1.2.4. `RegularKey` |
81 | | -A _pseudo-account_ **must not** have a `RegularKey` set. |
| 93 | +The following invariants must hold true for any `AccountRoot` entry functioning as a pseudo-account: |
82 | 94 |
|
83 | | -#### 2.1.3. Cost |
| 95 | +* The ledger object identified by the `<Object>ID` field must exist. |
| 96 | +* Exactly one `<Object>ID` field must be present on the `AccountRoot` (e.g., an account cannot be linked to both an `AMMID` and a `VaultID`). |
| 97 | +* The `lsfDisableMaster` and `lsfDepositAuth` flags must always be set. |
| 98 | +* The `Sequence` number must always be `0`. |
| 99 | +* A `RegularKey` must not be set. |
84 | 100 |
|
85 | | -A transaction that creates a `pseudo-account` must incur a higher-than-usual transaction fee to deter ledger spam. Additionally, the transaction must destroy at least the incremental owner reserve amount, currently `2 XRP`. |
| 101 | +### Security Considerations |
86 | 102 |
|
87 | | -#### 2.1.4. Invariant |
| 103 | +The design of pseudo-accounts includes several critical security features: |
88 | 104 |
|
89 | | -The following invariants **must** hold for a _pseudo-account_: |
90 | | -- The object identified by `<Object>ID` **must** exist on the ledger. |
91 | | -- Exactly one `<Object>ID` **must** be set (e.g., a _pseudo-account_ cannot have both `AMMID` and `VaultID` at the same time). |
92 | | -- The `lsfDepositAuth` and `lsfDisableMaster` flags **must** be set. |
93 | | -- The `Sequence` number **must** be `0`. |
94 | | -- The `RegularKey` **must not** be set. |
| 105 | +* **No Direct Control:** The mandatory `lsfDisableMaster` flag and the absence of a `RegularKey` ensure that no user can directly control the pseudo-account or its assets. All fund movements are governed exclusively by the rules of the associated protocol. |
| 106 | +* **Transaction Prevention:** A `Sequence` of `0` makes it impossible for the account to submit transactions, preventing any misuse of the account itself. |
| 107 | +* **Address Front-running Prevention:** The deterministic but unpredictable method for generating the account address prevents attackers from guessing the address and sending funds to it before it is officially created by the protocol. |
| 108 | +* **Controlled Deposits:** The `lsfDepositAuth` flag prevents arbitrary `Payment` transactions from being sent to the account, ensuring that its balances can only be modified through legitimate protocol transactions. |
0 commit comments