xrpld
Loading...
Searching...
No Matches
tx/paths/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/ledger/helpers/TokenHelpers.h>
7#include <xrpl/protocol/Concepts.h>
8#include <xrpl/protocol/Quality.h>
9#include <xrpl/protocol/Rules.h>
10#include <xrpl/protocol/SField.h>
11#include <xrpl/protocol/STLedgerEntry.h>
12
13#include <stdexcept>
14#include <utility>
15
16namespace xrpl {
17
18template <StepAmount TIn, StepAmount TOut>
19class TOffer
20{
21private:
27
29 void
31
32public:
33 TOffer() = default;
34
36
46 [[nodiscard]] Quality
47 quality() const noexcept
48 {
49 return quality_;
50 }
51
53 [[nodiscard]] AccountID const&
54 owner() const
55 {
56 return accountID_;
57 }
58
62 [[nodiscard]] TAmounts<TIn, TOut> const&
63 amount() const
64 {
65 return amounts_;
66 }
67
69 [[nodiscard]] bool
71 {
72 if (amounts_.in <= beast::kZero)
73 return true;
74 if (amounts_.out <= beast::kZero)
75 return true;
76 return false;
77 }
78
80 void
81 consume(ApplyView& view, TAmounts<TIn, TOut> const& consumed)
82 {
83 if (consumed.in > amounts_.in)
84 Throw<std::logic_error>("can't consume more than is available.");
85
86 if (consumed.out > amounts_.out)
87 Throw<std::logic_error>("can't produce more than is available.");
88
89 amounts_ -= consumed;
91 view.update(entry_);
92 }
93
94 [[nodiscard]] std::string
95 id() const
96 {
97 return to_string(entry_->key());
98 }
99
100 [[nodiscard]] std::optional<uint256>
101 key() const
102 {
103 return entry_->key();
104 }
105
106 [[nodiscard]] Asset const&
107 assetIn() const;
108 [[nodiscard]] Asset const&
109 assetOut() const;
110
111 [[nodiscard]] TAmounts<TIn, TOut>
112 limitOut(TAmounts<TIn, TOut> const& offerAmount, TOut const& limit, bool roundUp) const;
113
114 [[nodiscard]] TAmounts<TIn, TOut>
115 limitIn(TAmounts<TIn, TOut> const& offerAmount, TIn const& limit, bool roundUp) const;
116
117 template <typename... Args>
118 static TER
119 send(Args&&... args);
120
121 [[nodiscard]] bool
122 isFunded() const
123 {
124 // Offer owner is issuer; they have unlimited funds if IOU
125 return accountID_ == assetOut_.getIssuer() && assetOut_.holds<Issue>();
126 }
127
130 {
131 // CLOB offer pays the transfer fee
132 return {ofrInRate, ofrOutRate};
133 }
134
138 [[nodiscard]] bool
140 {
141 if (!isFeatureEnabled(fixAMMv1_3))
142 return true;
143
144 if (consumed.in > amounts_.in || consumed.out > amounts_.out)
145 {
146 // LCOV_EXCL_START
147 JLOG(j.error()) << "AMMOffer::checkInvariant failed: consumed "
148 << to_string(consumed.in) << " " << to_string(consumed.out)
149 << " amounts " << to_string(amounts_.in) << " "
150 << to_string(amounts_.out);
151
152 return false;
153 // LCOV_EXCL_STOP
154 }
155
156 return true;
157 }
158};
159
160template <StepAmount TIn, StepAmount TOut>
162 : entry_(std::move(entry)), quality_(quality), accountID_(entry_->getAccountID(sfAccount))
163{
164 auto const tp = entry_->getFieldAmount(sfTakerPays);
165 auto const tg = entry_->getFieldAmount(sfTakerGets);
166 amounts_.in = toAmount<TIn>(tp);
167 amounts_.out = toAmount<TOut>(tg);
168 assetIn_ = tp.asset();
169 assetOut_ = tg.asset();
170}
171
172template <StepAmount TIn, StepAmount TOut>
173void
175{
176 if constexpr (std::is_same_v<TIn, XRPAmount>)
177 {
178 entry_->setFieldAmount(sfTakerPays, toSTAmount(amounts_.in));
179 }
180 else
181 {
182 entry_->setFieldAmount(sfTakerPays, toSTAmount(amounts_.in, assetIn_));
183 }
184
186 {
187 entry_->setFieldAmount(sfTakerGets, toSTAmount(amounts_.out));
188 }
189 else
190 {
191 entry_->setFieldAmount(sfTakerGets, toSTAmount(amounts_.out, assetOut_));
192 }
193}
194
195template <StepAmount TIn, StepAmount TOut>
197TOffer<TIn, TOut>::limitOut(TAmounts<TIn, TOut> const& offerAmount, TOut const& limit, bool roundUp)
198 const
199{
200 // It turns out that the ceil_out implementation has some slop in
201 // it, which ceil_out_strict removes.
202 return quality().ceilOutStrict(offerAmount, limit, roundUp);
203}
204
205template <StepAmount TIn, StepAmount TOut>
207TOffer<TIn, TOut>::limitIn(TAmounts<TIn, TOut> const& offerAmount, TIn const& limit, bool roundUp)
208 const
209{
210 if (auto const& rules = getCurrentTransactionRules();
211 rules && rules->enabled(fixReducedOffersV2))
212 {
213 // It turns out that the ceil_in implementation has some slop in
214 // it. ceil_in_strict removes that slop. But removing that slop
215 // affects transaction outcomes, so the change must be made using
216 // an amendment.
217 return quality().ceilInStrict(offerAmount, limit, roundUp);
218 }
219 return quality_.ceilIn(offerAmount, limit);
220}
221
222template <StepAmount TIn, StepAmount TOut>
223template <typename... Args>
224TER
229
230template <StepAmount TIn, StepAmount TOut>
231Asset const&
233{
234 return assetIn_;
235}
236
237template <StepAmount TIn, StepAmount TOut>
238Asset const&
240{
241 return assetOut_;
242}
243
244template <StepAmount TIn, StepAmount TOut>
247{
248 return os << offer.id();
249}
250
251} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:38
Stream error() const
Definition Journal.h:315
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:118
virtual void update(SLE::ref sle)=0
Indicate changes to a peeked SLE.
A currency issued by an account.
Definition Issue.h:13
Represents the logical ratio of output currency to input currency.
Definition Quality.h:91
std::shared_ptr< STLedgerEntry > pointer
static TER send(Args &&... args)
TAmounts< TIn, TOut > amounts_
AccountID const & owner() const
Returns the account id of the offer's owner.
void consume(ApplyView &view, TAmounts< TIn, TOut > const &consumed)
Adjusts the offer to indicate that we consumed some (or all) of it.
Asset const & assetIn() const
static std::pair< std::uint32_t, std::uint32_t > adjustRates(std::uint32_t ofrInRate, std::uint32_t ofrOutRate)
std::optional< uint256 > key() const
Quality quality() const noexcept
Returns the quality of the offer.
TOffer()=default
bool fullyConsumed() const
Returns true if no more funds can flow through this offer.
bool isFunded() const
TAmounts< TIn, TOut > limitOut(TAmounts< TIn, TOut > const &offerAmount, TOut const &limit, bool roundUp) const
bool checkInvariant(TAmounts< TIn, TOut > const &consumed, beast::Journal j) const
Check any required invariant.
void setFieldAmounts()
SLE::pointer entry_
TAmounts< TIn, TOut > const & amount() const
Returns the in and out amounts.
AccountID accountID_
Asset const & assetOut() const
std::string id() const
TAmounts< TIn, TOut > limitIn(TAmounts< TIn, TOut > const &offerAmount, TIn const &limit, bool roundUp) const
T forward(T... args)
T is_same_v
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
bool isFeatureEnabled(uint256 const &feature, bool resultIfNoRules)
Check whether a feature is enabled in the current ledger rules.
Definition Rules.cpp:194
std::optional< Rules > const & getCurrentTransactionRules()
Definition Rules.cpp:30
std::ostream & operator<<(std::ostream &out, BaseUInt< Bits, Tag > const &u)
Definition base_uint.h:648
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
T toAmount(STAmount const &amt)=delete
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No, AllowMPTOverflow allowOverflow=AllowMPTOverflow::No)
Calls static accountSendIOU if saAmount represents Issue.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:28
TERSubset< CanCvtToTER > TER
Definition TER.h:634
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49
STAmount toSTAmount(IOUAmount const &iou, Asset const &asset)
Represents a pair of input and output currencies.
Definition Quality.h:26