20#include <xrpld/app/misc/AMMHelpers.h> 
   21#include <xrpld/app/misc/AMMUtils.h> 
   22#include <xrpld/app/tx/detail/InvariantCheck.h> 
   23#include <xrpld/app/tx/detail/NFTokenUtils.h> 
   24#include <xrpld/app/tx/detail/PermissionedDomainSet.h> 
   26#include <xrpl/basics/Log.h> 
   27#include <xrpl/beast/utility/instrumentation.h> 
   28#include <xrpl/ledger/CredentialHelpers.h> 
   29#include <xrpl/ledger/ReadView.h> 
   30#include <xrpl/ledger/View.h> 
   31#include <xrpl/protocol/Feature.h> 
   32#include <xrpl/protocol/Indexes.h> 
   33#include <xrpl/protocol/LedgerFormats.h> 
   34#include <xrpl/protocol/MPTIssue.h> 
   35#include <xrpl/protocol/SField.h> 
   36#include <xrpl/protocol/STArray.h> 
   37#include <xrpl/protocol/STNumber.h> 
   38#include <xrpl/protocol/SystemParameters.h> 
   39#include <xrpl/protocol/TER.h> 
   40#include <xrpl/protocol/TxFormats.h> 
   41#include <xrpl/protocol/Units.h> 
   42#include <xrpl/protocol/nftPageMask.h> 
   96    return safe_cast<Privilege>(
 
 
  101#pragma push_macro("TRANSACTION") 
  104#define TRANSACTION(tag, value, name, delegatable, amendment, privileges, ...) \ 
  106        return (privileges) & priv;                                            \ 
  114#include <xrpl/protocol/detail/transactions.macro> 
 
  122#pragma pop_macro("TRANSACTION") 
  144        JLOG(j.
fatal()) << 
"Invariant failed: fee paid was negative: " 
  153        JLOG(j.
fatal()) << 
"Invariant failed: fee paid exceeds system limit: " 
  162        JLOG(j.
fatal()) << 
"Invariant failed: fee paid is " << fee.
drops()
 
  163                        << 
" exceeds fee specified in transaction.";
 
 
  187        switch (before->getType())
 
  190                drops_ -= (*before)[sfBalance].xrp().drops();
 
  194                    ((*before)[sfAmount] - (*before)[sfBalance]).xrp().drops();
 
  197                if (
isXRP((*before)[sfAmount]))
 
  198                    drops_ -= (*before)[sfAmount].xrp().drops();
 
  207        switch (
after->getType())
 
  210                drops_ += (*after)[sfBalance].xrp().drops();
 
  214                    drops_ += ((*after)[sfAmount] - (*after)[sfBalance])
 
  220                    drops_ += (*after)[sfAmount].xrp().drops();
 
 
  240        JLOG(j.
fatal()) << 
"Invariant failed: XRP net change was positive: " 
  248        JLOG(j.
fatal()) << 
"Invariant failed: XRP net change of " << 
drops_ 
  249                        << 
" doesn't match fee " << fee.
drops();
 
 
  264    auto isBad = [](
STAmount const& balance) {
 
  265        if (!balance.native())
 
  268        auto const drops = balance.xrp();
 
  282    if (before && before->getType() == ltACCOUNT_ROOT)
 
  283        bad_ |= isBad((*before)[sfBalance]);
 
  285    if (
after && 
after->getType() == ltACCOUNT_ROOT)
 
 
  299        JLOG(j.
fatal()) << 
"Invariant failed: incorrect account XRP balance";
 
 
  316        if (pays < beast::zero)
 
  319        if (gets < beast::zero)
 
  323        return pays.
native() && gets.native();
 
  326    if (before && before->getType() == ltOFFER)
 
  327        bad_ |= isBad((*before)[sfTakerPays], (*before)[sfTakerGets]);
 
  330        bad_ |= isBad((*
after)[sfTakerPays], (*after)[sfTakerGets]);
 
 
  343        JLOG(j.
fatal()) << 
"Invariant failed: offer with a bad amount";
 
 
  358    auto isBad = [](
STAmount const& amount) {
 
  371            if (amount.holds<
Issue>())
 
  373                if (amount <= beast::zero)
 
  383                if (amount <= beast::zero)
 
  393    if (before && before->getType() == ltESCROW)
 
  394        bad_ |= isBad((*before)[sfAmount]);
 
  404    if (
after && 
after->getType() == ltMPTOKEN_ISSUANCE)
 
  406        auto const outstanding = (*after)[sfOutstandingAmount];
 
  407        checkAmount(outstanding);
 
  408        if (
auto const locked = (*
after)[~sfLockedAmount])
 
  410            checkAmount(*locked);
 
  411            bad_ = outstanding < *locked;
 
  417        auto const mptAmount = (*after)[sfMPTAmount];
 
  418        checkAmount(mptAmount);
 
  419        if (
auto const locked = (*
after)[~sfLockedAmount])
 
  421            checkAmount(*locked);
 
 
  436        JLOG(j.
fatal()) << 
"Invariant failed: escrow specifies invalid amount";
 
 
  451    if (isDelete && before && before->getType() == ltACCOUNT_ROOT)
 
 
  473            JLOG(j.
fatal()) << 
"Invariant failed: account deletion " 
  474                               "succeeded without deleting an account";
 
  476            JLOG(j.
fatal()) << 
"Invariant failed: account deletion " 
  477                               "succeeded but deleted multiple accounts!";
 
  491    JLOG(j.
fatal()) << 
"Invariant failed: an account root was deleted";
 
 
  503    if (isDelete && before && before->getType() == ltACCOUNT_ROOT)
 
 
  519    [[maybe_unused]] 
bool const enforce =
 
  523    auto const objectExists = [&view, enforce, &j](
auto const& keylet) {
 
  525        if (
auto const sle = view.
read(keylet))
 
  528            auto const typeName = [&sle]() {
 
  533                    return item->getName();
 
  538                << 
"Invariant failed: account deletion left behind a " 
  539                << typeName << 
" object";
 
  544                "ripple::AccountRootsDeletedClean::finalize::objectExists : " 
  545                "account deletion left no objects behind");
 
  553        auto const accountID = accountSLE->getAccountID(sfAccount);
 
  557            if (objectExists(
std::invoke(keyletfunc, accountID)) && enforce)
 
  572            if (key && objectExists(
Keylet{ltNFTOKEN_PAGE, *key}) && enforce)
 
  580            if (accountSLE->isFieldPresent(*field))
 
  582                auto const key = accountSLE->getFieldH256(*field);
 
 
  600    if (before && 
after && before->getType() != 
after->getType())
 
  605#pragma push_macro("LEDGER_ENTRY") 
  608#define LEDGER_ENTRY(tag, ...) case tag: 
  610        switch (
after->getType())
 
  612#include <xrpl/protocol/detail/ledger_entries.macro> 
  621#pragma pop_macro("LEDGER_ENTRY") 
 
  638        JLOG(j.
fatal()) << 
"Invariant failed: ledger entry type mismatch";
 
  643        JLOG(j.
fatal()) << 
"Invariant failed: invalid ledger entry type added";
 
 
  657    if (
after && 
after->getType() == ltRIPPLE_STATE)
 
 
  679    JLOG(j.
fatal()) << 
"Invariant failed: an XRP trust line was created";
 
 
  691    if (
after && 
after->getType() == ltRIPPLE_STATE)
 
  701            (lowDeepFreeze && !lowFreeze) || (highDeepFreeze && !highFreeze);
 
 
  716    JLOG(j.
fatal()) << 
"Invariant failed: a trust line with deep freeze flag " 
  717                       "without normal freeze was created";
 
 
  745    if (balanceChange.signum() == 0)
 
 
  777    [[maybe_unused]] 
bool const enforce =
 
  782        auto const issuerSle = 
findIssuer(issue.account, view);
 
  791                "ripple::TransfersNotFrozen::finalize : enforce " 
 
  816        after, 
"ripple::TransfersNotFrozen::isValidEntry : valid after.");
 
  822    if (
after->getType() == ltACCOUNT_ROOT)
 
  834    return after->getType() == ltRIPPLE_STATE &&
 
  835        (!before || before->getType() == ltRIPPLE_STATE);
 
 
  844    auto const getBalance = [](
auto const& line, 
auto const& other, 
bool zero) {
 
  846            line ? line->at(sfBalance) : other->at(sfBalance).zeroed();
 
  847        return zero ? amt.
zeroed() : amt;
 
  855    auto const balanceBefore = getBalance(before, 
after, 
false);
 
  862    auto const balanceAfter = getBalance(
after, before, isDelete);
 
  864    return balanceAfter - balanceBefore;
 
 
  872        "ripple::TransfersNotFrozen::recordBalance : valid trustline " 
  876        changes.senders.emplace_back(std::move(change));
 
  878        changes.receivers.emplace_back(std::move(change));
 
 
  886    auto const balanceChangeSign = balanceChange.
signum();
 
  887    auto const currency = 
after->at(sfBalance).getCurrency();
 
  891        {currency, 
after->at(sfHighLimit).getIssuer()},
 
  892        {
after, balanceChangeSign});
 
  896        {currency, 
after->at(sfLowLimit).getIssuer()},
 
  897        {
after, -balanceChangeSign});
 
 
  939        for (
auto const& change : actors)
 
  941            bool const high = change.line->at(sfLowLimit).getIssuer() ==
 
  942                issuer->at(sfAccount);
 
  945                    change, high, tx, j, enforce, globalFreeze))
 
 
  965    bool const deepFreeze =
 
  967    bool const frozen = globalFreeze || deepFreeze || freeze;
 
  979        JLOG(j.
debug()) << 
"Invariant check allowing funds to be moved " 
  981                        << 
