rippled
Loading...
Searching...
No Matches
AMMOffer.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2023 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================/
19#include <xrpld/app/paths/AMMOffer.h>
20
21#include <xrpld/app/paths/AMMLiquidity.h>
22#include <xrpl/protocol/QualityFunction.h>
23
24namespace ripple {
25
26template <typename TIn, typename TOut>
28 AMMLiquidity<TIn, TOut> const& ammLiquidity,
29 TAmounts<TIn, TOut> const& amounts,
30 TAmounts<TIn, TOut> const& balances,
31 Quality const& quality)
32 : ammLiquidity_(ammLiquidity)
33 , amounts_(amounts)
34 , balances_(balances)
35 , quality_(quality)
36 , consumed_(false)
37{
38}
39
40template <typename TIn, typename TOut>
41Issue const&
43{
44 return ammLiquidity_.issueIn();
45}
46
47template <typename TIn, typename TOut>
48AccountID const&
50{
51 return ammLiquidity_.ammAccount();
52}
53
54template <typename TIn, typename TOut>
55TAmounts<TIn, TOut> const&
57{
58 return amounts_;
59}
60
61template <typename TIn, typename TOut>
62void
64 ApplyView& view,
65 TAmounts<TIn, TOut> const& consumed)
66{
67 // Consumed offer must be less or equal to the original
68 if (consumed.in > amounts_.in || consumed.out > amounts_.out)
69 Throw<std::logic_error>("Invalid consumed AMM offer.");
70 // AMM pool is updated when the amounts are transferred
71 // in BookStep::consumeOffer().
72
73 consumed_ = true;
74
75 // Let the context know AMM offer is consumed
76 ammLiquidity_.context().setAMMUsed();
77}
78
79template <typename TIn, typename TOut>
80TAmounts<TIn, TOut>
82 TAmounts<TIn, TOut> const& offrAmt,
83 TOut const& limit,
84 bool roundUp) const
85{
86 // Change the offer size proportionally to the original offer quality
87 // to keep the strands quality order unchanged. The taker pays slightly
88 // more for the offer in this case, which results in a slightly higher
89 // pool product than the original pool product. I.e. if the original
90 // pool is poolPays, poolGets and the offer is assetIn, assetOut then
91 // poolPays * poolGets < (poolPays - assetOut) * (poolGets + assetIn)
92 if (ammLiquidity_.multiPath())
93 {
94 if (auto const& rules = getCurrentTransactionRules();
95 rules && rules->enabled(fixReducedOffersV1))
96 // It turns out that the ceil_out implementation has some slop in
97 // it. ceil_out_strict removes that slop. But removing that slop
98 // affects transaction outcomes, so the change must be made using
99 // an amendment.
100 return quality().ceil_out_strict(offrAmt, limit, roundUp);
101 return quality().ceil_out(offrAmt, limit);
102 }
103 // Change the offer size according to the conservation function. The offer
104 // quality is increased in this case, but it doesn't matter since there is
105 // only one path.
106 return {swapAssetOut(balances_, limit, ammLiquidity_.tradingFee()), limit};
107}
108
109template <typename TIn, typename TOut>
110TAmounts<TIn, TOut>
112 TAmounts<TIn, TOut> const& offrAmt,
113 TIn const& limit,
114 bool roundUp) const
115{
116 // See the comments above in limitOut().
117 if (ammLiquidity_.multiPath())
118 {
119 if (auto const& rules = getCurrentTransactionRules();
120 rules && rules->enabled(fixReducedOffersV2))
121 return quality().ceil_in_strict(offrAmt, limit, roundUp);
122
123 return quality().ceil_in(offrAmt, limit);
124 }
125 return {limit, swapAssetIn(balances_, limit, ammLiquidity_.tradingFee())};
126}
127
128template <typename TIn, typename TOut>
131{
132 if (ammLiquidity_.multiPath())
134 return QualityFunction{
135 balances_, ammLiquidity_.tradingFee(), QualityFunction::AMMTag{}};
136}
137
138template <typename TIn, typename TOut>
139bool
141 TAmounts<TIn, TOut> const& consumed,
142 beast::Journal j) const
143{
144 if (consumed.in > amounts_.in || consumed.out > amounts_.out)
145 {
146 JLOG(j.error()) << "AMMOffer::checkInvariant failed: consumed "
147 << to_string(consumed.in) << " "
148 << to_string(consumed.out) << " amounts "
149 << to_string(amounts_.in) << " "
150 << to_string(amounts_.out);
151
152 return false;
153 }
154
155 Number const product = balances_.in * balances_.out;
156 auto const newBalances = TAmounts<TIn, TOut>{
157 balances_.in + consumed.in, balances_.out - consumed.out};
158 Number const newProduct = newBalances.in * newBalances.out;
159
160 if (newProduct >= product ||
161 withinRelativeDistance(product, newProduct, Number{1, -7}))
162 return true;
163
164 JLOG(j.error()) << "AMMOffer::checkInvariant failed: balances "
165 << to_string(balances_.in) << " "
166 << to_string(balances_.out) << " new balances "
167 << to_string(newBalances.in) << " "
168 << to_string(newBalances.out) << " product/newProduct "
169 << product << " " << newProduct << " diff "
170 << (product != Number{0}
171 ? to_string((product - newProduct) / product)
172 : "undefined");
173 return false;
174}
175
176template class AMMOffer<STAmount, STAmount>;
177template class AMMOffer<IOUAmount, IOUAmount>;
178template class AMMOffer<XRPAmount, IOUAmount>;
179template class AMMOffer<IOUAmount, XRPAmount>;
180
181} // namespace ripple
A generic endpoint for log messages.
Definition: Journal.h:59
Stream error() const
Definition: Journal.h:335
AMMLiquidity class provides AMM offers to BookStep class.
Definition: AMMLiquidity.h:53
Represents synthetic AMM offer in BookStep.
Definition: AMMOffer.h:40
AMMOffer(AMMLiquidity< TIn, TOut > const &ammLiquidity, TAmounts< TIn, TOut > const &amounts, TAmounts< TIn, TOut > const &balances, Quality const &quality)
Definition: AMMOffer.cpp:27
AccountID const & owner() const
Definition: AMMOffer.cpp:49
TAmounts< TIn, TOut > limitOut(TAmounts< TIn, TOut > const &offrAmt, TOut const &limit, bool roundUp) const
Limit out of the provided offer.
Definition: AMMOffer.cpp:81
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:140
void consume(ApplyView &view, TAmounts< TIn, TOut > const &consumed)
Definition: AMMOffer.cpp:63
TAmounts< TIn, TOut > limitIn(TAmounts< TIn, TOut > const &offrAmt, TIn const &limit, bool roundUp) const
Limit in of the provided offer.
Definition: AMMOffer.cpp:111
Issue const & issueIn() const
Definition: AMMOffer.cpp:42
TAmounts< TIn, TOut > const & amount() const
Definition: AMMOffer.cpp:56
QualityFunction getQualityFunc() const
Definition: AMMOffer.cpp:130
Writeable view to a ledger, for applying a transaction.
Definition: ApplyView.h:140
A currency issued by an account.
Definition: Issue.h:36
Average quality of a path as a function of out: q(out) = m * out + b, where m = -1 / poolGets,...
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
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:465
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:629
std::optional< Rules > const & getCurrentTransactionRules()
Definition: Rules.cpp:39
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:130
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:538