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 if (auto const& rules = getCurrentTransactionRules();
245 rules && rules->enabled(fixReducedOffersV1))
246 // It turns out that the ceil_out implementation has some slop in
247 // it. ceil_out_strict removes that slop. But removing that slop
248 // affects transaction outcomes, so the change must be made using
249 // an amendment.
250 return quality().ceil_out_strict(offrAmt, limit, roundUp);
251 return m_quality.ceil_out(offrAmt, limit);
252}
253
254template <class TIn, class TOut>
255TAmounts<TIn, TOut>
257 TAmounts<TIn, TOut> const& offrAmt,
258 TIn const& limit,
259 bool roundUp) const
260{
261 if (auto const& rules = getCurrentTransactionRules();
262 rules && rules->enabled(fixReducedOffersV2))
263 // It turns out that the ceil_in implementation has some slop in
264 // it. ceil_in_strict removes that slop. But removing that slop
265 // affects transaction outcomes, so the change must be made using
266 // an amendment.
267 return quality().ceil_in_strict(offrAmt, limit, roundUp);
268 return m_quality.ceil_in(offrAmt, limit);
269}
270
271template <class TIn, class TOut>
272template <typename... Args>
273TER
275{
276 return accountSend(std::forward<Args>(args)...);
277}
278
279template <>
280inline void
282{
283 m_entry->setFieldAmount(sfTakerPays, m_amounts.in);
284 m_entry->setFieldAmount(sfTakerGets, m_amounts.out);
285}
286
287template <>
288inline void
290{
291 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
292 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
293}
294
295template <>
296inline void
298{
299 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
300 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out));
301}
302
303template <>
304inline void
306{
307 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in));
308 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
309}
310
311template <class TIn, class TOut>
312Issue const&
314{
315 return this->issIn_;
316}
317
318template <>
319inline Issue const&
321{
322 return m_amounts.in.issue();
323}
324
325template <class TIn, class TOut>
326Issue const&
328{
329 return this->issOut_;
330}
331
332template <>
333inline Issue const&
335{
336 return m_amounts.out.issue();
337}
338
339template <class TIn, class TOut>
342{
343 return os << offer.id();
344}
345
346} // namespace ripple
347
348#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:313
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:327
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:256
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:274
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: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