" a frozen trustline for AMMClawback " 
  986    JLOG(j.
fatal()) << 
"Invariant failed: Attempting to move frozen funds for " 
  991        "ripple::TransfersNotFrozen::validateFrozenState : enforce " 
 
 1010    if (!before && 
after->getType() == ltACCOUNT_ROOT)
 
 
 1032        JLOG(j.
fatal()) << 
"Invariant failed: multiple accounts " 
 1033                           "created in a single transaction";
 
 1040        bool const pseudoAccount =
 
 1045            JLOG(j.
fatal()) << 
"Invariant failed: pseudo-account created by a " 
 1046                               "wrong transaction type";
 
 1059            JLOG(j.
fatal()) << 
"Invariant failed: account created with " 
 1060                               "wrong starting sequence number";
 
 1071                    << 
"Invariant failed: pseudo-account created with " 
 1080    JLOG(j.
fatal()) << 
"Invariant failed: account root created illegally";
 
 
 1093    static constexpr uint256 const accountBits = ~pageBits;
 
 1095    if ((before && before->getType() != ltNFTOKEN_PAGE) ||
 
 1096        (
after && 
after->getType() != ltNFTOKEN_PAGE))
 
 1100        uint256 const account = sle->key() & accountBits;
 
 1101        uint256 const hiLimit = sle->key() & pageBits;
 
 1109            if (account != (*prev & accountBits))
 
 1112            if (hiLimit <= (*prev & pageBits))
 
 1116        if (
auto const next = (*sle)[~sfNextPageMin])
 
 1118            if (account != (*next & accountBits))
 
 1121            if (hiLimit >= (*next & pageBits))
 
 1126            auto const& nftokens = sle->getFieldArray(sfNFTokens);
 
 1129            if (
std::size_t const nftokenCount = nftokens.size();
 
 1130                (!isDelete && nftokenCount == 0) ||
 
 1137                prev ? *prev & pageBits : 
uint256(beast::zero);
 
 1141            for (
auto const& obj : nftokens)
 
 1143                uint256 const tokenID = obj[sfNFTokenID];
 
 1150                if (
uint256 const tokenPageBits = tokenID & pageBits;
 
 1151                    tokenPageBits < loLimit || tokenPageBits >= hiLimit)
 
 1154                if (
auto uri = obj[~sfURI]; uri && uri->empty())
 
 1168            before->isFieldPresent(sfPreviousPageMin))
 
 1177    if (!isDelete && before && 
after)
 
 1185            before->isFieldPresent(sfNextPageMin) &&
 
 1186            !
