fix Co-Signed Sponsoring Bypasses Sponsor Balance Check

This commit is contained in:
tequ
2026-04-13 15:26:24 +09:00
parent 84e84fbadf
commit 021eaa81bf
2 changed files with 69 additions and 26 deletions

View File

@@ -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
{

View File

@@ -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 <typename SubmitCallback>
void
@@ -5577,6 +5629,7 @@ public:
testSponsorReserve(bool cosigning)
{
testRequireFlag();
testSponsorReserveSimple(cosigning);
testAMM(cosigning);
testCheck(cosigning);
testOffer(cosigning);