1#include <xrpld/app/tx/detail/VaultWithdraw.h> 
    3#include <xrpl/ledger/CredentialHelpers.h> 
    4#include <xrpl/ledger/View.h> 
    5#include <xrpl/protocol/AccountID.h> 
    6#include <xrpl/protocol/Feature.h> 
    7#include <xrpl/protocol/SField.h> 
    8#include <xrpl/protocol/STNumber.h> 
    9#include <xrpl/protocol/TER.h> 
   10#include <xrpl/protocol/TxFlags.h> 
   17    if (ctx.
tx[sfVaultID] == beast::zero)
 
   19        JLOG(ctx.
j.
debug()) << 
"VaultWithdraw: zero/empty vault ID.";
 
   23    if (ctx.
tx[sfAmount] <= beast::zero)
 
   26    if (
auto const destination = ctx.
tx[~sfDestination];
 
   27        destination.has_value())
 
   29        if (*destination == beast::zero)
 
   32                << 
"VaultWithdraw: zero/empty destination account.";
 
 
   47    auto const assets = ctx.
tx[sfAmount];
 
   48    auto const vaultAsset = vault->at(sfAsset);
 
   49    auto const vaultShare = vault->at(sfShareMPTID);
 
   50    if (assets.asset() != vaultAsset && assets.asset() != vaultShare)
 
   53    if (vaultAsset.native())
 
   55    else if (vaultAsset.holds<
MPTIssue>())
 
   57        auto mptID = vaultAsset.get<
MPTIssue>().getMptID();
 
   65                << 
"VaultWithdraw: vault assets are non-transferable.";
 
   70    else if (vaultAsset.holds<
Issue>())
 
   78                << 
"VaultWithdraw: missing issuer of vault assets.";
 
   88        JLOG(ctx.
j.
error()) << 
"VaultWithdraw: invalid withdrawal policy.";
 
   93    auto const account = ctx.
tx[sfAccount];
 
   94    auto const dstAcct = ctx.
tx[~sfDestination].value_or(account);
 
   96    if (sleDst == 
nullptr)
 
  116    if (
auto const ter = 
requireAuth(ctx.
view, vaultAsset, dstAcct, authType);
 
 
  137    auto const mptIssuanceID = *((*vault)[sfShareMPTID]);
 
  142        JLOG(
j_.
error()) << 
"VaultWithdraw: missing issuance of vault shares.";
 
  152    auto const amount = 
ctx_.
tx[sfAmount];
 
  153    Asset const vaultAsset = vault->at(sfAsset);
 
  154    MPTIssue const share{mptIssuanceID};
 
  159        if (amount.asset() == vaultAsset)
 
  163                auto const maybeShares =
 
  167                sharesRedeemed = *maybeShares;
 
  170            if (sharesRedeemed == beast::zero)
 
  172            auto const maybeAssets =
 
  176            assetsWithdrawn = *maybeAssets;
 
  178        else if (amount.asset() == share)
 
  181            sharesRedeemed = amount;
 
  182            auto const maybeAssets =
 
  186            assetsWithdrawn = *maybeAssets;
 
  196            << 
"VaultWithdraw: overflow error with" 
  197            << 
" scale=" << (int)vault->at(sfScale).value()  
 
  198            << 
", assetsTotal=" << vault->at(sfAssetsTotal).value()
 
  199            << 
", sharesTotal=" << sleIssuance->at(sfOutstandingAmount)
 
  200            << 
", amount=" << amount.value();
 
  210            j_) < sharesRedeemed)
 
  212        JLOG(
j_.
debug()) << 
"VaultWithdraw: account doesn't hold enough shares";
 
  216    auto assetsAvailable = vault->at(sfAssetsAvailable);
 
  217    auto assetsTotal = vault->at(sfAssetsTotal);
 
  218    [[maybe_unused]] 
auto const lossUnrealized = vault->at(sfLossUnrealized);
 
  220        lossUnrealized <= (assetsTotal - assetsAvailable),
 
  221        "ripple::VaultWithdraw::doApply : loss and assets do balance");
 
  226    if (*assetsAvailable < assetsWithdrawn)
 
  228        JLOG(
j_.
debug()) << 
"VaultWithdraw: vault doesn't hold enough assets";
 
  232    assetsTotal -= assetsWithdrawn;
 
  233    assetsAvailable -= assetsWithdrawn;
 
  236    auto const& vaultAccount = vault->at(sfAccount);
 
  258                << 
"VaultWithdraw: removed empty MPToken for vault shares" 
  266                << 
"VaultWithdraw: failed to remove MPToken for vault shares" 
  277    if (!vaultAsset.
native() &&               
 
  302            assetsWithdrawn.
asset(),
 
  308        JLOG(
j_.
error()) << 
"VaultWithdraw: negative balance of vault assets.";
 
 
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
 
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
 
AccountID const & getIssuer() const
 
A currency issued by an account.
 
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
 
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
 
Asset const & asset() const
 
bool isFieldPresent(SField const &field) const
 
static TER preclaim(PreclaimContext const &ctx)
 
static NotTEC preflight(PreflightContext const &ctx)
 
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
 
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
 
Keylet account(AccountID const &id) noexcept
AccountID root.
 
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
 
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
 
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
 
TER checkFrozen(ReadView const &view, AccountID const &account, Issue const &issue)
 
std::optional< STAmount > assetsToSharesWithdraw(std::shared_ptr< SLE const > const &vault, std::shared_ptr< SLE const > const &issuance, STAmount const &assets, TruncateShares truncate=TruncateShares::no)
 
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No)
Calls static accountSendIOU if saAmount represents Issue.
 
TER requireAuth(ReadView const &view, Issue const &issue, AccountID const &account, AuthType authType=AuthType::Legacy)
Check if the account lacks required authorization.
 
std::optional< STAmount > sharesToAssetsWithdraw(std::shared_ptr< SLE const > const &vault, std::shared_ptr< SLE const > const &issuance, STAmount const &shares)
 
std::string transToken(TER code)
 
TER addEmptyHolding(ApplyView &view, AccountID const &accountID, XRPAmount priorBalance, Issue const &issue, beast::Journal journal)
Any transactors that call addEmptyHolding() in doApply must call canAddHolding() in preflight with th...
 
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
 
bool isTesSuccess(TER x) noexcept
 
std::string to_string(base_uint< Bits, Tag > const &a)
 
std::uint8_t constexpr vaultStrategyFirstComeFirstServe
Vault withdrawal policies.
 
TER removeEmptyHolding(ApplyView &view, AccountID const &accountID, Issue const &issue, beast::Journal journal)
 
TERSubset< CanCvtToNotTEC > NotTEC
 
State information when determining if a tx is likely to claim a fee.
 
State information when preflighting a tx.