Skip to content

checkInsufficientReserve ->checkXrpBalance#7542

Open
oleks-rip wants to merge 8 commits into
XRPLF:xrplf/sponsorfrom
oleks-rip:check_xrp
Open

checkInsufficientReserve ->checkXrpBalance#7542
oleks-rip wants to merge 8 commits into
XRPLF:xrplf/sponsorfrom
oleks-rip:check_xrp

Conversation

@oleks-rip

Copy link
Copy Markdown
Collaborator

High Level Overview of Change

This PR change reserve checking logic supporting Sponsor/Sponsorship/Delegate and their combination. Added more checks and automation to allow minimal usage code do maximum check.

AccountRootHelpers some refactoring
Added more comments
@oleks-rip oleks-rip requested review from mvadari and yinyiqian1 June 15, 2026 19:36
@codecov

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.03980% with 48 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.2%. Comparing base (4fc781e) to head (5e83693).
⚠️ Report is 1 commits behind head on xrplf/sponsor.

Files with missing lines Patch % Lines
src/libxrpl/ledger/helpers/AccountRootHelpers.cpp 76.0% 43 Missing ⚠️
...rpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp 98.5% 1 Missing ⚠️
src/libxrpl/tx/transactors/bridge/XChainBridge.cpp 91.7% 1 Missing ⚠️
src/libxrpl/tx/transactors/dex/AMMCreate.cpp 95.5% 1 Missing ⚠️
src/libxrpl/tx/transactors/payment/Payment.cpp 50.0% 1 Missing ⚠️
...transactors/payment_channel/PaymentChannelFund.cpp 66.7% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@               Coverage Diff               @@
##           xrplf/sponsor   #7542     +/-   ##
===============================================
- Coverage           82.3%   82.2%   -0.0%     
===============================================
  Files               1018    1018             
  Lines              78268   78211     -57     
  Branches            8972    8980      +8     
===============================================
- Hits               64390   64312     -78     
- Misses             13869   13890     +21     
  Partials               9       9             
Files with missing lines Coverage Δ
include/xrpl/ledger/helpers/AccountRootHelpers.h 100.0% <100.0%> (ø)
include/xrpl/ledger/helpers/EscrowHelpers.h 98.8% <100.0%> (-<0.1%) ⬇️
include/xrpl/ledger/helpers/NFTokenHelpers.h 100.0% <ø> (ø)
include/xrpl/ledger/helpers/SponsorHelpers.h 100.0% <100.0%> (+2.1%) ⬆️
include/xrpl/protocol/STTx.h 100.0% <ø> (ø)
include/xrpl/protocol/XRPAmount.h 100.0% <100.0%> (ø)
include/xrpl/tx/Transactor.h 100.0% <ø> (ø)
src/libxrpl/ledger/View.cpp 96.7% <100.0%> (-<0.1%) ⬇️
src/libxrpl/ledger/helpers/MPTokenHelpers.cpp 96.4% <100.0%> (-<0.1%) ⬇️
src/libxrpl/ledger/helpers/NFTokenHelpers.cpp 89.5% <100.0%> (+0.1%) ⬆️
... and 40 more

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

Comment thread src/test/app/SponsorSherlock_test.cpp
Comment thread src/libxrpl/ledger/helpers/AccountRootHelpers.cpp

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.

Pull request overview

This PR refactors XRP reserve/funds validation across many transactors to use a new checkXrpBalance flow (supporting sponsor/sponsorship/delegate combinations) and updates related sponsor + fee-payer plumbing.

Changes:

  • Replaces many checkInsufficientReserve call sites with checkXrpBalance and updates owner/sponsor reserve accounting helpers.
  • Renames STTx::getFeePayer() to STTx::getInitiator() and updates signing/multisigning validation accordingly.
  • Adds/updates extensive sponsor-related tests (including a new SponsorSherlock_test suite).

Reviewed changes

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

