Skip to content

feat: Introduce early-exit fee for closed-ended vaults - #638

Open
a1q123456 wants to merge 30 commits into
XRPLF:masterfrom
a1q123456:a1q123456/early-exit-fee
Open

a1q123456 wants to merge 30 commits into
XRPLF:masterfrom
a1q123456:a1q123456/early-exit-fee

Conversation

@a1q123456

@a1q123456 a1q123456 commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

High Level Overview of Change

Adds XLS-65.3: Closed-Ended Vault Early-Exit Fee, a patch specification under XLS-65 gated on a new LendingProtocolV1_2 amendment.

A closed-ended Vault may be created with one optional field, EarlyExitFeeRate (UINT32, 1/10th basis points, capped at 100000 = 100%). When the field is absent, the Vault behaves exactly as today. When the field is 0, early-exit is permitted free of charge. When the field is above 0, a VaultWithdraw is permitted during Investment and charged that rate. Shares are burned against the pre-fee amount while only the post-fee amount leaves the Vault, so the fee is an amount not withdrawn rather than an amount transferred: no new accounting field and no distribution step. The only invariant change is that parent VaultWithdraw invariants 1 and 2 are relaxed to admit a zero payout when the fee consumes the whole amount (65.3 section 3.4.3). The retained difference accrues to the remaining shareholders through the existing exchange-rate arithmetic. No owner or broker action can capture it, though an owner who holds shares benefits pro rata like any other remaining holder.

Context of Change

Partner validation: brokers already operate early-withdrawal penalties and want the option to let a depositor exit before RedemptionDate. The closed-ended Vault as specified admits no exceptions at any price, and an operator willing to offer one on terms that do not penalise the depositors who stay has no way to express it.

Scoped as a strictly additive, opt-in patch rather than a change to the lifecycle. An owner who sets no rate gets today's behaviour exactly; the entry side is untouched, with VaultDeposit still blocked for the whole Investment phase, and SubscriptionDate / RedemptionDate semantics unchanged. The exit remains best-efforts against Vault.AssetsAvailable — not a redemption right, and a Vault with its capital fully deployed rejects every exit with a positive post-fee payout (Security Considerations).

