diff --git a/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp b/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp index 3c63e3c42b..bf051a45ed 100644 --- a/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp +++ b/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp @@ -271,6 +271,11 @@ SponsorshipTransfer::preclaim(PreclaimContext const& ctx) // check object is sponsored if (!sle->isFieldPresent(sponsorField)) return tecNO_PERMISSION; + + // only the sponsor or sponsee can end sponsorship + auto const sponsor = sle->getAccountID(sponsorField); + if (account != sponsor && account != sponseeAccountID) + return tecNO_PERMISSION; } // check new sponsor have sufficient balance @@ -312,6 +317,11 @@ SponsorshipTransfer::preclaim(PreclaimContext const& ctx) // check account is sponsored if (!sponseeSle->isFieldPresent(sfSponsor)) return tecNO_PERMISSION; + + // only the sponsor or sponsee can end sponsorship + auto const sponsor = sponseeSle->getAccountID(sfSponsor); + if (account != sponsor && account != sponseeAccountID) + return tecNO_PERMISSION; } // check account have sufficient balance diff --git a/src/test/app/Sponsor_test.cpp b/src/test/app/Sponsor_test.cpp index 3b63c7aefe..c875aa2752 100644 --- a/src/test/app/Sponsor_test.cpp +++ b/src/test/app/Sponsor_test.cpp @@ -7,6 +7,8 @@ #include #include +#include "test/jtx/did.h" + namespace xrpl { namespace test { @@ -265,7 +267,7 @@ public: env.fund(XRP(1000000), alice, bob, gw, sp); env.close(); - // Create a vault to get a pseudo acconst count + // Create a vault to get a pseudo account Vault const vault{env}; auto [tx, keylet] = vault.create({.owner = alice, .asset = asset}); env(tx); @@ -733,6 +735,41 @@ public: ter(temMALFORMED)); } + { + // Invalid SponsorshipEnd permission (sponsor object/sponsor account) + Env env{*this, testable_amendments()}; + Account const alice("alice"); + Account const bob("bob"); + Account const sponsor("sponsor"); + env.fund(XRP(10000), alice, bob, sponsor); + env.close(); + + { + // sponsor object + env(did::set(alice), + did::uri("uri"), + sponsor::as(sponsor, spfSponsorReserve), + sig(sfSponsorSignature, sponsor)); + env.close(); + + auto const keylet = keylet::did(alice); + env(sponsor::transfer(bob, tfSponsorshipEnd, keylet.key), + sponsor::sponseeAcc(alice), + ter(tecNO_PERMISSION)); + } + { + // sponsor object + env(sponsor::transfer(alice, tfSponsorshipCreate), + sponsor::as(sponsor, spfSponsorReserve), + sig(sfSponsorSignature, sponsor)); + env.close(); + + env(sponsor::transfer(bob, tfSponsorshipEnd), + sponsor::sponseeAcc(alice), + ter(tecNO_PERMISSION)); + } + } + { // sponsor account Env env{*this, testable_amendments()}; @@ -3232,7 +3269,7 @@ public: env.close(); // for free mptoken checks - // adjustAccountXRPBalance(env, sponsconst or, reserve(env, 2)); + // adjustAccountXRPBalance(env, sponsor, reserve(env, 2)); std::uint32_t const ticketSeq{env.seq(sponsor) + 1}; env(ticket::create(sponsor, 2)); env.close();