Show a summary per file
File Description
src/xrpld/rpc/detail/TransactionSign.cpp Uses getInitiator() for signer array validation in delegated tx flows.
src/test/app/SponsorSherlock_test.cpp Adds regression tests for multiple sponsor/reserve edge cases from Sherlock issues.
src/test/app/Sponsor_test.cpp Expands sponsor tests for fee borrowing/reserve edge cases and adjusts expectations.
src/libxrpl/tx/transactors/vault/VaultWithdraw.cpp Adapts vault withdraw to new sponsor retrieval + send signature.
src/libxrpl/tx/transactors/vault/VaultDeposit.cpp Adapts vault deposit to new sponsor retrieval + send signature.
src/libxrpl/tx/transactors/vault/VaultCreate.cpp Switches vault create reserve checks to checkXrpBalance.
src/libxrpl/tx/transactors/token/TrustSet.cpp Refactors trustline reserve/sponsor handling to checkXrpBalance + per-side sponsor retrieval.
src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp Switches issuance reserve checks to checkXrpBalance.
src/libxrpl/tx/transactors/system/TicketCreate.cpp Switches ticket reserve checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp Updates sponsor transfer checks + overflow handling and uses new checkXrpBalanceHlp path.
src/libxrpl/tx/transactors/Sponsor/SponsorshipSet.cpp Refactors sponsorship object create/update reserve + fee logic.
src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp Switches reserve checks to checkXrpBalance.
src/libxrpl/tx/transactors/payment/Payment.cpp Updates fee payer logic to use new getFeePayer(view, tx) helper.
src/libxrpl/tx/transactors/payment/DepositPreauth.cpp Switches reserve checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/transactors/payment_channel/PaymentChannelFund.cpp Uses checkXrpBalance for post-fund reserve/funds check (bug found: wrong ownerCountAdj).
src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp Switches create reserve/funds checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/transactors/oracle/OracleSet.cpp Switches oracle reserve checks + sponsor wiring to new helpers.
src/libxrpl/tx/transactors/nft/NFTokenMint.cpp Routes NFT insertion + reserve checks through updated helper signatures.
src/libxrpl/tx/transactors/nft/NFTokenCreateOffer.cpp Updates offer creation to pass account SLE into helper.
src/libxrpl/tx/transactors/nft/NFTokenAcceptOffer.cpp Refactors buyer reserve checks into nft::insertToken + checkXrpBalance-based flow.
src/libxrpl/tx/transactors/lending/LoanSet.cpp Switches borrower reserve checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/transactors/lending/LoanBrokerSet.cpp Switches broker reserve checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/transactors/escrow/EscrowFinish.cpp Removes unused sponsor lookup in preclaim.
src/libxrpl/tx/transactors/escrow/EscrowCreate.cpp Switches escrow reserve/funds checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/transactors/did/DIDSet.cpp Switches DID reserve checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/transactors/dex/OfferCreate.cpp Switches offer reserve checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/transactors/dex/AMMWithdraw.cpp Refactors AMM withdraw reserve check to checkXrpBalance.
src/libxrpl/tx/transactors/dex/AMMDeposit.cpp Refactors AMM deposit reserve/funds checks to checkXrpBalance.
src/libxrpl/tx/transactors/dex/AMMCreate.cpp Refactors AMM create reserve/funds checks to checkXrpBalance.
src/libxrpl/tx/transactors/delegate/DelegateSet.cpp Switches delegate reserve checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/transactors/credentials/CredentialCreate.cpp Switches reserve checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/transactors/credentials/CredentialAccept.cpp Switches reserve checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/transactors/check/CheckCreate.cpp Switches reserve checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/transactors/check/CheckCash.cpp Switches reserve checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/transactors/bridge/XChainBridge.cpp Switches reserve checks + sponsor wiring to checkXrpBalance and simplifies reserve call.
src/libxrpl/tx/transactors/account/SignerListSet.cpp Switches signer list reserve checks + sponsor wiring to checkXrpBalance.
src/libxrpl/tx/Transactor.cpp Removes old Transactor::getFeePayer implementation and adopts new fee payer representation.
src/libxrpl/tx/paths/XRPEndpointStep.cpp Minor cleanup (removes stray semicolon).
src/libxrpl/protocol/STTx.cpp Renames fee-payer helper to getInitiator and updates multisign helper visibility.
src/libxrpl/ledger/View.cpp Updates accountSend sponsor argument passing.
src/libxrpl/ledger/helpers/TokenHelpers.cpp Minor brace cleanup.
src/libxrpl/ledger/helpers/RippleStateHelpers.cpp Fixes boolean expression style and switches trustline reserve checks to checkXrpBalance.
src/libxrpl/ledger/helpers/NFTokenHelpers.cpp Refactors NFT insertion + offer creation helpers to accept SLE/priorBalance and use checkXrpBalance.
src/libxrpl/ledger/helpers/MPTokenHelpers.cpp Refactors MPToken authorization reserve checks to checkXrpBalance and sponsor plumbing.
src/libxrpl/ledger/helpers/AccountRootHelpers.cpp Introduces checkXrpBalance* machinery, fee payer helper relocation, and owner/reserve count adjustments.
include/xrpl/tx/Transactor.h Removes FeePayer API from this header (API-break concern).
include/xrpl/protocol/XRPAmount.h Initializes drops_ and adds negative() helper.
include/xrpl/protocol/STTx.h Renames getFeePayer() to getInitiator() (API-break concern; shim suggested).
include/xrpl/ledger/helpers/SponsorHelpers.h Adds isFeeSponsored and refactors getTxReserveSponsor utilities + sponsor field helpers.
include/xrpl/ledger/helpers/NFTokenHelpers.h Updates function signatures to match new NFT helper APIs.
include/xrpl/ledger/helpers/EscrowHelpers.h Switches escrow helper reserve checks + sponsor wiring to checkXrpBalance.
include/xrpl/ledger/helpers/AccountRootHelpers.h Adds new FeePayer types and checkXrpBalance* APIs + new xrpLiquid overloads.

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