after->isFieldPresent(sfNextPageMin))
 
 
 1203        JLOG(j.
fatal()) << 
"Invariant failed: NFT page is improperly linked.";
 
 1209        JLOG(j.
fatal()) << 
"Invariant failed: NFT found in incorrect page.";
 
 1215        JLOG(j.
fatal()) << 
"Invariant failed: NFTs on page are not sorted.";
 
 1221        JLOG(j.
fatal()) << 
"Invariant failed: NFT contains empty URI.";
 
 1227        JLOG(j.
fatal()) << 
"Invariant failed: NFT page has invalid size.";
 
 1235            JLOG(j.
fatal()) << 
"Invariant failed: Last NFT page deleted with " 
 1236                               "non-empty directory.";
 
 1241            JLOG(j.
fatal()) << 
"Invariant failed: Lost NextMinPage link.";
 
 
 1256    if (before && before->getType() == ltACCOUNT_ROOT)
 
 1262    if (
after && 
after->getType() == ltACCOUNT_ROOT)
 
 
 1281            JLOG(j.
fatal()) << 
"Invariant failed: the number of minted tokens " 
 1282                               "changed without a mint transaction!";
 
 1288            JLOG(j.
fatal()) << 
"Invariant failed: the number of burned tokens " 
 1289                               "changed without a burn transaction!";
 
 1301                << 
"Invariant failed: successful minting didn't increase " 
 1302                   "the number of minted tokens.";
 
 1308            JLOG(j.
fatal()) << 
"Invariant failed: failed minting changed the " 
 1309                               "number of minted tokens.";
 
 1316                << 
"Invariant failed: minting changed the number of " 
 1329                    << 
"Invariant failed: successful burning didn't increase " 
 1330                       "the number of burned tokens.";
 
 1337            JLOG(j.
fatal()) << 
"Invariant failed: failed burning changed the " 
 1338                               "number of burned tokens.";
 
 1345                << 
"Invariant failed: burning changed the number of " 
 
 1362    if (before && before->getType() == ltRIPPLE_STATE)
 
 1365    if (before && before->getType() == ltMPTOKEN)
 
 
 1385                << 
"Invariant failed: more than one trustline changed.";
 
 1392                << 
"Invariant failed: more than one mptokens changed.";
 
 1404            if (holderBalance.
signum() < 0)
 
 1407                    << 
"Invariant failed: trustline balance is negative";
 
 1416            JLOG(j.
fatal()) << 
"Invariant failed: some trustlines were changed " 
 1417                               "despite failure of the transaction.";
 
 1423            JLOG(j.
fatal()) << 
"Invariant failed: some mptokens were changed " 
 1424                               "despite failure of the transaction.";
 
 
 1440    if (
after && 
after->getType() == ltMPTOKEN_ISSUANCE)
 
 
 1471                JLOG(j.
fatal()) << 
"Invariant failed: transaction " 
 1472                                   "succeeded without creating a MPT issuance";
 
 1476                JLOG(j.
fatal()) << 
"Invariant failed: transaction " 
 1477                                   "succeeded while removing MPT issuances";
 
 1481                JLOG(j.
fatal()) << 
"Invariant failed: transaction " 
 1482                                   "succeeded but created multiple issuances";
 
 1492                JLOG(j.
fatal()) << 
"Invariant failed: MPT issuance deletion " 
 1493                                   "succeeded without removing a MPT issuance";
 
 1497                JLOG(j.
fatal()) << 
"Invariant failed: MPT issuance deletion " 
 1498                                   "succeeded while creating MPT issuances";
 
 1502                JLOG(j.
fatal()) << 
"Invariant failed: MPT issuance deletion " 
 1503                                   "succeeded but deleted multiple issuances";
 
 1512        bool const enforceEscrowFinish = (tx.
getTxnType() == ttESCROW_FINISH) &&
 
 1519            enforceEscrowFinish)
 
 1525                JLOG(j.
fatal()) << 
"Invariant failed: MPT authorize " 
 1526                                   "succeeded but created MPT issuances";
 
 1531                JLOG(j.
fatal()) << 
"Invariant failed: MPT authorize " 
 1532                                   "succeeded but deleted issuances";
 
 1536                submittedByIssuer &&
 
 1540                    << 
"Invariant failed: MPT authorize submitted by issuer " 
 1541                       "succeeded but created/deleted mptokens";
 
 1551                    << 
"Invariant failed: MPT authorize submitted by holder " 
 1552                       "succeeded but created/deleted bad number of mptokens";
 
 1564                !enforceEscrowFinish,
 
 1565                "ripple::ValidMPTIssuance::finalize",
 
 1566                "not escrow finish tx");
 
 1578        JLOG(j.
fatal()) << 
"Invariant failed: a MPT issuance was created";
 
 1582        JLOG(j.
fatal()) << 
"Invariant failed: a MPT issuance was deleted";
 
 1586        JLOG(j.
fatal()) << 
"Invariant failed: a MPToken was created";
 
 1590        JLOG(j.
fatal()) << 
"Invariant failed: a MPToken was deleted";
 
 
 1605    if (before && before->getType() != ltPERMISSIONED_DOMAIN)
 
 1607    if (
after && 
after->getType() != ltPERMISSIONED_DOMAIN)
 
 1612        auto const& credentials = sle->getFieldArray(sfAcceptedCredentials);
 
 1623            for (
auto const& cred : sorted)
 
 1625                auto const& credTx = credentials[i++];
 
 1626                sleStatus.
