20#include <xrpld/app/tx/detail/AMMVote.h>
22#include <xrpld/app/misc/AMMHelpers.h>
23#include <xrpld/app/misc/AMMUtils.h>
24#include <xrpld/ledger/Sandbox.h>
25#include <xrpl/protocol/AMMCore.h>
26#include <xrpl/protocol/Feature.h>
27#include <xrpl/protocol/STAccount.h>
28#include <xrpl/protocol/TxFlags.h>
44 JLOG(ctx.
j.
debug()) <<
"AMM Vote: invalid asset pair.";
50 JLOG(ctx.
j.
debug()) <<
"AMM Vote: invalid flags.";
56 JLOG(ctx.
j.
debug()) <<
"AMM Vote: invalid trading fee.";
66 if (
auto const ammSle =
70 JLOG(ctx.
j.
debug()) <<
"AMM Vote: Invalid asset pair.";
73 else if (ammSle->getFieldAmount(sfLPTokenBalance) == beast::zero)
75 else if (
auto const lpTokensNew =
77 lpTokensNew == beast::zero)
79 JLOG(ctx.
j.
debug()) <<
"AMM Vote: account is not LP.";
93 auto const feeNew = ctx_.
tx[sfTradingFee];
97 STAmount const lptAMMBalance = (*ammSle)[sfLPTokenBalance];
107 bool foundAccount =
false;
113 for (
auto const& entry : ammSle->getFieldArray(sfVoteSlots))
115 auto const account = entry[sfAccount];
117 if (lpTokens == beast::zero)
120 <<
"AMMVote::applyVote, account " << account <<
" is not LP";
123 auto feeVal = entry[sfTradingFee];
126 if (account == account_)
128 lpTokens = lpTokensNew;
133 num += feeVal * lpTokens;
146 (lpTokens < *minTokens ||
147 (lpTokens == *minTokens &&
148 (feeVal < minFee || (feeVal == minFee && account < minAccount)))))
150 minTokens = lpTokens;
151 minPos = updatedVoteSlots.
size();
152 minAccount = account;
155 updatedVoteSlots.
push_back(std::move(newEntry));
172 num += feeNew * lpTokensNew;
175 *(updatedVoteSlots.
begin() + *minPos) = std::move(newEntry);
177 updatedVoteSlots.
push_back(std::move(newEntry));
186 lpTokensNew > *minTokens ||
187 (lpTokensNew == *minTokens && feeNew > minFee))
189 auto const entry = updatedVoteSlots.
begin() + minPos;
191 num -=
Number((*entry)[~sfTradingFee].value_or(0)) * *minTokens;
199 JLOG(j_.
debug()) <<
"AMMVote::applyVote, insufficient tokens to "
200 "override other votes";
206 ammSle->isFieldPresent(sfAuctionSlot),
207 "ripple::applyVote : has auction slot");
210 ammSle->setFieldArray(sfVoteSlots, updatedVoteSlots);
211 if (
auto const fee =
static_cast<std::int64_t>(num / den))
213 ammSle->setFieldU16(sfTradingFee, fee);
214 if (ammSle->isFieldPresent(sfAuctionSlot))
216 auto& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);
217 if (
auto const discountedFee =
219 auctionSlot.setFieldU16(sfDiscountedFee, discountedFee);
220 else if (auctionSlot.isFieldPresent(sfDiscountedFee))
221 auctionSlot.makeFieldAbsent(sfDiscountedFee);
226 if (ammSle->isFieldPresent(sfTradingFee))
227 ammSle->makeFieldAbsent(sfTradingFee);
228 if (ammSle->isFieldPresent(sfAuctionSlot))
230 auto& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);
231 if (auctionSlot.isFieldPresent(sfDiscountedFee))
232 auctionSlot.makeFieldAbsent(sfDiscountedFee);
A generic endpoint for log messages.
static NotTEC preflight(PreflightContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
State information when applying a tx.
beast::Journal const journal
A currency issued by an account.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
void push_back(STObject const &object)
void setFieldU16(SField const &field, std::uint16_t)
static STObject makeInnerObject(SField const &name)
void setAccountID(SField const &field, AccountID const &)
void setFieldU32(SField const &field, std::uint32_t)
std::uint32_t getFlags() const
Discardable, editable view to a ledger.
void update(std::shared_ptr< SLE > const &sle) override
Indicate changes to a peeked SLE.
std::shared_ptr< SLE > peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
static std::pair< TER, bool > applyVote(ApplyContext &ctx_, Sandbox &sb, AccountID const &account_, beast::Journal j_)
bool ammEnabled(Rules const &)
Return true if required AMM amendments are enabled.
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
STAmount ammLPHolds(ReadView const &view, Currency const &cur1, Currency const &cur2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
std::uint32_t constexpr VOTE_WEIGHT_SCALE_FACTOR
NotTEC invalidAMMAssetPair(Issue const &issue1, Issue const &issue2, std::optional< std::pair< Issue, Issue > > const &pair=std::nullopt)
constexpr std::uint32_t tfUniversalMask
std::uint16_t constexpr VOTE_MAX_SLOTS
TERSubset< CanCvtToTER > TER
std::uint16_t constexpr TRADING_FEE_THRESHOLD
TERSubset< CanCvtToNotTEC > NotTEC
std::uint32_t constexpr AUCTION_SLOT_DISCOUNTED_FEE_FRACTION
State information when determining if a tx is likely to claim a fee.
State information when preflighting a tx.