docs: Add global Vault ledger entry invariants (3.1.10) - #555
Conversation
…tion - Add Example JSON sections for Vault ledger entry and all transactions (VaultCreate, VaultSet, VaultDelete, VaultDeposit, VaultWithdraw, VaultClawback, Payment) with real transaction data - Add invariants for the Vault ledger entry (universal checks) and all transaction types derived from the ValidVault invariant checker - Restructure section 10 from "API" to "RPC: vault_info" matching the amendment template format with Request Fields, Response Fields, Failure Conditions, Example Request, and Example Response subsections - Update response fields table with missing fields (Data, Asset.mpt_issuance_id, shares.DomainID, shares.MPTokenMetadata) and correct Always Present values - Update response examples to use proper JSON format with response envelope - Add section 9.1 Fields for Payment transaction - Remove Index section and all Return to Index links Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Reorganize top-level sections: Abstract (1), Introduction (2), Specification (3), Rationale (4), Security Considerations (5), Appendix - Move all ledger entry, transaction, and RPC sections under "3. Specification" as subsections (3.1-3.9) - Remove "1.1 Overview" heading, merge content into Introduction body - Renumber Introduction subsections: Terminology (2.1), Actors (2.2), Connecting to the Vault (2.3) - Demote all specification headings by one level with new numbering - Add Rationale section explaining decoupled vault design - Rename FAQ section to "Appendix A: FAQ" with A.x numbering - Fix heading levels for Key Variables and Vault State Update Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove functional additions (invariants, example JSONs, error codes) added in this branch and retain only structural changes that bring the spec into conformance with AMENDMENT_TEMPLATE.md and XLS_TEMPLATE.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Convert failure conditions and state changes from numbered lists back to master's original nested bullet-point format. Keep the Data Verification / Protocol-Level Failures subsection headers as template compliance, but use master's original content and structure inside them. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Convert bullet points in Failure Conditions and State Changes sections to numbered lists with nested sub-numbering, per template requirements. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Mayukha Vadari <mvadari@gmail.com>
…-invariants # Conflicts: # XLS-0065-single-asset-vault/README.md
tyalymov
left a comment
There was a problem hiding this comment.
As written, Invariant 11 and Invariant 12 contradict each other. Invariant 12 says a Vault is modified only by vault transaction types, but Invariant 11 says LossUnrealized is modified by lending protocol transactions, and LossUnrealized is a field on the Vault. So a lending transaction that updates it (LoanManage on impair/unimpair/default) violates Invariant 12.
The code actually matches Invariant 11, not Invariant 12. VaultInvariant.cpp (finalize) gates vault modification on the MustModifyVault / MayModifyVault privileges, not on "vault transaction types." Lending transactions hold those privileges too: LoanManage has MayModifyVault, and LoanSet / LoanPay have MustModifyVault. That privilege is what lets LoanManage write Vault.LossUnrealized.
Could we reword Invariant 12 to match, along the lines of: a Vault is modified only by transactions authorized to modify it (the vault transactions, plus lending transactions holding MayModifyVault / MustModifyVault)? That also removes the conflict with Invariant 11.
Summary
VaultInvariant.cpp(visitEntry+ universal checks infinalize).Invariants added
Vault.AssetsAvailable >= 0Vault.AssetsTotal >= 0Vault.AssetsMaximum >= 0Vault.AssetsAvailable <= Vault.AssetsTotalVault.LossUnrealized <= (Vault.AssetsTotal - Vault.AssetsAvailable)OutstandingAmount == 0:AssetsTotal == 0andAssetsAvailable == 0AssetsMaximum > 0:AssetsTotal <= AssetsMaximumMPTokenIssuance(Vault.ShareMPTID).Issuer == Vault.AccountAccountRoot(Vault.Account)is a pseudo-account withVaultIDpointing hereAsset,Account,ShareMPTIDare immutableLossUnrealizedmodified only by lending protocol transactionsVaultis modified only by vault tx types; at most one per transactionSource
src/libxrpl/tx/invariants/VaultInvariant.cpp— universal checks block infinalize().