isSorted_ = (cred.first == credTx[sfIssuer]) &&
 
 1627                    (cred.second == credTx[sfCredentialType]);
 
 
 1661            JLOG(j.
fatal()) << 
"Invariant failed: permissioned domain with " 
 1669            JLOG(j.
fatal()) << 
"Invariant failed: permissioned domain bad " 
 1678                << 
"Invariant failed: permissioned domain credentials " 
 1686                << 
"Invariant failed: permissioned domain credentials " 
 
 1710    if (
after && 
after->getType() == ltACCOUNT_ROOT)
 
 1712        bool const isPseudo = [&]() {
 
 1719            if (
after->at(sfSequence) == 0)
 
 1740                        return after->isFieldPresent(*sf);
 
 1745                    error << 
"pseudo-account has " << numFields
 
 1746                          << 
" pseudo-account fields set";
 
 1750            if (before && before->at(sfSequence) != 
after->at(sfSequence))
 
 1759            if (
after->isFieldPresent(sfRegularKey))
 
 
 1775    bool const enforce = view.
rules().
enabled(featureSingleAssetVault);
 
 1780        "ripple::ValidPseudoAccounts::finalize : no bad " 
 1781        "changes or enforce invariant");
 
 1784        for (
auto const& error : 
errors_)
 
 1786            JLOG(j.
fatal()) << 
"Invariant failed: " << error;
 
 
 1804        if (
after->isFieldPresent(sfDomainID))
 
 1810        if (
after->isFieldPresent(sfDomainID))
 
 1818            (!
after->isFieldPresent(sfDomainID) ||
 
 1819             !
after->isFieldPresent(sfAdditionalBooks) ||
 
 1820             after->getFieldArray(sfAdditionalBooks).size() > 1))
 
 
 1834    if ((txType != ttPAYMENT && txType != ttOFFER_CREATE) ||
 
 1842        JLOG(j.
fatal()) << 
"Invariant failed: hybrid offer is malformed";
 
 1853        JLOG(j.
fatal()) << 
"Invariant failed: domain doesn't exist";
 
 1863            JLOG(j.
fatal()) << 
"Invariant failed: transaction" 
 1864                               " consumed wrong domains";
 
 1871        JLOG(j.
fatal()) << 
"Invariant failed: domain transaction" 
 1872                           " affected regular offers";
 
 
 1890        auto const type = 
after->getType();
 
 1900            (type == ltACCOUNT_ROOT && 
after->isFieldPresent(sfAMMID)))
 
 1909        if (before->getType() == ltAMM)
 
 
 1923    bool const positive = amount > beast::zero && amount2 > beast::zero &&
 
 1924        lptAMMBalance > beast::zero;
 
 1927            (amount == beast::zero && amount2 == beast::zero &&
 
 1928             lptAMMBalance == beast::zero);
 
 
 1939        JLOG(j.
error()) << 
"AMMVote invariant failed: " 
 
 1958        JLOG(j.
error()) << 
"AMMBid invariant failed: pool changed";
 
 
 1991            << 
"AMMCreate invariant failed: AMM object is not created";
 
 2001            tx[sfAmount].get<Issue>(),
 
 2002            tx[sfAmount2].get<Issue>(),
 
 2013            JLOG(j.
error()) << 
"AMMCreate invariant failed: " << amount << 
" " 
 
 2030            ? 
"AMM object is not deleted on tesSUCCESS" 
 2031            : 
"AMM object is changed on tecINCOMPLETE";
 
 2032        JLOG(j.
error()) << 
"AMMDelete invariant failed: " << msg;
 
 
 2047        JLOG(j.
error()) << 
"AMM swap invariant failed: AMM object changed";
 
 
 2066        tx[sfAsset].get<Issue>(),
 
 2067        tx[sfAsset2].get<Issue>(),
 
 2074    auto const poolProductMean = 
root2(amount * amount2);
 
 2075    bool const nonNegativeBalances =
 
 2079    auto weakInvariantCheck = [&]() {
 
 2084    if (!nonNegativeBalances ||
 
 2085        (!strongInvariantCheck && !weakInvariantCheck()))
 
 2090                        << 
" " << poolProductMean << 
" " 
 
 2112        JLOG(j.
error()) << 
"AMMDeposit invariant failed: AMM object is deleted";
 
 
 2164        case ttAMM_CLAWBACK:
 
 2165        case ttAMM_WITHDRAW:
 
 2174        case ttOFFER_CREATE:
 
 
 2191        "ValidVault::Vault::make : from Vault object");
 
 2195    self.
asset = from.
at(sfAsset);
 
 
 2209        from.
getType() == ltMPTOKEN_ISSUANCE,
 
 2210        "ValidVault::Shares::make : from MPTokenIssuance object");
 
 
 2230        after != 
nullptr && (before != 
nullptr || !isDelete),
 
 2231        "ripple::ValidVault::visitEntry : some object is available");
 
 2242        switch (before->getType())
 
 2247            case ltMPTOKEN_ISSUANCE:
 
 2252                    before->getFieldU64(sfOutstandingAmount));
 
 2257                    static_cast<std::int64_t>(before->getFieldU64(sfMPTAmount));
 
 2260            case ltACCOUNT_ROOT:
 
 2261            case ltRIPPLE_STATE:
 
 2262                balanceDelta = before->getFieldAmount(sfBalance);
 
 2269    if (!isDelete && 
after)
 
 2271        switch (
after->getType())
 
 2276            case ltMPTOKEN_ISSUANCE:
 
 2281                    after->getFieldU64(sfOutstandingAmount)));
 
 2289            case ltACCOUNT_ROOT:
 
 2290            case ltRIPPLE_STATE:
 
 2291                balanceDelta -= 