Comment thread src/libxrpl/tx/transactors/payment_channel/PaymentChannelFund.cpp
Comment thread src/libxrpl/ledger/helpers/AccountRootHelpers.cpp Outdated
Comment thread include/xrpl/protocol/STTx.h
Comment thread include/xrpl/tx/Transactor.h
}

// simple + sponsor(re-usage, checks on caller) + balance adjustment
template <class V>

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.

Are all these different versions of the function necessary?

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.

If they more than 1, why not?

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's harder to read and audit, and a larger diff

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.

larger in 1 place, lesser in all usage places (~ 30).

Comment thread include/xrpl/ledger/helpers/AccountRootHelpers.h
XRPAmount
xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j)
static FeePayer
getFeePayerHlp(

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 code would be simpler to read if this was getFeePayer and the sponsorshipSle was just defaulted to empty.

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 is protection for special case. For re-use sponsor. Usually getFeePayer doesn't use it

Comment thread src/libxrpl/ledger/helpers/AccountRootHelpers.cpp Outdated
Comment thread src/libxrpl/ledger/helpers/AccountRootHelpers.cpp
Comment on lines +37 to +45
[[nodiscard]] XRPAmount
xrpLiquid(
ReadView const& view,
SLE::const_ref accSle,
std::int32_t ownerCountAdj,
beast::Journal j);

[[nodiscard]] XRPAmount
xrpLiquid(

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 first helper is only used once in source code and the second helper isn't used at all. I would prefer just refactoring those areas so that we don't need to keep these.

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.

First helper used twice, second maybe left after it was used, need to remove

Comment thread include/xrpl/ledger/helpers/AccountRootHelpers.h
Comment on lines +105 to +106
std::optional<AccountID> const& accID,
std::optional<std::reference_wrapper<SLE::const_pointer const>> const& accOpt,

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.

Why are both these fields needed?

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.

Sometime tx have sle, sometime doesn't, to decrease number of shamap searches.

Comment on lines +109 to +111
std::int32_t ownerCountAdj,
std::int32_t reserveCountAdj,
XRPAmount balanceAdj,

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.

What are the differences between these 3 values?

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.

Aren't they self explanatory?
Owner count adjustement adjust the number of the objectes owned by the account
Reserve count adjustement adjust the number of the accounts "owned" by the account
Balance adjustement adjust the balance of the account.
Adjustments need to make calculation BEFORE actually change the values

XRPAmount balanceAdj,
bool moreThan2, // special case, reserve doesn't check if current ownerCount < 2
beast::Journal j,
bool checkApplicability = true // SponsorTransfer can break relations tx[sfAccount] === accSle

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.

I don't understand what this comment means/what checkApplicability means

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.

There is check tx[sfAccount] === accSle, if not - throw. SponsorTransfer can break it. Flag for special case added

STTx const& tx,
std::optional<AccountID> const& accID,
std::optional<std::reference_wrapper<SLE::const_pointer const>> const& accOpt,
XRPAmount balanceAcc, // if set disable automatic balance calculation

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.

Why is this needed if you're passing in the account SLE?

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.

Special cases when balance passed after some tx manipulations

// additional expenses (balanceAdj). Works through xrpLiquid()

TER
checkXrpBalanceHlp(

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.

IMO a function with this many parameters is a code smell

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.

Ye, that why it is helper, not intended for user usage. If you like to refactor - you should start from amm / token functions, which are not helpers and have more parameters

Comment on lines +68 to +69
if (ret == tecINTERNAL && !view.rules().enabled(fixCleanup3_2_0))
return tefEXCEPTION;

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.

Where did this come from? Looks like a potential consensus breaking change

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.

From that bug that you simulate to keep consensus. It is hard to simulate it now, so we simulate exception

Comment thread include/xrpl/ledger/helpers/SponsorHelpers.h
Comment thread include/xrpl/ledger/helpers/SponsorHelpers.h
Comment on lines +111 to +122
if (sle.isFlag(lsfHighReserve))
{
auto const highAccount = sle.getFieldAmount(sfHighLimit).getIssuer();
if (highAccount == owner)
return sfHighSponsor;
}
if (sle.isFlag(lsfLowReserve))
{
auto const lowAccount = sle.getFieldAmount(sfLowLimit).getIssuer();
if (lowAccount == owner)
return sfLowSponsor;
}

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 feels buggy in bidirectional trustline cases (when both sides of a trustline are paying the reserve)

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 don't think there is such a code (when both sides of a trustline are paying the reserve)

@github-actions

Copy link
Copy Markdown

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

std::int32_t ownerCountAdj,
std::int32_t reserveCountAdj,
XRPAmount balanceAdj,
bool moreThan2, // special case, reserve doesn't check if current ownerCount < 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.

Defining a policy enum can be more descriptive and robust.

enum class ReserveCheckPolicy {
Enforce,
SkipIfOwnerCountBelow2,
};

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