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
20#include <xrpld/app/paths/AMMLiquidity.h>
21#include <xrpld/app/paths/AMMOffer.h>
22
23#include <xrpl/protocol/QualityFunction.h>
24
25namespace ripple {
26
27template <typename TIn, typename TOut>
29 AMMLiquidity<TIn, TOut> const& ammLiquidity,
30 TAmounts<TIn, TOut> const& amounts,
31 TAmounts<TIn, TOut> const& balances,
32 Quality const& quality)
33 : ammLiquidity_(ammLiquidity)
34 , amounts_(amounts)
35 , balances_(balances)
36 , quality_(quality)
37 , consumed_(false)
38{
39}
40
41template <typename TIn, typename TOut>
42Issue const&
44{
45 return ammLiquidity_.issueIn();
46}
47
48template <typename TIn, typename TOut>
49AccountID const&
51{
52 return ammLiquidity_.ammAccount();
53}
54
55template <typename TIn, typename TOut>
56TAmounts<TIn, TOut> const&
58{
59 return amounts_;
60}
61
62template <typename TIn, typename TOut>
63void
65 ApplyView& view,
66 TAmounts<TIn, TOut> const& consumed)
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 <typename TIn, typename TOut>
81TAmounts<TIn, TOut>
83 TAmounts<TIn, TOut> const& offrAmt,
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 if (auto const& rules = getCurrentTransactionRules();
96 rules && rules->enabled(fixReducedOffersV1))
97 // It turns out that the ceil_out implementation has some slop in
98 // it. ceil_out_strict removes that slop. But removing that slop
99 // affects transaction outcomes, so the change must be made using
100 // an amendment.
101 return quality().ceil_out_strict(offrAmt, limit, roundUp);
102 return quality().ceil_out(offrAmt, limit);
103 }
104 // Change the offer size according to the conservation function. The offer
105 // quality is increased in this case, but it doesn't matter since there is
106 // only one path.
107 return {swapAssetOut(balances_, limit, ammLiquidity_.tradingFee()), limit};
108}
109
110template <typename TIn, typename TOut>
111TAmounts<TIn, TOut>
113 TAmounts<TIn, TOut> const& offrAmt,
114 TIn const& limit,
115 bool roundUp) const
116{
117 // See the comments above in limitOut().
118 if (ammLiquidity_.multiPath())
119 {
120 if (auto const& rules = getCurrentTransactionRules();
121 rules && rules->enabled(fixReducedOffersV2))
122 return quality().ceil_in_strict(offrAmt, limit, roundUp);
123
124 return quality().ceil_in(offrAmt, limit);
125 }
126 return {limit, swapAssetIn(balances_, limit, ammLiquidity_.tradingFee())};
127}
128
129template <typename TIn, typename TOut>
132{
133 if (ammLiquidity_.multiPath())
135 return QualityFunction{
136 balances_, ammLiquidity_.tradingFee(), QualityFunction::AMMTag{}};
137}
138
139template <typename TIn, typename TOut>
140bool
142 TAmounts<TIn, TOut> const& consumed,
143 beast::Journal j) const
144{
145 if (consumed.in > amounts_.in || consumed.out > amounts_.out)
146 {
147 JLOG(j.error()) << "AMMOffer::checkInvariant failed: consumed "
148 << to_string(consumed.in) << " "
149 << to_string(consumed.out) << " amounts "
150 << to_string(amounts_.in) << " "
151 << to_string(amounts_.out);
152
153 return false;
154 }
155
156 Number const product = balances_.in * balances_.out;
157 auto const newBalances = TAmounts<TIn, TOut>{
158 balances_.in + consumed.in, balances_.out - consumed.out};
159 Number const newProduct = newBalances.in * newBalances.out;
160
161 if (newProduct >= product ||
162 withinRelativeDistance(product, newProduct, Number{1, -7}))
163 return true;
164
165 JLOG(j.error()) << "AMMOffer::checkInvariant failed: balances "
166 << to_string(balances_.in) << " "
167 << to_string(balances_.out) << " new balances "
168 << to_string(newBalances.in) << " "
169 << to_string(newBalances.out) << " product/newProduct "
170 << product << " " << newProduct << " diff "
171 << (product != Number{0}
172 ? to_string((product - newProduct) / product)
173 : "undefined");
174 return false;
175}
176
177template class AMMOffer<STAmount, STAmount>;
178template class AMMOffer<IOUAmount, IOUAmount>;
179template class AMMOffer<XRPAmount, IOUAmount>;
180template class AMMOffer<IOUAmount, XRPAmount>;
181
182} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:60
Stream error() const
Definition Journal.h:346
AMMLiquidity class provides AMM offers to BookStep class.
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:28
AccountID const & owner() const
Definition AMMOffer.cpp:50
TAmounts< TIn, TOut > limitOut(TAmounts< TIn, TOut > const &offrAmt, TOut const &limit, bool roundUp) const
Limit out of the provided offer.
Definition AMMOffer.cpp:82
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:141
void consume(ApplyView &view, TAmounts< TIn, TOut > const &consumed)
Definition AMMOffer.cpp:64
TAmounts< TIn, TOut > limitIn(TAmounts< TIn, TOut > const &offrAmt, TIn const &limit, bool roundUp) const
Limit in of the provided offer.
Definition AMMOffer.cpp:112
Issue const & issueIn() const
Definition AMMOffer.cpp:43
TAmounts< TIn, TOut > const & amount() const
Definition AMMOffer.cpp:57
QualityFunction getQualityFunc() const
Definition AMMOffer.cpp:131
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:143
A currency issued by an account.
Definition Issue.h:33
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:25
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:464
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
std::optional< Rules > const & getCurrentTransactionRules()
Definition Rules.cpp:47
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:129
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:537