xrpld
Loading...
Searching...
No Matches
AMMOffer.cpp
1#include <xrpl/tx/paths/AMMOffer.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/Number.h>
5#include <xrpl/basics/contract.h>
6#include <xrpl/beast/utility/Journal.h>
7#include <xrpl/ledger/ApplyView.h>
8#include <xrpl/ledger/helpers/AMMHelpers.h>
9#include <xrpl/protocol/AccountID.h>
10#include <xrpl/protocol/Asset.h>
11#include <xrpl/protocol/Concepts.h>
12#include <xrpl/protocol/Feature.h>
13#include <xrpl/protocol/IOUAmount.h>
14#include <xrpl/protocol/MPTAmount.h>
15#include <xrpl/protocol/Quality.h>
16#include <xrpl/protocol/QualityFunction.h>
17#include <xrpl/protocol/Rules.h>
18#include <xrpl/protocol/XRPAmount.h>
19#include <xrpl/tx/paths/AMMLiquidity.h>
20
21#include <stdexcept>
22
23namespace xrpl {
24
25template <StepAmount TIn, StepAmount TOut>
27 AMMLiquidity<TIn, TOut> const& ammLiquidity,
28 TAmounts<TIn, TOut> const& amounts,
29 TAmounts<TIn, TOut> const& balances,
30 Quality const& quality)
31 : ammLiquidity_(ammLiquidity), amounts_(amounts), balances_(balances), quality_(quality)
32
33{
34}
35
36template <StepAmount TIn, StepAmount TOut>
37Asset const&
39{
40 return ammLiquidity_.assetIn();
41}
42
43template <StepAmount TIn, StepAmount TOut>
44Asset const&
46{
47 return ammLiquidity_.assetOut();
48}
49
50template <StepAmount TIn, StepAmount TOut>
51AccountID const&
53{
54 return ammLiquidity_.ammAccount();
55}
56
57template <StepAmount TIn, StepAmount TOut>
60{
61 return amounts_;
62}
63
64template <StepAmount TIn, StepAmount TOut>
65void
67{
68 // Consumed offer must be less or equal to the original
69 if (consumed.in > amounts_.in || consumed.out > amounts_.out)
70 Throw<std::logic_error>("Invalid consumed AMM offer.");
71 // AMM pool is updated when the amounts are transferred
72 // in BookStep::consumeOffer().
73
74 consumed_ = true;
75
76 // Let the context know AMM offer is consumed
77 ammLiquidity_.context().setAMMUsed();
78}
79
80template <StepAmount TIn, StepAmount TOut>
83 TAmounts<TIn, TOut> const& offerAmount,
84 TOut const& limit,
85 bool roundUp) const
86{
87 // Change the offer size proportionally to the original offer quality
88 // to keep the strands quality order unchanged. The taker pays slightly
89 // more for the offer in this case, which results in a slightly higher
90 // pool product than the original pool product. I.e. if the original
91 // pool is poolPays, poolGets and the offer is assetIn, assetOut then
92 // poolPays * poolGets < (poolPays - assetOut) * (poolGets + assetIn)
93 if (ammLiquidity_.multiPath())
94 {
95 // It turns out that the ceil_out implementation has some slop in
96 // it, which ceil_out_strict removes.
97 return quality().ceilOutStrict(offerAmount, limit, roundUp);
98 }
99 // Change the offer size according to the conservation function. The offer
100 // quality is increased in this case, but it doesn't matter since there is
101 // only one path.
102 return {swapAssetOut(balances_, limit, ammLiquidity_.tradingFee()), limit};
103}
104
105template <StepAmount TIn, StepAmount TOut>
107AMMOffer<TIn, TOut>::limitIn(TAmounts<TIn, TOut> const& offerAmount, TIn const& limit, bool roundUp)
108 const
109{
110 // See the comments above in limitOut().
111 if (ammLiquidity_.multiPath())
112 {
113 if (auto const& rules = getCurrentTransactionRules();
114 rules && rules->enabled(fixReducedOffersV2))
115 return quality().ceilInStrict(offerAmount, limit, roundUp);
116
117 return quality().ceilIn(offerAmount, limit);
118 }
119 return {limit, swapAssetIn(balances_, limit, ammLiquidity_.tradingFee())};
120}
121
122template <StepAmount TIn, StepAmount TOut>
130
131template <StepAmount TIn, StepAmount TOut>
132bool
134{
135 if (consumed.in > amounts_.in || consumed.out > amounts_.out)
136 {
137 JLOG(j.error()) << "AMMOffer::checkInvariant failed: consumed " << to_string(consumed.in)
138 << " " << to_string(consumed.out) << " amounts " << to_string(amounts_.in)
139 << " " << to_string(amounts_.out);
140
141 return false;
142 }
143
144 Number const product = balances_.in * balances_.out;
145 auto const newBalances =
146 TAmounts<TIn, TOut>{balances_.in + consumed.in, balances_.out - consumed.out};
147 Number const newProduct = newBalances.in * newBalances.out;
148
149 if (newProduct >= product || withinRelativeDistance(product, newProduct, Number{1, -7}))
150 return true;
151
152 JLOG(j.error()) << "AMMOffer::checkInvariant failed: balances " << to_string(balances_.in)
153 << " " << to_string(balances_.out) << " new balances "
154 << to_string(newBalances.in) << " " << to_string(newBalances.out)
155 << " product/newProduct " << product << " " << newProduct << " diff "
156 << (product != Number{0} ? to_string((product - newProduct) / product)
157 : "undefined");
158 return false;
159}
160
161template class AMMOffer<IOUAmount, IOUAmount>;
162template class AMMOffer<XRPAmount, IOUAmount>;
163template class AMMOffer<IOUAmount, XRPAmount>;
164template class AMMOffer<MPTAmount, MPTAmount>;
165template class AMMOffer<XRPAmount, MPTAmount>;
166template class AMMOffer<MPTAmount, XRPAmount>;
167template class AMMOffer<IOUAmount, MPTAmount>;
168template class AMMOffer<MPTAmount, IOUAmount>;
169
170} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:38
Stream error() const
Definition Journal.h:315
AMMLiquidity class provides AMM offers to BookStep class.
Represents synthetic AMM offer in BookStep.
Definition AMMOffer.h:22
Asset const & assetOut() const
Definition AMMOffer.cpp:45
Quality const quality_
Definition AMMOffer.h:39
AMMOffer(AMMLiquidity< TIn, TOut > const &ammLiquidity, TAmounts< TIn, TOut > const &amounts, TAmounts< TIn, TOut > const &balances, Quality const &quality)
Definition AMMOffer.cpp:26
TAmounts< TIn, TOut > const amounts_
Definition AMMOffer.h:34
void consume(ApplyView &view, TAmounts< TIn, TOut > const &consumed)
Definition AMMOffer.cpp:66
TAmounts< TIn, TOut > const & amount() const
Definition AMMOffer.cpp:59
QualityFunction getQualityFunc() const
Definition AMMOffer.cpp:124
TAmounts< TIn, TOut > limitOut(TAmounts< TIn, TOut > const &offerAmount, TOut const &limit, bool roundUp) const
Limit out of the provided offer.
Definition AMMOffer.cpp:82
Asset const & assetIn() const
Definition AMMOffer.cpp:38
TAmounts< TIn, TOut > const balances_
Definition AMMOffer.h:36
AMMLiquidity< TIn, TOut > const & ammLiquidity_
Definition AMMOffer.h:24
bool checkInvariant(TAmounts< TIn, TOut > const &consumed, beast::Journal j) const
Check the new pool product is greater or equal to the old pool product or if decreases then within so...
Definition AMMOffer.cpp:133
AccountID const & owner() const
Definition AMMOffer.cpp:52
Quality quality() const noexcept
Definition AMMOffer.h:51
TAmounts< TIn, TOut > limitIn(TAmounts< TIn, TOut > const &offerAmount, TIn const &limit, bool roundUp) const
Limit in of the provided offer.
Definition AMMOffer.cpp:107
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:118
Number is a floating point type that can represent a wide range of values.
Definition Number.h:306
Average quality of a path as a function of out: q(out) = m * out + b, where m = -1 / poolGets,...
Represents the logical ratio of output currency to input currency.
Definition Quality.h:91
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::optional< Rules > const & getCurrentTransactionRules()
Definition Rules.cpp:30
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) ...
Definition AMMHelpers.h:427
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:28
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.
Definition AMMHelpers.h:493
bool withinRelativeDistance(Quality const &calcQuality, Quality const &reqQuality, Number const &dist)
Check if the relative distance between the qualities is within the requested distance.
Definition AMMHelpers.h:115
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49
Represents a pair of input and output currencies.
Definition Quality.h:26