Two amendments are hard prerequisites: LendingProtocolV1_1 (XLS-65.1.4, the closed-ended Vault proposal #587), which introduces the Investment-phase withdrawal gate this patch conditionally lifts, and fixCleanup3_4_0 (XLS-65.2), which defines the posterior scale the fee is computed at. The rate convention is reused from XLS-66 LoanBroker.ManagementFeeRate (3.2.1). Reference implementation is TBD.

Also updates XLS-65 section 2.8 and Appendix B to index the new patch, and XLS-65.1.1 to note that 65.3 adds EarlyExitFeeRate to the immutable-field invariant.

Type of Change

  • New XLS Draft
  • XLS Update (changes to an existing XLS)
  • XLS Status Change (e.g., Draft → Final, Draft → Stagnant)
  • Process/Meta (changes to CONTRIBUTING.md, XLS-1, templates, etc.)
  • Infrastructure (CI, workflows, scripts, website)
  • Documentation (README updates, typo fixes)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved moderate findings affect normative consistency, references, and test expectations.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds XLS-65.3, an opt-in early-exit fee for closed-ended Vaults under LendingProtocolV1_2.

Changes:

  • Defines fee calculation, validation, withdrawal behavior, invariants, RPC details, and tests.
  • Updates the XLS-65 parent specification and amendment registry.
  • Documents EarlyExitFeeRate as immutable.
File summaries
File Summary and final review findings
XLS-0065-single-asset-vault/README.md Integrates the new field and withdrawal rules. Nit (3 votes): update the stale updated date. Nit (1 vote): reconcile the description with the parent invariant changes.
XLS-0065-single-asset-vault/65.3/README.md Defines the early-exit fee amendment. Moderate (2 votes): replace unresolved closed-ended proposal references. Moderate (1 vote): correct the sole-holder LossUnrealized formula. Nit (3 votes): provide the required proposal URL. Moderate (1 vote): clarify the scope beyond the Investment-phase gate. Moderate (1 vote): relax the test expecting strictly higher serialized payouts.
XLS-0065-single-asset-vault/65.1/65.1.1-unmodifiable-vault-fields.md Documents EarlyExitFeeRate immutability. Moderate (1 vote): add the corresponding LendingProtocolV1_2 invariant or remove the claim.
Review details

Suppressed comments (8)

XLS-0065-single-asset-vault/65.1/65.1.1-unmodifiable-vault-fields.md:17

  • The changed abstract claims that EarlyExitFeeRate is added on the same immutable terms, but the normative invariant list in §3.1.1 still ends at RedemptionDate (item 12) and never states immutability for this field. Add the LendingProtocolV1_2 invariant to this document or remove the claim that this document carries that rule.
Under the `LendingProtocolV1_1` amendment, `Sequence`, `OwnerNode`, `Owner`, `WithdrawalPolicy`, `Scale` and `LEVersion` are immutable on a `Vault` once set, in addition to `Asset`, `Account` and `ShareMPTID`. The same amendment introduces `VaultKind`, `SubscriptionDate` and `RedemptionDate` through the closed-ended vault proposal, and those three fields are immutable under the same rule. The later `LendingProtocolV1_2` amendment adds `EarlyExitFeeRate` on the same terms; [XLS-65.3](../65.3/README.md) states that rule.

XLS-0065-single-asset-vault/65.3/README.md:61

  • The parent withdrawal algorithm waives LossUnrealized for a sole outstanding shareholder by using Vault.AssetsTotal, but this formula always uses Vault.AssetsTotal - LossUnrealized. That contradicts the preceding waiver statement and the later sole-holder behavior, under-calculating both the pre-fee amount and fee whenever a sole holder partially withdraws from an impaired Vault.
- $\Delta_{assets}$, the **pre-fee** asset amount those shares are worth, $\dfrac{\Delta_{shares} \times (\Gamma_{assets} - \iota)}{\Gamma_{shares}}$, is likewise computed exactly as in the parent.

XLS-0065-single-asset-vault/65.3/README.md:69

  • For IOU assets this does not define a deterministic fee: XLS-65.2 says the Vault accounting fields, pseudo-account balance, and destination balance can each quantize on different STAmount grids. Therefore “the precision at which the payout is transferred” has no single defined scale and can vary with the destination and amount, allowing implementations to compute different F values. Specify the exact rounding scale and order, including its interaction with fixCleanup3_4_0.
where $\lceil \cdot \rceil$ rounds **up** to the smallest amount of `Vault.Asset` representable at the precision at which the payout is transferred. Rounding up means any non-zero rate charges at least one unit on any non-zero withdrawal, so a withdrawal cannot be split into pieces small enough to round the fee away (4.3). If $\Delta_{assets}^{paid}$ is not positive, the withdrawal fails with `tecPRECISION_LOSS` (3.4.1).

XLS-0065-single-asset-vault/65.3/README.md:205

  • This says the clawback path is unchanged, but parent XLS-65 §3.7 explicitly says VaultClawback must respect future fees or penalties. Without an explicit override here, an implementation can charge EarlyExitFeeRate on clawbacks despite this paragraph's first sentence. Clarify that the parent future-fees clause does not include this fee.
Unchanged. `VaultClawback` is never charged the fee, in any phase, and parent 3.7 applies as written (4.5).

XLS-0065-single-asset-vault/65.3/README.md:392

  • This formula does not guarantee that a caller receives X: parent §3.1.7.2.3 rounds an asset-denominated request to shares and then recomputes \Delta_{assets}, which can differ from Amount, and the fee is applied to that recomputed value. Present this as an ideal-arithmetic estimate and require clients to simulate the parent rounding and fee calculation.
Not during the Investment phase. `Amount` is the pre-fee amount: shares are burned as if you withdrew 100,000, and you receive 100,000 less the fee. To receive a specific amount $X$ after the fee, request

$$\text{Amount} = \frac{X}{1 - \phi}$$

rounded up, where $\phi$ is the rate as a fraction (3.2.1) — for a 2% rate, ask for 102,041 to receive 100,000. Outside the Investment phase there is no fee and `Amount` behaves exactly as it does today.

XLS-0065-single-asset-vault/65.3/README.md:29

  • This paragraph says the patch changes only the Investment-phase gate, but the specification below also changes the withdrawal payout, accounting deltas, and liquidity check. That scope statement contradicts the normative rules and could cause an implementation to omit the fee behavior; name those additional changes explicitly.
This patch changes the parent [XLS-65](../README.md) sections named below, and the sections of [XLS-65.1.4](../65.1/65.1.4-closed-ended-vault.md) it identifies. All other parent behavior is unchanged. `LendingProtocolV1_1` is a hard prerequisite: `EarlyExitFeeRate` may only be set on a closed-ended Vault, and the only behavior it changes is the Investment-phase gate that [XLS-65.1.4](../65.1/65.1.4-closed-ended-vault.md) introduces.

XLS-0065-single-asset-vault/65.3/README.md:312

  • A strictly higher rational exchange rate does not guarantee a strictly higher serialized payout for integral XRP/MPT amounts. For example, at AssetsTotal = Shares = 1000 and a 50% fee, a 2-share redemption pays 1 and leaves AssetsTotal = 999, Shares = 998; the next identical redemption's fee rounding can still leave a payout of 1 (or reject it for precision), not a value strictly greater than 1. This test expectation is stronger than the invariant and would reject conforming quantized behavior; compare the unrounded value or allow equal integral payouts.
- The exchange rate after a fee-charging withdrawal is strictly higher than before, and a second depositor redeeming an identical share amount immediately afterwards receives strictly more assets than the first.

XLS-0065-single-asset-vault/README.md:358

  • The PR description says there is “no change to any parent Vault invariant,” but this diff extends parent invariant 14, adds a new parent Vault invariant, and adds a new VaultWithdraw invariant. Please qualify the description to say that no existing accounting invariant is changed, or otherwise reconcile the stated scope with the normative changes.
14. - `SingleAssetVault`: `Vault.Asset`, `Vault.Account` and `Vault.ShareMPTID` are immutable once set.
    - `LendingProtocolV1_1`: `Vault.Sequence`, `Vault.OwnerNode`, `Vault.Owner`, `Vault.WithdrawalPolicy`, `Vault.Scale`, `Vault.LEVersion`, `Vault.VaultKind`, `Vault.SubscriptionDate`, `Vault.RedemptionDate`, `Vault.Asset`, `Vault.Account` and `Vault.ShareMPTID` are immutable once set. If `Vault.LEVersion`, `Vault.VaultKind`, `Vault.SubscriptionDate` or `Vault.RedemptionDate` is absent, it remains absent, except when the transaction creates the entry.
    - `LendingProtocolV1_2`: As above, and `Vault.EarlyExitFeeRate` joins the set. If it is absent, it remains absent, except when the transaction creates the entry.
15. `Vault.LossUnrealized` may only be changed by `LoanManage` and `LoanPay`. Every other transaction that modifies the entry must leave it unchanged.
16. A `Vault` is modified only by a transaction type that declares a vault privilege — `VaultCreate`, `VaultSet`, `VaultDelete`, `VaultDeposit`, `VaultWithdraw`, `VaultClawback`, `LoanSet`, `LoanPay` and `LoanManage` — and at most one `Vault` is modified per transaction. `LoanManage` has `MayModifyVault` and may succeed without modifying one; each other listed transaction has `MustModifyVault` and must create, modify or delete one.
17. `LendingProtocolV1_2`: If `Vault.EarlyExitFeeRate` is present, then `Vault.VaultKind == ClosedEnded` and `0 < Vault.EarlyExitFeeRate <= 50000`, as described in [XLS-65.3](./65.3/README.md).
  • Files reviewed: 3/3 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread XLS-0065-single-asset-vault/65.3/README.md Outdated
Comment thread XLS-0065-single-asset-vault/65.3/README.md Outdated
Comment thread XLS-0065-single-asset-vault/README.md Outdated
## 1. Abstract

Under the `LendingProtocolV1_1` amendment, `Sequence`, `OwnerNode`, `Owner`, `WithdrawalPolicy`, `Scale` and `LEVersion` are immutable on a `Vault` once set, in addition to `Asset`, `Account` and `ShareMPTID`. The same amendment introduces `VaultKind`, `SubscriptionDate` and `RedemptionDate` through the closed-ended vault proposal, and those three fields are immutable under the same rule.
Under the `LendingProtocolV1_1` amendment, `Sequence`, `OwnerNode`, `Owner`, `WithdrawalPolicy`, `Scale` and `LEVersion` are immutable on a `Vault` once set, in addition to `Asset`, `Account` and `ShareMPTID`. The same amendment introduces `VaultKind`, `SubscriptionDate` and `RedemptionDate` through the closed-ended vault proposal, and those three fields are immutable under the same rule. The later `LendingProtocolV1_2` amendment adds `EarlyExitFeeRate` on the same terms; [XLS-65.3](../65.3/README.md) states that rule.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@a1q123456 since this change will be implemented under a new amendment, it should be written under the new amendment. Old amendment patches shouldn't be modified.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks, Vito. Have updated it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@a1q123456 please remove changes from this specification. 1.2 changes are in it's own document, and this spec should not be changed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Normative behavior, amendment mapping, arithmetic, and documentation inconsistencies remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 Medium severity · 1 Low severity

Open (3)
Resolved since last review (3)

Comment thread XLS-0065-single-asset-vault/65.3/README.md Outdated
Comment thread XLS-0065-single-asset-vault/65.3/README.md Outdated
Comment thread XLS-0065-single-asset-vault/65.3/README.md Outdated
a1q123456 and others added 3 commits September 22, 2026 10:58
Clarified the application of fees related to VaultClawback under LendingProtocolV1_2.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Unresolved specification inconsistencies affect fee arithmetic, dependencies, rounding, clawbacks, and withdrawal behavior.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 3 Medium severity

Open (3)
Resolved since last review (3)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Account for share and asset rounding in withdrawal estimates

XLS-0065-single-asset-vault/​65.3/​README.md:377

The formula treats the exchange as continuous, but parent §3.1.7.2.3 rounds Δshares to a whole share before recomputing the payout, and §3.4.2 adds asset-scale rounding. Therefore ceil(X/(1-φ)) does not guarantee X and can even result in zero shares and tecPRECISION_LOSS; clients need an estimate caveat and must simulate the protocol rounding.

Comment thread XLS-0065-single-asset-vault/65.3/README.md Outdated
Comment thread XLS-0065-single-asset-vault/65.3/README.md Outdated
Comment thread XLS-0065-single-asset-vault/65.3/README.md Outdated
a1q123456 and others added 3 commits September 22, 2026 12:15
Clarified the computation steps for asset withdrawal and redemption, including formulas and rounding instructions.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Moderate specification conflicts and related normative and documentation corrections remain unresolved.

Review effort: Lite
Findings: None

Resolved since last review (4)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Clarify payout rounding and full-exit fee waiver

XLS-0065-single-asset-vault/​65.3/​README.md:132

Amount is not guaranteed to equal the pre-fee Δassets: the parent Withdraw formula rounds Δshares and then recomputes the payout, so even a zero-rate withdrawal can receive a rounded amount different from the requested asset Amount. The full-exit waiver also makes a non-zero rate fee-free when all shares are burned. Define the payout only as Δassets_paid from 3.4.2 and qualify these cases; otherwise clients may quote an amount the protocol does not deliver.

This issue also appears on line 407 of the same file.

Medium severity Preserve full-redemption path for all-share withdrawals

XLS-0065-single-asset-vault/​65.3/​README.md:170

XLS-65.2 defines a separate full-redemption path that zeros both Vault totals and pays the prior AssetsAvailable, rather than applying one Δasset. This replacement instead says steps 6–9 always apply Δassets_paid, so an all-share withdrawal with deployed capital or unrealized loss has two conflicting outcomes. State explicitly that the existing full-redemption path is preserved and how the fee waiver and payout interact with it; otherwise implementations can diverge on the exact case this patch exempts.

This issue also appears on line 218 of the same file.

@xrplf-bot
xrplf-bot requested a lite review from Copilot September 22, 2026 12:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Unresolved specification, invariant, scope, documentation, and metadata issues remain.

Review effort: Lite
Findings: None

Resolved since last review (2)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Preserve issuer and rounding exceptions for positive withdrawals

XLS-0065-single-asset-vault/​65.3/​README.md:243

The parent explicitly preserves two cases where a positive withdrawal need not produce a persisted destination balance increase: an IOU withdrawal to the asset issuer changes only the vault side, and fixCleanup3_4_0 permits sub-ULP/one-unit destination rounding differences (XLS-65 §3.6.3–3.6.4 and XLS-65.2 §3.1.2.2). Thus a valid withdrawal can leave one balance unchanged while Δassets_paid > 0; this new invariant makes those parent cases impossible. Preserve the parent positive-delta requirements for the vault and non-issuer destination, together with its issuer and precision exceptions, while allowing both balances to remain unchanged for a zero payout.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

A critical liquidity-check defect and several specification and test inconsistencies remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Compare zero-fee results with parent calculations

XLS-0065-single-asset-vault/​65.3/​README.md:368

The parent Withdraw/Redeem formulas round the share amount and the posterior asset delta (parent §3.1.7.2 and XLS-65.2 §3.1.2.3). With a rate of 0, that rounding can leave residual value in AssetsTotal, so the effective exchange rate can change even though no fee is charged. This test expectation is false; compare the result with the parent/open-ended calculation rather than requiring an unchanged rate.

Comment thread XLS-0065-single-asset-vault/65.3/README.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

A critical ambiguity in posterior-scale determination affects fee rounding and payouts.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Low severity Fix VaultClawback subsection numbering

XLS-0065-single-asset-vault/​65.3/​README.md:274

The VaultClawback section is numbered 3.5, but its subsections are labeled 3.7.1–3.7.4, which collides with the later ledger_entry RPC's 3.7.1 and makes local section references ambiguous. Number these subsections 3.5.1–3.5.4.

Comment thread XLS-0065-single-asset-vault/65.3/README.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Critical invariant and zero-payout ambiguities, along with related specification and test issues, remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 High severity

Open (2)
Resolved since last review (1)

Comment thread XLS-0065-single-asset-vault/65.3/README.md Outdated
Comment thread XLS-0065-single-asset-vault/65.3/README.md
Clarified the precision-loss check and investment-phase gate rules in the README.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Unresolved parser, specification, and metadata issues remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (2)
Previously missed (2)

In code that hasn't changed since last review

Low severity Renumber VaultClawback subsection headings to match section 3.5

XLS-0065-single-asset-vault/​65.3/​README.md:278

The VaultClawback subsection headings are numbered 3.7.1–3.7.4 even though this patch declares the section as 3.5; 3.7.1 also collides with the later ledger_entry RPC subsection. This makes references to the patch's sections ambiguous; renumber these headings to 3.5.1–3.5.4.

Low severity Guard FAQ formula against the 100% early-exit fee rate

XLS-0065-single-asset-vault/​65.3/​README.md:463

The FAQ formula divides by 1 - φ, but φ = 1 is an allowed configuration (MAX_EARLY_EXIT_FEE_RATE). As written, a client following this guidance encounters division by zero instead of the documented full-exit-only behavior; restrict the formula to rates below 100% and explicitly exclude the maximum rate.

Comment thread XLS-0065-single-asset-vault/65.3/README.md Outdated
Updated author email format in README.md

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

## 1. Abstract

Under the `LendingProtocolV1_2` amendment, a closed-ended Vault may carry one additional immutable field, `EarlyExitFeeRate`, set at creation. When it is absent, the Vault behaves exactly as [XLS-65.1.4](../65.1/65.1.4-closed-ended-vault.md) describes: `VaultWithdraw` is rejected for the whole Investment phase. When it is present, a `VaultWithdraw` is permitted during Investment and is charged that percentage of the pre-fee withdrawal. A zero-percent rate permits the exit and charges nothing for it. At a rate of 100% the fee consumes the entire payout of a partial withdrawal, so the withdrawal burns the shares and transfers nothing. A withdrawal that burns the entire outstanding share supply pays no fee (3.4.2). Shares are burned against the pre-fee amount while only the post-fee amount leaves the Vault, so the difference stays in the Vault and raises the value of every remaining share. The fee is paid to no party. The exit still draws on `Vault.AssetsAvailable`, so it is best-efforts, not guaranteed. Open-ended Vaults, and closed-ended Vaults outside Investment, are unaffected.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Let's rephrase this abstract.

First, start with what this change does (introduces an early-exit fee set at creation, and what that fee does. The fact that we're introducing a new field, while important, is not needed in the abstract. The purpose of an abstract is to, in one paragraph, inform and entice the reader to read the document.

Comment on lines +22 to +29
A closed-ended Vault locks capital for a fixed term. That lock is the point of the structure where it gives the operator a known amount of capital to deploy, but it admits no exceptions. A depositor who needs liquidity mid-term has no option at all, and an operator willing to let one out on terms that do not penalize the depositors who stay has no way to offer it.

An early-exit fee makes that option a per-Vault setting. The owner fixes a rate at creation; a depositor may then leave during Investment and pay that percentage for the privilege. The fee is not revenue. It never leaves the Vault, so it accrues to the depositors who remain, compensating them for the liquidity consumed and the term cut short.

Whether a mid-term exit is possible and what it costs are two separate decisions, and the field expresses both. An owner who sets no rate at all gets the closed-ended Vault unchanged, with no early exit at any price. An owner who sets a rate of `0` permits mid-term exits and charges nothing for them, which is the right configuration for a Vault whose term is a plan rather than a promise. Absence is the conservative default, so every Vault created before this amendment keeps its meaning (3.2.1).

Fixing the rate at creation and exposing it on the ledger means a depositor knows the exit terms before committing capital, in the same way they know `SubscriptionDate` and `RedemptionDate`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This paragraph as some AI-tell-tell signs. Such as "The fee is not reveneue, [..], it's X". It can be stated plainly that:

The fee is subtracted from the Depositors withdrawal, ans is kept in the Vault for the remaining depositors, compensating them for the liquidity consumed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Unresolved critical and moderate specification issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (1)

Comment on lines +154 to +158
**The Investment-phase gate** of [XLS-65.1.4](../65.1/65.1.4-closed-ended-vault.md) is superseded by the rule below. That specification states the gate as a protocol-level failure of its own `VaultWithdraw` section rather than as a numbered check of parent 3.6.2.2, so it carries no parent check number to replace.

- `SingleAssetVault`: The rule does not apply.
- `LendingProtocolV1_1`: The Vault is closed-ended and `SubscriptionDate < now < RedemptionDate`, where `now` is the parent ledger close time. (`tecTOO_SOON`)
- `LendingProtocolV1_2`: As above, and `Vault.EarlyExitFeeRate` is absent. (`tecTOO_SOON`)

@Tapanito Tapanito left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

First pass.

Please update the patch to match the XLS Template exactly.

Also, please add the changes from 65.3. to the main spec.
The patch shows just the changes, but the patch still has to be applied to the main spec.


Whether a mid-term exit is possible and what it costs are two separate decisions, and the field expresses both. An owner who sets no rate at all gets the closed-ended Vault unchanged, with no early exit at any price. An owner who sets a rate of `0` permits mid-term exits and charges nothing for them, which is the right configuration for a Vault whose term is a plan rather than a promise. Absence is the conservative default, so every Vault created before this amendment keeps its meaning (3.2.1).

Fixing the rate at creation and exposing it on the ledger means a depositor knows the exit terms before committing capital, in the same way they know `SubscriptionDate` and `RedemptionDate`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This sentence could be part of the second paragraph. There's also no need to compare ti Subscription or Redemption dates, especially since those fields might not be fixed.


#### 3.2.1 Fields

Add this field to parent 3.1.2:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It is implict that this section adds a new field to the parent spec.

It's enough to say:

"This feature introduces the following new fields: "


| Field Name | Constant | Required | JSON Type | Internal Type | Default Value | Description |
| ------------------ | :------: | :------: | :-------: | :-----------: | :-----------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `EarlyExitFeeRate` | Yes | No | `number` | `UINT32` | `N/A` | The early-exit fee, in 1/10th basis points, charged on a withdrawal made during the Investment phase. Its presence is what permits a withdrawal during Investment at all. Immutable after creation. |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The description is repeating the information that's already in the table (the fact that the field is immutable)

| Field Name | Constant | Required | JSON Type | Internal Type | Default Value | Description |
| ------------------ | :------: | :------: | :-------: | :-----------: | :-----------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `EarlyExitFeeRate` | Yes | No | `number` | `UINT32` | `N/A` | The early-exit fee, in 1/10th basis points, charged on a withdrawal made during the Investment phase. Its presence is what permits a withdrawal during Investment at all. Immutable after creation. |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There's a missing subsection here:

3.2.1.1. EarlyExitFeeRate


#### 3.3.1 Fields

Add `EarlyExitFeeRate` from 3.2.1 to parent 3.2.1 with the same type. It is optional and has no default, and it is permitted only when `VaultKind == ClosedEnded`. Submitting it with a value of `0` is the way to create a closed-ended Vault that permits a mid-term exit free of charge; omitting it is the way to create one that permits none.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please us a table.

Whether a mid-term exit is possible and what it costs are two separate decisions, and the field expresses both. An owner who sets no rate at all gets the closed-ended Vault unchanged, with no early exit at any price. An owner who sets a rate of `0` permits mid-term exits and charges nothing for them, which is the right configuration for a Vault whose term is a plan rather than a promise. Absence is the conservative default, so every Vault created before this amendment keeps its meaning (3.2.1).

Fixing the rate at creation and exposing it on the ledger means a depositor knows the exit terms before committing capital, in the same way they know `SubscriptionDate` and `RedemptionDate`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please spell-out the full mathematics of the Fee.

Comment on lines +138 to +143
`Amount` keeps its meaning in both denominations and is the **pre-fee** amount. The payout is $\Delta_{assets}^{paid}$ of 3.4.2 and nothing else. An asset-denominated `Amount` is a request, not a payout, for two reasons that are independent of this patch:

- Parent 3.1.7.2.3 rounds $\Delta_{shares}$ and recomputes the asset amount from the rounded shares, so the pre-fee $\Delta_{assets}$ may already differ from `Amount`.
- [XLS-65.2](../65.2/README.md) 3.1.2.3 then rounds $\Delta_{assets}$ down at the posterior scale.

The fee is subtracted from that rounded pre-fee amount. During Investment on a Vault whose rate is greater than `0`, the payout is therefore the parent's payout for the same request less $F$, unless the full-exit waiver of 3.4.2 applies. The payout is not ordered relative to `Amount`, because the parent's rounding of $\Delta_{shares}$ to the nearest whole number may move the pre-fee amount above `Amount` by more than $F$. On a Vault with a rate of `0`, or outside Investment, the payout equals the parent's payout for the same request. Parent 3.6.1 is otherwise unchanged.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The full maths need to be spelled out, rather than "what the changes are"

This branch has not been deployed

No deployments
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.

3 participants