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 // LCOV_EXCL_START
229#ifdef _MSC_VER
230 UNREACHABLE("ripple::TOffer::setFieldAmounts : must be specialized");
231#else
232 static_assert(sizeof(TOut) == -1, "Must be specialized");
233#endif
234 // LCOV_EXCL_STOP
235}
236
237template <class TIn, class TOut>
238TAmounts<TIn, TOut>
240 TAmounts<TIn, TOut> const& offrAmt,
241 TOut const& limit,
242 bool roundUp) const
243{
244 // It turns out that the ceil_out implementation has some slop in
245 // it, which ceil_out_strict removes.
246 return quality().ceil_out_strict(offrAmt, limit, roundUp);
247}
248
249template <class TIn, class TOut>
250TAmounts<TIn, TOut>
252 TAmounts<TIn, TOut> const& offrAmt,
253 TIn const& limit,
254 bool roundUp) const
255{
256 if (auto const& rules = getCurrentTransactionRules();
257 rules && rules->enabled(fixReducedOffersV2))
258 // It turns out that the ceil_in implementation has some slop in
259 // it. ceil_in_strict removes that slop. But removing that slop
260 // affects transaction outcomes, so the change must be made using
261 // an amendment.
262 return quality().ceil_in_strict(offrAmt, limit, roundUp);
263 return m_quality.ceil_in(offrAmt, limit);
264}
265
266template <class TIn, class TOut>
267template <typename... Args>
268TER
270{
271 return accountSend(std::forward<Args>(args)...);
272}
273
274template <>
275inline void
277{
278 m_entry->setFieldAmount(sfTakerPays, m_amounts.in);
279 m_entry->setFieldAmount(sfTakerGets, m_amounts.out);
280}
281
282template <>
283inline void
285{
286 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
287 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
288}
289
290template <>
291inline void
293{
294 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
295 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out));
296}
297
298template <>
299inline void
301{
302 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in));
303 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
304}
305
306template <class TIn, class TOut>
307Issue const&
309{
310 return this->issIn_;
311}
312
313template <>
314inline Issue const&
316{
317 return m_amounts.in.issue();
318}
319
320template <class TIn, class TOut>
321Issue const&
323{
324 return this->issOut_;
325}
326
327template <>
328inline Issue const&
330{
331 return m_amounts.out.issue();
332}
333
334template <class TIn, class TOut>
337{
338 return os << offer.id();
339}
340
341} // namespace ripple
342
343#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:308
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:322
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:251
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:239
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:269
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:155
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
std::ostream & operator<<(std::ostream &out, base_uint< Bits, Tag > const &u)
Definition base_uint.h:647
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:2191
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
std::optional< Rules > const & getCurrentTransactionRules()
Definition Rules.cpp:47