From 688e568e397cb763733b5984e5d144e0546a5912 Mon Sep 17 00:00:00 2001 From: tequ Date: Thu, 30 Apr 2026 09:58:36 +0900 Subject: [PATCH] fix: getLedgerEntryOwner missing ltLOAN_BROKER and ltLOAN prevents object sponsorship --- .../Sponsor/SponsorshipTransfer.cpp | 3 + src/test/app/Sponsor_test.cpp | 66 +++++++++++++++++-- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp b/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp index 8f07ed6bb5..695d1b7c1c 100644 --- a/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp +++ b/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp @@ -118,6 +118,7 @@ getLedgerEntryOwner(ReadView const& view, T const& sle, AccountID const& account case ltORACLE: case ltPERMISSIONED_DOMAIN: case ltVAULT: + case ltLOAN_BROKER: return sle->getAccountID(sfOwner); case ltCHECK: case ltDID: @@ -134,6 +135,8 @@ getLedgerEntryOwner(ReadView const& view, T const& sle, AccountID const& account return sle->getAccountID(sfAccount); case ltMPTOKEN_ISSUANCE: return sle->getAccountID(sfIssuer); + case ltLOAN: + return sle->getAccountID(sfBorrower); case ltSIGNER_LIST: { auto const signerList = view.read(keylet::signers(account)); if (!signerList) diff --git a/src/test/app/Sponsor_test.cpp b/src/test/app/Sponsor_test.cpp index 987fdbbb69..2f2bdf3d95 100644 --- a/src/test/app/Sponsor_test.cpp +++ b/src/test/app/Sponsor_test.cpp @@ -5129,11 +5129,12 @@ public: Account const bob("bob"); Account const issuer("issuer"); Account const sponsor("sponsor"); + Account const sponsor2("sponsor2"); // LoanBrokerSet / LoanBrokerDelete { Env env{*this, testable_amendments()}; - env.fund(XRP(1000000), alice, bob, sponsor); + env.fund(XRP(1000000), alice, bob, sponsor, sponsor2); env.close(); PrettyAsset const asset{xrpIssue(), 1'000'000}; @@ -5167,14 +5168,41 @@ public: BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 1); BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 1); - // LoanBrokerDelete auto const brokerKeylet = keylet::loanbroker(alice.id(), env.seq(alice) - 1); + + if (cosigning) + { + // transfer sponsor + env(sponsor::transfer(alice, tfSponsorshipReassign, brokerKeylet.key), + sponsor::as(sponsor2, spfSponsorReserve), + sig(sfSponsorSignature, sponsor2)); + env.close(); + } + else + { + env(sponsor::set_reserve(sponsor2, 0, 1), sponsor::sponseeAcc(alice)); + env.close(); + + // transfer sponsor + env(sponsor::transfer(alice, tfSponsorshipReassign, brokerKeylet.key), + sponsor::as(sponsor2, spfSponsorReserve)); + env.close(); + } + + BEAST_EXPECT( + ownerCount(env, alice) == + 5); // LoanBroker, PseudoAccount(LB), (Vault, PseudoAccount(Vault), MPToken(Vault)) + BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 1); + BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 0); + BEAST_EXPECT(sponsoringOwnerCount(env, sponsor2) == 1); + + // LoanBrokerDelete env(loanBroker::del(alice, brokerKeylet.key, 0)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 3); BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 0); - BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 0); + BEAST_EXPECT(sponsoringOwnerCount(env, sponsor2) == 0); } // LoanBrokerConverDeposit/Withdraw/Clawback @@ -5258,7 +5286,7 @@ public: // LoanSet { Env env{*this, testable_amendments()}; - env.fund(XRP(1000000), alice, bob, issuer, sponsor); + env.fund(XRP(1000000), alice, bob, issuer, sponsor, sponsor2); env.close(); MPTTester mptt{env, issuer, mptInitNoFund}; @@ -5346,6 +5374,36 @@ public: BEAST_EXPECT(ownerCount(env, alice) == 2); BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 1); + // before transfer + BEAST_EXPECT(ownerCount(env, alice) == 2); + BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 1); + BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 1); + + if (cosigning) + { + // transfer sponsor + env(sponsor::transfer(alice, tfSponsorshipReassign, loanKeylet.key), + sponsor::as(sponsor2, spfSponsorReserve), + sig(sfSponsorSignature, sponsor2)); + env.close(); + } + else + { + env(sponsor::set_reserve(sponsor2, 0, 1), sponsor::sponseeAcc(alice)); + env.close(); + + // transfer sponsor + env(sponsor::transfer(alice, tfSponsorshipReassign, loanKeylet.key), + sponsor::as(sponsor2, spfSponsorReserve)); + env.close(); + } + + // after transfer + BEAST_EXPECT(ownerCount(env, alice) == 2); + BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 1); + BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 0); + BEAST_EXPECT(sponsoringOwnerCount(env, sponsor2) == 1); + // LoanDelete env(loan::del(alice, loanKeylet.key), sponsor::as(sponsor, spfSponsorReserve),