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#include <xrpl/basics/contract.h>
25#include <xrpl/protocol/Quality.h>
26#include <xrpl/protocol/Rules.h>
27#include <xrpl/protocol/SField.h>
28#include <xrpl/protocol/STLedgerEntry.h>
29#include <ostream>
30#include <stdexcept>
31
32namespace ripple {
33
34template <class TIn, class TOut>
36{
37protected:
40};
41
42template <>
44{
45public:
46 explicit TOfferBase() = default;
47};
48
49template <class TIn = STAmount, class TOut = STAmount>
50class TOffer : private TOfferBase<TIn, TOut>
51{
52private:
54 Quality m_quality;
56
57 TAmounts<TIn, TOut> m_amounts;
58 void
60
61public:
62 TOffer() = default;
63
64 TOffer(SLE::pointer const& entry, Quality quality);
65
75 Quality
76 quality() const noexcept
77 {
78 return m_quality;
79 }
80
82 AccountID const&
83 owner() const
84 {
85 return m_account;
86 }
87
91 TAmounts<TIn, TOut> const&
92 amount() const
93 {
94 return m_amounts;
95 }
96
98 bool
100 {
101 if (m_amounts.in <= beast::zero)
102 return true;
103 if (m_amounts.out <= beast::zero)
104 return true;
105 return false;
106 }
107
109 void
110 consume(ApplyView& view, TAmounts<TIn, TOut> const& consumed)
111 {
112 if (consumed.in > m_amounts.in)
113 Throw<std::logic_error>("can't consume more than is available.");
114
115 if (consumed.out > m_amounts.out)
116 Throw<std::logic_error>("can't produce more than is available.");
117
118 m_amounts -= consumed;
120 view.update(m_entry);
121 }
122
124 id() const
125 {
126 return to_string(m_entry->key());
127 }
128
130 key() const
131 {
132 return m_entry->key();
133 }
134
135 Issue const&
136 issueIn() const;
137 Issue const&
138 issueOut() const;
139
140 TAmounts<TIn, TOut>
142 TAmounts<TIn, TOut> const& offrAmt,
143 TOut const& limit,
144 bool roundUp) const;
145
146 TAmounts<TIn, TOut>
147 limitIn(TAmounts<TIn, TOut> const& offrAmt, TIn const& limit, bool roundUp)
148 const;
149
150 template <typename... Args>
151 static TER
152 send(Args&&... args);
153
154 bool
155 isFunded() const
156 {
157 // Offer owner is issuer; they have unlimited funds
158 return m_account == issueOut().account;
159 }
160
163 {
164 // CLOB offer pays the transfer fee
165 return {ofrInRate, ofrOutRate};
166 }
167
171 bool
172 checkInvariant(TAmounts<TIn, TOut> const&, beast::Journal j) const
173 {
174 return true;
175 }
176};
177
179
180template <class TIn, class TOut>
181TOffer<TIn, TOut>::TOffer(SLE::pointer const& entry, Quality quality)
182 : m_entry(entry)
183 , m_quality(quality)
184 , m_account(m_entry->getAccountID(sfAccount))
185{
186 auto const tp = m_entry->getFieldAmount(sfTakerPays);
187 auto const tg = m_entry->getFieldAmount(sfTakerGets);
188 m_amounts.in = toAmount<TIn>(tp);
189 m_amounts.out = toAmount<TOut>(tg);
190 this->issIn_ = tp.issue();
191 this->issOut_ = tg.issue();
192}
193
194template <>
196 SLE::pointer const& entry,
197 Quality quality)
198 : m_entry(entry)
199 , m_quality(quality)
200 , m_account(m_entry->getAccountID(sfAccount))
201 , m_amounts(
202 m_entry->getFieldAmount(sfTakerPays),
203 m_entry->getFieldAmount(sfTakerGets))
204{
205}
206
207template <class TIn, class TOut>
208void
210{
211#ifdef _MSC_VER
212 UNREACHABLE("ripple::TOffer::setFieldAmounts : must be specialized");
213#else
214 static_assert(sizeof(TOut) == -1, "Must be specialized");
215#endif
216}
217
218template <class TIn, class TOut>
219TAmounts<TIn, TOut>
221 TAmounts<TIn, TOut> const& offrAmt,
222 TOut const& limit,
223 bool roundUp) const
224{
225 if (auto const& rules = getCurrentTransactionRules();
226 rules && rules->enabled(fixReducedOffersV1))
227 // It turns out that the ceil_out implementation has some slop in
228 // it. ceil_out_strict removes that slop. But removing that slop
229 // affects transaction outcomes, so the change must be made using
230 // an amendment.
231 return quality().ceil_out_strict(offrAmt, limit, roundUp);
232 return m_quality.ceil_out(offrAmt, limit);
233}
234
235template <class TIn, class TOut>
236TAmounts<TIn, TOut>
238 TAmounts<TIn, TOut> const& offrAmt,
239 TIn const& limit,
240 bool roundUp) const
241{
242 if (auto const& rules = getCurrentTransactionRules();
243 rules && rules->enabled(fixReducedOffersV2))
244 // It turns out that the ceil_in implementation has some slop in
245 // it. ceil_in_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_in_strict(offrAmt, limit, roundUp);
249 return m_quality.ceil_in(offrAmt, limit);
250}
251
252template <class TIn, class TOut>
253template <typename... Args>
254TER
256{
257 return accountSend(std::forward<Args>(args)...);
258}
259
260template <>
261inline void
263{
264 m_entry->setFieldAmount(sfTakerPays, m_amounts.in);
265 m_entry->setFieldAmount(sfTakerGets, m_amounts.out);
266}
267
268template <>
269inline void
271{
272 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
273 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
274}
275
276template <>
277inline void
279{
280 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
281 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out));
282}
283
284template <>
285inline void
287{
288 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in));
289 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
290}
291
292template <class TIn, class TOut>
293Issue const&
295{
296 return this->issIn_;
297}
298
299template <>
300inline Issue const&
302{
303 return m_amounts.in.issue();
304}
305
306template <class TIn, class TOut>
307Issue const&
309{
310 return this->issOut_;
311}
312
313template <>
314inline Issue const&
316{
317 return m_amounts.out.issue();
318}
319
320template <class TIn, class TOut>
323{
324 return os << offer.id();
325}
326
327} // namespace ripple
328
329#endif
A generic endpoint for log messages.
Definition: Journal.h:59
Writeable view to a ledger, for applying a transaction.
Definition: ApplyView.h:140
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:39
Issue issIn_
Definition: Offer.h:38
bool checkInvariant(TAmounts< TIn, TOut > const &, beast::Journal j) const
Check any required invariant.
Definition: Offer.h:172
bool fully_consumed() const
Returns true if no more funds can flow through this offer.
Definition: Offer.h:99
TOffer()=default
Issue const & issueIn() const
Definition: Offer.h:294
TOffer(SLE::pointer const &entry, Quality quality)
Definition: Offer.h:181
Quality m_quality
Definition: Offer.h:54
SLE::pointer m_entry
Definition: Offer.h:53
Issue const & issueOut() const
Definition: Offer.h:308
Quality quality() const noexcept
Returns the quality of the offer.
Definition: Offer.h:76
TAmounts< TIn, TOut > limitIn(TAmounts< TIn, TOut > const &offrAmt, TIn const &limit, bool roundUp) const
Definition: Offer.h:237
std::string id() const
Definition: Offer.h:124
TAmounts< TIn, TOut > limitOut(TAmounts< TIn, TOut > const &offrAmt, TOut const &limit, bool roundUp) const
Definition: Offer.h:220
AccountID const & owner() const
Returns the account id of the offer's owner.
Definition: Offer.h:83
bool isFunded() const
Definition: Offer.h:155
TAmounts< TIn, TOut > const & amount() const
Returns the in and out amounts.
Definition: Offer.h:92
std::optional< uint256 > key() const
Definition: Offer.h:130
static std::pair< std::uint32_t, std::uint32_t > adjustRates(std::uint32_t ofrInRate, std::uint32_t ofrOutRate)
Definition: Offer.h:162
static TER send(Args &&... args)
Definition: Offer.h:255
void setFieldAmounts()
Definition: Offer.h:209
TAmounts< TIn, TOut > m_amounts
Definition: Offer.h:57
AccountID m_account
Definition: Offer.h:55
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:110
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:636
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:629
std::optional< Rules > const & getCurrentTransactionRules()
Definition: Rules.cpp:39
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:1609