diff --git a/src/libxrpl/tx/Transactor.cpp b/src/libxrpl/tx/Transactor.cpp index 2aefaa4a08..b2e48f93a1 100644 --- a/src/libxrpl/tx/Transactor.cpp +++ b/src/libxrpl/tx/Transactor.cpp @@ -1211,7 +1211,12 @@ Transactor::reset(XRPAmount fee) // If for some reason we are unable to consume the ticket or sequence // then the ledger is corrupted. Rather than make things worse we // reject the transaction. - payerSle->setFieldAmount(payer.balanceField, balance - fee); + auto const feeAmountAfter = balance - fee; + if (feeAmountAfter == beast::zero && payer.balanceField == sfFeeAmount) + // Because ltSponsorship.sfFeeAmount is soeOptional + payerSle->makeFieldAbsent(payer.balanceField); + else + payerSle->setFieldAmount(payer.balanceField, feeAmountAfter); TER const ter{consumeSeqProxy(txnAcct)}; XRPL_ASSERT(isTesSuccess(ter), "xrpl::Transactor::reset : result is tesSUCCESS"); diff --git a/src/test/app/Sponsor_test.cpp b/src/test/app/Sponsor_test.cpp index b48c81660e..d14fe7a298 100644 --- a/src/test/app/Sponsor_test.cpp +++ b/src/test/app/Sponsor_test.cpp @@ -7,6 +7,7 @@ #include #include +#include "test/jtx/check.h" #include "test/jtx/did.h" namespace xrpl { @@ -1448,8 +1449,8 @@ public: env.fund(XRP(10000), alice, bob, sponsor); env.close(); - auto const sponsorFeeBalance = [&](Account const& sponsor, Account const& alice) { - return env.le(keylet::sponsor(sponsor, alice))->getFieldAmount(sfFeeAmount).xrp(); + auto const sponsorFeeBalance = [&](Account const& sponsor, Account const& sponsee) { + return env.le(keylet::sponsor(sponsor, sponsee))->getFieldAmount(sfFeeAmount).xrp(); }; { @@ -1578,6 +1579,24 @@ public: BEAST_EXPECT(env.balance(sponsor) == sponsorBalance); BEAST_EXPECT(sponsorFeeBalance(sponsor, alice) == sponsorFee - feeAmt); } + + // make sfFeeAmount absent if tec error and all fee is paid + { + // reset FeeAmount and MaxFee + env(sponsor::del(sponsor), sponsor::sponseeAcc(alice)); + env(sponsor::set_fee(sponsor, 0, XRP(10)), sponsor::sponseeAcc(alice)); + env.close(); + + BEAST_EXPECT(env.le(keylet::sponsor(sponsor, alice))->isFieldPresent(sfFeeAmount)); + auto sponsorAvailableFee = sponsorFeeBalance(sponsor, alice); + printf("sponsorAvailableFee: %s\n", to_string(sponsorAvailableFee).c_str()); + env(check::cancel(alice, uint256(1)), + fee(sponsorAvailableFee), + sponsor::as(sponsor, spfSponsorFee), + ter(tecNO_ENTRY)); + env.close(); + BEAST_EXPECT(!env.le(keylet::sponsor(sponsor, alice))->isFieldPresent(sfFeeAmount)); + } } // test lsfSponsorshipRequireSignForFee