rippled
Loading...
Searching...
No Matches
Offer.h
1#pragma once
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/contract.h>
5#include <xrpl/ledger/View.h>
6#include <xrpl/protocol/Quality.h>
7#include <xrpl/protocol/Rules.h>
8#include <xrpl/protocol/SField.h>
9#include <xrpl/protocol/STLedgerEntry.h>
10
11#include <stdexcept>
12
13namespace xrpl {
14
15template <class TIn, class TOut>
17{
18protected:
21};
22
23template <>
25{
26public:
27 explicit TOfferBase() = default;
28};
29
30template <class TIn = STAmount, class TOut = STAmount>
31class TOffer : private TOfferBase<TIn, TOut>
32{
33private:
35 Quality m_quality;
37
38 TAmounts<TIn, TOut> m_amounts;
39 void
41
42public:
43 TOffer() = default;
44
45 TOffer(SLE::pointer const& entry, Quality quality);
46
56 Quality
57 quality() const noexcept
58 {
59 return m_quality;
60 }
61
63 AccountID const&
64 owner() const
65 {
66 return m_account;
67 }
68
72 TAmounts<TIn, TOut> const&
73 amount() const
74 {
75 return m_amounts;
76 }
77
79 bool
81 {
82 if (m_amounts.in <= beast::zero)
83 return true;
84 if (m_amounts.out <= beast::zero)
85 return true;
86 return false;
87 }
88
90 void
91 consume(ApplyView& view, TAmounts<TIn, TOut> const& consumed)
92 {
93 if (consumed.in > m_amounts.in)
94 Throw<std::logic_error>("can't consume more than is available.");
95
96 if (consumed.out > m_amounts.out)
97 Throw<std::logic_error>("can't produce more than is available.");
98
99 m_amounts -= consumed;
101 view.update(m_entry);
102 }
103
105 id() const
106 {
107 return to_string(m_entry->key());
108 }
109
111 key() const
112 {
113 return m_entry->key();
114 }
115
116 Issue const&
117 issueIn() const;
118 Issue const&
119 issueOut() const;
120
121 TAmounts<TIn, TOut>
122 limitOut(TAmounts<TIn, TOut> const& offerAmount, TOut const& limit, bool roundUp) const;
123
124 TAmounts<TIn, TOut>
125 limitIn(TAmounts<TIn, TOut> const& offerAmount, TIn const& limit, bool roundUp) const;
126
127 template <typename... Args>
128 static TER
129 send(Args&&... args);
130
131 bool
132 isFunded() const
133 {
134 // Offer owner is issuer; they have unlimited funds
135 return m_account == issueOut().account;
136 }
137
140 {
141 // CLOB offer pays the transfer fee
142 return {ofrInRate, ofrOutRate};
143 }
144
148 bool
149 checkInvariant(TAmounts<TIn, TOut> const& consumed, beast::Journal j) const
150 {
151 if (!isFeatureEnabled(fixAMMv1_3))
152 return true;
153
154 if (consumed.in > m_amounts.in || consumed.out > m_amounts.out)
155 {
156 // LCOV_EXCL_START
157 JLOG(j.error()) << "AMMOffer::checkInvariant failed: consumed " << to_string(consumed.in) << " "
158 << to_string(consumed.out) << " amounts " << to_string(m_amounts.in) << " "
159 << to_string(m_amounts.out);
160
161 return false;
162 // LCOV_EXCL_STOP
163 }
164
165 return true;
166 }
167};
168
170
171template <class TIn, class TOut>
172TOffer<TIn, TOut>::TOffer(SLE::pointer const& entry, Quality quality)
173 : m_entry(entry), m_quality(quality), m_account(m_entry->getAccountID(sfAccount))
174{
175 auto const tp = m_entry->getFieldAmount(sfTakerPays);
176 auto const tg = m_entry->getFieldAmount(sfTakerGets);
177 m_amounts.in = toAmount<TIn>(tp);
178 m_amounts.out = toAmount<TOut>(tg);
179 this->issIn_ = tp.issue();
180 this->issOut_ = tg.issue();
181}
182
183template <>
184inline TOffer<STAmount, STAmount>::TOffer(SLE::pointer const& entry, Quality quality)
185 : m_entry(entry)
186 , m_quality(quality)
187 , m_account(m_entry->getAccountID(sfAccount))
188 , m_amounts(m_entry->getFieldAmount(sfTakerPays), m_entry->getFieldAmount(sfTakerGets))
189{
190}
191
192template <class TIn, class TOut>
193void
195{
196 // LCOV_EXCL_START
197#ifdef _MSC_VER
198 UNREACHABLE("xrpl::TOffer::setFieldAmounts : must be specialized");
199#else
200 static_assert(sizeof(TOut) == -1, "Must be specialized");
201#endif
202 // LCOV_EXCL_STOP
203}
204
205template <class TIn, class TOut>
206TAmounts<TIn, TOut>
207TOffer<TIn, TOut>::limitOut(TAmounts<TIn, TOut> const& offerAmount, TOut const& limit, bool roundUp) const
208{
209 // It turns out that the ceil_out implementation has some slop in
210 // it, which ceil_out_strict removes.
211 return quality().ceil_out_strict(offerAmount, limit, roundUp);
212}
213
214template <class TIn, class TOut>
215TAmounts<TIn, TOut>
216TOffer<TIn, TOut>::limitIn(TAmounts<TIn, TOut> const& offerAmount, TIn const& limit, bool roundUp) const
217{
218 if (auto const& rules = getCurrentTransactionRules(); rules && rules->enabled(fixReducedOffersV2))
219 // It turns out that the ceil_in implementation has some slop in
220 // it. ceil_in_strict removes that slop. But removing that slop
221 // affects transaction outcomes, so the change must be made using
222 // an amendment.
223 return quality().ceil_in_strict(offerAmount, limit, roundUp);
224 return m_quality.ceil_in(offerAmount, limit);
225}
226
227template <class TIn, class TOut>
228template <typename... Args>
229TER
231{
232 return accountSend(std::forward<Args>(args)...);
233}
234
235template <>
236inline void
238{
239 m_entry->setFieldAmount(sfTakerPays, m_amounts.in);
240 m_entry->setFieldAmount(sfTakerGets, m_amounts.out);
241}
242
243template <>
244inline void
246{
247 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
248 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
249}
250
251template <>
252inline void
254{
255 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in, issIn_));
256 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out));
257}
258
259template <>
260inline void
262{
263 m_entry->setFieldAmount(sfTakerPays, toSTAmount(m_amounts.in));
264 m_entry->setFieldAmount(sfTakerGets, toSTAmount(m_amounts.out, issOut_));
265}
266
267template <class TIn, class TOut>
268Issue const&
270{
271 return this->issIn_;
272}
273
274template <>
275inline Issue const&
277{
278 return m_amounts.in.issue();
279}
280
281template <class TIn, class TOut>
282Issue const&
284{
285 return this->issOut_;
286}
287
288template <>
289inline Issue const&
291{
292 return m_amounts.out.issue();
293}
294
295template <class TIn, class TOut>
298{
299 return os << offer.id();
300}
301
302} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:40
Stream error() const
Definition Journal.h:318
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:114
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:13
AccountID account
Definition Issue.h:16
Issue issOut_
Definition Offer.h:20
Issue issIn_
Definition Offer.h:19
Issue const & issueOut() const
Definition Offer.h:283
static TER send(Args &&... args)
Definition Offer.h:230
bool fully_consumed() const
Returns true if no more funds can flow through this offer.
Definition Offer.h:80
AccountID const & owner() const
Returns the account id of the offer's owner.
Definition Offer.h:64
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:91
static std::pair< std::uint32_t, std::uint32_t > adjustRates(std::uint32_t ofrInRate, std::uint32_t ofrOutRate)
Definition Offer.h:139
std::optional< uint256 > key() const
Definition Offer.h:111
Quality quality() const noexcept
Returns the quality of the offer.
Definition Offer.h:57
TAmounts< TIn, TOut > m_amounts
Definition Offer.h:38
TOffer()=default
AccountID m_account
Definition Offer.h:36
Quality m_quality
Definition Offer.h:35
TOffer(SLE::pointer const &entry, Quality quality)
Definition Offer.h:172
bool isFunded() const
Definition Offer.h:132
TAmounts< TIn, TOut > limitOut(TAmounts< TIn, TOut > const &offerAmount, TOut const &limit, bool roundUp) const
Definition Offer.h:207
bool checkInvariant(TAmounts< TIn, TOut > const &consumed, beast::Journal j) const
Check any required invariant.
Definition Offer.h:149
void setFieldAmounts()
Definition Offer.h:194
TAmounts< TIn, TOut > const & amount() const
Returns the in and out amounts.
Definition Offer.h:73
Issue const & issueIn() const
Definition Offer.h:269
std::string id() const
Definition Offer.h:105
TAmounts< TIn, TOut > limitIn(TAmounts< TIn, TOut > const &offerAmount, TIn const &limit, bool roundUp) const
Definition Offer.h:216
SLE::pointer m_entry
Definition Offer.h:34
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:597
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
std::ostream & operator<<(std::ostream &out, base_uint< Bits, Tag > const &u)
Definition base_uint.h:612
std::optional< Rules > const & getCurrentTransactionRules()
Definition Rules.cpp:31
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:2446
bool isFeatureEnabled(uint256 const &feature)
Definition Rules.cpp:141