Skip to content

Conversation

@Tapanito
Copy link
Collaborator

@Tapanito Tapanito commented Dec 8, 2025

In the context of the Single Asset Vault there exists a situation where Vault.AssetsTotal and Vault.AssetsAvailable are zero, but the Vault still has shares. Such a situation may arise due to a Loan that was issued for the total of Vault's assets defaulting. The problem with such situation is that the Vault becomes permanently stuck, deposits will not be able to settle the balance, and the Vault object is non-deletable. This PR fixes this problem, namely:

The PR updates the logic of VaultClawback transaction allowing the Owner of the Vault to submit VaultClawback transaction to burn shares of a depositor only when the there are no assets in the vault.

Edit:

The link to specification PR: XRPLF/XRPL-Standards#422

High Level Overview of Change

Context of Change

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (non-breaking change that only restructures code)
  • Performance (increase or change in throughput and/or latency)
  • Tests (you added tests for code that already exists, or your new feature included in this PR)
  • Documentation update
  • Chore (no impact to binary, e.g. .gitignore, formatting, dropping support for older tooling)
  • Release

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)

Copy link
Collaborator

@gregtatcam gregtatcam left a comment

Choose a reason for hiding this comment

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

LGTM

@Tapanito Tapanito force-pushed the tapanito/vault-owner-clawback branch from 1ba2f8d to 2c63982 Compare December 11, 2025 18:11
@Tapanito
Copy link
Collaborator Author

Sorry for the force-push, the devcontainer commit wasn't signed

@Tapanito Tapanito requested a review from gregtatcam December 11, 2025 18:25
@codecov
Copy link

codecov bot commented Dec 11, 2025

Codecov Report

❌ Patch coverage is 97.50000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.2%. Comparing base (f80059e) to head (8034a79).
⚠️ Report is 1 commits behind head on develop.

Files with missing lines Patch % Lines
src/xrpld/app/tx/detail/VaultClawback.cpp 97.0% 4 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##           develop   #6120   +/-   ##
=======================================
  Coverage     79.1%   79.2%           
=======================================
  Files          836     836           
  Lines        71257   71312   +55     
  Branches      8305    8299    -6     
=======================================
+ Hits         56393   56448   +55     
  Misses       14864   14864           
Files with missing lines Coverage Δ
src/xrpld/app/tx/detail/InvariantCheck.cpp 92.2% <100.0%> (+<0.1%) ⬆️
src/xrpld/app/tx/detail/InvariantCheck.h 100.0% <ø> (ø)
src/xrpld/app/tx/detail/VaultClawback.h 100.0% <ø> (ø)
src/xrpld/app/tx/detail/VaultClawback.cpp 97.3% <97.0%> (+2.4%) ⬆️

... and 2 files 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.

if (sharesTotal > 0 && assetsTotal == 0 && assetsAvailable == 0 &&
account == owner)
{
if (auto const amount = ctx.tx[~sfAmount]; amount)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't need to have this additional amount check.

if (auto const amount = ctx.tx[~sfAmount])

@Tapanito Tapanito added the Ready to merge *PR author* thinks it's ready to merge. Has passed code review. Perf sign-off may still be required. label Dec 16, 2025
@ximinez
Copy link
Collaborator

ximinez commented Dec 18, 2025

If this PR gets merged into develop, remember to also cherry pick it into ximinez/lending-3.1 #6156.

}
});

testCase([&](Env& env,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@ximinez @gregtatcam , since the Clawback transaction serves two purposes, the owner can submit the transaction to burn own shares.

This unit test checks if the issuer is trying to clawback from itself, however since now it's a valid use-case to submit the same account as "issuer" and "holder", these unit-tests are no longer valid (as the code they're testing was removed)

AccountID const issuer = ctx.tx[sfAccount];
AccountID const holder = ctx.tx[sfHolder];

if (issuer == holder)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@ximinez , @gregtatcam this check is no longer valid, as the Vault Owner may submit a clawback transaction to burn their own shares.

Copy link
Collaborator

@ximinez ximinez left a comment

Choose a reason for hiding this comment

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

In addition to these, there are a couple of comments from my first review still left pending.

@Tapanito
Copy link
Collaborator Author

@ximinez , @gregtatcam thank you for your time reviewing this PR 🙇

@vvysokikh1 vvysokikh1 removed the Ready to merge *PR author* thinks it's ready to merge. Has passed code review. Perf sign-off may still be required. label Jan 2, 2026
@vvysokikh1 vvysokikh1 requested a review from ximinez January 2, 2026 16:15
MPTIssue const share{mptIssuanceID};

Asset const vaultAsset = vault->at(sfAsset);
STAmount const amount = [&]() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe makes sense to have a helper function? There is a similar block of code in preclaim.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added a helper function.

env(pay(issuer, owner, MPT(1000)));
env(pay(issuer, depositor, MPT(1000)));
env.close();
testCase(MPT, "MPT", owner, depositor);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should add unit-tests when owner is the issuer.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I added the unit test and found a bug. Great call Greg!

Copy link
Collaborator

@ximinez ximinez left a comment

Choose a reason for hiding this comment

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

I left a couple of minor style suggestions, but otherwise this looks good, aside from the items that @gregtatcam has identified.

Comment on lines 5589 to 5591
}
else
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

Minor: You could return at the end of the if block, instead of having the else.

Comment on lines 5467 to 5469
BEAST_EXPECT(vaultSle != nullptr);
if (!vaultSle)
return;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Minor: This could be written as

                if (!BEAST_EXPECT(vaultSle != nullptr))
                    return;

Copy link
Collaborator

@gregtatcam gregtatcam left a comment

Choose a reason for hiding this comment

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

Looks good. I just have a couple of minor suggestions left for your consideration and a request to update the unit-test when an asset's issuer is also the vault holder.

@Tapanito Tapanito added the Ready to merge *PR author* thinks it's ready to merge. Has passed code review. Perf sign-off may still be required. label Jan 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready to merge *PR author* thinks it's ready to merge. Has passed code review. Perf sign-off may still be required.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants