Skip to content
Open
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5480349
adds cash-based share valuation
Tapanito Jul 16, 2026
ec48162
adds Vault version
Tapanito Jul 21, 2026
8edeab3
update the spec to not skip SLEVersion 1
Tapanito Jul 22, 2026
4a1b926
Merge branch 'master' into tapanito/lending-cash-basis
Tapanito Jul 23, 2026
50abc3b
docs: align cash-basis Vault/LoanBroker text with develop
Tapanito Sep 4, 2026
bf4ee3e
docs: restate XLS-65.1 and XLS-66.1 patches in XLS template format
Tapanito Sep 4, 2026
87a5819
docs: address PR 582 review comments
Tapanito Sep 4, 2026
ece0e37
docs(XLS-65.1): treat absent LEVersion as 0
Tapanito Sep 4, 2026
118f612
docs: align cash-basis patches with develop accounting
Tapanito Sep 4, 2026
f485760
Merge remote-tracking branch 'origin/master' into tapanito/lending-ca…
Tapanito Sep 4, 2026
0632fff
docs: number the Amendments section as an Introduction subsection
Tapanito Sep 4, 2026
1d0f16d
docs: consolidate the LendingProtocolV1_1 patches into one document p…
Tapanito Sep 4, 2026
e5db49c
Merge remote-tracking branch 'origin/master' into tapanito/lending-ca…
Tapanito Sep 7, 2026
215f13a
docs: restore cash-basis LoanBroker and LoanManage details
Tapanito Sep 7, 2026
df735b0
docs: match Vault Constant column and LoanSet phase checks
Tapanito Sep 7, 2026
07ae495
docs: correct valueChange scope and cross-ref VaultKind to XLS-65.1
Tapanito Sep 8, 2026
7819e26
Merge origin/master into tapanito/lending-cash-basis
Tapanito Sep 8, 2026
64b6528
Merge origin/master into tapanito/lending-cash-basis
Tapanito Sep 8, 2026
19a240a
docs(XLS-66): leave closed-ended lending rules to XLS draft
Tapanito Sep 9, 2026
40201e9
docs: format cash-basis patches and inline amendment behaviour
Tapanito Sep 9, 2026
0c8d45c
docs: scope LEVersion immutability and label the Vault excerpt
Tapanito Sep 9, 2026
bb136b8
docs: make DefaultAmount principal-only for cash-basis Vaults in form…
Tapanito Sep 9, 2026
edce470
docs: note that formula 34 is principal-only when LEVersion is 1
Tapanito Sep 9, 2026
4c2a50a
docs: point closed-ended LendingProtocolV1_1 checks at PR 587
Tapanito Sep 9, 2026
85be555
docs: add CoverAvailable to formula 35 and vault_info LEVersion
Tapanito Sep 9, 2026
58a3ea8
Merge remote-tracking branch 'origin/master' into tapanito/lending-ca…
Tapanito Sep 9, 2026
f2219ad
style: apply prettier to vault and lending specs
Tapanito Sep 9, 2026
fe59dfc
docs: drop patch-title prefixes and name parent amendments
Tapanito Sep 9, 2026
c0847b9
Merge remote-tracking branch 'origin/master' into tapanito/lending-ca…
Tapanito Sep 11, 2026
8e22494
docs: state origination InterestDue recognition and patch-over-parent…
Tapanito Sep 11, 2026
80dbd85
Merge branch 'master' into tapanito/lending-cash-basis
Tapanito Sep 14, 2026
8a68652
docs(XLS-65): gate the VaultSet cap invariant on fixCleanup3_4_0
Tapanito Sep 14, 2026
9542a81
Merge origin/master and number cash-basis as XLS-65.1.3
Tapanito Sep 14, 2026
34f8b77
docs: fix DebtTotal valueChange, AssetsMaximum cap, and 66.1 requires
Tapanito Sep 15, 2026
7840c9b
docs: match VaultCreate AssetsMaximum to the deposit cap
Tapanito Sep 15, 2026
4d3ae67
docs(XLS-65): split LoanSet cap invariant for cash-basis Vaults
Tapanito Sep 15, 2026
90d9c00
docs(XLS-66): bump updated date and label legacy accounting examples
Tapanito Sep 15, 2026
c7f12a4
docs(XLS-66): label first-loss default example as legacy
Tapanito Sep 15, 2026
375a7b0
docs(XLS-66): gate remaining valueChange prose to legacy Vaults
Tapanito Sep 15, 2026
3c259da
docs: call legacy Vault accounting instant interest recognition
Tapanito Sep 16, 2026
08873e0
Move cash-basis accounting into 65.1.3 and 66.1.1 patches
Tapanito Oct 1, 2026
a3f9aa8
Merge remote-tracking branch 'origin/master' into HEAD
Tapanito Oct 13, 2026
5f81ed4
docs(XLS-66.1.1): keep parent LoanSet check numbers, add test plan, p…
Tapanito Oct 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions XLS-0065-single-asset-vault/65.1/65.1.3-vault-cash-basis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<pre>
xls: 65.1.3
title: Single Asset Vault Cash-Basis Accounting
description: Introduces Cash-Basis accounting for the Single Asset Vault
author: Vytautas Vito Tumas <vtumas@ripple.com>
proposal-from: https://github.com/XRPLF/XRPL-Standards/discussions/192
status: Draft
category: Amendment
created: 2026-09-04
updated: 2026-09-14
</pre>

# 65.1.3 Single Asset Vault Cash-Basis Accounting

## 1. Abstract