Number(
after->getFieldAmount(sfBalance));
 
 2298    uint256 const key = (before ? before->key() : 
after->key());
 
 
 2316    bool const enforce = view.
rules().
enabled(featureSingleAssetVault);
 
 2326                "Invariant failed: vault operation succeeded without modifying " 
 2329                enforce, 
"ripple::ValidVault::finalize : vault noop invariant");
 
 2338            "Invariant failed: vault updated by a wrong transaction type";
 
 2341            "ripple::ValidVault::finalize : illegal vault transaction " 
 2349            "Invariant failed: vault operation updated more than single vault";
 
 2351            enforce, 
"ripple::ValidVault::finalize : single vault invariant");
 
 2361        if (txnType != ttVAULT_DELETE)
 
 2364                "Invariant failed: vault deleted by a wrong transaction type";
 
 2367                "ripple::ValidVault::finalize : illegal vault deletion " 
 2382                if (e.share.getMptID() == beforeVault.shareMPTID)
 
 2383                    return std::move(e);
 
 2390            JLOG(j.
fatal()) << 
"Invariant failed: deleted vault must also " 
 2394                "ripple::ValidVault::finalize : shares deletion invariant");
 
 2399        if (deletedShares->sharesTotal != 0)
 
 2401            JLOG(j.
fatal()) << 
"Invariant failed: deleted vault must have no " 
 2402                               "shares outstanding";
 
 2405        if (beforeVault.assetsTotal != 
zero)
 
 2407            JLOG(j.
fatal()) << 
"Invariant failed: deleted vault must have no " 
 2408                               "assets outstanding";
 
 2411        if (beforeVault.assetsAvailable != 
zero)
 
 2413            JLOG(j.
fatal()) << 
"Invariant failed: deleted vault must have no " 
 2420    else if (txnType == ttVAULT_DELETE)
 
 2422        JLOG(j.
fatal()) << 
"Invariant failed: vault deletion succeeded without " 
 2425            enforce, 
"ripple::ValidVault::finalize : vault deletion invariant");
 
 2433        "ripple::ValidVault::finalize : single vault operation");
 
 2443            if (e.share.getMptID() == afterVault.shareMPTID)
 
 2447        auto const sleShares =
 
 2460        if (afterVault.asset != beforeVault.asset ||
 
 2461            afterVault.pseudoId != beforeVault.pseudoId ||
 
 2462            afterVault.shareMPTID != beforeVault.shareMPTID)
 
 2465                << 
"Invariant failed: violation of vault immutable data";
 
 2472        JLOG(j.
fatal()) << 
"Invariant failed: updated vault must have shares";
 
 2475            "ripple::ValidVault::finalize : vault has shares invariant");
 
 2479    if (updatedShares->sharesTotal == 0)
 
 2481        if (afterVault.assetsTotal != 
zero)
 
 2483            JLOG(j.
fatal()) << 
"Invariant failed: updated zero sized " 
 2484                               "vault must have no assets outstanding";
 
 2487        if (afterVault.assetsAvailable != 
zero)
 
 2489            JLOG(j.
fatal()) << 
"Invariant failed: updated zero sized " 
 2490                               "vault must have no assets available";
 
 2494    else if (updatedShares->sharesTotal > updatedShares->sharesMaximum)
 
 2497            << 
"Invariant failed: updated shares must not exceed maximum " 
 2498            << updatedShares->sharesMaximum;
 
 2502    if (afterVault.assetsAvailable < 
zero)
 
 2505            << 
"Invariant failed: assets available must be positive";
 
 2509    if (afterVault.assetsAvailable > afterVault.assetsTotal)
 
 2511        JLOG(j.
fatal()) << 
"Invariant failed: assets available must " 
 2512                           "not be greater than assets outstanding";
 
 2516        afterVault.lossUnrealized >
 
 2517        afterVault.assetsTotal - afterVault.assetsAvailable)
 
 2520            << 
"Invariant failed: loss unrealized must not exceed " 
 2521               "the difference between assets outstanding and available";
 
 2525    if (afterVault.assetsTotal < 
zero)
 
 2528            << 
"Invariant failed: assets outstanding must be positive";
 
 2532    if (afterVault.assetsMaximum < 
zero)
 
 2534        JLOG(j.
fatal()) << 
"Invariant failed: assets maximum must be positive";
 
 2543            "Invariant failed: vault created by a wrong transaction type";
 
 2545            enforce, 
"ripple::ValidVault::finalize : vault creation invariant");
 
 2550        afterVault.lossUnrealized != 
beforeVault_[0].lossUnrealized)
 
 2553            "Invariant failed: vault transaction must not change loss " 
 2565            if (e.share.getMptID() == beforeVault.shareMPTID)
 
 2566                return std::move(e);
 
 2571    if (!beforeShares &&
 
 2576        JLOG(j.
fatal()) << 
"Invariant failed: vault operation succeeded " 
 2577                           "without updating shares";
 
 2579            enforce, 
"ripple::ValidVault::finalize : shares noop invariant");
 
 2583    auto const& vaultAsset = afterVault.asset;
 
 2590            return it->second * 
sign;
 
 2594            [&]<
typename TIss>(TIss 
const& issue) {
 
 2601                        id > issue.getIssuer() ? -1 : 1);
 
 2609            vaultAsset.value());
 
 2612        auto ret = deltaAssets(tx[sfAccount]);
 
 2614        if (!ret.has_value() || !vaultAsset.native())
 
 2618        if (
auto const delegate = tx[~sfDelegate];
 
 2619            delegate.has_value() && *delegate != tx[sfAccount])
 
 2622        *ret += fee.
