Skip to content

refactor: Move LendingHelpers into libxrpl/ledger/helpers#6638

Open
mvadari wants to merge 23 commits intodevelopfrom
mvadari/move-more-helpers
Open

refactor: Move LendingHelpers into libxrpl/ledger/helpers#6638
mvadari wants to merge 23 commits intodevelopfrom
mvadari/move-more-helpers

Conversation

@mvadari
Copy link
Copy Markdown
Collaborator

@mvadari mvadari commented Mar 24, 2026

High Level Overview of Change

This PR moves all remaining helper files into the libxrpl/ledger/helpers folder, after #6453.

This is a pure refactor. There is no functionality change.

Context of Change

Prepping for #6620 and downstream PRs

API Impact

N/A

@mvadari mvadari requested review from Tapanito and bthomee March 24, 2026 19:57
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.

No issues.

Review by Claude Opus 4.6 · Prompt: V12

Comment on lines +4 to +5
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AMMUtils.h>
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.

Can these two files be combined perhaps? Looking at their contents, seems like it should be fine to move the functionality from AMMUtils into AMMHelpers, unless that's problematic for (circular) header inclusion reasons.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I was going to leave that for a second PR, to keep this one dead simple.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

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.

Took a pass through this

Three concerns worth confirming: (1) missing MPTokenHelpers.h include in EscrowHelpers.h, (2) potential MPToken authorization bypass via EscrowFinish/Cancel, (3) the checkLendingProtocolDependencies refactor may not be behaviorally equivalent to the VaultCreate::checkExtraFeatures it replaced. Also flagged a question about whether AMM transactors have PermissionedDEX credential checks comparable to OfferCreate. See inline comments.


Review by ReviewBot 🤖

Review by Claude Opus 4.6 · Prompt: V12


if (auto const ter = MPTokenAuthorize::createMPToken(view, mptID, receiver, 0);
!isTesSuccess(ter))
if (auto const ter = createMPToken(view, mptID, receiver, 0); !isTesSuccess(ter))
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.

Header isn't self-contained — createMPToken() is used but MPTokenHelpers.h is never included. Add the missing include near the top of the file:

#include <xrpl/ledger/helpers/MPTokenHelpers.h>

(This was lost when MPTokenAuthorize.h was removed.)


bool
checkLendingProtocolDependencies(PreflightContext const& ctx)
checkLendingProtocolDependencies(Rules const& rules, STTx const& tx)
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.

Replacing VaultCreate::checkExtraFeatures(ctx) with inlined logic changes the function signature and behavior. Please confirm the new checks (featureSingleAssetVault, featureMPTokensV1, conditional featurePermissionedDomains) are exactly equivalent to what VaultCreate::checkExtraFeatures enforced — any divergence silently changes preflight acceptance in a consensus system.

@@ -1,17 +1,16 @@
#include <xrpl/ledger/OrderBookDB.h>
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.

AMM transactors may be missing PermissionedDEX credential checks that OfferCreate enforces via PermissionedDEXHelpers. AMM deposits/withdrawals are economically equivalent to offer placement, so accounts could bypass DEX access controls by routing through an AMM pool. Please verify all AMM transactors apply the same access-control gates as OfferCreate.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Permissioned DEX doesn't support AMM right now.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 24, 2026

Codecov Report

❌ Patch coverage is 94.11765% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 81.4%. Comparing base (f239256) to head (068c583).
⚠️ Report is 19 commits behind head on develop.

Files with missing lines Patch % Lines
src/libxrpl/ledger/helpers/LendingHelpers.cpp 87.5% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##           develop   #6638     +/-   ##
=========================================
- Coverage     81.4%   81.4%   -0.0%     
=========================================
  Files         1006    1006             
  Lines        74462   74468      +6     
  Branches      7561    7554      -7     
