diff --git a/src/test/app/Sponsor_test.cpp b/src/test/app/Sponsor_test.cpp index 5640f8c0ce..e293cafad9 100644 --- a/src/test/app/Sponsor_test.cpp +++ b/src/test/app/Sponsor_test.cpp @@ -138,6 +138,13 @@ public: sponsor::sponseeAcc(alice), ter(temBAD_AMOUNT)); } + // Invalid MaxFee + for (auto amt : {XRP(-1), XRP(0), USD(1)}) + { + env(sponsor::set_fee(sponsor, 0, XRP(1), amt), + sponsor::sponseeAcc(alice), + ter(temBAD_AMOUNT)); + } // Invalid reserveCount env(sponsor::set_reserve(sponsor, 0, 0), @@ -153,6 +160,14 @@ public: ter(temMALFORMED)); // TODO: test MaxFee with tfDeleteObject + // Invalid SponsorAccount with non-Delete operation + env(sponsor::set_reserve(sponsor, 0, 100), + sponsor::sponsorAcc(alice), + ter(temMALFORMED)); + env(sponsor::set_fee(sponsor, 0, XRP(1), XRP(1)), + sponsor::sponsorAcc(alice), + ter(temMALFORMED)); + // // preclaim // @@ -162,14 +177,21 @@ public: sponsor::sponseeAcc(noFunded), ter(tecNO_DST)); - // Invalid Delete operation (not found) + // Invalid Delete operation (sponsorship not found) env(sponsor::set(sponsor, tfDeleteObject), sponsor::sponseeAcc(alice), ter(tecNO_ENTRY)); // DisallowIncomingSponsor: tested in other testcase + // insufficent reserve to create sponsorship + adjustAccountXRPBalance(env, sponsor, reserve(env, 1) - drops(1)); + env(sponsor::set(sponsor, 0, 100, XRP(100)), + sponsor::sponseeAcc(alice), + ter(tecUNFUNDED)); + // create sponsor to use above tests + adjustAccountXRPBalance(env, sponsor, reserve(env, 1)); env(sponsor::set(sponsor, 0, 100, XRP(100)), sponsor::sponseeAcc(alice), ter(tesSUCCESS)); @@ -612,14 +634,12 @@ public: Account const bob("bob"); Account const sponsor1("sponsor1"); Account const sponsor2("sponsor2"); - env.fund(XRP(10000), alice, bob); - env.fund( - env.current()->fees().reserve + - env.current()->fees().increment - drops(1), - sponsor1, - sponsor2); + env.fund(XRP(10000), alice, bob, sponsor1, sponsor2); env.close(); + adjustAccountXRPBalance(env, sponsor1, reserve(env, 1) - drops(1)); + adjustAccountXRPBalance(env, sponsor2, reserve(env, 1) - drops(1)); + auto const seq = env.seq(alice); env(check::create(alice, bob, XRP(1))); env.close(); @@ -636,6 +656,13 @@ public: env(pay(alice, sponsor1, drops(1))); env.close(); + // Invalid ObjectID (not found) + env(sponsor::transfer(alice, keylet::check(alice, 0).key), + sponsor::as(sponsor1, tfSponsorReserve), + sig(sfSponsorSignature, sponsor1), + ter(tecNO_ENTRY)); + env.close(); + // Invalid Owner env(sponsor::transfer(bob, checkId), sponsor::as(sponsor1, tfSponsorReserve), @@ -688,20 +715,26 @@ public: BEAST_EXPECT(sle2->getAccountID(sfSponsorAccount) == sponsor2.id()); // dissolve sponsor - env(pay(alice, - sponsor2, - (env.balance(alice).value() - - env.current()->fees().reserve - - env.current()->fees().increment - XRP(1) + drops(1))), - fee(XRP(1))); - env.close(); + adjustAccountXRPBalance(env, alice, reserve(env, 1) - drops(1)); env(sponsor::transfer(alice, checkId), ter(tecINSUFFICIENT_RESERVE)); env.close(); - env(pay(sponsor2, alice, XRP(1))); + adjustAccountXRPBalance(env, alice, reserve(env, 1)); + + // object doesn't sponsored + auto const ticketSeq = env.seq(alice); + env(ticket::create(alice, 1)); env.close(); + auto ticketId = keylet::ticket(alice, ticketSeq + 1).key; + BEAST_EXPECT(env.le(keylet::unchecked(ticketId))); + env(sponsor::transfer(alice, ticketId), ter(tecNO_PERMISSION)); + env.close(); + env(noop(alice), ticket::use(ticketSeq + 1)); + env.close(); + + adjustAccountXRPBalance(env, alice, reserve(env, 1)); env(sponsor::transfer(alice, checkId)); env.close(); @@ -4351,6 +4384,59 @@ public: Account const bob("bob"); Account const carol("carol"); + // + // SponsorshipTransfer + // + { + Env env{*this, testable_amendments()}; + env.fund(XRP(1000000), alice, bob, carol); + env.close(); + + auto const seq = env.seq(alice); + env(check::create(alice, bob, XRP(1))); + env.close(); + + auto const keylet = keylet::check(alice, seq); + + env(sponsor::transfer(alice, keylet.key), + sponsor::as(bob, tfSponsorReserve), + sig(sfSponsorSignature, bob), + delegate::as(carol), + ter(terNO_DELEGATE_PERMISSION)); + + env(delegate::set(alice, carol, {"SponsorshipTransfer"})); + env.close(); + + env(sponsor::transfer(alice, keylet.key), + sponsor::as(bob, tfSponsorReserve), + sig(sfSponsorSignature, bob), + delegate::as(carol), + ter(tesSUCCESS)); + env.close(); + } + // + // SponsorshipSet + // + { + Env env{*this, testable_amendments()}; + env.fund(XRP(1000000), alice, bob, carol); + env.close(); + + env(sponsor::set(alice, 0, 100, XRP(100)), + sponsor::sponseeAcc(bob), + delegate::as(carol), + ter(terNO_DELEGATE_PERMISSION)); + + env(delegate::set(alice, carol, {"SponsorshipSet"})); + env.close(); + + env(sponsor::set(alice, 0, 100, XRP(100)), + sponsor::sponseeAcc(bob), + delegate::as(carol), + ter(tesSUCCESS)); + env.close(); + } + // // Permission SponsorFee // diff --git a/src/xrpld/app/tx/detail/SponsorshipSet.cpp b/src/xrpld/app/tx/detail/SponsorshipSet.cpp index c2d19276d8..5aef0cb899 100644 --- a/src/xrpld/app/tx/detail/SponsorshipSet.cpp +++ b/src/xrpld/app/tx/detail/SponsorshipSet.cpp @@ -43,10 +43,6 @@ SponsorshipSet::preflight(PreflightContext const& ctx) !ctx.tx.isFieldPresent(sfSponsee))) return temMALFORMED; - // if (ctx.tx.isFieldPresent(sfSponsorAccount) && - // !ctx.tx.isFlag(tfDeleteObject)) - // return temMALFORMED; - auto const sponsor = ctx.tx.isFieldPresent(sfSponsorAccount) ? ctx.tx.getAccountID(sfSponsorAccount) : ctx.tx.getAccountID(sfAccount); @@ -186,7 +182,7 @@ SponsorshipSet::doApply() auto const sponsorAccSle = ctx_.view().peek(keylet::account(sponsorAcc)); if (!sponsorAccSle) - return tecINTERNAL; + return tecINTERNAL; // LCOV_EXCL_LINE auto const sponsorObjSle = ctx_.view().peek(keylet); @@ -345,7 +341,7 @@ SponsorshipSet::deleteSponsorship( // adjust balance auto const sponsorAccSle = view.peek(keylet::account(sponsor)); if (!sponsorAccSle) - return tecINTERNAL; + return tecINTERNAL; // LCOV_EXCL_LINE auto const feeAmount = sle->getFieldAmount(sfFeeAmount); (*sponsorAccSle)[sfBalance] += feeAmount; diff --git a/src/xrpld/app/tx/detail/SponsorshipTransfer.cpp b/src/xrpld/app/tx/detail/SponsorshipTransfer.cpp index d1f9fddb96..a379c575c0 100644 --- a/src/xrpld/app/tx/detail/SponsorshipTransfer.cpp +++ b/src/xrpld/app/tx/detail/SponsorshipTransfer.cpp @@ -134,10 +134,12 @@ getLedgerEntrySponsorField(T const& sle, AccountID const& owner) if (lowAccount == owner) return sfLowSponsorAccount; } + // LCOV_EXCL_START XRPL_ASSERT( false, "Should not happen. Owner should be checked before calling " "this function."); + // LCOV_EXCL_END } default: return sfSponsorAccount; @@ -178,7 +180,8 @@ SponsorshipTransfer::preclaim(PreclaimContext const& ctx) // transfer sponsor // check if the object owner isn't the same as the new sponsor if ((*newSponsor)->getAccountID(sfAccount) == owner) - return tecNO_PERMISSION; + // checked in above + return tecINTERNAL; // LCOV_EXCL_LINE } } else