Skip to content

feat: Make VaultID conditional on LoanBrokerSet#6528

Open
Tapanito wants to merge 45 commits into
developfrom
tapanito/loan-broker-set
Open

feat: Make VaultID conditional on LoanBrokerSet#6528
Tapanito wants to merge 45 commits into
developfrom
tapanito/loan-broker-set

Conversation

@Tapanito

@Tapanito Tapanito commented Mar 11, 2026

Copy link
Copy Markdown
Collaborator

When updating an existing LoanBroker (LoanBrokerID present), VaultID must not be provided the vault association is read from the broker object on ledger. VaultID remains required when creating a new LoanBroker. This change is gated behind fixLendingProtocolV1_1; pre-amendment behavior is preserved for historical transaction replay.

  • Change sfVaultID from soeREQUIRED to soeOPTIONAL
  • Gate VaultID field presence rules in preflight by amendment
  • Refactor preclaim into readVault/preclaimUpdate/preclaimCreate
  • Add pre- and post-amendment unit test coverage

Specification: XRPLF/XRPL-Standards#497

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)

@Tapanito Tapanito requested review from a1q123456 and ximinez March 11, 2026 14:25
@codecov

codecov Bot commented Mar 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.82716% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.3%. Comparing base (ecf7f80) to head (79bdbf3).
⚠️ Report is 1 commits behind head on develop.

Files with missing lines Patch % Lines
...c/libxrpl/tx/transactors/lending/LoanBrokerSet.cpp 93.4% 5 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##           develop   #6528   +/-   ##
=======================================
  Coverage     82.3%   82.3%           
=======================================
  Files         1024    1024           
  Lines        78397   78443   +46     
  Branches      8973    8973           
=======================================
+ Hits         64514   64566   +52     
+ Misses       13874   13868    -6     
  Partials         9       9           
Files with missing lines Coverage Δ
include/xrpl/protocol/detail/transactions.macro 100.0% <ø> (ø)
...xrpl/protocol_autogen/transactions/LoanBrokerSet.h 100.0% <100.0%> (ø)
src/libxrpl/tx/transactors/vault/VaultDelete.cpp 87.5% <ø> (ø)
...c/libxrpl/tx/transactors/lending/LoanBrokerSet.cpp 94.7% <93.4%> (+1.0%) ⬆️

... and 4 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.

Tapanito added 2 commits June 8, 2026 11:28
…ix-amendment

# Conflicts:
#	include/xrpl/ledger/helpers/LendingHelpers.h
#	include/xrpl/protocol/STAmount.h
#	include/xrpl/protocol/detail/features.macro
#	include/xrpl/protocol/detail/transactions.macro
#	src/libxrpl/tx/invariants/VaultInvariant.cpp
#	src/test/app/Invariants_test.cpp
#	src/test/app/LoanBroker_test.cpp
#	src/test/app/Loan_test.cpp
#	src/test/app/Vault_test.cpp
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

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

@Tapanito Tapanito added this to the Lending Protocol 1.1 milestone Jun 8, 2026
Tapanito added 2 commits June 8, 2026 13:14
Resolved conflicts in LoanBrokerSet.cpp, transactions.macro, LoanBrokerSet.h,
TestHelpers (h/cpp), and LoanBroker_test.cpp.

Key decisions:
- sfVaultID remains SoeOptional (our change) with new capitalization style
- Amendment-gated preflight logic preserved alongside kZero renames
- testZeroVaultID lambda removed (field is optional on update under V1_1)
- Both testLoanBrokerSetVaultIDAmendment and testCoverPrecisionGuard included
- All k-prefix helper renames from lending-fix-amendment applied
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

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

@xrplf-ai-reviewer xrplf-ai-reviewer Bot 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.

No issues.

Review by Claude Sonnet 4.6 · Prompt: V15

@xrplf-ai-reviewer xrplf-ai-reviewer Bot 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.

No issues.

Review by Claude Sonnet 4.6 · Prompt: V15

@github-actions

Copy link
Copy Markdown

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

