20#ifndef RIPPLE_APP_MISC_AMMHELPERS_H_INCLUDED 
   21#define RIPPLE_APP_MISC_AMMHELPERS_H_INCLUDED 
   23#include <xrpl/basics/Log.h> 
   24#include <xrpl/basics/Number.h> 
   25#include <xrpl/beast/utility/Journal.h> 
   26#include <xrpl/protocol/AMMCore.h> 
   27#include <xrpl/protocol/AmountConversions.h> 
   28#include <xrpl/protocol/Feature.h> 
   29#include <xrpl/protocol/IOUAmount.h> 
   30#include <xrpl/protocol/Issue.h> 
   31#include <xrpl/protocol/Quality.h> 
   32#include <xrpl/protocol/Rules.h> 
   33#include <xrpl/protocol/STAmount.h> 
   42    static Number const reducedOfferPct(9999, -4);
 
   46    return amount * reducedOfferPct;
 
 
   60    STAmount 
const& asset1,
 
   61    STAmount 
const& asset2,
 
   62    Issue 
const& lptIssue);
 
   73    STAmount 
const& asset1Balance,
 
   74    STAmount 
const& asset1Deposit,
 
   75    STAmount 
const& lptAMMBalance,
 
   87    STAmount 
const& asset1Balance,
 
   88    STAmount 
const& lptAMMBalance,
 
   89    STAmount 
const& lpTokens,
 
  102    STAmount 
const& asset1Balance,
 
  103    STAmount 
const& asset1Withdraw,
 
  104    STAmount 
const& lptAMMBalance,
 
  116    STAmount 
const& assetBalance,
 
  117    STAmount 
const& lptAMMBalance,
 
  118    STAmount 
const& lpTokens,
 
  130    Quality 
const& calcQuality,
 
  131    Quality 
const& reqQuality,
 
  134    if (calcQuality == reqQuality)
 
  136    auto const [min, max] = 
std::minmax(calcQuality, reqQuality);
 
  140    return ((min.rate() - max.rate()) / min.rate()) < dist;
 
 
  151template <
typename Amt>
 
  161    return ((max - min) / max) < dist;
 
 
  194template <
typename TIn, 
typename TOut>
 
  197    TAmounts<TIn, TOut> 
const& pool,
 
  198    Quality 
