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/contract.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&, beast::Journal j) const
174 {
175 return true;
176 }
177};
178
180
181template <class TIn, class TOut>
182TOffer<TIn, TOut>::TOffer(SLE::pointer const& entry, Quality quality)
183 : m_entry(entry)
184 , m_quality(quality)
185 , m_account(m_entry->getAccountID(sfAccount))
186{
187 auto const tp = m_entry->getFieldAmount(sfTakerPays);
188 auto const tg = m_entry->getFieldAmount(sfTakerGets);
189 m_amounts.in = toAmount<TIn>(tp);
190 m_amounts.out = toAmount<TOut>(tg);
191 this->issIn_ = tp.issue();
192 this->issOut_ = tg.issue();
193}
194
195template <>
197 SLE::pointer const& entry,
198 Quality quality)
199 : m_entry(entry)
200 , m_quality(quality)
201 , m_account(m_entry->getAccountID(sfAccount))
202 , m_amounts(
203 m_entry->getFieldAmount(sfTakerPays),
204 m_entry->getFieldAmount(sfTakerGets))
205{
206}
207
208template <class TIn, class TOut>
209void
211{
212#ifdef _MSC_VER
213 UNREACHABLE("ripple::TOffer::setFieldAmounts : must be specialized");
214#else
215 static_assert(sizeof(TOut) == -1, "Must be specialized");
216#endif
217}
218
219template <class TIn, class TOut>
220TAmounts<TIn, TOut>
222 TAmounts<TIn, TOut> const& offrAmt,
223 TOut const& limit,
224 bool roundUp) const
225{
226 if (auto const& rules = getCurrentTransactionRules();
227 rules && rules->enabled(fixReducedOffersV1))
228 // It turns out that the ceil_out implementation has some slop in
229 // it. ceil_out_strict removes that slop. But removing that slop
230 // affects transaction outcomes, so the change must be made using
231 // an amendment.
232 return quality().ceil_out_strict(offrAmt, limit, roundUp);
233 return m_quality.ceil_out(offrAmt, limit);
234}
235
236template <class TIn, class TOut>
237TAmounts<TIn, TOut>
239 TAmounts<TIn, TOut> const& offrAmt,
240 TIn const& limit,
241 bool roundUp) const
242{
243 if (auto const& rules = getCurrentTransactionRules();
244 rules && rules->enabled(fixReducedOffersV2))
245 // It turns out that the ceil_in implementation has some slop in
246 // it. ceil_in_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_in_strict(offrAmt, limit, roundUp);
250 return m_quality.ceil_in(offrAmt, limit);
251}
252
253template <class TIn, class TOut>
254template <typename... Args>
255TER
257{
258 return accountSend(std::forward<Args>(args)...);
259}
260
261template <>
262inline void
264{
265 m_entry->setFieldAmount(sfTakerPays, m_amounts.in);
266 m_entry->setFieldAmount(sfTakerGets, m_amounts.out);
267}
268
269template <>
270inline void
272{
273 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
274 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
275}
276
277template <>
278inline void
280{
281 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
282 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out));
283}
284
285template <>
286inline void
288{
289 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in));
290 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
291}
292
293template <class TIn, class TOut>
294Issue const&
296{
297 return this->issIn_;
298}
299
300template <>
301inline Issue const&
303{
304 return m_amounts.in.issue();
305}
306
307template <class TIn, class TOut>
308Issue const&
310{
311 return this->issOut_;
312}
313
314template <>
315inline Issue const&
317{
318 return m_amounts.out.issue();
319}
320
321template <class TIn, class TOut>
324{
325 return os << offer.id();
326}
327
328} // namespace ripple
329
330#endif
A generic endpoint for log messages.
Definition: Journal.h:60
Writeable view to a ledger, for applying a transaction.
Definition: ApplyView.h:141
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:36
AccountID account
Definition: Issue.h:39
Issue issOut_
Definition: Offer.h:40
Issue issIn_
Definition: Offer.h:39
bool checkInvariant(TAmounts< TIn, TOut > const &, beast::Journal j) const
Check any required invariant.
Definition: Offer.h:173
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:295
TOffer(SLE::pointer const &entry, Quality quality)
Definition: Offer.h:182
Quality m_quality
Definition: Offer.h:55
SLE::pointer m_entry
Definition: Offer.h:54
Issue const & issueOut() const
Definition: Offer.h:309
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:238
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:221
AccountID const & owner() const
Returns the account id of the offer's owner.
Definition: Offer.h:84
bool isFunded() const
Definition: Offer.h:156
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:256
void setFieldAmounts()
Definition: Offer.h:210
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
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
Definition: offer.cpp:29
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
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:1978