rippled
Loading...
Searching...
No Matches
AMMOffer.cpp
1#include <xrpl/protocol/QualityFunction.h>
2#include <xrpl/tx/paths/AMMLiquidity.h>
3#include <xrpl/tx/paths/AMMOffer.h>
4
5namespace xrpl {
6
7template <typename TIn, typename TOut>
9 AMMLiquidity<TIn, TOut> const& ammLiquidity,
10 TAmounts<TIn, TOut> const& amounts,
11 TAmounts<TIn, TOut> const& balances,
12 Quality const& quality)
13 : ammLiquidity_(ammLiquidity), amounts_(amounts), balances_(balances), quality_(quality)
14
15{
16}
17
18template <typename TIn, typename TOut>
19Issue const&
21{
22 return ammLiquidity_.issueIn();
23}
24
25template <typename TIn, typename TOut>
26AccountID const&
28{
29 return ammLiquidity_.ammAccount();
30}
31
32template <typename TIn, typename TOut>
33TAmounts<TIn, TOut> const&
35{
36 return amounts_;
37}
38
39template <typename TIn, typename TOut>
40void
41AMMOffer<TIn, TOut>::consume(ApplyView& view, TAmounts<TIn, TOut> const& consumed)
42{
43 // Consumed offer must be less or equal to the original
44 if (consumed.in > amounts_.in || consumed.out > amounts_.out)
45 Throw<std::logic_error>("Invalid consumed AMM offer.");
46 // AMM pool is updated when the amounts are transferred
47 // in BookStep::consumeOffer().
48
49 consumed_ = true;
50
51 // Let the context know AMM offer is consumed
52 ammLiquidity_.context().setAMMUsed();
53}
54
55template <typename TIn, typename TOut>
56TAmounts<TIn, TOut>
58 TAmounts<TIn, TOut> const& offerAmount,
59 TOut const& limit,
60 bool roundUp) const
61{
62 // Change the offer size proportionally to the original offer quality
63 // to keep the strands quality order unchanged. The taker pays slightly
64 // more for the offer in this case, which results in a slightly higher
65 // pool product than the original pool product. I.e. if the original
66 // pool is poolPays, poolGets and the offer is assetIn, assetOut then
67 // poolPays * poolGets < (poolPays - assetOut) * (poolGets + assetIn)
68 if (ammLiquidity_.multiPath())
69 {
70 // It turns out that the ceil_out implementation has some slop in
71 // it, which ceil_out_strict removes.
72 return quality().ceil_out_strict(offerAmount, limit, roundUp);
73 }
74 // Change the offer size according to the conservation function. The offer
75 // quality is increased in this case, but it doesn't matter since there is
76 // only one path.
77 return {swapAssetOut(balances_, limit, ammLiquidity_.tradingFee()), limit};
78}
79
80template <typename TIn, typename TOut>
81TAmounts<TIn, TOut>
82AMMOffer<TIn, TOut>::limitIn(TAmounts<TIn, TOut> const& offerAmount, TIn const& limit, bool roundUp)
83 const
84{
85 // See the comments above in limitOut().
86 if (ammLiquidity_.multiPath())
87 {
88 if (auto const& rules = getCurrentTransactionRules();
89 rules && rules->enabled(fixReducedOffersV2))
90 return quality().ceil_in_strict(offerAmount, limit, roundUp);
91
92 return quality().ceil_in(offerAmount, limit);
93 }
94 return {limit, swapAssetIn(balances_, limit, ammLiquidity_.tradingFee())};
95}
96
97template <typename TIn, typename TOut>
100{
101 if (ammLiquidity_.multiPath())
103 return QualityFunction{balances_, ammLiquidity_.tradingFee(), QualityFunction::AMMTag{}};
104}
105
106template <typename TIn, typename TOut>
107bool
108AMMOffer<TIn, TOut>::checkInvariant(TAmounts<TIn, TOut> const& consumed, beast::Journal j) const
109{
110 if (consumed.in > amounts_.in || consumed.out > amounts_.out)
111 {
112 JLOG(j.error()) << "AMMOffer::checkInvariant failed: consumed " << to_string(consumed.in)
113 << " " << to_string(consumed.out) << " amounts " << to_string(amounts_.in)
114 << " " << to_string(amounts_.out);
115
116 return false;
117 }
118
119 Number const product = balances_.in * balances_.out;
120 auto const newBalances =
121 TAmounts<TIn, TOut>{balances_.in + consumed.in, balances_.out - consumed.out};
122 Number const newProduct = newBalances.in * newBalances.out;
123
124 if (newProduct >= product || withinRelativeDistance(product, newProduct, Number{1, -7}))
125 return true;
126
127 JLOG(j.error()) << "AMMOffer::checkInvariant failed: balances " << to_string(balances_.in)
128 << " " << to_string(balances_.out) << " new balances "
129 << to_string(newBalances.in) << " " << to_string(newBalances.out)
130 << " product/newProduct " << product << " " << newProduct << " diff "
131 << (product != Number{0} ? to_string((product - newProduct) / product)
132 : "undefined");
133 return false;
134}
135
136template class AMMOffer<STAmount, STAmount>;
137template class AMMOffer<IOUAmount, IOUAmount>;
138template class AMMOffer<XRPAmount, IOUAmount>;
139template class AMMOffer<IOUAmount, XRPAmount>;
140
141} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:40
Stream error() const
Definition Journal.h:319
AMMLiquidity class provides AMM offers to BookStep class.
Represents synthetic AMM offer in BookStep.
Definition AMMOffer.h:21
AMMOffer(AMMLiquidity< TIn, TOut > const &ammLiquidity, TAmounts< TIn, TOut > const &amounts, TAmounts< TIn, TOut > const &balances, Quality const &quality)
Definition AMMOffer.cpp:8
void consume(ApplyView &view, TAmounts< TIn, TOut > const &consumed)
Definition AMMOffer.cpp:41
TAmounts< TIn, TOut > const & amount() const
Definition AMMOffer.cpp:34
QualityFunction getQualityFunc() const
Definition AMMOffer.cpp:99
TAmounts< TIn, TOut > limitOut(TAmounts< TIn, TOut > const &offerAmount, TOut const &limit, bool roundUp) const
Limit out of the provided offer.
Definition AMMOffer.cpp:57
Issue const & issueIn() const
Definition AMMOffer.cpp:20
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:108
AccountID const & owner() const
Definition AMMOffer.cpp:27
TAmounts< TIn, TOut > limitIn(TAmounts< TIn, TOut > const &offerAmount, TIn const &limit, bool roundUp) const
Limit in of the provided offer.
Definition AMMOffer.cpp:82
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:116
A currency issued by an account.
Definition Issue.h:13
Number is a floating point type that can represent a wide range of values.
Definition Number.h:207
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:5
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:602
std::optional< Rules > const & getCurrentTransactionRules()
Definition Rules.cpp:31
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:413
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:481
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:106