rippled
Loading...
Searching...
No Matches
Offer.h
1#ifndef XRPL_APP_BOOK_OFFER_H_INCLUDED
2#define XRPL_APP_BOOK_OFFER_H_INCLUDED
3
4#include <xrpl/basics/Log.h>
5#include <xrpl/basics/contract.h>
6#include <xrpl/ledger/View.h>
7#include <xrpl/protocol/Quality.h>
8#include <xrpl/protocol/Rules.h>
9#include <xrpl/protocol/SField.h>
10#include <xrpl/protocol/STLedgerEntry.h>
11
12#include <stdexcept>
13
14namespace ripple {
15
16template <class TIn, class TOut>
18{
19protected:
22};
23
24template <>
26{
27public:
28 explicit TOfferBase() = default;
29};
30
31template <class TIn = STAmount, class TOut = STAmount>
32class TOffer : private TOfferBase<TIn, TOut>
33{
34private:
36 Quality m_quality;
38
39 TAmounts<TIn, TOut> m_amounts;
40 void
42
43public:
44 TOffer() = default;
45
46 TOffer(SLE::pointer const& entry, Quality quality);
47
57 Quality
58 quality() const noexcept
59 {
60 return m_quality;
61 }
62
64 AccountID const&
65 owner() const
66 {
67 return m_account;
68 }
69
73 TAmounts<TIn, TOut> const&
74 amount() const
75 {
76 return m_amounts;
77 }
78
80 bool
82 {
83 if (m_amounts.in <= beast::zero)
84 return true;
85 if (m_amounts.out <= beast::zero)
86 return true;
87 return false;
88 }
89
91 void
92 consume(ApplyView& view, TAmounts<TIn, TOut> const& consumed)
93 {
94 if (consumed.in > m_amounts.in)
95 Throw<std::logic_error>("can't consume more than is available.");
96
97 if (consumed.out > m_amounts.out)
98 Throw<std::logic_error>("can't produce more than is available.");
99
100 m_amounts -= consumed;
102 view.update(m_entry);
103 }
104
106 id() const
107 {
108 return to_string(m_entry->key());
109 }
110
112 key() const
113 {
114 return m_entry->key();
115 }
116
117 Issue const&
118 issueIn() const;
119 Issue const&
120 issueOut() const;
121
122 TAmounts<TIn, TOut>
124 TAmounts<TIn, TOut> const& offrAmt,
125 TOut const& limit,
126 bool roundUp) const;
127
128 TAmounts<TIn, TOut>
129 limitIn(TAmounts<TIn, TOut> const& offrAmt, TIn const& limit, bool roundUp)
130 const;
131
132 template <typename... Args>
133 static TER
134 send(Args&&... args);
135
136 bool
137 isFunded() const
138 {
139 // Offer owner is issuer; they have unlimited funds
140 return m_account == issueOut().account;
141 }
142
145 {
146 // CLOB offer pays the transfer fee
147 return {ofrInRate, ofrOutRate};
148 }
149
153 bool
154 checkInvariant(TAmounts<TIn, TOut> const& consumed, beast::Journal j) const
155 {
156 if (!isFeatureEnabled(fixAMMv1_3))
157 return true;
158
159 if (consumed.in > m_amounts.in || consumed.out > m_amounts.out)
160 {
161 // LCOV_EXCL_START
162 JLOG(j.error())
163 << "AMMOffer::checkInvariant failed: consumed "
164 << to_string(consumed.in) << " " << to_string(consumed.out)
165 << " amounts " << to_string(m_amounts.in) << " "
166 << to_string(m_amounts.out);
167
168 return false;
169 // LCOV_EXCL_STOP
170 }
171
172 return true;
173 }
174};
175
177
178template <class TIn, class TOut>
179TOffer<TIn, TOut>::TOffer(SLE::pointer const& entry, Quality quality)
180 : m_entry(entry)
181 , m_quality(quality)
182 , m_account(m_entry->getAccountID(sfAccount))
183{
184 auto const tp = m_entry->getFieldAmount(sfTakerPays);
185 auto const tg = m_entry->getFieldAmount(sfTakerGets);
186 m_amounts.in = toAmount<TIn>(tp);
187 m_amounts.out = toAmount<TOut>(tg);
188 this->issIn_ = tp.issue();
189 this->issOut_ = tg.issue();
190}
191
192template <>
194 SLE::pointer const& entry,
195 Quality quality)
196 : m_entry(entry)
197 , m_quality(quality)
198 , m_account(m_entry->getAccountID(sfAccount))
199 , m_amounts(
200 m_entry->getFieldAmount(sfTakerPays),
201 m_entry->getFieldAmount(sfTakerGets))
202{
203}
204
205template <class TIn, class TOut>
206void
208{
209 // LCOV_EXCL_START
210#ifdef _MSC_VER
211 UNREACHABLE("ripple::TOffer::setFieldAmounts : must be specialized");
212#else
213 static_assert(sizeof(TOut) == -1, "Must be specialized");
214#endif
215 // LCOV_EXCL_STOP
216}
217
218template <class TIn, class TOut>
219TAmounts<TIn, TOut>
221 TAmounts<TIn, TOut> const& offrAmt,
222 TOut const& limit,
223 bool roundUp) const
224{
225 // It turns out that the ceil_out implementation has some slop in
226 // it, which ceil_out_strict removes.
227 return quality().ceil_out_strict(offrAmt, limit, roundUp);
228}
229
230template <class TIn, class TOut>
231TAmounts<TIn, TOut>
233 TAmounts<TIn, TOut> const& offrAmt,
234 TIn const& limit,
235 bool roundUp) const
236{
237 if (auto const& rules = getCurrentTransactionRules();
238 rules && rules->enabled(fixReducedOffersV2))
239 // It turns out that the ceil_in implementation has some slop in
240 // it. ceil_in_strict removes that slop. But removing that slop
241 // affects transaction outcomes, so the change must be made using
242 // an amendment.
243 return quality().ceil_in_strict(offrAmt, limit, roundUp);
244 return m_quality.ceil_in(offrAmt, limit);
245}
246
247template <class TIn, class TOut>
248template <typename... Args>
249TER
251{
252 return accountSend(std::forward<Args>(args)...);
253}
254
255template <>
256inline void
258{
259 m_entry->setFieldAmount(sfTakerPays, m_amounts.in);
260 m_entry->setFieldAmount(sfTakerGets, m_amounts.out);
261}
262
263template <>
264inline void
266{
267 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
268 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
269}
270
271template <>
272inline void
274{
275 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
276 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out));
277}
278
279template <>
280inline void
282{
283 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in));
284 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
285}
286
287template <class TIn, class TOut>
288Issue const&
290{
291 return this->issIn_;
292}
293
294template <>
295inline Issue const&
297{
298 return m_amounts.in.issue();
299}
300
301template <class TIn, class TOut>
302Issue const&
304{
305 return this->issOut_;
306}
307
308template <>
309inline Issue const&
311{
312 return m_amounts.out.issue();
313}
314
315template <class TIn, class TOut>
318{
319 return os << offer.id();
320}
321
322} // namespace ripple
323
324#endif
A generic endpoint for log messages.
Definition Journal.h:41
Stream error() const
Definition Journal.h:327
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:124
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
A currency issued by an account.
Definition Issue.h:14
AccountID account
Definition Issue.h:17
bool fully_consumed() const
Returns true if no more funds can flow through this offer.
Definition Offer.h:81
TOffer()=default
Issue const & issueIn() const
Definition Offer.h:289
TOffer(SLE::pointer const &entry, Quality quality)
Definition Offer.h:179
Quality m_quality
Definition Offer.h:36
SLE::pointer m_entry
Definition Offer.h:35
Issue const & issueOut() const
Definition Offer.h:303
Quality quality() const noexcept
Returns the quality of the offer.
Definition Offer.h:58
TAmounts< TIn, TOut > limitIn(TAmounts< TIn, TOut > const &offrAmt, TIn const &limit, bool roundUp) const
Definition Offer.h:232
std::string id() const
Definition Offer.h:106
TAmounts< TIn, TOut > limitOut(TAmounts< TIn, TOut > const &offrAmt, TOut const &limit, bool roundUp) const
Definition Offer.h:220
AccountID const & owner() const
Returns the account id of the offer's owner.
Definition Offer.h:65
bool isFunded() const
Definition Offer.h:137
bool checkInvariant(TAmounts< TIn, TOut > const &consumed, beast::Journal j) const
Check any required invariant.
Definition Offer.h:154
TAmounts< TIn, TOut > const & amount() const
Returns the in and out amounts.
Definition Offer.h:74
std::optional< uint256 > key() const
Definition Offer.h:112
static std::pair< std::uint32_t, std::uint32_t > adjustRates(std::uint32_t ofrInRate, std::uint32_t ofrOutRate)
Definition Offer.h:144
static TER send(Args &&... args)
Definition Offer.h:250
void setFieldAmounts()
Definition Offer.h:207
TAmounts< TIn, TOut > m_amounts
Definition Offer.h:39
AccountID m_account
Definition Offer.h:37
void consume(ApplyView &view, TAmounts< TIn, TOut > const &consumed)
Adjusts the offer to indicate that we consumed some (or all) of it.
Definition Offer.h:92
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
bool isFeatureEnabled(uint256 const &feature)
Definition Rules.cpp:136
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
std::ostream & operator<<(std::ostream &out, base_uint< Bits, Tag > const &u)
Definition base_uint.h:628
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No)
Calls static accountSendIOU if saAmount represents Issue.
Definition View.cpp:2172
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
std::optional< Rules > const & getCurrentTransactionRules()
Definition Rules.cpp:28