=========================================
+ Hits         60646   60647      +1     
- Misses       13816   13821      +5     
Files with missing lines Coverage Δ
include/xrpl/ledger/helpers/LendingHelpers.h 95.2% <ø> (ø)
include/xrpl/tx/transactors/lending/LoanSet.h 100.0% <ø> (ø)
...tx/transactors/lending/LoanBrokerCoverClawback.cpp 97.8% <100.0%> (ø)
.../tx/transactors/lending/LoanBrokerCoverDeposit.cpp 94.7% <100.0%> (ø)
...tx/transactors/lending/LoanBrokerCoverWithdraw.cpp 96.3% <100.0%> (ø)
...ibxrpl/tx/transactors/lending/LoanBrokerDelete.cpp 88.6% <100.0%> (ø)
...c/libxrpl/tx/transactors/lending/LoanBrokerSet.cpp 96.0% <100.0%> (ø)
src/libxrpl/tx/transactors/lending/LoanDelete.cpp 96.4% <100.0%> (ø)
src/libxrpl/tx/transactors/lending/LoanManage.cpp 89.7% <100.0%> (ø)
src/libxrpl/tx/transactors/lending/LoanPay.cpp 95.3% <100.0%> (ø)
... and 2 more

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

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.

Took a pass through this

The MR description says "pure refactor, no source code change" but LendingHelpers.cpp inlines feature checks that previously delegated to VaultCreate::checkExtraFeatures — in a consensus system any behavioral difference could cause forks. Also flagged: a stale forward declaration, a missing MPTokenHelpers.h include in EscrowHelpers.h, and widened visibility of the security-sensitive createMPToken primitive. See inline comments.


Review by ReviewBot 🤖

Review by Claude Opus 4.6 · Prompt: V12

Comment thread src/libxrpl/ledger/helpers/LendingHelpers.cpp Outdated

bool
checkLendingProtocolDependencies(PreflightContext const& ctx)
checkLendingProtocolDependencies(Rules const& rules, STTx const& tx)
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.

Correctness risk in a consensus system — the old code delegated to VaultCreate::checkExtraFeatures(ctx) but this inlines three explicit checks. Please confirm these are exactly equivalent to what VaultCreate::checkExtraFeatures returned. Any behavioral difference could cause ledger forks.


bool
checkLendingProtocolDependencies(PreflightContext const& ctx)
checkLendingProtocolDependencies(Rules const& rules, STTx const& tx)
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.

Possible incomplete feature-gate replication — if VaultCreate::checkExtraFeatures checked flags beyond featureSingleAssetVault, featureMPTokensV1, and featurePermissionedDomains, lending transactions could become reachable in states where they should still be gated. Audit VaultCreate::checkExtraFeatures and add a unit test covering every flag-disabled combination the old code would have rejected.


if (auto const ter = MPTokenAuthorize::createMPToken(view, mptID, receiver, 0);
!isTesSuccess(ter))
if (auto const ter = createMPToken(view, mptID, receiver, 0); !isTesSuccess(ter))
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.

Missing include: createMPToken (declared in MPTokenHelpers.h) is called here but the header for it was removed with no replacement. Add #include <xrpl/ledger/helpers/MPTokenHelpers.h> — the header currently compiles only by accident via consumer TUs.

}

