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 <xrpld/ledger/View.h>
24
25#include <xrpl/basics/Log.h>
26#include <xrpl/basics/contract.h>
27#include <xrpl/protocol/Quality.h>
28#include <xrpl/protocol/Rules.h>
29#include <xrpl/protocol/SField.h>
30#include <xrpl/protocol/STLedgerEntry.h>
31
32#include <stdexcept>
33
34namespace ripple {
35
36template <class TIn, class TOut>
38{
39protected:
42};
43
44template <>
46{
47public:
48 explicit TOfferBase() = default;
49};
50
51template <class TIn = STAmount, class TOut = STAmount>
52class TOffer : private TOfferBase<TIn, TOut>
53{
54private:
56 Quality m_quality;
58
59 TAmounts<TIn, TOut> m_amounts;
60 void
62
63public:
64 TOffer() = default;
65
66 TOffer(SLE::pointer const& entry, Quality quality);
67
77 Quality
78 quality() const noexcept
79 {
80 return m_quality;
81 }
82
84 AccountID const&
85 owner() const
86 {
87 return m_account;
88 }
89
93 TAmounts<TIn, TOut> const&
94 amount() const
95 {
96 return m_amounts;
97 }
98
100 bool
102 {
103 if (m_amounts.in <= beast::zero)
104 return true;
105 if (m_amounts.out <= beast::zero)
106 return true;
107 return false;
108 }
109
111 void
112 consume(ApplyView& view, TAmounts<TIn, TOut> const& consumed)
113 {
114 if (consumed.in > m_amounts.in)
115 Throw<std::logic_error>("can't consume more than is available.");
116
117 if (consumed.out > m_amounts.out)
118 Throw<std::logic_error>("can't produce more than is available.");
119
120 m_amounts -= consumed;
122 view.update(m_entry);
123 }
124
126 id() const
127 {
128 return to_string(m_entry->key());
129 }
130
132 key() const
133 {
134 return m_entry->key();
135 }
136
137 Issue const&
138 issueIn() const;
139 Issue const&
140 issueOut() const;
141
142 TAmounts<TIn, TOut>
144 TAmounts<TIn, TOut> const& offrAmt,
145 TOut const& limit,
146 bool roundUp) const;
147
148 TAmounts<TIn, TOut>
149 limitIn(TAmounts<TIn, TOut> const& offrAmt, TIn const& limit, bool roundUp)
150 const;
151
152 template <typename... Args>
153 static TER
154 send(Args&&... args);
155
156 bool
157 isFunded() const
158 {
159 // Offer owner is issuer; they have unlimited funds
160 return m_account == issueOut().account;
161 }
162
165 {
166 // CLOB offer pays the transfer fee
167 return {ofrInRate, ofrOutRate};
168 }
169
173 bool
174 checkInvariant(TAmounts<TIn, TOut> const& consumed, beast::Journal j) const
175 {
176 if (!isFeatureEnabled(fixAMMv1_3))
177 return true;
178
179 if (consumed.in > m_amounts.in || consumed.out > m_amounts.out)
180 {
181 // LCOV_EXCL_START
182 JLOG(j.error())
183 << "AMMOffer::checkInvariant failed: consumed "
184 << to_string(consumed.in) << " " << to_string(consumed.out)
185 << " amounts " << to_string(m_amounts.in) << " "
186 << to_string(m_amounts.out);
187
188 return false;
189 // LCOV_EXCL_STOP
190 }
191
192 return true;
193 }
194};
195
197
198template <class TIn, class TOut>
199TOffer<TIn, TOut>::TOffer(SLE::pointer const& entry, Quality quality)
200 : m_entry(entry)
201 , m_quality(quality)
202 , m_account(m_entry->getAccountID(sfAccount))
203{
204 auto const tp = m_entry->getFieldAmount(sfTakerPays);
205 auto const tg = m_entry->getFieldAmount(sfTakerGets);
206 m_amounts.in = toAmount<TIn>(tp);
207 m_amounts.out = toAmount<TOut>(tg);
208 this->issIn_ = tp.issue();
209 this->issOut_ = tg.issue();
210}
211
212template <>
214 SLE::pointer const& entry,
215 Quality quality)
216 : m_entry(entry)
217 , m_quality(quality)
218 , m_account(m_entry->getAccountID(sfAccount))
219 , m_amounts(
220 m_entry->getFieldAmount(sfTakerPays),
221 m_entry->getFieldAmount(sfTakerGets))
222{
223}
224
225template <class TIn, class TOut>
226void
228{
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}
235
236template <class TIn, class TOut>
237TAmounts<TIn, TOut>
239 TAmounts<TIn, TOut> const& offrAmt,
240 TOut const& limit,
241 bool roundUp) const
242{
243 if (auto const& rules = getCurrentTransactionRules();
244 rules && rules->enabled(fixReducedOffersV1))
245 // It turns out that the ceil_out implementation has some slop in
246 // it. ceil_out_strict removes that slop. But removing that slop
247 // affects transaction outcomes, so the change must be made using
248 // an amendment.
249 return quality().ceil_out_strict(offrAmt, limit, roundUp);
250 return m_quality.ceil_out(offrAmt, limit);
251}
252
253template <class TIn, class TOut>
254TAmounts<TIn, TOut>
256 TAmounts<TIn, TOut> const& offrAmt,
257 TIn const& limit,
258 bool roundUp) const
259{
260 if (auto const& rules = getCurrentTransactionRules();
261 rules && rules->enabled(fixReducedOffersV2))
262 // It turns out that the ceil_in implementation has some slop in
263 // it. ceil_in_strict removes that slop. But removing that slop
264 // affects transaction outcomes, so the change must be made using
265 // an amendment.
266 return quality().ceil_in_strict(offrAmt, limit, roundUp);
267 return m_quality.ceil_in(offrAmt, limit);
268}
269
270template <class TIn, class TOut>
271template <typename... Args>
272TER
274{
275 return accountSend(std::forward<Args>(args)...);
276}
277
278template <>
279inline void
281{
282 m_entry->setFieldAmount(sfTakerPays, m_amounts.in);
283 m_entry->setFieldAmount(sfTakerGets, m_amounts.out);
284}
285
286template <>
287inline void
289{
290 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
291 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
292}
293
294template <>
295inline void
297{
298 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
299 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out));
300}
301
302template <>
303inline void
305{
306 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in));
307 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
308}
309
310template <class TIn, class TOut>
311Issue const&
313{
314 return this->issIn_;
315}
316
317template <>
318inline Issue const&
320{
321 return m_amounts.in.issue();
322}
323
324template <class TIn, class TOut>
325Issue const&
327{
328 return this->issOut_;
329}
330
331template <>
332inline Issue const&
334{
335 return m_amounts.out.issue();
336}
337
338template <class TIn, class TOut>
341{
342 return os << offer.id();
343}
344
345} // namespace ripple
346
347#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:144
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
Issue issOut_
Definition: Offer.h:41
Issue issIn_
Definition: Offer.h:40
bool fully_consumed() const
Returns true if no more funds can flow through this offer.
Definition: Offer.h:101
TOffer()=default
Issue const & issueIn() const
Definition: Offer.h:312
TOffer(SLE::pointer const &entry, Quality quality)
Definition: Offer.h:199
Quality m_quality
Definition: Offer.h:56
SLE::pointer m_entry
Definition: Offer.h:55
Issue const & issueOut() const
Definition: Offer.h:326
Quality quality() const noexcept
Returns the quality of the offer.
Definition: Offer.h:78
TAmounts< TIn, TOut > limitIn(TAmounts< TIn, TOut > const &offrAmt, TIn const &limit, bool roundUp) const
Definition: Offer.h:255
std::string id() const
Definition: Offer.h:126
TAmounts< TIn, TOut > limitOut(TAmounts< TIn, TOut > const &offrAmt, TOut const &limit, bool roundUp) const
Definition: Offer.h:238
AccountID const & owner() const
Returns the account id of the offer's owner.
Definition: Offer.h:85
bool isFunded() const
Definition: Offer.h:157
bool checkInvariant(TAmounts< TIn, TOut > const &consumed, beast::Journal j) const
Check any required invariant.
Definition: Offer.h:174
TAmounts< TIn, TOut > const & amount() const
Returns the in and out amounts.
Definition: Offer.h:94
std::optional< uint256 > key() const
Definition: Offer.h:132
static std::pair< std::uint32_t, std::uint32_t > adjustRates(std::uint32_t ofrInRate, std::uint32_t ofrOutRate)
Definition: Offer.h:164
static TER send(Args &&... args)
Definition: Offer.h:273
void setFieldAmounts()
Definition: Offer.h:227
TAmounts< TIn, TOut > m_amounts
Definition: Offer.h:59
AccountID m_account
Definition: Offer.h:57
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:112
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
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:630
std::optional< Rules > const & getCurrentTransactionRules()
Definition: Rules.cpp:47
TER accountSend(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee)
Calls static accountSendIOU if saAmount represents Issue.
Definition: View.cpp:2011