const& targetQuality,
 
  201    if (targetQuality.rate() == beast::zero)
 
  207    auto const b = pool.in * (1 - 1 / f) / targetQuality.rate() - 2 * pool.out;
 
  209        pool.out * pool.out - (pool.in * pool.out) / targetQuality.rate();
 
  212    if (!nTakerGets || *nTakerGets <= 0)
 
  215    auto const nTakerGetsConstraint =
 
  216        pool.out - pool.in / (targetQuality.rate() * f);
 
  217    if (nTakerGetsConstraint <= 0)
 
  221    if (nTakerGetsConstraint < *nTakerGets)
 
  222        nTakerGets = nTakerGetsConstraint;
 
  224    auto getAmounts = [&pool, &tfee](
Number const& nTakerGetsProposed) {
 
  227        auto const takerGets = toAmount<TOut>(
 
  229        return TAmounts<TIn, TOut>{
 
  235    if (
auto const amounts = getAmounts(*nTakerGets);
 
  236        Quality{amounts} < targetQuality)
 
 
  265template <
typename TIn, 
typename TOut>
 
  268    TAmounts<TIn, TOut> 
const& pool,
 
  269    Quality 
const& targetQuality,
 
  272    if (targetQuality.rate() == beast::zero)
 
  278    auto const b = pool.in * (1 + f);
 
  280        pool.in * pool.in - pool.in * pool.out * targetQuality.rate();
 
  283    if (!nTakerPays || nTakerPays <= 0)
 
  286    auto const nTakerPaysConstraint =
 
  287        pool.out * targetQuality.rate() - pool.in / f;
 
  288    if (nTakerPaysConstraint <= 0)
 
  292    if (nTakerPaysConstraint < *nTakerPays)
 
  293        nTakerPays = nTakerPaysConstraint;
 
  295    auto getAmounts = [&pool, &tfee](
Number const& nTakerPaysProposed) {
 
  298        auto const takerPays = toAmount<TIn>(
 
  300        return TAmounts<TIn, TOut>{
 
  306    if (
auto const amounts = getAmounts(*nTakerPays);
 
  307        Quality{amounts} < targetQuality)
 
 
  329template <
typename TIn, 
typename TOut>
 
  332    TAmounts<TIn, TOut> 
const& pool,
 
  333    Quality 
const& quality,
 
  338    if (!rules.
enabled(fixAMMv1_1))
 
  348        auto const b = pool.in * (1 + f);
 
  350            pool.in * pool.in - pool.in * pool.out * quality.rate();
 
  351        if (
auto const res = b * b - 4 * a * c; res < 0)
 
  353        else if (
auto const nTakerPaysPropose = (-b + 
root2(res)) / (2 * a);
 
  354                 nTakerPaysPropose > 0)
 
  356            auto const nTakerPays = [&]() {
 
  361                auto const nTakerPaysConstraint =
 
  362                    pool.out * quality.rate() - pool.in / f;
 
  363                if (nTakerPaysPropose > nTakerPaysConstraint)
 
  364                    return nTakerPaysConstraint;
 
  365                return nTakerPaysPropose;
 
  370                    << 
"changeSpotPriceQuality calc failed: " 
  372                    << quality << 
" " << tfee;
 
  375            auto const takerPays =
 
  378            if (
auto const amounts =
 
  381                Quality{amounts} < quality &&
 
  383                    Quality{amounts}, quality, 
Number(1, -7)))
 
  386                    << 
"changeSpotPriceQuality failed: " << 
to_string(pool.in)
 
  388                    << 
" " << quality << 
" " << tfee << 
" " 
  390                Throw<std::runtime_error>(
"changeSpotPriceQuality failed");
 
  395                    << 
"changeSpotPriceQuality succeeded: " 
  397                    << 
" " << quality << 
" " << tfee << 
" " 
  402        JLOG(j.
trace()) << 
"changeSpotPriceQuality calc failed: " 
  404                        << 
" " << quality << 
" " << tfee;
 
  410    auto const amounts = [&]() {
 
  417        JLOG(j.
trace()) << 
"changeSpotPrice calc failed: " << 
to_string(pool.in)
 
  418                        << 
" " << 
to_string(pool.out) << 
" " << quality << 
" " 
  423    if (Quality{*amounts} < quality)
 
  425        JLOG(j.
error()) << 
"changeSpotPriceQuality failed: " 
  427                        << 
" " << quality << 
" " << tfee << 
" " 
  433    JLOG(j.
trace()) << 
"changeSpotPriceQuality succeeded: " 
  435                    << 
" " << quality << 
" " << tfee << 
" " 
 
  462template <
typename TIn, 
typename TOut>
 
  465    TAmounts<TIn, TOut> 
const& pool,
 
  470        rules && rules->enabled(fixAMMv1_1))
 
  496        auto const numerator = pool.in * pool.out;
 
  497        auto const fee = 
getFee(tfee);
 
  500        auto const denom = pool.in + assetIn * (1 - fee);
 
  502        if (denom.signum() <= 0)
 
  503            return toAmount<TOut>(
getIssue(pool.out), 0);
 
  506        auto const ratio = numerator / denom;
 
  509        auto const swapOut = pool.out - ratio;
 
  511        if (swapOut.signum() < 0)
 
  512            return toAmount<TOut>(
getIssue(pool.out), 0);
 
  518        return toAmount<TOut>(
 
  521                (pool.in * pool.out) / (pool.in + assetIn * 
feeMult(tfee)),
 
 
  535template <
typename TIn, 
typename TOut>
 
  538    TAmounts<TIn, TOut> 
const& pool,
 
  539    TOut 
const& assetOut,
 
  543        rules && rules->enabled(fixAMMv1_1))
 
  565        auto const numerator = pool.in * pool.out;
 
  568        auto const denom = pool.out - assetOut;
 
  569        if (denom.signum() <= 0)
 
  571            return toMaxAmount<TIn>(
getIssue(pool.in));
 
  575        auto const ratio = numerator / denom;
 
  576        auto const numerator2 = ratio - pool.in;
 
  577        auto const fee = 
getFee(tfee);
 
  583        auto const swapIn = numerator2 / 
feeMult;
 
  584        if (swapIn.signum() < 0)
 
  585            return toAmount<TIn>(
getIssue(pool.in), 0);
 
  591        return toAmount<TIn>(
 
  593            ((pool.in * pool.out) / (pool.out - assetOut) - pool.in) /
 
 
  617    STAmount 
const& lptAMMBalance,
 
  618    STAmount 
const& lpTokens,
 
  634    STAmount 
const& amountBalance,
 
  635    STAmount 
const& amount,
 
  637    STAmount 
const& lptAMMBalance,
 
  638    STAmount 
const& lpTokens,
 
  684    if (!rules.
enabled(fixAMMv1_3))
 
 
  708    STAmount 
const& balance,
 
  722    STAmount 
const& balance,
 
  741    STAmount 
const& lptAMMBalance,
 
  759    STAmount 
const& balance,
 
  760    STAmount 
const& amount,
 
  761    STAmount 
const& lptAMMBalance,
 
  762    STAmount 
const& tokens,
 
  767    STAmount 
const& balance,
 
  768    STAmount 
const& amount,
 
  769    STAmount 
const& lptAMMBalance,
 
  770    STAmount 
const& tokens,
 
  779    STAmount 
const& lptAMMBalance,
 
  780    STAmount 
const& tokens,
 
A generic endpoint for log messages.
 
Stream trace() const
Severity stream access functions.
 
static rounding_mode getround()
 
static rounding_mode setround(rounding_mode mode)
 
Rules controlling protocol behavior.
 
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
 
Issue const & issue() const
 
Number::rounding_mode getAssetRounding(IsDeposit isDeposit)
 
Number::rounding_mode getLPTokenRounding(IsDeposit isDeposit)
 
Number reduceOffer(auto const &amount)
 
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
 
std::pair< STAmount, STAmount > adjustAssetInByTokens(Rules const &rules, STAmount const &balance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &tokens, std::uint16_t tfee)
 
bool isXRP(AccountID const &c)
 
std::optional< Number > solveQuadraticEqSmallest(Number const &a, Number const &b, Number const &c)
Solve quadratic equation to find takerGets or takerPays.
 
Issue getIssue(T const &amt)
 
Number solveQuadraticEq(Number const &a, Number const &b, Number const &c)
Positive solution for quadratic equation: x = (-b + sqrt(b**2 + 4*a*c))/(2*a)
 
std::pair< STAmount, STAmount > adjustAssetOutByTokens(Rules const &rules, STAmount const &balance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &tokens, std::uint16_t tfee)
 
TOut swapAssetIn(TAmounts< TIn, TOut > const &pool, TIn const &assetIn, std::uint16_t tfee)
AMM pool invariant - the product (A * B) after swap in/out has to remain at least the same: (A + in) ...
 
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
 
STAmount ammAssetIn(STAmount const &asset1Balance, STAmount const &lptAMMBalance, STAmount const &lpTokens, std::uint16_t tfee)
Calculate asset deposit given LP Tokens.
 
Number square(Number const &n)
Return square of n.
 
STAmount multiply(STAmount const &amount, Rate const &rate)
 
std::optional< TAmounts< TIn, TOut > > getAMMOfferStartWithTakerGets(TAmounts< TIn, TOut > const &pool, Quality const &targetQuality, std::uint16_t const &tfee)
Generate AMM offer starting with takerGets when AMM pool from the payment perspective is IOU(in)/XRP(...
 
STAmount getRoundedLPTokens(Rules const &rules, STAmount const &balance, Number const &frac, IsDeposit isDeposit)
Round AMM deposit/withdrawal LPToken amount.
 
STAmount adjustLPTokens(STAmount const &lptAMMBalance, STAmount const &lpTokens, IsDeposit isDeposit)
Adjust LP tokens to deposit/withdraw.
 
Number feeMult(std::uint16_t tfee)
Get fee multiplier (1 - tfee) @tfee trading fee in basis points.
 
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...
 
std::optional< TAmounts< TIn, TOut > > changeSpotPriceQuality(TAmounts< TIn, TOut > const &pool, Quality const &quality, std::uint16_t tfee, Rules const &rules, beast::Journal j)
Generate AMM offer so that either updated Spot Price Quality (SPQ) is equal to LOB quality (in this c...
 
STAmount ammAssetOut(STAmount const &assetBalance, STAmount const &lptAMMBalance, STAmount const &lpTokens, std::uint16_t tfee)
Calculate asset withdrawal by tokens.
 
Number getFee(std::uint16_t tfee)
Convert to the fee from the basis points.
 
STAmount ammLPTokens(STAmount const &asset1, STAmount const &asset2, Issue const &lptIssue)
Calculate LP Tokens given AMM pool reserves.
 
std::string to_string(base_uint< Bits, Tag > const &a)
 
std::optional< Rules > const & getCurrentTransactionRules()
 
STAmount lpTokensIn(STAmount const &asset1Balance, STAmount const &asset1Withdraw, STAmount const &lptAMMBalance, std::uint16_t tfee)
Calculate LP Tokens given asset's withdraw amount.
 
STAmount lpTokensOut(STAmount const &asset1Balance, STAmount const &asset1Deposit, STAmount const &lptAMMBalance, std::uint16_t tfee)
Calculate LP Tokens given asset's deposit amount.
 
STAmount getRoundedAsset(Rules const &rules, STAmount const &balance, A const &frac, IsDeposit isDeposit)
Round AMM equal deposit/withdrawal amount.
 
std::optional< TAmounts< TIn, TOut > > getAMMOfferStartWithTakerPays(TAmounts< TIn, TOut > const &pool, Quality const &targetQuality, std::uint16_t tfee)
Generate AMM offer starting with takerPays when AMM pool from the payment perspective is XRP(in)/IOU(...
 
bool withinRelativeDistance(Quality const &calcQuality, Quality const &reqQuality, Number const &dist)
Check if the relative distance between the qualities is within the requested distance.
 
Number adjustFracByTokens(Rules const &rules, STAmount const &lptAMMBalance, STAmount const &tokens, Number const &frac)
Find a fraction of tokens after the tokens are adjusted.
 
TIn swapAssetOut(TAmounts< TIn, TOut > const &pool, TOut const &assetOut, std::uint16_t tfee)
Swap assetOut out of the pool and swap in a proportional amount of the other asset.