TER
createMPToken(
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.

Widened visibility of a security-sensitive primitivecreateMPToken was previously scoped to MPTokenAuthorize and is now a free function callable by any includer. It inserts an MPToken into the ledger with no authorization check. Document in the header that callers must verify authorization independently, add [[nodiscard]] to the return TER, and audit all call sites to confirm authorization is enforced upstream.

mvadari and others added 2 commits March 24, 2026 20:51
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
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.

Took a pass through this

Two correctness concerns flagged inline: a potential semantic mismatch in the isFlag() → bitwise replacement in MPTokenHelpers.cpp, and a possibly incomplete inlining of VaultCreate::checkExtraFeatures in LendingHelpers.cpp that could silently drop amendment gates.


Review by ReviewBot 🤖

Review by Claude Opus 4.6 · Prompt: V12

return tecOBJECT_NOT_FOUND;

if (!sleIssuance->isFlag(lsfMPTCanTransfer))
if ((sleIssuance->getFieldU32(sfFlags) & lsfMPTCanTransfer) == 0u)
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.

Verify semantic equivalence with the replaced isFlag() call — confirm lsfMPTCanTransfer is the correct bit mask and no normalization step was dropped. If this tests a different bit position than isFlag() did, flag state written by MPTokenIssuanceSet will be misread here and in MPTokenAuthorize, potentially enabling features (transferability, clawback) that should remain disabled.

Please confirm this is equivalent to the previous:

    if (!sleIssuance->isFlag(lsfMPTCanTransfer))

checkLendingProtocolDependencies(Rules const& rules, STTx const& tx)
{
return ctx.rules.enabled(featureSingleAssetVault) && VaultCreate::checkExtraFeatures(ctx);
if (!rules.enabled(featureSingleAssetVault))
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.

Missing amendment gates from the removed VaultCreate::checkExtraFeatures call — verify the inline expansion is complete. The old implementation was:

return ctx.rules.enabled(featureSingleAssetVault) && VaultCreate::checkExtraFeatures(ctx);

If checkExtraFeatures enforced additional amendment checks beyond featureMPTokensV1 and featurePermissionedDomains, all eight lending transactors that delegate here will silently skip those gates, potentially accepting transactions that should be rejected — which could cause consensus divergence between nodes on different amendment sets.

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.

Three issues flagged inline: possible dropped feature-gate constraints in LendingHelpers (high severity), undocumented reserve-check precondition on the new public createMPToken API, and a isFlag() → manual bitwise substitution that needs semantic verification.

Review by Claude Opus 4.6 · Prompt: V12

beast::Journal j);

TER
createMPToken(
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.

Newly public createMPToken has no documented reserve-check precondition — callers may skip it.

The function was extracted from MPTokenAuthorize where the reserve check was always performed before calling it. Now that it's a shared public API, document the precondition prominently so future callers know they must validate reserve balance first.

// PRECONDITION: Caller must have already verified the account has
// sufficient owner reserve before invoking this function.
TER
createMPToken(
    ApplyView& view,
    MPTID const& mptIssuanceID,
    AccountID const& account,
    std::uint32_t const flags);


bool
checkLendingProtocolDependencies(PreflightContext const& ctx)
checkLendingProtocolDependencies(Rules const& rules, STTx const& tx)
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.

Refactor may silently drop constraints from VaultCreate::checkExtraFeatures — verify nothing was lost.

The old implementation was ctx.rules.enabled(featureSingleAssetVault) && VaultCreate::checkExtraFeatures(ctx). The new version inlines only three rules.enabled() checks. If VaultCreate::checkExtraFeatures enforced any additional feature flags, field validations, or invariants beyond these three, those checks are now silently removed. In a consensus-critical path, this could allow transactions that should be rejected to proceed.

Please audit the full implementation of VaultCreate::checkExtraFeatures and confirm that every condition it enforced is either replicated here or explicitly justified as removed. Add regression tests covering each previously-checked condition.

return tecOBJECT_NOT_FOUND;

if (!sleIssuance->isFlag(lsfMPTCanTransfer))
if ((sleIssuance->getFieldU32(sfFlags) & lsfMPTCanTransfer) == 0u)
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.

Manual bitwise check replaces isFlag() — verify the semantics are identical.

If SLE::isFlag() does anything beyond (getFieldU32(sfFlags) & flag) != 0 (e.g., reads a cached/normalized field), this substitution silently changes transfer-authorization logic. Confirm isFlag() is a pure bitwise check, or revert to using it.

Suggested change
if ((sleIssuance->getFieldU32(sfFlags) & lsfMPTCanTransfer) == 0u)
if (!sleIssuance->isFlag(lsfMPTCanTransfer))

@github-actions

This comment was marked as resolved.


bool
checkLendingProtocolDependencies(PreflightContext const& ctx)
checkLendingProtocolDependencies(Rules const& rules, STTx const& tx)
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 PR is no longer just structural change. Could we keep this logic as it was for now?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It fails levelization if I don't change 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.

You can run the levelization script, and commit the updated output. Of course, if it introduces a new loop (circular dependency) then that's not great and would need to be fixed through other changes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, that's what I had to do here

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@Tapanito this PR has shrunk to just moving LendingHelpers over, so we can discuss specifically this issue. The business logic is still identical with this change.

Copilot AI review requested due to automatic review settings April 3, 2026 14:24
@github-actions

This comment was marked as resolved.

This comment was marked as resolved.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 6, 2026

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

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 7, 2026

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

@mvadari mvadari changed the title refactor: Move more helper files into libxrpl/ledger/helpers refactor: Move LendingHelper into libxrpl/ledger/helpers Apr 7, 2026
@mvadari mvadari changed the title refactor: Move LendingHelper into libxrpl/ledger/helpers refactor: Move LendingHelpers into libxrpl/ledger/helpers Apr 7, 2026
@github-actions
Copy link
Copy Markdown

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

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.

4 participants