1#include <xrpl/tx/transactors/dex/AMMWithdraw.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/Number.h>
5#include <xrpl/beast/utility/Zero.h>
6#include <xrpl/beast/utility/instrumentation.h>
7#include <xrpl/core/ServiceRegistry.h>
8#include <xrpl/ledger/Sandbox.h>
9#include <xrpl/ledger/helpers/AMMHelpers.h>
10#include <xrpl/ledger/helpers/MPTokenHelpers.h>
11#include <xrpl/ledger/helpers/RippleStateHelpers.h>
12#include <xrpl/ledger/helpers/TokenHelpers.h>
13#include <xrpl/protocol/AMMCore.h>
14#include <xrpl/protocol/AccountID.h>
15#include <xrpl/protocol/Asset.h>
16#include <xrpl/protocol/Feature.h>
17#include <xrpl/protocol/IOUAmount.h>
18#include <xrpl/protocol/Indexes.h>
19#include <xrpl/protocol/Issue.h>
20#include <xrpl/protocol/Keylet.h>
21#include <xrpl/protocol/MPTIssue.h>
22#include <xrpl/protocol/SField.h>
23#include <xrpl/protocol/STAmount.h>
24#include <xrpl/protocol/STLedgerEntry.h>
25#include <xrpl/protocol/STTx.h>
26#include <xrpl/protocol/TER.h>
27#include <xrpl/protocol/TxFlags.h>
28#include <xrpl/protocol/XRPAmount.h>
29#include <xrpl/tx/Transactor.h>
47 auto const amount = ctx.
tx[~sfAmount];
48 auto const amount2 = ctx.
tx[~sfAmount2];
52 !(amount && amount->holds<
MPTIssue>()) && !(amount2 && amount2->holds<
MPTIssue>()));
58 return tfAMMWithdrawMask;
66 auto const amount = ctx.
tx[~sfAmount];
67 auto const amount2 = ctx.
tx[~sfAmount2];
68 auto const ePrice = ctx.
tx[~sfEPrice];
69 auto const lpTokens = ctx.
tx[~sfLPTokenIn];
80 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: invalid flags.";
85 if (!lpTokens || amount || amount2 || ePrice)
88 else if (ctx.
tx.
isFlag(tfWithdrawAll))
90 if (lpTokens || amount || amount2 || ePrice)
93 else if (ctx.
tx.
isFlag(tfOneAssetWithdrawAll) || ctx.
tx.
isFlag(tfSingleAsset))
95 if (!amount || lpTokens || amount2 || ePrice)
100 if (!amount || !amount2 || lpTokens || ePrice)
103 else if (ctx.
tx.
isFlag(tfOneAssetLPToken))
105 if (!amount || !lpTokens || amount2 || ePrice)
108 else if (ctx.
tx.
isFlag(tfLimitLPToken))
110 if (!amount || !ePrice || lpTokens || amount2)
114 auto const asset = ctx.
tx[sfAsset];
115 auto const asset2 = ctx.
tx[sfAsset2];
118 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: Invalid asset pair.";
122 if (amount && amount2 && amount->asset() == amount2->asset())
124 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: invalid tokens, same issue." << amount->asset() <<
" "
129 if (lpTokens && *lpTokens <= beast::kZero)
131 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: invalid tokens.";
140 ((flags & (tfOneAssetWithdrawAll | tfOneAssetLPToken)) != 0u) || ePrice))
142 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: invalid Asset1Out";
152 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: invalid Asset2OutAmount";
161 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: invalid EPrice";
175 if ((flags & (tfWithdrawAll | tfOneAssetWithdrawAll)) != 0u)
183 auto const accountID = ctx.
tx[sfAccount];
188 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: Invalid asset pair.";
192 auto const amount = ctx.
tx[~sfAmount];
193 auto const amount2 = ctx.
tx[~sfAmount2];
204 return expected.error();
205 auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected;
206 if (lptAMMBalance == beast::kZero)
208 if (amountBalance <= beast::kZero || amount2Balance <= beast::kZero ||
209 lptAMMBalance < beast::kZero)
212 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: reserves or tokens balance is zero.";
217 auto const ammAccountID = ammSle->getAccountID(sfAccount);
222 if (amount > balance)
225 <<
"AMM Withdraw: withdrawing more than the balance, " << *amount;
233 <<
"AMM Withdraw: account is not authorized, " << amount->asset();
239 ctx.
view, ammAccountID, accountID, accountID, amount->asset()))
241 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: frozen, " <<
to_string(accountID) <<
" "
249 if (
auto const ter =
checkFrozen(ctx.
view, ammAccountID, amount->asset());
253 <<
"AMM Withdraw: AMM account or currency is frozen or locked, "
262 <<
"AMM Withdraw: account is frozen or locked, " <<
to_string(accountID)
271 if (
auto const ter = checkAmount(amount, amountBalance))
274 if (
auto const ter = checkAmount(amount2, amount2Balance))
280 if (lpTokens <= beast::kZero)
282 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: tokens balance is zero.";
286 if (lpTokensWithdraw && lpTokensWithdraw->asset() != lpTokens.asset())
288 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: invalid LPTokens.";
292 if (lpTokensWithdraw && *lpTokensWithdraw > lpTokens)
294 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: invalid tokens.";
298 if (
auto const ePrice = ctx.
tx[~sfEPrice]; ePrice && ePrice->asset() != lpTokens.asset())
300 JLOG(ctx.
j.
debug()) <<
"AMM Withdraw: invalid EPrice.";
304 if ((ctx.
tx.
getFlags() & (tfLPToken | tfWithdrawAll)) != 0u)
306 if (
auto const ter = checkAmount(amountBalance, amountBalance))
308 if (
auto const ter = checkAmount(amount2Balance, amount2Balance))
321 if (!
ctx_.view().rules().enabled(fixCleanup3_3_0))
324 auto const asset1 =
Asset{
ctx_.tx[sfAsset]};
325 auto const asset2 =
Asset{
ctx_.tx[sfAsset2]};
326 if (!asset1.native() &&
accountID_ == asset1.getIssuer())
328 if (!asset2.native() &&
accountID_ == asset2.getIssuer())
337 auto const amount =
ctx_.tx[~sfAmount];
338 auto const amount2 =
ctx_.tx[~sfAmount2];
339 auto const ePrice =
ctx_.tx[~sfEPrice];
343 auto const ammAccountID = (*ammSle)[sfAccount];
348 auto const lpTokensWithdraw =
356 return {res.error(),
false};
372 return {expected.error(),
false};
373 auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected;
376 auto const [result, newLPTokenBalance] = [&,
377 &amountBalance = amountBalance,
378 &amount2Balance = amount2Balance,
381 if (subTxType & tfTwoAsset)
394 if (subTxType & tfOneAssetLPToken || subTxType & tfOneAssetWithdrawAll)
406 if (subTxType & tfLimitLPToken)
409 sb, *ammSle, ammAccountID, amountBalance, lptAMMBalance, *amount, *ePrice, tfee);
411 if (subTxType & tfSingleAsset)
414 sb, *ammSle, ammAccountID, amountBalance, lptAMMBalance, *amount, tfee);
416 if (subTxType & tfLPToken || subTxType & tfWithdrawAll)
431 JLOG(
j_.error()) <<
"AMM Withdraw: invalid options.";
437 return {result,
false};
442 sb, ammAccountID,
ctx_.tx[sfAsset],
ctx_.tx[sfAsset2], newLPTokenBalance,
j_);
450 sb, ammSle, newLPTokenBalance,
ctx_.tx[sfAsset],
ctx_.tx[sfAsset2],
j_);
453 return {res.first,
false};
456 JLOG(
ctx_.journal.trace()) <<
"AMM Withdraw: tokens " <<
to_string(newLPTokenBalance.iou())
457 <<
" " <<
to_string(lpTokens.iou()) <<
" "
507 return {ter, newLPTokenBalance};
530 view, ammSle, amountWithdraw.
asset(), std::nullopt, freezeHandling, authHandling, journal);
535 auto const [curBalance, curBalance2, _] = *expected;
538 auto const [amountWithdrawActual, amount2WithdrawActual, lpTokensWithdrawActual] =
551 return std::make_tuple(amountWithdraw, amount2Withdraw, lpTokensWithdraw);
554 if (lpTokensWithdrawActual <= beast::kZero || lpTokensWithdrawActual > lpTokens)
556 JLOG(journal.
debug()) <<
"AMM Withdraw: failed to withdraw, invalid LP tokens: "
557 << lpTokensWithdrawActual <<
" " << lpTokens <<
" "
558 << lpTokensAMMBalance;
564 if (
view.rules().enabled(fixAMMv1_1) && lpTokensWithdrawActual > lpTokensAMMBalance)
567 JLOG(journal.
debug()) <<
"AMM Withdraw: failed to withdraw, unexpected LP tokens: "
568 << lpTokensWithdrawActual <<
" " << lpTokens <<
" "
569 << lpTokensAMMBalance;
575 if ((amountWithdrawActual == curBalance && amount2WithdrawActual != curBalance2) ||
576 (amount2WithdrawActual == curBalance2 && amountWithdrawActual != curBalance))
578 JLOG(journal.
debug()) <<
"AMM Withdraw: failed to withdraw one side of the pool "
579 <<
" curBalance: " << curBalance <<
" " << amountWithdrawActual
580 <<
" lpTokensBalance: " << lpTokensWithdraw <<
" lptBalance "
581 << lpTokensAMMBalance;
586 if (lpTokensWithdrawActual == lpTokensAMMBalance &&
587 (amountWithdrawActual != curBalance || amount2WithdrawActual != curBalance2))
589 JLOG(journal.
debug()) <<
"AMM Withdraw: failed to withdraw all tokens "
590 <<
" curBalance: " << curBalance <<
" " << amountWithdrawActual
591 <<
" curBalance2: " << amount2WithdrawActual.value_or(
STAmount{0})
592 <<
" lpTokensBalance: " << lpTokensWithdraw <<
" lptBalance "
593 << lpTokensAMMBalance;
598 if (amountWithdrawActual > curBalance || amount2WithdrawActual > curBalance2)
600 JLOG(journal.
debug()) <<
"AMM Withdraw: withdrawing more than the pool's balance "
601 <<
" curBalance: " << curBalance <<
" " << amountWithdrawActual
602 <<
" curBalance2: " << curBalance2 <<
" "
603 << (amount2WithdrawActual ? *amount2WithdrawActual :
STAmount{})
604 <<
" lpTokensBalance: " << lpTokensWithdraw <<
" lptBalance "
605 << lpTokensAMMBalance;
611 if (
view.rules().enabled(featureMPTokensV2))
613 bool const newBalanceZero = (curBalance - amountWithdrawActual) == beast::kZero;
614 bool const newBalance2Zero =
615 (curBalance2 - amount2WithdrawActual.value_or(curBalance2.asset())) == beast::kZero;
616 bool const newLPTokensZero = (lpTokensAMMBalance - lpTokensWithdrawActual) == beast::kZero;
619 bool const valid = [&]() {
620 if (!amount2WithdrawActual)
621 return newBalanceZero == newLPTokensZero;
622 return newBalanceZero == newBalance2Zero && newBalance2Zero == newLPTokensZero;
626 JLOG(journal.
debug()) <<
"AMM Withdraw: some balances are zero"
627 <<
" curBalance: " << curBalance <<
" " << amountWithdrawActual
628 <<
" curBalance2: " << curBalance2 <<
" "
629 << (amount2WithdrawActual ? *amount2WithdrawActual :
STAmount{})
630 <<
" lpTokensBalance: " << lpTokensWithdraw <<
" lptBalance "
631 << lpTokensAMMBalance;
637 bool const enabledFixAmMv12 =
view.rules().enabled(fixAMMv1_2);
641 auto sufficientReserve = [&](
Asset const& asset) ->
TER {
642 mptokenKey = std::nullopt;
643 if (!enabledFixAmMv12 ||
isXRP(asset))
645 bool const isIssue = asset.holds<
Issue>();
646 bool const assetNotExists = [&] {
651 if (!
view.exists(*mptokenKey))
653 mptokenKey = std::nullopt;
661 STAmount const balance = (*sleAccount)[sfBalance];
662 std::uint32_t const ownerCount = sleAccount->at(sfOwnerCount);
666 (ownerCount < 2) ?
XRPAmount(beast::kZero)
667 :
view.fees().accountReserve(ownerCount + 1));
669 auto const balanceAdj = isIssue ?
std::max(priorBalance, balance.
xrp()) : priorBalance;
670 if (balanceAdj < reserve)
679 if (mptokenKey && account != asset.getIssuer())
681 auto const& mptIssue = asset.get<
MPTIssue>();
695 if (
auto const err = sufficientReserve(amountWithdrawActual.asset()))
707 JLOG(journal.
debug()) <<
"AMM Withdraw: failed to withdraw " << amountWithdrawActual;
713 if (amount2WithdrawActual)
715 if (
auto const err = sufficientReserve(amount2WithdrawActual->asset()); !
isTesSuccess(err))
726 JLOG(journal.
debug()) <<
"AMM Withdraw: failed to withdraw " << *amount2WithdrawActual;
734 view, account, lpTokensWithdrawActual, lpTokensWithdrawActual.get<
Issue>(), journal);
738 JLOG(journal.
debug()) <<
"AMM Withdraw: failed to withdraw LPTokens";
745 lpTokensAMMBalance - lpTokensWithdrawActual,
746 amountWithdrawActual,
747 amount2WithdrawActual);
758 return lpTokensWithdraw;
794 return {ter, newLPTokenBalance};
807 bool updateBalance =
true;
808 if (lpTokenBalance == beast::kZero)
819 ammSle->setFieldAmount(sfLPTokenBalance, lpTokenBalance);
849 if (lpTokensWithdraw == lptAMMBalance)
869 auto const tokensAdj =
871 if (
view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::kZero)
874 auto const frac =
divide(tokensAdj, lptAMMBalance,
noIssue());
875 auto const amountWithdraw =
877 auto const amount2Withdraw =
883 if (amountWithdraw == beast::kZero || amount2Withdraw == beast::kZero)
906 JLOG(journal.
error()) <<
"AMMWithdraw::equalWithdrawTokens exception " << e.
what();
949 auto frac =
Number{amount} / amountBalance;
951 if (
view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::kZero)
956 if (amount2Withdraw <= amount2)
970 frac =
Number{amount2} / amount2Balance;
973 if (
view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::kZero)
978 if (!
view.rules().enabled(fixAMMv1_3))
982 amountWithdraw <= amount,
983 "xrpl::AMMWithdraw::equalWithdrawLimit : maximum amountWithdraw");
986 else if (amountWithdraw > amount)
1020 lpTokensIn(amountBalance, amount, lptAMMBalance, tfee),
1022 if (tokens == beast::kZero)
1024 if (!
view.rules().enabled(fixAMMv1_3))
1032 auto const [tokensAdj, amountWithdrawAdj] =
1034 if (
view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::kZero)
1069 auto const tokensAdj =
1071 if (
view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::kZero)
1074 auto const amountWithdraw =
ammAssetOut(amountBalance, lptAMMBalance, tokensAdj, tfee);
1075 if (amount == beast::kZero || amountWithdraw >= amount)
1132 Number const ae = amountBalance * ePrice;
1133 auto const f =
getFee(tfee);
1134 auto const denom = lptAMMBalance * f - ae;
1137 if (
view.rules().enabled(fixCleanup3_3_0) && denom == beast::kZero)
1139 auto tokNoRoundCb = [&] {
return lptAMMBalance * (lptAMMBalance + ae * (f - 2)) / denom; };
1140 auto tokProdCb = [&] {
return (lptAMMBalance + ae * (f - 2)) / denom; };
1141 auto const tokensAdj =
1143 if (tokensAdj <= beast::kZero)
1145 if (!
view.rules().enabled(fixAMMv1_3))
1152 auto amtNoRoundCb = [&] {
return tokensAdj / ePrice; };
1153 auto amtProdCb = [&] {
return tokensAdj / ePrice; };
1155 auto const amountWithdraw =
1157 if (amount == beast::kZero || amountWithdraw >= amount)
1177 if ((tx[sfFlags] & (tfWithdrawAll | tfOneAssetWithdrawAll)) != 0u)
A generic endpoint for log messages.
FreezeHandling issuerFreezeHandling() const
Returns IgnoreFreeze when the withdrawer is the issuer of a pool asset (post-fixCleanup3_3_0),...
static std::pair< TER, bool > deleteAMMAccountIfEmpty(Sandbox &sb, SLE::pointer const ammSle, STAmount const &lpTokenBalance, Asset const &asset1, Asset const &asset2, beast::Journal const &journal)
static WithdrawAll isWithdrawAll(STTx const &tx)
Check from the flags if it's withdraw all.
static NotTEC preflight(PreflightContext const &ctx)
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
void visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override
Inspect a single ledger entry modified by this transaction.
static TER preclaim(PreclaimContext const &ctx)
std::pair< TER, STAmount > equalWithdrawLimit(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &amount2, std::uint16_t tfee)
Withdraw both assets (Asset1Out, Asset2Out) with the constraints on the maximum amount of each asset ...
bool finalizeInvariants(STTx const &tx, TER result, XRPAmount fee, ReadView const &view, beast::Journal const &j) override
Check transaction-specific post-conditions after all entries have been visited.
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > withdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, AccountID const &account, STAmount const &amountBalance, STAmount const &amountWithdraw, std::optional< STAmount > const &amount2Withdraw, STAmount const &lpTokensAMMBalance, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHandling, AuthHandling authHandling, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Withdraw requested assets and token from AMM into LP account.
std::pair< TER, STAmount > singleWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &lpTokensWithdraw, std::uint16_t tfee)
Single asset withdrawal (Asset1Out, LPTokens) proportional to the share specified by tokens.
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > equalWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const account, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokens, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHandling, AuthHandling authHandling, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Equal-asset withdrawal (LPTokens) of some AMM instance pools shares represented by the number of LPTo...
std::pair< TER, STAmount > singleWithdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, std::uint16_t tfee)
Single asset withdrawal (Asset1Out) equivalent to the amount specified in Asset1Out.
static bool checkExtraFeatures(PreflightContext const &ctx)
std::pair< TER, bool > applyGuts(Sandbox &view)
std::pair< TER, STAmount > singleWithdrawEPrice(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &ePrice, std::uint16_t tfee)
Withdraw single asset (Asset1Out, EPrice) with two constraints.
A currency issued by an account.
Number is a floating point type that can represent a wide range of values.
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
Rules controlling protocol behavior.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Asset const & asset() const
std::shared_ptr< STLedgerEntry > pointer
std::shared_ptr< STLedgerEntry const > const & const_ref
bool isFlag(std::uint32_t) const
std::uint32_t getFlags() const
Discardable, editable view to a ledger.
AccountID const accountID_
SLE::pointer peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
void update(SLE::ref sle) override
Indicate changes to a peeked SLE.
SLE::const_pointer read(Keylet const &k) const override
Return the state item associated with a key.
Rules const & rules() const override
Returns the tx processing rules.
T make_optional(T... args)
TER valid(STTx const &tx, ReadView const &view, AccountID const &src, beast::Journal j)
Keylet mptokenIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet trustLine(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
NotTEC invalidAMMAmount(STAmount const &amount, std::optional< std::pair< Asset, Asset > > const &pair=std::nullopt, bool validZero=false)
Validate the amount.
STAmount divide(STAmount const &amount, Rate const &rate)
STAmount ammLPHolds(ReadView const &view, Asset const &asset1, Asset const &asset2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
FreezeHandling
Controls the treatment of frozen account balances.
WithdrawAll
AMMWithdraw implements AMM withdraw Transactor.
TER checkIndividualFrozen(ReadView const &view, AccountID const &account, Asset const &asset)
bool ammEnabled(Rules const &)
Return true if required AMM amendment is enabled.
bool isXRP(AccountID const &c)
Number adjustFracByTokens(Rules const &rules, STAmount const &lptAMMBalance, STAmount const &tokens, Number const &frac)
Find a fraction of tokens after the tokens are adjusted.
TER checkCreateMPT(xrpl::ApplyView &view, xrpl::MPTIssue const &mptIssue, xrpl::AccountID const &holder, beast::Journal j)
std::expected< bool, TER > verifyAndAdjustLPTokenBalance(Sandbox &sb, STAmount const &lpTokens, SLE::pointer &ammSle, AccountID const &account)
Due to rounding, the LPTokenBalance of the last LP might not match the LP's trustline balance.
NotTEC invalidAMMAssetPair(Asset const &asset1, Asset const &asset2, std::optional< std::pair< Asset, Asset > > const &pair=std::nullopt)
TER checkFrozen(ReadView const &view, AccountID const &account, Issue const &issue)
static std::optional< STAmount > tokensWithdraw(STAmount const &lpTokens, std::optional< STAmount > const &tokensIn, std::uint32_t flags)
STAmount adjustLPTokens(STAmount const &lptAMMBalance, STAmount const &lpTokens, IsDeposit isDeposit)
Adjust LP tokens to deposit/withdraw.
STAmount ammAssetOut(STAmount const &assetBalance, STAmount const &lptAMMBalance, STAmount const &lpTokens, std::uint16_t tfee)
Calculate asset withdrawal by tokens.
STAmount getRoundedLPTokens(Rules const &rules, STAmount const &balance, Number const &frac, IsDeposit isDeposit)
Round AMM deposit/withdrawal LPToken amount.
std::string to_string(BaseUInt< Bits, Tag > const &a)
static STAmount adjustLPTokensIn(Rules const &rules, STAmount const &lptAMMBalance, STAmount const &lpTokensWithdraw, WithdrawAll withdrawAll)
std::pair< STAmount, STAmount > adjustAssetOutByTokens(Rules const &rules, STAmount const &balance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &tokens, std::uint16_t tfee)
TER deleteAMMAccount(Sandbox &view, Asset const &asset, Asset const &asset2, beast::Journal j)
Delete trustlines to AMM.
TERSubset< CanCvtToNotTEC > NotTEC
TER createMPToken(ApplyView &view, MPTID const &mptIssuanceID, AccountID const &account, std::uint32_t const flags)
STAmount getRoundedAsset(Rules const &rules, STAmount const &balance, A const &frac, IsDeposit isDeposit)
Round AMM equal deposit/withdrawal amount.
AuthHandling
Controls the treatment of unauthorized MPT balances.
TER checkWithdrawFreeze(ReadView const &view, AccountID const &srcAcct, AccountID const &submitterAcct, AccountID const &dstAcct, Asset const &asset)
Checks freeze compliance for withdrawing an asset from a pseudo-account (e.g.
TER checkAMMPrecisionLoss(Number const &poolProductMean, STAmount const &newLPTokenBalance)
Check AMM pool product invariant after an AMM operation that changes LP tokens (deposit/withdraw/claw...
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No, AllowMPTOverflow allowOverflow=AllowMPTOverflow::No)
Calls static accountSendIOU if saAmount represents Issue.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
std::tuple< STAmount, std::optional< STAmount >, STAmount > adjustAmountsByLPTokens(STAmount const &amountBalance, STAmount const &amount, std::optional< STAmount > const &amount2, STAmount const &lptAMMBalance, STAmount const &lpTokens, std::uint16_t tfee, IsDeposit isDeposit)
Calls adjustLPTokens() and adjusts deposit or withdraw amounts if the adjusted LP tokens are less tha...
TER redeemIOU(ApplyView &view, AccountID const &account, STAmount const &amount, Issue const &issue, beast::Journal j)
bool isTesSuccess(TER x) noexcept
STAmount lpTokensIn(STAmount const &asset1Balance, STAmount const &asset1Withdraw, STAmount const &lptAMMBalance, std::uint16_t tfee)
Calculate LP Tokens given asset's withdraw amount.
Number getFee(std::uint16_t tfee)
Convert to the fee from the basis points.
TERSubset< CanCvtToTER > TER
TER requireAuth(ReadView const &view, MPTIssue const &mptIssue, AccountID const &account, AuthType authType=AuthType::Legacy, std::uint8_t depth=0)
Check if the account lacks required authorization for MPT.
Issue const & noIssue()
Returns an asset specifier that represents no account and currency.
@ tecINSUFFICIENT_RESERVE
std::expected< std::tuple< STAmount, STAmount, STAmount >, TER > ammHolds(ReadView const &view, SLE const &ammSle, std::optional< Asset > const &optAsset1, std::optional< Asset > const &optAsset2, FreezeHandling freezeHandling, AuthHandling authHandling, beast::Journal const j)
Get AMM pool and LP token balances.
std::uint16_t getTradingFee(ReadView const &view, SLE const &ammSle, AccountID const &account)
Get AMM trading fee for the given account.
constexpr FlagValue tfWithdrawSubTx
State information when determining if a tx is likely to claim a fee.
State information when preflighting a tx.