Under the `LendingProtocolV1_1` amendment, a Single Asset Vault accounts for the interest earned by its Loans on a cash basis. `AssetsTotal` counts interest only once a Borrower has paid it, rather than counting the interest a Loan is expected to earn from the moment the Loan is issued. The share exchange rate of the Vault therefore tracks the assets the Vault holds instead of the income it is owed, and a Borrower who stops paying costs the Vault only the principal it lent out. A Vault created before the amendment keeps instant interest recognition, in which `LoanSet` immediately adds all expected net `InterestDue` to `AssetsTotal` at origination (XLS-66 §3.8.6), because changing the accounting model of an existing Vault would change the value of the shares it has already issued. Which model a Vault uses is recorded in its `LEVersion` field and fixed when the Vault is created.

## 2. Motivation

Instant interest recognition credits a Vault with interest that a Borrower has not paid yet, so the share exchange rate reflects income the Vault has not received. A depositor can redeem shares at a rate inflated by interest that later defaults, and the loss falls on the depositors who remain. Cash-basis accounting removes that mismatch by recognising interest only when it is paid.

Existing Vaults cannot switch accounting models without changing the value of shares already issued, so the model has to be recorded per Vault rather than derived from the amendment state at the time of the transaction.

## 3. Specification

### 3.1 Ledger Entry: `Vault`

#### 3.1.1 Fields

| Field Name | Constant | Required | Internal Type | Default Value | Description |
| ----------- | :------: | :------: | :-----------: | :-----------: | ------------------------------------------------------------------------------------------------------------------------------------- |
| `LEVersion` | Yes | No | `UINT8` | absent (`0`) | The accounting model the Vault applies to `AssetsTotal`. Absent is treated as `0` (instant interest recognition). Immutable once set. |

#### 3.1.2 `LEVersion`

`LEVersion` selects the accounting model of the Vault:

- `LEVersion` absent (treated as `0`, instant interest recognition): `AssetsTotal` includes the full expected net `InterestDue` booked at origination. This is the pre-amendment behaviour and continues to apply to every Vault created before the amendment was enabled.
- `LEVersion = 1` (cash basis): `AssetsTotal` excludes uncollected interest and increases only as interest is collected in cash.

The field is written once by `VaultCreate` and is immutable after creation. A Vault created while the amendment is enabled is always cash-basis, and a Vault created before it always uses instant interest recognition; neither can be converted to the other.

#### 3.1.3 Invariants

- On an update to an existing Vault: `Vault.LEVersion == Vault'.LEVersion`. Immutability of `LEVersion` is specified in [65.1.1 Unmodifiable Vault Fields](./65.1.1-unmodifiable-vault-fields.md).

#### 3.1.4 Partial Ledger Entry Example

The following excerpt shows the accounting fields introduced or affected by this patch; it is not a complete serialized `Vault` ledger entry:

```json
{
"LedgerEntryType": "Vault",
"LEVersion": 1,
"Asset": {
"currency": "USD",
"issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn"
},
"AssetsTotal": "1000",
"AssetsAvailable": "1000"
}
```

### 3.2 Transaction: `VaultCreate`

#### 3.2.1 Failure Conditions

No failure conditions related to cash-basis accounting are added or removed. `LEVersion` is not a transaction field and cannot be supplied by the submitter.

#### 3.2.2 State Changes

1. Create a new `Vault` ledger object, setting `Vault.LEVersion = 1`.

## 4. Rationale

The alternative to a per-entry version field is to derive the accounting model from the amendment state at the time each Loan transaction executes. That was rejected because it would silently change the share exchange rate of every existing Vault on the ledger at the moment the amendment activates.

`LEVersion` is a version number rather than a boolean flag so that a later accounting change can be expressed as a further version without another field.

## 5. Security Considerations

Cash-basis accounting reduces, but does not remove, the exposure of a depositor to an unpaid Loan: the Vault still carries the principal at face value until the Loan defaults or is impaired. `LossUnrealized` remains the mechanism for reporting an expected shortfall.

Because `LEVersion` is immutable, an implementation must read it from the `Vault` ledger entry rather than from the amendment state when computing the interest accounting of a Loan. Reading the amendment state instead would apply cash-basis rules to Vaults that use instant interest recognition and misprice their shares.
Comment thread
mvadari marked this conversation as resolved.
9 changes: 5 additions & 4 deletions XLS-0065-single-asset-vault/65.1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ This index groups the Vault changes introduced by the `LendingProtocolV1_1` amen

These specifications are introduced by the `LendingProtocolV1_1` amendment:

| Spec | Description |
| ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| [65.1.1 Unmodifiable Vault Fields](./65.1.1-unmodifiable-vault-fields.md) | Makes `Sequence`, `OwnerNode`, `Owner`, `WithdrawalPolicy`, `Scale` and `LEVersion` immutable on the Vault once set. |
| [65.1.2 Vault Deletion Memo](./65.1.2-vault-deletion-memo.md) | Adds an optional `MemoData` field to `VaultDelete` that, if present, must be 1–256 bytes. |
| Spec | Description |
| ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| [65.1.1 Unmodifiable Vault Fields](./65.1.1-unmodifiable-vault-fields.md) | Makes `Sequence`, `OwnerNode`, `Owner`, `WithdrawalPolicy`, `Scale` and `LEVersion` immutable on the Vault once set. |
| [65.1.2 Vault Deletion Memo](./65.1.2-vault-deletion-memo.md) | Adds an optional `MemoData` field to `VaultDelete` that, if present, must be 1–256 bytes. |
| [65.1.3 Single Asset Vault Cash-Basis Accounting](./65.1.3-vault-cash-basis.md) | Records the accounting model in `LEVersion` so `AssetsTotal` counts interest only when a Borrower pays it. |

## 3. Rationale

Expand Down
Loading