drops();
 
 2629        auto const it = [&]() {
 
 2630            if (
id == afterVault.pseudoId)
 
 2647            case ttVAULT_CREATE: {
 
 2653                        << 
"Invariant failed: create operation must not have " 
 2658                if (afterVault.assetsAvailable != 
zero ||
 
 2659                    afterVault.assetsTotal != 
zero ||
 
 2660                    afterVault.lossUnrealized != 
zero ||
 
 2661                    updatedShares->sharesTotal != 0)
 
 2664                        << 
"Invariant failed: created vault must be empty";
 
 2668                if (afterVault.pseudoId != updatedShares->share.getIssuer())
 
 2671                        << 
"Invariant failed: shares issuer and vault " 
 2672                           "pseudo-account must be the same";
 
 2676                auto const sleSharesIssuer = view.
read(
 
 2678                if (!sleSharesIssuer)
 
 2681                        << 
"Invariant failed: shares issuer must exist";
 
 2688                        << 
"Invariant failed: shares issuer must be a " 
 2693                if (
auto const vaultId = (*sleSharesIssuer)[~sfVaultID];
 
 2694                    !vaultId || *vaultId != afterVault.key)
 
 2697                        << 
"Invariant failed: shares issuer pseudo-account " 
 2698                           "must point back to the vault";
 
 2709                    "ripple::ValidVault::finalize : set updated a vault");
 
 2712                auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId);
 
 2713                if (vaultDeltaAssets)
 
 2716                        "Invariant failed: set must not change vault balance";
 
 2720                if (beforeVault.assetsTotal != afterVault.assetsTotal)
 
 2723                        "Invariant failed: set must not change assets " 
 2728                if (afterVault.assetsMaximum > 
zero &&
 
 2729                    afterVault.assetsTotal > afterVault.assetsMaximum)
 
 2732                        "Invariant failed: set assets outstanding must not " 
 2733                        "exceed assets maximum";
 
 2737                if (beforeVault.assetsAvailable != afterVault.assetsAvailable)
 
 2740                        "Invariant failed: set must not change assets " 
 2745                if (beforeShares && updatedShares &&
 
 2746                    beforeShares->sharesTotal != updatedShares->sharesTotal)
 
 2749                        "Invariant failed: set must not change shares " 
 2756            case ttVAULT_DEPOSIT: {
 
 2761                    "ripple::ValidVault::finalize : deposit updated a vault");
 
 2764                auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId);
 
 2766                if (!vaultDeltaAssets)
 
 2769                        "Invariant failed: deposit must change vault balance";
 
 2773                if (*vaultDeltaAssets > tx[sfAmount])
 
 2776                        "Invariant failed: deposit must not change vault " 
 2777                        "balance by more than deposited amount";
 
 2781                if (*vaultDeltaAssets <= 
zero)
 
 2784                        "Invariant failed: deposit must increase vault balance";
 
 2790                bool const issuerDeposit = [&]() -> 
