Skip to content

spec(XLS-65): Update VaultWithdraw failure conditions and state changes - #553

Open
Tapanito wants to merge 36 commits into
masterfrom
tapanito/spec-vault-withdraw
Open

spec(XLS-65): Update VaultWithdraw failure conditions and state changes#553
Tapanito wants to merge 36 commits into
masterfrom
tapanito/spec-vault-withdraw

Conversation

@Tapanito

Copy link
Copy Markdown
Collaborator

Syncs the VaultWithdraw spec section with the current implementation in src/libxrpl/tx/transactors/vault/VaultWithdraw.cpp.

Data Verification (3.6.2.1) — was _None._, now has three items:

  • VaultID = 0 (temMALFORMED)
  • Amount ≤ 0 (temBAD_AMOUNT)
  • Destination = 0 (temMALFORMED)

Protocol-Level Failures (3.6.2.2) — reworked:

  • Removed MPT non-transferable check: post-fixCleanup3_2_0, VaultWithdraw waives lsfMPTCanTransfer (recovery path allowing withdrawal even when issuer revokes transferability)
  • Added: vault shares frozen/locked for submitter (tecFROZEN / tecLOCKED)
  • Added: destination lacks required authorization (tecNO_AUTH)
  • Added: destination account conditions (tecNO_DST, tecDST_TAG_NEEDED, tecNO_PERMISSION)
  • Added: computed share amount is zero (tecPRECISION_LOSS)
  • Added: arithmetic overflow (tecPATH_DRY)
  • Added error codes to all items

State Changes (3.6.3) — corrected:

  • Fixed terminology throughout: "depositor" → "submitter" / "destination"
  • Added: share MPToken is deleted when balance reaches zero (for non-owners)
  • Clarified that "destination" is Destination if provided, otherwise Account
  • Reordered to match code execution order

Tapanito and others added 30 commits February 11, 2026 15:15
…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>
Base automatically changed from tapanito/vault-enhanced to master May 28, 2026 15:12
An error occurred while trying to automatically change base from tapanito/vault-enhanced to master May 28, 2026 15:12
…-withdraw

# Conflicts:
#	XLS-0065-single-asset-vault/README.md

@tyalymov tyalymov left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The definition changed from Vault.AssetsTotal to the total assets in the vault, including any future yield.

Two things I'd check:

  1. What field or formula is "future yield"? The withdrawal conversion in the code uses Vault.AssetsTotal - Vault.LossUnrealized with no yield term anywhere.
  2. The rest of 3.6 uses concrete fields: State Changes and invariant 3.6.4 reconcile Vault.AssetsTotal, and the liquidity check uses Vault.AssetsAvailable. If Gamma_asset is a larger, yield-inclusive value, the conversion rate and the accounting no longer share a base, which could over-value shares on withdrawal.
    Could we bind Gamma_asset to a concrete field , or spell out what "future yield" refers to?

Redefine Gamma_asset as Vault.AssetsTotal - Vault.LossUnrealized,
matching the conversion base actually used in
assetsToSharesWithdraw/sharesToAssetsWithdraw, instead of the
undefined "including any future yield" wording. Note the
sole-shareholder waiver exception (fixCleanup3_2_0).

Addresses review feedback on PR #553.
@Tapanito

Copy link
Copy Markdown
Collaborator Author

You're right — checked VaultHelpers.cpp: the withdraw conversion base is Vault.AssetsTotal - Vault.LossUnrealized (the ι term already used elsewhere in section 2.1.7), not a yield-inclusive figure. There's one wrinkle: when the withdrawer is the sole shareholder, the LossUnrealized subtraction is waived (they own 100% of both realized and unrealized value, so no proportional haircut applies). Rebound Γ_asset to Vault.AssetsTotal - Vault.LossUnrealized, noted the sole-shareholder waiver, and dropped "including any future yield" — it didn't correspond to anything in the implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants