rippled
Loading...
Searching...
No Matches
Offer.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2014 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#ifndef RIPPLE_APP_BOOK_OFFER_H_INCLUDED
21#define RIPPLE_APP_BOOK_OFFER_H_INCLUDED
22
23#include <xrpl/basics/Log.h>
24#include <xrpl/basics/contract.h>
25#include <xrpl/ledger/View.h>
26#include <xrpl/protocol/Quality.h>
27#include <xrpl/protocol/Rules.h>
28#include <xrpl/protocol/SField.h>
29#include <xrpl/protocol/STLedgerEntry.h>
30
31#include <stdexcept>
32
33namespace ripple {
34
35template <class TIn, class TOut>
37{
38protected:
41};
42
43template <>
45{
46public:
47 explicit TOfferBase() = default;
48};
49
50template <class TIn = STAmount, class TOut = STAmount>
51class TOffer : private TOfferBase<TIn, TOut>
52{
53private:
55 Quality m_quality;
57
58 TAmounts<TIn, TOut> m_amounts;
59 void
61
62public:
63 TOffer() = default;
64
65 TOffer(SLE::pointer const& entry, Quality quality);
66
76 Quality
77 quality() const noexcept
78 {
79 return m_quality;
80 }
81
83 AccountID const&
84 owner() const
85 {
86 return m_account;
87 }
88
92 TAmounts<TIn, TOut> const&
93 amount() const
94 {
95 return m_amounts;
96 }
97
99 bool
101 {
102 if (m_amounts.in <= beast::zero)
103 return true;
104 if (m_amounts.out <= beast::zero)
105 return true;
106 return false;
107 }
108
110 void
111 consume(ApplyView& view, TAmounts<TIn, TOut> const& consumed)
112 {
113 if (consumed.in > m_amounts.in)
114 Throw<std::logic_error>("can't consume more than is available.");
115
116 if (consumed.out > m_amounts.out)
117 Throw<std::logic_error>("can't produce more than is available.");
118
119 m_amounts -= consumed;
121 view.update(m_entry);
122 }
123
125 id() const
126 {
127 return to_string(m_entry->key());
128 }
129
131 key() const
132 {
133 return m_entry->key();
134 }
135
136 Issue const&
137 issueIn() const;
138 Issue const&
139 issueOut() const;
140
141 TAmounts<TIn, TOut>
143 TAmounts<TIn, TOut> const& offrAmt,
144 TOut const& limit,
145 bool roundUp) const;
146
147 TAmounts<TIn, TOut>
148 limitIn(TAmounts<TIn, TOut> const& offrAmt, TIn const& limit, bool roundUp)
149 const;
150
151 template <typename... Args>
152 static TER
153 send(Args&&... args);
154
155 bool
156 isFunded() const
157 {
158 // Offer owner is issuer; they have unlimited funds
159 return m_account == issueOut().account;
160 }
161
164 {
165 // CLOB offer pays the transfer fee
166 return {ofrInRate, ofrOutRate};
167 }
168
172 bool
173 checkInvariant(TAmounts<TIn, TOut> const& consumed, beast::Journal j) const
174 {
175 if (!isFeatureEnabled(fixAMMv1_3))
176 return true;
177
178 if (consumed.in > m_amounts.in || consumed.out > m_amounts.out)
179 {
180 // LCOV_EXCL_START
181 JLOG(j.error())
182 << "AMMOffer::checkInvariant failed: consumed "
183 << to_string(consumed.in) << " " << to_string(consumed.out)
184 << " amounts " << to_string(m_amounts.in) << " "
185 << to_string(m_amounts.out);
186
187 return false;
188 // LCOV_EXCL_STOP
189 }
190
191 return true;
192 }
193};
194
196
197template <class TIn, class TOut>
198TOffer<TIn, TOut>::TOffer(SLE::pointer const& entry, Quality quality)
199 : m_entry(entry)
200 , m_quality(quality)
201 , m_account(m_entry->getAccountID(sfAccount))
202{
203 auto const tp = m_entry->getFieldAmount(sfTakerPays);
204 auto const tg = m_entry->getFieldAmount(sfTakerGets);
205 m_amounts.in = toAmount<TIn>(tp);
206 m_amounts.out = toAmount<TOut>(tg);
207 this->issIn_ = tp.issue();
208 this->issOut_ = tg.issue();
209}
210
211template <>
213 SLE::pointer const& entry,
214 Quality quality)
215 : m_entry(entry)
216 , m_quality(quality)
217 , m_account(m_entry->getAccountID(sfAccount))
218 , m_amounts(
219 m_entry->getFieldAmount(sfTakerPays),
220 m_entry->getFieldAmount(sfTakerGets))
221{
222}
223
224template <class TIn, class TOut>
225void
227{
228#ifdef _MSC_VER
229 UNREACHABLE("ripple::TOffer::setFieldAmounts : must be specialized");
230#else
231 static_assert(sizeof(TOut) == -1, "Must be specialized");
232#endif
233}
234
235template <class TIn, class TOut>
236TAmounts<TIn, TOut>
238 TAmounts<TIn, TOut> const& offrAmt,
239 TOut const& limit,
240 bool roundUp) const
241{
242 if (auto const& rules = getCurrentTransactionRules();
243 rules && rules->enabled(fixReducedOffersV1))
244 // It turns out that the ceil_out implementation has some slop in
245 // it. ceil_out_strict removes that slop. But removing that slop
246 // affects transaction outcomes, so the change must be made using
247 // an amendment.
248 return quality().ceil_out_strict(offrAmt, limit, roundUp);
249 return m_quality.ceil_out(offrAmt, limit);
250}
251
252template <class TIn, class TOut>
253TAmounts<TIn, TOut>
255 TAmounts<TIn, TOut> const& offrAmt,
256 TIn const& limit,
257 bool roundUp) const
258{
259 if (auto const& rules = getCurrentTransactionRules();
260 rules && rules->enabled(fixReducedOffersV2))
261 // It turns out that the ceil_in implementation has some slop in
262 // it. ceil_in_strict removes that slop. But removing that slop
263 // affects transaction outcomes, so the change must be made using
264 // an amendment.
265 return quality().ceil_in_strict(offrAmt, limit, roundUp);
266 return m_quality.ceil_in(offrAmt, limit);
267}
268
269template <class TIn, class TOut>
270template <typename... Args>
271TER
273{
274 return accountSend(std::forward<Args>(args)...);
275}
276
277template <>
278inline void
280{
281 m_entry->setFieldAmount(sfTakerPays, m_amounts.in);
282 m_entry->setFieldAmount(sfTakerGets, m_amounts.out);
283}
284
285template <>
286inline void
288{
289 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
290 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
291}
292
293template <>
294inline void
296{
297 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
298 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out));
299}
300
301template <>
302inline void
304{
305 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in));
306 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
307}
308
309template <class TIn, class TOut>
310Issue const&
312{
313 return this->issIn_;
314}
315
316template <>
317inline Issue const&
319{
320 return m_amounts.in.issue();
321}
322
323template <class TIn, class TOut>
324Issue const&
326{
327 return this->issOut_;
328}
329
330template <>
331inline Issue const&
333{
334 return m_amounts.out.issue();
335}
336
337template <class TIn, class TOut>
340{
341 return os << offer.id();
342}
343
344} // namespace ripple
345
346#endif
A generic endpoint for log messages.
Definition Journal.h:60
Stream error() const
Definition Journal.h:346
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:143
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:33
AccountID account
Definition Issue.h:36
bool fully_consumed() const
Returns true if no more funds can flow through this offer.
Definition Offer.h:100
TOffer()=default
Issue const & issueIn() const
Definition Offer.h:311
TOffer(SLE::pointer const &entry, Quality quality)
Definition Offer.h:198
Quality m_quality
Definition Offer.h:55
SLE::pointer m_entry
Definition Offer.h:54
Issue const & issueOut() const
Definition Offer.h:325
Quality quality() const noexcept
Returns the quality of the offer.
Definition Offer.h:77
TAmounts< TIn, TOut > limitIn(TAmounts< TIn, TOut > const &offrAmt, TIn const &limit, bool roundUp) const
Definition Offer.h:254
std::string id() const
Definition Offer.h:125
TAmounts< TIn, TOut > limitOut(TAmounts< TIn, TOut > const &offrAmt, TOut const &limit, bool roundUp) const
Definition Offer.h:237
AccountID const & owner() const
Returns the account id of the offer's owner.
Definition Offer.h:84
bool isFunded() const
Definition Offer.h:156
bool checkInvariant(TAmounts< TIn, TOut > const &consumed, beast::Journal j) const
Check any required invariant.
Definition Offer.h:173
TAmounts< TIn, TOut > const & amount() const
Returns the in and out amounts.
Definition Offer.h:93
std::optional< uint256 > key() const
Definition Offer.h:131
static std::pair< std::uint32_t, std::uint32_t > adjustRates(std::uint32_t ofrInRate, std::uint32_t ofrOutRate)
Definition Offer.h:163
static TER send(Args &&... args)
Definition Offer.h:272
void setFieldAmounts()
Definition Offer.h:226
TAmounts< TIn, TOut > m_amounts
Definition Offer.h:58
AccountID m_account
Definition Offer.h:56
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:111
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
bool isFeatureEnabled(uint256 const &feature)
Definition Rules.cpp:166
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
std::ostream & operator<<(std::ostream &out, base_uint< Bits, Tag > const &u)
Definition base_uint.h:637
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:2113
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
std::optional< Rules > const & getCurrentTransactionRules()
Definition Rules.cpp:47