diff --git a/src/test/app/MPToken_test.cpp b/src/test/app/MPToken_test.cpp index 0cac8811366..029ddc214b0 100644 --- a/src/test/app/MPToken_test.cpp +++ b/src/test/app/MPToken_test.cpp @@ -1015,6 +1015,28 @@ class MPToken_test : public beast::unit_test::suite // destroyed, it should fail mptAlice.pay(alice, bob, 100, tecMPT_ISSUANCE_NOT_FOUND); } + + // Issuers issues maximum amount of MPT to a holder, the holder should + // be able to transfer the max amount to someone else + { + Env env{*this, features}; + Account const alice("alice"); + Account const carol("bob"); + Account const bob("carol"); + + MPTTester mptAlice(env, alice, {.holders = {&bob, &carol}}); + + mptAlice.create( + {.maxAmt = 100, .ownerCount = 1, .flags = tfMPTCanTransfer}); + + mptAlice.authorize({.account = &bob}); + mptAlice.authorize({.account = &carol}); + + mptAlice.pay(alice, bob, 100); + + // transfer max amount to another holder + mptAlice.pay(bob, carol, 100); + } } void diff --git a/src/xrpld/ledger/detail/View.cpp b/src/xrpld/ledger/detail/View.cpp index 3a422c0c88a..ad1d5d05faa 100644 --- a/src/xrpld/ledger/detail/View.cpp +++ b/src/xrpld/ledger/detail/View.cpp @@ -1353,6 +1353,20 @@ rippleSend( if (uSenderID == issuer || uReceiverID == issuer || issuer == noAccount()) { + // if sender is issuer, check that the new OutstandingAmount will not + // exceed MaximumAmount + if (uSenderID == issuer) + { + auto const mptID = keylet::mptIssuance(saAmount.issue().getMptID()); + auto const sle = view.peek(mptID); + if (!sle) + return tecMPT_ISSUANCE_NOT_FOUND; + + if (sle->getFieldU64(sfOutstandingAmount) + saAmount.value() > + (*sle)[~sfMaximumAmount].value_or(maxMPTokenAmount)) + return tecMPT_MAX_AMOUNT_EXCEEDED; + } + // Direct send: redeeming IOUs and/or sending own IOUs. auto const ter = rippleCredit(view, uSenderID, uReceiverID, saAmount, j); @@ -1380,8 +1394,8 @@ rippleSend( rippleCredit(view, issuer, uReceiverID, saAmount, j); terResult != tesSUCCESS) return terResult; - else - return rippleCredit(view, uSenderID, issuer, saActual, j); + + return rippleCredit(view, uSenderID, issuer, saActual, j); } return tecINTERNAL; @@ -1872,10 +1886,6 @@ rippleCredit( sfOutstandingAmount, sle->getFieldU64(sfOutstandingAmount) + saAmount.value()); - if (sle->getFieldU64(sfOutstandingAmount) > - (*sle)[~sfMaximumAmount].value_or(maxMPTokenAmount)) - return tecMPT_MAX_AMOUNT_EXCEEDED; - view.update(sle); } else