bool {
 
 2791                    if (vaultAsset.native())
 
 2793                    return tx[sfAccount] == vaultAsset.getIssuer();
 
 2798                    auto const accountDeltaAssets = deltaAssetsTxAccount();
 
 2799                    if (!accountDeltaAssets)
 
 2802                            "Invariant failed: deposit must change depositor " 
 2807                    if (*accountDeltaAssets >= 
zero)
 
 2810                            "Invariant failed: deposit must decrease depositor " 
 2815                    if (*accountDeltaAssets * -1 != *vaultDeltaAssets)
 
 2818                            "Invariant failed: deposit must change vault and " 
 2819                            "depositor balance by equal amount";
 
 2824                if (afterVault.assetsMaximum > 
zero &&
 
 2825                    afterVault.assetsTotal > afterVault.assetsMaximum)
 
 2828                        "Invariant failed: deposit assets outstanding must not " 
 2829                        "exceed assets maximum";
 
 2833                auto const accountDeltaShares = deltaShares(tx[sfAccount]);
 
 2834                if (!accountDeltaShares)
 
 2837                        "Invariant failed: deposit must change depositor " 
 2842                if (*accountDeltaShares <= 
zero)
 
 2845                        "Invariant failed: deposit must increase depositor " 
 2850                auto const vaultDeltaShares = deltaShares(afterVault.pseudoId);
 
 2851                if (!vaultDeltaShares || *vaultDeltaShares == 
zero)
 
 2854                        "Invariant failed: deposit must change vault shares";
 
 2858                if (*vaultDeltaShares * -1 != *accountDeltaShares)
 
 2861                        "Invariant failed: deposit must change depositor and " 
 2862                        "vault shares by equal amount";
 
 2866                if (beforeVault.assetsTotal + *vaultDeltaAssets !=
 
 2867                    afterVault.assetsTotal)
 
 2869                    JLOG(j.
fatal()) << 
"Invariant failed: deposit and assets " 
 2870                                       "outstanding must add up";
 
 2873                if (beforeVault.assetsAvailable + *vaultDeltaAssets !=
 
 2874                    afterVault.assetsAvailable)
 
 2876                    JLOG(j.
fatal()) << 
"Invariant failed: deposit and assets " 
 2877                                       "available must add up";
 
 2883            case ttVAULT_WITHDRAW: {
 
 2888                    "ripple::ValidVault::finalize : withdrawal updated a " 
 2892                auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId);
 
 2894                if (!vaultDeltaAssets)
 
 2896                    JLOG(j.
fatal()) << 
"Invariant failed: withdrawal must " 
 2897                                       "change vault balance";
 
 2901                if (*vaultDeltaAssets >= 
zero)
 
 2903                    JLOG(j.
fatal()) << 
"Invariant failed: withdrawal must " 
 2904                                       "decrease vault balance";
 
 2910                bool const issuerWithdrawal = [&]() -> 
bool {
 
 2911                    if (vaultAsset.native())
 
 2913                    auto const destination =
 
 2914                        tx[~sfDestination].value_or(tx[sfAccount]);
 
 2915                    return destination == vaultAsset.getIssuer();
 
 2918                if (!issuerWithdrawal)
 
 2920                    auto const accountDeltaAssets = deltaAssetsTxAccount();
 
 2921                    auto const otherAccountDelta =
 
 2923                        if (
auto const destination = tx[~sfDestination];
 
 2924                            destination && *destination != tx[sfAccount])
 
 2925                            return deltaAssets(*destination);
 
 2929                    if (accountDeltaAssets.has_value() ==
 
 2930                        otherAccountDelta.has_value())
 
 2933                            "Invariant failed: withdrawal must change one " 
 2934                            "destination balance";
 
 2938                    auto const destinationDelta =  
 
 2939                        accountDeltaAssets ? *accountDeltaAssets
 
 2940                                           : *otherAccountDelta;
 
 2942                    if (destinationDelta <= 
zero)
 
 2945                            "Invariant failed: withdrawal must increase " 
 2946                            "destination balance";
 
 2950                    if (*vaultDeltaAssets * -1 != destinationDelta)
 
 2953                            "Invariant failed: withdrawal must change vault " 
 2954                            "and destination balance by equal amount";
 
 2959                auto const accountDeltaShares = deltaShares(tx[sfAccount]);
 
 2960                if (!accountDeltaShares)
 
 2963                        "Invariant failed: withdrawal must change depositor " 
 2968                if (*accountDeltaShares >= 
zero)
 
 2971                        "Invariant failed: withdrawal must decrease depositor " 
 2976                auto const vaultDeltaShares = deltaShares(afterVault.pseudoId);
 
 2977                if (!vaultDeltaShares || *vaultDeltaShares == 
zero)
 
 2980                        "Invariant failed: withdrawal must change vault shares";
 
 2984                if (*vaultDeltaShares * -1 != *accountDeltaShares)
 
 2987                        "Invariant failed: withdrawal must change depositor " 
 2988                        "and vault shares by equal amount";
 
 2993                if (beforeVault.assetsTotal + *vaultDeltaAssets !=
 
 2994                    afterVault.assetsTotal)
 
 2996                    JLOG(j.
fatal()) << 
"Invariant failed: withdrawal and " 
 2997                                       "assets outstanding must add up";
 
 3001                if (beforeVault.assetsAvailable + *vaultDeltaAssets !=
 
 3002                    afterVault.assetsAvailable)
 
 3004                    JLOG(j.
fatal()) << 
"Invariant failed: withdrawal and " 
 3005                                       "assets available must add up";
 
 3011            case ttVAULT_CLAWBACK: {
 
 3016                    "ripple::ValidVault::finalize : clawback updated a vault");
 
 3019                if (vaultAsset.native() ||
 
 3020                    vaultAsset.getIssuer() != tx[sfAccount])
 
 3023                        "Invariant failed: clawback may only be performed by " 
 3028                auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId);
 
 3030                if (!vaultDeltaAssets)
 
 3033                        "Invariant failed: clawback must change vault balance";
 
 3037                if (*vaultDeltaAssets >= 
zero)
 
 3040                        "Invariant failed: clawback must decrease vault " 
 3045                auto const accountDeltaShares = deltaShares(tx[sfHolder]);
 
 3046                if (!accountDeltaShares)
 
 3049                        "Invariant failed: clawback must change holder shares";
 
 3053                if (*accountDeltaShares >= 
zero)
 
 3056                        "Invariant failed: clawback must decrease holder " 
 3061                auto const vaultDeltaShares = deltaShares(afterVault.pseudoId);
 
 3062                if (!vaultDeltaShares || *vaultDeltaShares == 
zero)
 
 3065                        "Invariant failed: clawback must change vault shares";
 
 3069                if (*vaultDeltaShares * -1 != *accountDeltaShares)
 
 3072                        "Invariant failed: clawback must change holder and " 
 3073                        "vault shares by equal amount";
 
 3077                if (beforeVault.assetsTotal + *vaultDeltaAssets !=
 
 3078                    afterVault.assetsTotal)
 
 3081                        "Invariant failed: clawback and assets outstanding " 
 3086                if (beforeVault.assetsAvailable + *vaultDeltaAssets !=
 
 3087                    afterVault.assetsAvailable)
 
 3090                        "Invariant failed: clawback and assets available must " 
 3101                    "ripple::ValidVault::finalize : unknown transaction type");
 
 3111        XRPL_ASSERT(enforce, 
"ripple::ValidVault::finalize : vault invariants");
 
 
A generic endpoint for log messages.
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
std::vector< std::shared_ptr< SLE const  > > accountsDeleted_
 
std::uint32_t accountsDeleted_
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
A currency issued by an account.
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
std::uint32_t afterMintedTotal
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
std::uint32_t afterBurnedTotal
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
std::uint32_t beforeBurnedTotal
 
std::uint32_t beforeMintedTotal
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
bool deepFreezeWithoutFreeze_
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
 
virtual std::optional< key_type > succ(key_type const &key, std::optional< key_type > const &last=std::nullopt) const =0
Return the key of the next state item.
 
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
 
LedgerIndex seq() const
Returns the sequence number of the base ledger.
 
virtual Rules const & rules() const =0
Returns the tx processing rules.
 
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
 
Currency const & getCurrency() const
 
int signum() const noexcept
 
AccountID const & getIssuer() const
 
bool native() const noexcept
 
STAmount zeroed() const
Returns a zero value with the same issuer and currency.
 
LedgerEntryType getType() const
 
uint256 const & key() const
Returns the 'key' (or 'index') of this item.
 
uint192 getFieldH192(SField const &field) const
 
AccountID getAccountID(SField const &field) const
 
T::value_type at(TypedField< T > const &f) const
Get the value of a field.
 
std::uint32_t getFieldU32(SField const &field) const
 
STAmount const & getFieldAmount(SField const &field) const
 