@Tapanito Tapanito force-pushed the tapanito/lending-fix-amendment branch from eaf80ce to 60700c5 Compare June 26, 2026 12:48
Base automatically changed from tapanito/lending-fix-amendment to develop July 1, 2026 00:25
@bthomee bthomee dismissed a1q123456’s stale review July 1, 2026 00:25

The base branch was changed.

@a1q123456 a1q123456 self-requested a review July 1, 2026 10:43
@Tapanito Tapanito removed the request for review from ximinez July 1, 2026 11:45
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

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

@xrplf-ai-reviewer xrplf-ai-reviewer Bot 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.

No issues.

Review by Claude Sonnet 4.6 · Prompt: V15

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

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

Comment on lines +49 to 71
// Amendment-specific field presence rules
if (ctx.rules.enabled(featureLendingProtocolV1_1))
{
if (isLoanBrokerUpdate)
{
if (tx.isFieldPresent(sfVaultID))
return temINVALID;
}
else
{
if (!tx.isFieldPresent(sfVaultID) || tx[sfVaultID] == beast::zero)
return temINVALID;
}
}
else
{
if (*vaultID == beast::zero)
// Pre-amendment: VaultID was soeREQUIRED, must always be present
if (!tx.isFieldPresent(sfVaultID))
return temINVALID;

if (tx[sfVaultID] == beast::zero)
return temINVALID;
}

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 is more complex and harder to read than it needs to be. You can still take advantage tx[~sfVaultID] to make it a little simpler.

Suggested change
// Amendment-specific field presence rules
if (ctx.rules.enabled(featureLendingProtocolV1_1))
{
if (isLoanBrokerUpdate)
{
if (tx.isFieldPresent(sfVaultID))
return temINVALID;
}
else
{
if (!tx.isFieldPresent(sfVaultID) || tx[sfVaultID] == beast::zero)
return temINVALID;
}
}
else
{
if (*vaultID == beast::zero)
// Pre-amendment: VaultID was soeREQUIRED, must always be present
if (!tx.isFieldPresent(sfVaultID))
return temINVALID;
if (tx[sfVaultID] == beast::zero)
return temINVALID;
}
// Amendment-specific field presence rules
if (auto const vaultID = tx[~sfVaultID]; ctx.rules.enabled(featureLendingProtocolV1_1))
{
if (isLoanBrokerUpdate)
{
if (vaultID)
return temINVALID;
}
else
{
if (!vaultID || *vaultID == beast::zero)
return temINVALID;
}
}
else
{
// Pre-amendment: VaultID was soeREQUIRED, must always be present
if (!vaultID)
return temINVALID;
if (*vaultID == beast::zero)
return temINVALID;
}

{
auto const account = ctx.tx[sfAccount];

auto const maybeVault = [&]() -> std::expected<std::shared_ptr<SLE const>, TER> {

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.

Optional nit: Since both functions that you're going to call return the same type, you may not need to specify it explicitly as the return type of the lambda.

// Check that relevant values can be represented as the vault asset
// type. This is mostly only relevant for integral (non-IOU) types
// type. This is mostly only relevant for integral (non-IOU) types.
Asset const asset = (*maybeVault)->at(sfAsset);

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.

Optional nit: This might be more readable if you define an auto const sleVault = *maybeVault;, and then get the asset with sleVault->at(sfAsset).


json::Value
set(AccountID const& account, uint256 const& vaultId, uint32_t flags)
set(AccountID const& account, std::optional<uint256> const& vaultId, uint32_t flags)

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 usual convention for these jtx builder functions is to only include the required fields in the "main" function, and populate the optional fields using helpers like kLoanBrokerId.

You could define a similar kVaultId alongside the kLoanBrokerId, and remove it from this function. The downside is that then you'd have to find all the calls to set where you are passing a Vault ID now, and rewrite them to use the helper.

Because this is a conversion, I'm fine with being a little looser. I have no idea how many of those there are, so if it's too much hassle, I'd be ok with leaving this as-is. But don't get into the habit of it. 😅

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants