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 // It turns out that the ceil_out implementation has some slop in
96 // it, which ceil_out_strict removes.
97 return quality().ceil_out_strict(offrAmt, 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 <typename TIn, typename TOut>
106TAmounts<TIn, TOut>
108 TAmounts<TIn, TOut> const& offrAmt,
109 TIn const& limit,
110 bool roundUp) const
111{
112 // See the comments above in limitOut().
113 if (ammLiquidity_.multiPath())
114 {
115 if (auto const& rules = getCurrentTransactionRules();
116 rules && rules->enabled(fixReducedOffersV2))
117 return quality().ceil_in_strict(offrAmt, limit, roundUp);
118
119 return quality().ceil_in(offrAmt, limit);
120 }
121 return {limit, swapAssetIn(balances_, limit, ammLiquidity_.tradingFee())};
122}
123
124template <typename TIn, typename TOut>
127{
128 if (ammLiquidity_.multiPath())
130 return QualityFunction{
131 balances_, ammLiquidity_.tradingFee(), QualityFunction::AMMTag{}};
132}
133
134template <typename TIn, typename TOut>
135bool
137 TAmounts<TIn, TOut> const& consumed,
138 beast::Journal j) const
139{
140 if (consumed.in > amounts_.in || consumed.out > amounts_.out)
141 {
142 JLOG(j.error()) << "AMMOffer::checkInvariant failed: consumed "
143 << to_string(consumed.in) << " "
144 << to_string(consumed.out) << " amounts "
145 << to_string(amounts_.in) << " "
146 << to_string(amounts_.out);
147
148 return false;
149 }
150
151 Number const product = balances_.in * balances_.out;
152 auto const newBalances = TAmounts<TIn, TOut>{
153 balances_.in + consumed.in, balances_.out - consumed.out};
154 Number const newProduct = newBalances.in * newBalances.out;
155
156 if (newProduct >= product ||
157 withinRelativeDistance(product, newProduct, Number{1, -7}))
158 return true;
159
160 JLOG(j.error()) << "AMMOffer::checkInvariant failed: balances "
161 << to_string(balances_.in) << " "
162 << to_string(balances_.out) << " new balances "
163 << to_string(newBalances.in) << " "
164 << to_string(newBalances.out) << " product/newProduct "
165 << product << " " << newProduct << " diff "
166 << (product != Number{0}
167 ? to_string((product - newProduct) / product)
168 : "undefined");
169 return false;
170}
171
172template class AMMOffer<STAmount, STAmount>;
173template class AMMOffer<IOUAmount, IOUAmount>;
174template class AMMOffer<XRPAmount, IOUAmount>;
175template class AMMOffer<IOUAmount, XRPAmount>;
176
177} // 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:136
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:107
Issue const & issueIn() const
Definition AMMOffer.cpp:43
TAmounts< TIn, TOut > const & amount() const
Definition AMMOffer.cpp:57
QualityFunction getQualityFunc() const
Definition AMMOffer.cpp:126
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