Skip to content

fix: Clamp VaultClawback to assetsAvailable for zero-amount clawback#6646

Open
Tapanito wants to merge 3 commits intodevelopfrom
tapanito/fix-vault-clawback-clamp
Open

fix: Clamp VaultClawback to assetsAvailable for zero-amount clawback#6646
Tapanito wants to merge 3 commits intodevelopfrom
tapanito/fix-vault-clawback-clamp

Conversation

@Tapanito
Copy link
Copy Markdown
Collaborator

Zero-amount clawback (meaning "clawback all") returned early without clamping to assetsAvailable, allowing more assets to be recovered than available when there was an outstanding loan. Move the zero-amount path inside the try block so it shares the same clamping logic as non-zero clawback.

The old early-return behavior is retained behind a !fixAssortedFixes gate for ledger replay compatibility.

High Level Overview of Change

Context of Change

API Impact

  • Public API: New feature (new methods and/or new fields)
  • Public API: Breaking change (in general, breaking changes should only impact the next api_version)
  • libxrpl change (any change that may affect libxrpl or dependents of libxrpl)
  • Peer protocol change (must be backward compatible or bump the peer protocol version)

Zero-amount clawback (meaning "clawback all") returned early without
clamping to assetsAvailable, allowing more assets to be recovered than
available when there was an outstanding loan. Move the zero-amount
path inside the try block so it shares the same clamping logic as
non-zero clawback.

The old early-return behavior is retained behind a !fixAssortedFixes
gate for ledger replay compatibility.
@Tapanito Tapanito added Amendment AI Triage Bugs and fixes that have been triaged via AI initiatives labels Mar 25, 2026
- Add test for the pre-fixAssortedFixes legacy code path where
  zero-amount clawback does not clamp to assetsAvailable, verifying
  the transaction fails with tefINTERNAL for ledger replay fidelity
- Remove unused sharesBefore variable in zero-amount post-fix test
- Normalize env.balance() calls to use PrettyAsset directly
- Strengthen non-zero clawback share assertions from inequality
  checks to exact expected values matching the zero-amount test
@github-actions
Copy link
Copy Markdown

This PR has conflicts, please resolve them in order for the PR to be reviewed.

…_1_3

Resolve amendment conflict: drop placeholder fixAssortedFixes, adopt
fixSecurity3_1_3 (Supported::no) from develop. Update VaultClawback
and tests to reference the new amendment name and explicitly enable
it in the test Env since it is disabled by default.
@github-actions
Copy link
Copy Markdown

All conflicts have been resolved. Assigned reviewers can now start or resume their review.

@Tapanito Tapanito marked this pull request as ready for review March 26, 2026 09:47
@Tapanito
Copy link
Copy Markdown
Collaborator Author

/ai-review

Copy link
Copy Markdown
Contributor

@xrplf-ai-reviewer xrplf-ai-reviewer bot left a comment

Choose a reason for hiding this comment

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

One low-severity naming collision in setupVault — see inline.

Review by Claude Opus 4.6 · Prompt: V12

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.5%. Comparing base (2c765f6) to head (1dbf8dd).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##           develop   #6646   +/-   ##
=======================================
  Coverage     81.4%   81.5%           
=======================================
  Files          998     998           
  Lines        74443   74450    +7     
  Branches      7563    7558    -5     
=======================================
+ Hits         60632   60640    +8     
+ Misses       13811   13810    -1     
Files with missing lines Coverage Δ
src/libxrpl/tx/transactors/vault/VaultClawback.cpp 97.8% <100.0%> (+0.1%) ⬆️

... and 1 file with indirect coverage changes

Impacted file tree graph

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a VaultClawback edge case where a zero-amount clawback (“claw back all”) could recover more than sfAssetsAvailable when loans are outstanding, by ensuring the zero-amount path shares the same clamping logic as non-zero clawbacks (while retaining legacy behavior behind a feature gate for replay compatibility).

Changes:

  • Update VaultClawback::assetsToClawback to compute and clamp recovered assets for zero-amount clawback within the same guarded path as non-zero clawback.
  • Add regression tests covering zero-amount and non-zero clawback clamping when sfAssetsAvailable < sfAssetsTotal due to an outstanding loan.
  • Add a legacy-path test to validate pre-fix behavior when the relevant feature is disabled.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/test/app/Vault_test.cpp Adds regression and legacy-path tests for clamping behavior under outstanding loans; enables the relevant feature for the test environment.
src/libxrpl/tx/transactors/vault/VaultClawback.cpp Refactors zero-amount clawback handling so it is clamped to sfAssetsAvailable, preserving legacy behavior behind a feature flag.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +5054 to +5055
auto const sharesBefore = env.balance(depositor, shares);

Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

sharesBefore is computed but never used in this test case, which can trigger an unused-variable warning (often treated as an error in CI). Please remove it or use it in an assertion (e.g., verify the expected reduction in shares).

Suggested change
auto const sharesBefore = env.balance(depositor, shares);

Copilot uses AI. Check for mistakes.
Comment on lines +230 to +234
// Pre-fixSecurity3_1_3: zero-amount clawback returned early without
// clamping to assetsAvailable, allowing more assets to be recovered
// than available when there was an outstanding loan. Retained for
// ledger replay compatibility.
if (!ctx_.view().rules().enabled(fixSecurity3_1_3) && clawbackAmount == beast::zero)
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

The PR description mentions keeping the legacy behavior behind a !fixAssortedFixes gate, but the code gates it on !fixSecurity3_1_3. Since fixAssortedFixes doesn't appear to exist in the codebase, please either update the PR description to match the actual feature flag or switch the gate to the intended amendment if different.

Copilot uses AI. Check for mistakes.
Comment on lines +4967 to +4969
BEAST_EXPECT(vaultSle != nullptr);
if (!vaultSle)
return;
Copy link
Copy Markdown
Collaborator

@shawnxie999 shawnxie999 Mar 27, 2026

Choose a reason for hiding this comment

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

nit - alternatively could be (same for places down below)

if (!BEAST_EXPECT(vaultSle))
    return;

Copy link
Copy Markdown
Collaborator

@shawnxie999 shawnxie999 left a comment

Choose a reason for hiding this comment

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

LGTM - left minor comment

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

Labels

AI Triage Bugs and fixes that have been triaged via AI initiatives Amendment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants