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 xrpl {
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& offerAmount,
125 TOut const& limit,
126 bool roundUp) const;
127
128 TAmounts<TIn, TOut>
130 TAmounts<TIn, TOut> const& offerAmount,
131 TIn const& limit,
132 bool roundUp) const;
133
134 template <typename... Args>
135 static TER
136 send(Args&&... args);
137
138 bool
139 isFunded() const
140 {
141 // Offer owner is issuer; they have unlimited funds
142 return m_account == issueOut().account;
143 }
144
147 {
148 // CLOB offer pays the transfer fee
149 return {ofrInRate, ofrOutRate};
150 }
151
155 bool
156 checkInvariant(TAmounts<TIn, TOut> const& consumed, beast::Journal j) const
157 {
158 if (!isFeatureEnabled(fixAMMv1_3))
159 return true;
160
161 if (consumed.in > m_amounts.in || consumed.out > m_amounts.out)
162 {
163 // LCOV_EXCL_START
164 JLOG(j.error())
165 << "AMMOffer::checkInvariant failed: consumed "
166 << to_string(consumed.in) << " " << to_string(consumed.out)
167 << " amounts " << to_string(m_amounts.in) << " "
168 << to_string(m_amounts.out);
169
170 return false;
171 // LCOV_EXCL_STOP
172 }
173
174 return true;
175 }
176};
177
179
180template <class TIn, class TOut>
181TOffer<TIn, TOut>::TOffer(SLE::pointer const& entry, Quality quality)
182 : m_entry(entry)
183 , m_quality(quality)
184 , m_account(m_entry->getAccountID(sfAccount))
185{
186 auto const tp = m_entry->getFieldAmount(sfTakerPays);
187 auto const tg = m_entry->getFieldAmount(sfTakerGets);
188 m_amounts.in = toAmount<TIn>(tp);
189 m_amounts.out = toAmount<TOut>(tg);
190 this->issIn_ = tp.issue();
191 this->issOut_ = tg.issue();
192}
193
194template <>
196 SLE::pointer const& entry,
197 Quality quality)
198 : m_entry(entry)
199 , m_quality(quality)
200 , m_account(m_entry->getAccountID(sfAccount))
201 , m_amounts(
202 m_entry->getFieldAmount(sfTakerPays),
203 m_entry->getFieldAmount(sfTakerGets))
204{
205}
206
207template <class TIn, class TOut>
208void
210{
211 // LCOV_EXCL_START
212#ifdef _MSC_VER
213 UNREACHABLE("xrpl::TOffer::setFieldAmounts : must be specialized");
214#else
215 static_assert(sizeof(TOut) == -1, "Must be specialized");
216#endif
217 // LCOV_EXCL_STOP
218}
219
220template <class TIn, class TOut>
221TAmounts<TIn, TOut>
223 TAmounts<TIn, TOut> const& offerAmount,
224 TOut const& limit,
225 bool roundUp) const
226{
227 // It turns out that the ceil_out implementation has some slop in
228 // it, which ceil_out_strict removes.
229 return quality().ceil_out_strict(offerAmount, limit, roundUp);
230}
231
232template <class TIn, class TOut>
233TAmounts<TIn, TOut>
235 TAmounts<TIn, TOut> const& offerAmount,
236 TIn const& limit,
237 bool roundUp) const
238{
239 if (auto const& rules = getCurrentTransactionRules();
240 rules && rules->enabled(fixReducedOffersV2))
241 // It turns out that the ceil_in implementation has some slop in
242 // it. ceil_in_strict removes that slop. But removing that slop
243 // affects transaction outcomes, so the change must be made using
244 // an amendment.
245 return quality().ceil_in_strict(offerAmount, limit, roundUp);
246 return m_quality.ceil_in(offerAmount, limit);
247}
248
249template <class TIn, class TOut>
250template <typename... Args>
251TER
253{
254 return accountSend(std::forward<Args>(args)...);
255}
256
257template <>
258inline void
260{
261 m_entry->setFieldAmount(sfTakerPays, m_amounts.in);
262 m_entry->setFieldAmount(sfTakerGets, m_amounts.out);
263}
264
265template <>
266inline void
268{
269 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
270 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
271}
272
273template <>
274inline void
276{
277 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
278 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out));
279}
280
281template <>
282inline void
284{
285 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in));
286 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
287}
288
289template <class TIn, class TOut>
290Issue const&
292{
293 return this->issIn_;
294}
295
296template <>
297inline Issue const&
299{
300 return m_amounts.in.issue();
301}
302
303template <class TIn, class TOut>
304Issue const&
306{
307 return this->issOut_;
308}
309
310template <>
311inline Issue const&
313{
314 return m_amounts.out.issue();
315}
316
317template <class TIn, class TOut>
320{
321 return os << offer.id();
322}
323
324} // namespace xrpl
325
326#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
Issue issOut_
Definition Offer.h:21
Issue issIn_
Definition Offer.h:20
Issue const & issueOut() const
Definition Offer.h:305
static TER send(Args &&... args)
Definition Offer.h:252
bool fully_consumed() const
Returns true if no more funds can flow through this offer.
Definition Offer.h:81
AccountID const & owner() const
Returns the account id of the offer's owner.
Definition Offer.h:65
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
static std::pair< std::uint32_t, std::uint32_t > adjustRates(std::uint32_t ofrInRate, std::uint32_t ofrOutRate)
Definition Offer.h:146
std::optional< uint256 > key() const
Definition Offer.h:112
Quality quality() const noexcept
Returns the quality of the offer.
Definition Offer.h:58
TAmounts< TIn, TOut > m_amounts
Definition Offer.h:39
TOffer()=default
AccountID m_account
Definition Offer.h:37
Quality m_quality
Definition Offer.h:36
TOffer(SLE::pointer const &entry, Quality quality)
Definition Offer.h:181
bool isFunded() const
Definition Offer.h:139
TAmounts< TIn, TOut > limitOut(TAmounts< TIn, TOut > const &offerAmount, TOut const &limit, bool roundUp) const
Definition Offer.h:222
bool checkInvariant(TAmounts< TIn, TOut > const &consumed, beast::Journal j) const
Check any required invariant.
Definition Offer.h:156
void setFieldAmounts()
Definition Offer.h:209
TAmounts< TIn, TOut > const & amount() const
Returns the in and out amounts.
Definition Offer.h:74
Issue const & issueIn() const
Definition Offer.h:291
std::string id() const
Definition Offer.h:106
TAmounts< TIn, TOut > limitIn(TAmounts< TIn, TOut > const &offerAmount, TIn const &limit, bool roundUp) const
Definition Offer.h:234
SLE::pointer m_entry
Definition Offer.h:35
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
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
std::optional< Rules > const & getCurrentTransactionRules()
Definition Rules.cpp:28
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:2777
bool isFeatureEnabled(uint256 const &feature)
Definition Rules.cpp:136