diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index f861aff41c..3efd6ab2b7 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -326,37 +326,27 @@ checkInsufficientReserve( auto const sle = view.read( keylet::sponsor(sponsorSle->getAccountID(sfAccount), accSle->getAccountID(sfAccount))); - if (isCoSigning) + if (!isCoSigning && !sle) + // prefunded sponsor should have a sponsorship entry + return tecINTERNAL; // LCOV_EXCL_LINE + + if (sle) { - if (sle) - { - auto const reserveCountAllowed = sle->getFieldU32(sfReserveCount); - if (reserveCountAllowed < ownerCountDelta) - return tecINSUFFICIENT_RESERVE; - - return tesSUCCESS; - } - auto const sponsorBalance = sponsorSle->getFieldAmount(sfBalance); - STAmount const sponsorReserve{view.fees().accountReserve( - sponsorSle->getFieldU32(sfOwnerCount), - sponsorSle->getFieldU32(sfSponsoredOwnerCount), - sponsorSle->getFieldU32(sfSponsoringOwnerCount) + ownerCountDelta, - sponsorSle->isFieldPresent(sfSponsor), - sponsorSle->getFieldU32(sfSponsoringAccountCount) + accountCountDelta)}; - - if (sponsorBalance < sponsorReserve) - return tecINSUFFICIENT_RESERVE; - } - else - { - // pre funded - if (!sle) - return tecINTERNAL; // LCOV_EXCL_LINE - auto const reserveCountAllowed = sle->getFieldU32(sfReserveCount); if (reserveCountAllowed < ownerCountDelta) return tecINSUFFICIENT_RESERVE; } + + auto const sponsorBalance = sponsorSle->getFieldAmount(sfBalance); + STAmount const sponsorReserve{view.fees().accountReserve( + sponsorSle->getFieldU32(sfOwnerCount), + sponsorSle->getFieldU32(sfSponsoredOwnerCount), + sponsorSle->getFieldU32(sfSponsoringOwnerCount) + ownerCountDelta, + sponsorSle->isFieldPresent(sfSponsor), + sponsorSle->getFieldU32(sfSponsoringAccountCount) + accountCountDelta)}; + + if (sponsorBalance < sponsorReserve) + return tecINSUFFICIENT_RESERVE; } else { diff --git a/src/test/app/Sponsor_test.cpp b/src/test/app/Sponsor_test.cpp index 9c48f8ba25..cad1892fca 100644 --- a/src/test/app/Sponsor_test.cpp +++ b/src/test/app/Sponsor_test.cpp @@ -1854,6 +1854,58 @@ public: } } + void + testSponsorReserveSimple(bool cosigning) + { + testcase("SponsorReserveSimple"); + using namespace test::jtx; + Env env{*this, testable_amendments()}; + Account const alice("alice"); + Account const sponsor("sponsor"); + + env.fund(XRP(10000), alice, sponsor); + env.close(); + + // test Sufficient sponsor balance + if (cosigning) + { + adjustAccountXRPBalance(env, sponsor, reserve(env, 99)); + + env(ticket::create(alice, 100), + sponsor::as(sponsor, spfSponsorReserve), + sig(sfSponsorSignature, sponsor), + ter(tecINSUFFICIENT_RESERVE)); + env.close(); + + adjustAccountXRPBalance(env, sponsor, reserve(env, 100)); + + env(ticket::create(alice, 100), + sponsor::as(sponsor, spfSponsorReserve), + sig(sfSponsorSignature, sponsor), + ter(tesSUCCESS)); + env.close(); + } + else + { + env(sponsor::set_reserve(sponsor, 0, 250), sponsor::sponseeAcc(alice)); + env.close(); + + adjustAccountXRPBalance(env, sponsor, reserve(env, 99 + 1 /* sponsor object*/)); + + env(ticket::create(alice, 100), + sponsor::as(sponsor, spfSponsorReserve), + ter(tecINSUFFICIENT_RESERVE)); + env.close(); + + adjustAccountXRPBalance(env, sponsor, reserve(env, 100 + 1 /* sponsor object*/)); + + env(ticket::create(alice, 100), + sponsor::as(sponsor, spfSponsorReserve), + ter(tesSUCCESS)); + env.close(); + } + } + // test helper for both cosigning and pre-funded sponsorship template void @@ -5577,6 +5629,7 @@ public: testSponsorReserve(bool cosigning) { testRequireFlag(); + testSponsorReserveSimple(cosigning); testAMM(cosigning); testCheck(cosigning); testOffer(cosigning);