uint256 getHash(HashPrefix prefix) const
 
bool isFieldPresent(SField const &field) const
 
uint256 getFieldH256(SField const &field) const
 
TxType getTxnType() const
 
uint256 getTransactionID() const
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
std::map< AccountID, std::shared_ptr< SLE const  > const  > possibleIssuers_
 
bool isValidEntry(std::shared_ptr< SLE const > const &before, std::shared_ptr< SLE const > const &after)
 
void recordBalance(Issue const &issue, BalanceChange change)
 
std::shared_ptr< SLE const > findIssuer(AccountID const &issuerID, ReadView const &view)
 
bool validateIssuerChanges(std::shared_ptr< SLE const > const &issuer, IssuerChanges const &changes, STTx const &tx, beast::Journal const &j, bool enforce)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
STAmount calculateBalanceChange(std::shared_ptr< SLE const > const &before, std::shared_ptr< SLE const > const &after, bool isDelete)
 
void recordBalanceChanges(std::shared_ptr< SLE const > const &after, STAmount const &balanceChange)
 
bool validateFrozenState(BalanceChange const &change, bool high, STTx const &tx, beast::Journal const &j, bool enforce, bool globalFreeze)
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
bool finalizeWithdraw(STTx const &, ReadView const &, bool enforce, beast::Journal const &) const
 
bool finalizeDEX(bool enforce, beast::Journal const &) const
 
std::optional< STAmount > lptAMMBalanceAfter_
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
bool finalizeBid(bool enforce, beast::Journal const &) const
 
std::optional< AccountID > ammAccount_
 
bool finalizeDelete(bool enforce, TER res, beast::Journal const &) const
 
bool finalizeCreate(STTx const &, ReadView const &, bool enforce, beast::Journal const &) const
 
bool finalizeVote(bool enforce, beast::Journal const &) const
 
bool finalizeDeposit(STTx const &, ReadView const &, bool enforce, beast::Journal const &) const
 
bool generalInvariant(STTx const &, ReadView const &, ZeroAllowed zeroAllowed, beast::Journal const &) const
 
std::optional< STAmount > lptAMMBalanceBefore_
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
std::uint32_t trustlinesChanged
 
std::uint32_t mptokensChanged
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
std::uint32_t mptIssuancesCreated_
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
std::uint32_t mptokensCreated_
 
std::uint32_t mptIssuancesDeleted_
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
std::uint32_t mptokensDeleted_
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
std::uint32_t accountsCreated_
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
std::uint32_t accountSeq_
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
hash_set< uint256 > domains_
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
std::optional< SleStatus > sleStatus_[2]
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
std::vector< std::string > errors_
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
std::vector< Shares > beforeMPTs_
 
std::vector< Vault > beforeVault_
 
std::unordered_map< uint256, Number > deltas_
 
static Number constexpr zero
 
std::vector< Shares > afterMPTs_
 
std::vector< Vault > afterVault_
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
constexpr value_type drops() const
Returns the number of drops.
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
 
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
 
T emplace_back(T... args)
 
std::set< std::pair< AccountID, Slice > > makeSorted(STArray const &credentials)
 
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
 
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
 
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
 
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
 
Keylet account(AccountID const &id) noexcept
AccountID root.
 
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
 
Keylet nftpage_min(AccountID const &owner)
NFT page keylets.
 
Keylet nftpage_max(AccountID const &owner)
A keylet for the owner's last possible NFT page.
 
bool compareTokens(uint256 const &a, uint256 const &b)
 
uint256 constexpr pageMask(std::string_view("0000000000000000000000000000000000000000ffffffffffffffffffffffff"))
 
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
 
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
 
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
 
bool isXRP(AccountID const &c)
 
constexpr base_uint< Bits, Tag > operator|(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
 
static bool validBalances(STAmount const &amount, STAmount const &amount2, STAmount const &lptAMMBalance, ValidAMM::ZeroAllowed zeroAllowed)
 
std::size_t constexpr maxPermissionedDomainCredentialsArraySize
The maximum number of credentials can be passed in array for permissioned domain.
 
bool hasPrivilege(STTx const &tx, Privilege priv)
 
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safe_cast(Src s) noexcept
 
std::uint64_t constexpr maxMPTokenAmount
The maximum amount of MPTokenIssuance.
 
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
 
std::size_t constexpr dirMaxTokensPerPage
The maximum number of items in an NFT page.
 
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &message)
Generate a signature for a message.
 
std::array< keyletDesc< AccountID const  & >, 6 > const directAccountKeylets
 
std::pair< STAmount, STAmount > ammPoolHolds(ReadView const &view, AccountID const &ammAccountID, Issue const &issue1, Issue const &issue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool balances.
 
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
 
bool isTesSuccess(TER x) noexcept
 
STAmount ammLPTokens(STAmount const &asset1, STAmount const &asset2, Issue const &lptIssue)
Calculate LP Tokens given AMM pool reserves.
 
T get(Section const §ion, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
 
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
 
@ transactionID
transaction plus signature to give transaction ID
 
MPTID makeMptID(std::uint32_t sequence, AccountID const &account)
 
std::vector< SField const * > const & getPseudoAccountFields()
 
bool withinRelativeDistance(Quality const &calcQuality, Quality const &reqQuality, Number const &dist)
Check if the relative distance between the qualities is within the requested distance.
 
bool isPseudoAccount(std::shared_ptr< SLE const > sleAcct)
 
A pair of SHAMap key and LedgerEntryType.
 
int const balanceChangeSign
 
std::shared_ptr< SLE const  > const line
 
std::vector< BalanceChange > receivers
 
std::vector< BalanceChange > senders
 
std::size_t credentialsSize_
 
std::uint64_t sharesMaximum
 
static Shares make(SLE const &)
 
std::uint64_t sharesTotal
 
static Vault make(SLE const &)