Compare commits

...

1 Commits

Author SHA1 Message Date
Mayukha Vadari
f0c32fad3c refactor: Use AMMEntry everywhere
Replace raw AMM SLE pointers with AMMEntryR/AMMEntryW in the AMM
transactors, AMMHelpers, the payment path steps, TrustSet, and the
LPToken checks in View.cpp and TokenHelpers.cpp. Helpers that take an
AMM SLE (ammHolds, ammLPHolds, getTradingFee, initializeFeeAuctionVote,
verifyAndAdjustLPTokenBalance, and the AMMWithdraw/AMMClawback private
members) now take AMMEntryR const& or AMMEntryW& and stay where they
are.

AMMInfo and the jtx AMM helper wrap their existing SLE to match the new
ammLPHolds signature. TheoreticalQuality_test no longer uses a const
PaymentSandbox, because read-only entries peek() through an ApplyView.

No behavior change.
2026-10-05 13:40:46 +01:00
19 changed files with 125 additions and 98 deletions

View File

@@ -8,6 +8,7 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/AccountID.h>
@@ -820,7 +821,7 @@ checkAMMPrecisionLoss(
std::expected<std::tuple<STAmount, STAmount, STAmount>, TER>
ammHolds(
ReadView const& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
std::optional<Asset> const& optAsset1,
std::optional<Asset> const& optAsset2,
FreezeHandling freezeHandling,
@@ -842,7 +843,7 @@ ammLPHolds(
STAmount
ammLPHolds(
ReadView const& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& lpAccount,
beast::Journal const j);
@@ -852,7 +853,7 @@ ammLPHolds(
* accounts.
*/
std::uint16_t
getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account);
getTradingFee(ReadView const& view, AMMEntryR const& ammSle, AccountID const& account);
/**
* Returns total amount held by AMM for the given token.
@@ -873,7 +874,7 @@ deleteAMMAccount(Sandbox& view, Asset const& asset, Asset const& asset2, beast::
void
initializeFeeAuctionVote(
ApplyView& view,
SLE::pointer& ammSle,
AMMEntryW& ammSle,
AccountID const& account,
Asset const& lptAsset,
std::uint16_t tfee);
@@ -895,7 +896,7 @@ std::expected<bool, TER>
verifyAndAdjustLPTokenBalance(
Sandbox& sb,
STAmount const& lpTokens,
SLE::pointer& ammSle,
AMMEntryW& ammSle,
AccountID const& account);
} // namespace xrpl

View File

@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -52,7 +53,7 @@ checkFreeze(
if (auto const sleDst = view.read(keylet::account(dst));
sleDst && sleDst->isFieldPresent(sfAMMID))
{
auto const sleAmm = view.read(keylet::amm((*sleDst)[sfAMMID]));
AMMEntryR const sleAmm((*sleDst)[sfAMMID], view);
if (!sleAmm)
return tecINTERNAL; // LCOV_EXCL_LINE

View File

@@ -3,6 +3,7 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STTx.h>
@@ -71,7 +72,7 @@ private:
std::tuple<TER, STAmount, STAmount, std::optional<STAmount>>
equalWithdrawMatchingOneAmount(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& holder,
AccountID const& ammAccount,
STAmount const& amountBalance,

View File

@@ -3,6 +3,7 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Asset.h>
@@ -121,7 +122,7 @@ public:
static std::tuple<TER, STAmount, STAmount, std::optional<STAmount>>
equalWithdrawTokens(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const account,
std::optional<AccountID> const& clawbackIssuer,
AccountID const& ammAccount,
@@ -168,7 +169,7 @@ public:
static std::tuple<TER, STAmount, STAmount, std::optional<STAmount>>
withdraw(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
std::optional<AccountID> const& clawbackIssuer,
AccountID const& account,
@@ -188,7 +189,7 @@ public:
static std::pair<TER, bool>
deleteAMMAccountIfEmpty(
Sandbox& sb,
SLE::pointer const ammSle,
AMMEntryW& ammSle,
STAmount const& lpTokenBalance,
Asset const& asset1,
Asset const& asset2,
@@ -221,7 +222,7 @@ private:
std::pair<TER, STAmount>
withdraw(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
STAmount const& amountWithdraw,
@@ -247,7 +248,7 @@ private:
std::pair<TER, STAmount>
equalWithdrawTokens(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
STAmount const& amount2Balance,
@@ -273,7 +274,7 @@ private:
std::pair<TER, STAmount>
equalWithdrawLimit(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
STAmount const& amount2Balance,
@@ -296,7 +297,7 @@ private:
std::pair<TER, STAmount>
singleWithdraw(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
STAmount const& lptAMMBalance,
@@ -318,7 +319,7 @@ private:
std::pair<TER, STAmount>
singleWithdrawTokens(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
STAmount const& lptAMMBalance,
@@ -341,7 +342,7 @@ private:
std::pair<TER, STAmount>
singleWithdrawEPrice(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
STAmount const& lptAMMBalance,

View File

@@ -9,6 +9,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
@@ -193,7 +194,7 @@ canTransferLPToken(
if (!sleIssuer || !sleIssuer->isFieldPresent(sfAMMID))
return tesSUCCESS;
auto const sleAmm = view.read(keylet::amm((*sleIssuer)[sfAMMID]));
AMMEntryR const sleAmm((*sleIssuer)[sfAMMID], view);
if (!sleAmm)
return tecINTERNAL; // LCOV_EXCL_LINE

View File

@@ -11,6 +11,7 @@
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
@@ -474,7 +475,7 @@ checkAMMPrecisionLoss(
std::expected<std::tuple<STAmount, STAmount, STAmount>, TER>
ammHolds(
ReadView const& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
std::optional<Asset> const& optAsset1,
std::optional<Asset> const& optAsset2,
FreezeHandling freezeHandling,
@@ -482,8 +483,8 @@ ammHolds(
beast::Journal const j)
{
auto const assets = [&]() -> std::optional<std::pair<Asset, Asset>> {
auto const asset1 = ammSle[sfAsset];
auto const asset2 = ammSle[sfAsset2];
auto const asset1 = (*ammSle)[sfAsset];
auto const asset2 = (*ammSle)[sfAsset2];
if (optAsset1 && optAsset2)
{
if (invalidAMMAssetPair(
@@ -530,13 +531,13 @@ ammHolds(
return std::unexpected(tecAMM_INVALID_TOKENS);
auto const [amount1, amount2] = ammPoolHolds(
view,
ammSle.getAccountID(sfAccount),
ammSle->getAccountID(sfAccount),
assets->first,
assets->second,
freezeHandling,
authHandling,
j);
return std::make_tuple(amount1, amount2, ammSle[sfLPTokenBalance]);
return std::make_tuple(amount1, amount2, (*ammSle)[sfLPTokenBalance]);
}
STAmount
@@ -592,21 +593,22 @@ ammLPHolds(
STAmount
ammLPHolds(
ReadView const& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& lpAccount,
beast::Journal const j)
{
return ammLPHolds(view, ammSle[sfAsset], ammSle[sfAsset2], ammSle[sfAccount], lpAccount, j);
return ammLPHolds(
view, (*ammSle)[sfAsset], (*ammSle)[sfAsset2], (*ammSle)[sfAccount], lpAccount, j);
}
std::uint16_t
getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account)
getTradingFee(ReadView const& view, AMMEntryR const& ammSle, AccountID const& account)
{
using namespace std::chrono;
XRPL_ASSERT(ammSle.isFieldPresent(sfAuctionSlot), "xrpl::getTradingFee : auction present");
if (ammSle.isFieldPresent(sfAuctionSlot))
XRPL_ASSERT(ammSle->isFieldPresent(sfAuctionSlot), "xrpl::getTradingFee : auction present");
if (ammSle->isFieldPresent(sfAuctionSlot))
{
auto const& auctionSlot = safeDowncast<STObject const&>(ammSle.peekAtField(sfAuctionSlot));
auto const& auctionSlot = safeDowncast<STObject const&>(ammSle->peekAtField(sfAuctionSlot));
// Not expired
if (auto const expiration = auctionSlot[~sfExpiration];
duration_cast<seconds>(view.header().parentCloseTime.time_since_epoch()).count() <
@@ -624,7 +626,7 @@ getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account)
}
}
}
return ammSle[sfTradingFee];
return (*ammSle)[sfTradingFee];
}
STAmount
@@ -747,7 +749,7 @@ deleteAMMMPTokens(Sandbox& sb, AccountID const& ammAccountID, beast::Journal j)
TER
deleteAMMAccount(Sandbox& sb, Asset const& asset, Asset const& asset2, beast::Journal j)
{
auto ammSle = sb.peek(keylet::amm(asset, asset2));
AMMEntryW ammSle(asset, asset2, sb, j);
if (!ammSle)
{
// LCOV_EXCL_START
@@ -794,7 +796,7 @@ deleteAMMAccount(Sandbox& sb, Asset const& asset, Asset const& asset2, beast::Jo
// LCOV_EXCL_STOP
}
sb.erase(ammSle);
ammSle.erase();
sb.erase(sleAMMRoot);
return tesSUCCESS;
@@ -803,7 +805,7 @@ deleteAMMAccount(Sandbox& sb, Asset const& asset, Asset const& asset2, beast::Jo
void
initializeFeeAuctionVote(
ApplyView& view,
SLE::pointer& ammSle,
AMMEntryW& ammSle,
AccountID const& account,
Asset const& lptAsset,
std::uint16_t tfee)
@@ -961,7 +963,7 @@ std::expected<bool, TER>
verifyAndAdjustLPTokenBalance(
Sandbox& sb,
STAmount const& lpTokens,
SLE::pointer& ammSle,
AMMEntryW& ammSle,
AccountID const& account)
{
auto const res = isOnlyLiquidityProvider(sb, lpTokens.get<Issue>(), account);
@@ -976,7 +978,7 @@ verifyAndAdjustLPTokenBalance(
lpTokens, ammSle->getFieldAmount(sfLPTokenBalance), Number{1, -3}))
{
ammSle->setFieldAmount(sfLPTokenBalance, lpTokens);
sb.update(ammSle);
ammSle.update();
}
else
{

View File

@@ -7,6 +7,7 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
@@ -300,7 +301,7 @@ getLineIfUsable(
}
if (sleIssuer->isFieldPresent(sfAMMID))
{
auto const sleAmm = view.read(keylet::amm((*sleIssuer)[sfAMMID]));
AMMEntryR const sleAmm((*sleIssuer)[sfAMMID], view);
if (!sleAmm ||
isLPTokenFrozen(view, account, (*sleAmm)[sfAsset], (*sleAmm)[sfAsset2]))

View File

@@ -7,6 +7,7 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
@@ -106,13 +107,13 @@ private:
, j_(ctx.j)
, strandDeliver_(ctx.strandDeliver)
{
if (auto const ammSle = ctx.view.read(keylet::amm(in, out));
if (AMMEntryR const ammSle(in, out, ctx.view);
ammSle && ammSle->getFieldAmount(sfLPTokenBalance) != beast::kZero)
{
ammLiquidity_.emplace(
ctx.view,
(*ammSle)[sfAccount],
getTradingFee(ctx.view, *ammSle, ctx.ammContext.account()),
getTradingFee(ctx.view, ammSle, ctx.ammContext.account()),
in,
out,
ctx.ammContext,

View File

@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
@@ -104,7 +105,7 @@ AMMBid::preflight(PreflightContext const& ctx)
TER
AMMBid::preclaim(PreclaimContext const& ctx)
{
auto const ammSle = ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
AMMEntryR const ammSle(ctx.tx[sfAsset], ctx.tx[sfAsset2], ctx.view);
if (!ammSle)
{
JLOG(ctx.j.debug()) << "AMM Bid: Invalid asset pair.";
@@ -127,7 +128,7 @@ AMMBid::preclaim(PreclaimContext const& ctx)
}
}
auto const lpTokens = ammLPHolds(ctx.view, *ammSle, ctx.tx[sfAccount], ctx.j);
auto const lpTokens = ammLPHolds(ctx.view, ammSle, ctx.tx[sfAccount], ctx.j);
// Not LP
if (lpTokens == beast::kZero)
{
@@ -179,11 +180,11 @@ static std::pair<TER, bool>
applyBid(ApplyContext& ctx, Sandbox& sb, AccountID const& account, beast::Journal j)
{
using namespace std::chrono;
auto const ammSle = sb.peek(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
AMMEntryW ammSle(ctx.tx[sfAsset], ctx.tx[sfAsset2], sb, j);
if (!ammSle)
return {tecINTERNAL, false};
STAmount const lptAMMBalance = (*ammSle)[sfLPTokenBalance];
auto const lpTokens = ammLPHolds(sb, *ammSle, account, ctx.journal);
auto const lpTokens = ammLPHolds(sb, ammSle, account, ctx.journal);
XRPL_ASSERT(ammSle->isFieldPresent(sfAuctionSlot), "xrpl::applyBid : has auction slot");
if (!ammSle->isFieldPresent(sfAuctionSlot))
@@ -250,7 +251,7 @@ applyBid(ApplyContext& ctx, Sandbox& sb, AccountID const& account, beast::Journa
return res;
}
ammSle->setFieldAmount(sfLPTokenBalance, lptAMMBalance - saBurn);
sb.update(ammSle);
ammSle.update();
return tesSUCCESS;
};

View File

@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
@@ -109,7 +110,7 @@ AMMClawback::preclaim(PreclaimContext const& ctx)
if (!ctx.view.read(keylet::account(ctx.tx[sfHolder])))
return terNO_ACCOUNT;
auto const ammSle = ctx.view.read(keylet::amm(asset, asset2));
AMMEntryR const ammSle(asset, asset2, ctx.view);
if (!ammSle)
{
JLOG(ctx.j.debug()) << "AMM Clawback: Invalid asset pair.";
@@ -173,7 +174,7 @@ AMMClawback::applyGuts(Sandbox& sb)
Asset const asset = ctx_.tx[sfAsset];
Asset const asset2 = ctx_.tx[sfAsset2];
auto ammSle = sb.peek(keylet::amm(asset, asset2));
AMMEntryW ammSle(asset, asset2, sb, j_);
if (!ammSle)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -185,7 +186,7 @@ AMMClawback::applyGuts(Sandbox& sb)
if (sb.rules().enabled(fixAMMClawbackRounding))
{
// retrieve LP token balance inside the amendment gate to avoid inconsistent error behavior
auto const lpTokenBalance = ammLPHolds(sb, *ammSle, holder, j_);
auto const lpTokenBalance = ammLPHolds(sb, ammSle, holder, j_);
if (lpTokenBalance == beast::kZero)
return tecAMM_BALANCE;
@@ -196,7 +197,7 @@ AMMClawback::applyGuts(Sandbox& sb)
auto const expected = ammHolds(
sb,
*ammSle,
ammSle,
asset,
asset2,
FreezeHandling::IgnoreFreeze,
@@ -214,7 +215,7 @@ AMMClawback::applyGuts(Sandbox& sb)
// calling a second time on purpose since `verifyAndAdjustLPTokenBalance` rounds and may adjust
// the balance
auto const holdLPtokens = ammLPHolds(sb, *ammSle, holder, j_);
auto const holdLPtokens = ammLPHolds(sb, ammSle, holder, j_);
if (holdLPtokens == beast::kZero)
return tecAMM_BALANCE;
@@ -225,7 +226,7 @@ AMMClawback::applyGuts(Sandbox& sb)
std::tie(result, newLPTokenBalance, amountWithdraw, amount2Withdraw) =
AMMWithdraw::equalWithdrawTokens(
sb,
*ammSle,
ammSle,
holder,
issuer,
ammAccount,
@@ -247,7 +248,7 @@ AMMClawback::applyGuts(Sandbox& sb)
std::tie(result, newLPTokenBalance, amountWithdraw, amount2Withdraw) =
equalWithdrawMatchingOneAmount(
sb,
*ammSle,
ammSle,
holder,
ammAccount,
amountBalance,
@@ -304,7 +305,7 @@ AMMClawback::applyGuts(Sandbox& sb)
std::tuple<TER, STAmount, STAmount, std::optional<STAmount>>
AMMClawback::equalWithdrawMatchingOneAmount(
Sandbox& sb,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& holder,
AccountID const& ammAccount,
STAmount const& amountBalance,

View File

@@ -5,6 +5,7 @@
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
@@ -98,7 +99,7 @@ AMMCreate::preclaim(PreclaimContext const& ctx)
// Check if AMM already exists for the token pair
if (auto const ammKeylet = keylet::amm(amount.asset(), amount2.asset());
ctx.view.read(ammKeylet))
AMMEntryR(ammKeylet, ctx.view))
{
JLOG(ctx.j.debug()) << "AMM Instance: ltAMM already exists.";
return tecDUPLICATE;
@@ -291,7 +292,8 @@ applyCreate(ApplyContext& ctx, Sandbox& sb, AccountID const& account, beast::Jou
auto const lpTokens = ammLPTokens(amount, amount2, lptIss);
// Create ltAMM
auto ammSle = std::make_shared<SLE>(ammKeylet);
AMMEntryW ammSle(ammKeylet, sb, j);
ammSle.newSLE();
ammSle->setAccountID(sfAccount, accountId);
ammSle->setFieldAmount(sfLPTokenBalance, lpTokens);
auto const& [asset1, asset2] = std::minmax(amount.asset(), amount2.asset());
@@ -301,12 +303,14 @@ applyCreate(ApplyContext& ctx, Sandbox& sb, AccountID const& account, beast::Jou
initializeFeeAuctionVote(ctx.view(), ammSle, account, lptIss, ctx.tx[sfTradingFee]);
// Add owner directory to link the root account and AMM object.
if (auto ter = dirLink(sb, accountId, ammSle); ter)
// dirLink takes a non-const pointer reference; a copy shares the same SLE.
auto ammRawSle = ammSle.mutableRawSle();
if (auto ter = dirLink(sb, accountId, ammRawSle); ter)
{
JLOG(j.debug()) << "AMM Instance: failed to insert owner dir";
return {ter, false};
}
sb.insert(ammSle);
ammSle.insert();
// Send LPT to LP.
auto res = accountSend(sb, accountId, account, lpTokens, ctx.journal);

View File

@@ -2,11 +2,12 @@
#include <xrpl/basics/Log.h>
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/MPTIssue.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STLedgerEntry.h>
@@ -36,7 +37,7 @@ AMMDelete::preflight(PreflightContext const& ctx)
TER
AMMDelete::preclaim(PreclaimContext const& ctx)
{
auto const ammSle = ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
AMMEntryR const ammSle(ctx.tx[sfAsset], ctx.tx[sfAsset2], ctx.view);
if (!ammSle)
{
JLOG(ctx.j.debug()) << "AMM Delete: Invalid asset pair.";

View File

@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
@@ -179,7 +180,7 @@ AMMDeposit::preclaim(PreclaimContext const& ctx)
{
auto const accountID = ctx.tx[sfAccount];
auto const ammSle = ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
AMMEntryR const ammSle(ctx.tx[sfAsset], ctx.tx[sfAsset2], ctx.view);
if (!ammSle)
{
JLOG(ctx.j.debug()) << "AMM Deposit: Invalid asset pair.";
@@ -188,7 +189,7 @@ AMMDeposit::preclaim(PreclaimContext const& ctx)
auto const expected = ammHolds(
ctx.view,
*ammSle,
ammSle,
std::nullopt,
std::nullopt,
FreezeHandling::IgnoreFreeze,
@@ -388,7 +389,7 @@ AMMDeposit::preclaim(PreclaimContext const& ctx)
// Check the reserve for LPToken trustline if not LP.
// We checked above but need to check again if depositing IOU only.
if (ammLPHolds(ctx.view, *ammSle, accountID, ctx.j) == beast::kZero)
if (ammLPHolds(ctx.view, ammSle, accountID, ctx.j) == beast::kZero)
{
STAmount const xrpBalance = xrpLiquid(ctx.view, accountID, 1, ctx.j);
// Insufficient reserve
@@ -416,14 +417,14 @@ AMMDeposit::applyGuts(Sandbox& sb)
auto const amount2 = ctx_.tx[~sfAmount2];
auto const ePrice = ctx_.tx[~sfEPrice];
auto const lpTokensDeposit = ctx_.tx[~sfLPTokenOut];
auto ammSle = sb.peek(keylet::amm(ctx_.tx[sfAsset], ctx_.tx[sfAsset2]));
AMMEntryW ammSle(ctx_.tx[sfAsset], ctx_.tx[sfAsset2], sb, j_);
if (!ammSle)
return {tecINTERNAL, false}; // LCOV_EXCL_LINE
auto const ammAccountID = (*ammSle)[sfAccount];
auto const expected = ammHolds(
sb,
*ammSle,
ammSle,
amount ? amount->asset() : std::optional<Asset>{},
amount2 ? amount2->asset() : std::optional<Asset>{},
FreezeHandling::ZeroIfFrozen,
@@ -434,7 +435,7 @@ AMMDeposit::applyGuts(Sandbox& sb)
auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected;
auto const tfee = (lptAMMBalance == beast::kZero)
? ctx_.tx[~sfTradingFee].value_or(0)
: getTradingFee(ctx_.view(), *ammSle, accountID_);
: getTradingFee(ctx_.view(), ammSle, accountID_);
auto const subTxType = ctx_.tx.getFlags() & tfDepositSubTx;
@@ -541,7 +542,7 @@ AMMDeposit::applyGuts(Sandbox& sb)
if (lptAMMBalance == beast::kZero)
initializeFeeAuctionVote(sb, ammSle, accountID_, lptAMMBalance.asset(), tfee);
sb.update(ammSle);
ammSle.update();
}
return {result, isTesSuccess(result)};

View File

@@ -4,12 +4,13 @@
#include <xrpl/basics/Number.h>
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/MPTIssue.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STArray.h>
@@ -58,7 +59,7 @@ AMMVote::preflight(PreflightContext const& ctx)
TER
AMMVote::preclaim(PreclaimContext const& ctx)
{
auto const ammSle = ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
AMMEntryR const ammSle(ctx.tx[sfAsset], ctx.tx[sfAsset2], ctx.view);
if (!ammSle)
{
JLOG(ctx.j.debug()) << "AMM Vote: Invalid asset pair.";
@@ -68,7 +69,7 @@ AMMVote::preclaim(PreclaimContext const& ctx)
{
return tecAMM_EMPTY;
}
if (auto const lpTokensNew = ammLPHolds(ctx.view, *ammSle, ctx.tx[sfAccount], ctx.j);
if (auto const lpTokensNew = ammLPHolds(ctx.view, ammSle, ctx.tx[sfAccount], ctx.j);
lpTokensNew == beast::kZero)
{
JLOG(ctx.j.debug()) << "AMM Vote: account is not LP.";
@@ -82,11 +83,11 @@ static std::pair<TER, bool>
applyVote(ApplyContext& ctx, Sandbox& sb, AccountID const& accountID, beast::Journal j)
{
auto const feeNew = ctx.tx[sfTradingFee];
auto ammSle = sb.peek(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
AMMEntryW ammSle(ctx.tx[sfAsset], ctx.tx[sfAsset2], sb, j);
if (!ammSle)
return {tecINTERNAL, false};
STAmount const lptAMMBalance = (*ammSle)[sfLPTokenBalance];
auto const lpTokensNew = ammLPHolds(sb, *ammSle, accountID, ctx.journal);
auto const lpTokensNew = ammLPHolds(sb, ammSle, accountID, ctx.journal);
std::optional<STAmount> minTokens;
std::size_t minPos{0};
AccountID minAccount{0};
@@ -104,7 +105,7 @@ applyVote(ApplyContext& ctx, Sandbox& sb, AccountID const& accountID, beast::Jou
for (auto const& entry : ammSle->getFieldArray(sfVoteSlots))
{
auto const entryAccount = entry[sfAccount];
auto lpTokens = ammLPHolds(sb, *ammSle, entryAccount, ctx.journal);
auto lpTokens = ammLPHolds(sb, ammSle, entryAccount, ctx.journal);
if (lpTokens == beast::kZero)
{
JLOG(j.debug()) << "AMMVote::applyVote, accountID " << entryAccount << " is not LP";
@@ -226,7 +227,7 @@ applyVote(ApplyContext& ctx, Sandbox& sb, AccountID const& accountID, beast::Jou
auctionSlot.makeFieldAbsent(sfDiscountedFee);
}
}
sb.update(ammSle);
ammSle.update();
return {tesSUCCESS, true};
}

View File

@@ -6,6 +6,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
@@ -185,7 +186,7 @@ AMMWithdraw::preclaim(PreclaimContext const& ctx)
{
auto const accountID = ctx.tx[sfAccount];
auto const ammSle = ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
AMMEntryR const ammSle(ctx.tx[sfAsset], ctx.tx[sfAsset2], ctx.view);
if (!ammSle)
{
JLOG(ctx.j.debug()) << "AMM Withdraw: Invalid asset pair.";
@@ -197,7 +198,7 @@ AMMWithdraw::preclaim(PreclaimContext const& ctx)
auto const expected = ammHolds(
ctx.view,
*ammSle,
ammSle,
amount ? amount->asset() : std::optional<Asset>{},
amount2 ? amount2->asset() : std::optional<Asset>{},
FreezeHandling::IgnoreFreeze,
@@ -277,7 +278,7 @@ AMMWithdraw::preclaim(PreclaimContext const& ctx)
if (auto const ter = checkAmount(amount2, amount2Balance))
return ter;
auto const lpTokens = ammLPHolds(ctx.view, *ammSle, ctx.tx[sfAccount], ctx.j);
auto const lpTokens = ammLPHolds(ctx.view, ammSle, ctx.tx[sfAccount], ctx.j);
auto const lpTokensWithdraw = tokensWithdraw(lpTokens, ctx.tx[~sfLPTokenIn], ctx.tx.getFlags());
if (lpTokens <= beast::kZero)
@@ -340,14 +341,14 @@ AMMWithdraw::applyGuts(Sandbox& sb)
auto const amount = ctx_.tx[~sfAmount];
auto const amount2 = ctx_.tx[~sfAmount2];
auto const ePrice = ctx_.tx[~sfEPrice];
auto ammSle = sb.peek(keylet::amm(ctx_.tx[sfAsset], ctx_.tx[sfAsset2]));
AMMEntryW ammSle(ctx_.tx[sfAsset], ctx_.tx[sfAsset2], sb, j_);
if (!ammSle)
return {tecINTERNAL, false}; // LCOV_EXCL_LINE
auto const ammAccountID = (*ammSle)[sfAccount];
auto const accountSle = sb.read(keylet::account(ammAccountID));
if (!accountSle)
return {tecINTERNAL, false}; // LCOV_EXCL_LINE
auto const lpTokens = ammLPHolds(ctx_.view(), *ammSle, ctx_.tx[sfAccount], ctx_.journal);
auto const lpTokens = ammLPHolds(ctx_.view(), ammSle, ctx_.tx[sfAccount], ctx_.journal);
auto const lpTokensWithdraw =
tokensWithdraw(lpTokens, ctx_.tx[~sfLPTokenIn], ctx_.tx.getFlags());
@@ -359,13 +360,13 @@ AMMWithdraw::applyGuts(Sandbox& sb)
return {res.error(), false};
}
auto const tfee = getTradingFee(ctx_.view(), *ammSle, accountID_);
auto const tfee = getTradingFee(ctx_.view(), ammSle, accountID_);
auto const freezeHandling = issuerFreezeHandling();
auto const expected = ammHolds(
sb,
*ammSle,
ammSle,
amount ? amount->asset() : std::optional<Asset>{},
amount2 ? amount2->asset() : std::optional<Asset>{},
freezeHandling,
@@ -384,7 +385,7 @@ AMMWithdraw::applyGuts(Sandbox& sb)
{
return equalWithdrawLimit(
sb,
*ammSle,
ammSle,
ammAccountID,
amountBalance,
amount2Balance,
@@ -397,7 +398,7 @@ AMMWithdraw::applyGuts(Sandbox& sb)
{
return singleWithdrawTokens(
sb,
*ammSle,
ammSle,
ammAccountID,
amountBalance,
lptAMMBalance,
@@ -408,18 +409,18 @@ AMMWithdraw::applyGuts(Sandbox& sb)
if (subTxType & tfLimitLPToken)
{
return singleWithdrawEPrice(
sb, *ammSle, ammAccountID, amountBalance, lptAMMBalance, *amount, *ePrice, tfee);
sb, ammSle, ammAccountID, amountBalance, lptAMMBalance, *amount, *ePrice, tfee);
}
if (subTxType & tfSingleAsset)
{
return singleWithdraw(
sb, *ammSle, ammAccountID, amountBalance, lptAMMBalance, *amount, tfee);
sb, ammSle, ammAccountID, amountBalance, lptAMMBalance, *amount, tfee);
}
if (subTxType & tfLPToken || subTxType & tfWithdrawAll)
{
return equalWithdrawTokens(
sb,
*ammSle,
ammSle,
ammAccountID,
amountBalance,
amount2Balance,
@@ -502,7 +503,7 @@ AMMWithdraw::doApply()
std::pair<TER, STAmount>
AMMWithdraw::withdraw(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
STAmount const& amountWithdraw,
@@ -537,7 +538,7 @@ AMMWithdraw::withdraw(
std::tuple<TER, STAmount, STAmount, std::optional<STAmount>>
AMMWithdraw::withdraw(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
std::optional<AccountID> const& clawbackIssuer,
AccountID const& account,
@@ -835,7 +836,7 @@ adjustLPTokensIn(
std::pair<TER, STAmount>
AMMWithdraw::equalWithdrawTokens(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
STAmount const& amount2Balance,
@@ -870,7 +871,7 @@ AMMWithdraw::equalWithdrawTokens(
std::pair<TER, bool>
AMMWithdraw::deleteAMMAccountIfEmpty(
Sandbox& sb,
SLE::pointer const ammSle,
AMMEntryW& ammSle,
STAmount const& lpTokenBalance,
Asset const& asset1,
Asset const& asset2,
@@ -890,7 +891,7 @@ AMMWithdraw::deleteAMMAccountIfEmpty(
if (updateBalance)
{
ammSle->setFieldAmount(sfLPTokenBalance, lpTokenBalance);
sb.update(ammSle);
ammSle.update();
}
return {ter, true};
@@ -902,7 +903,7 @@ AMMWithdraw::deleteAMMAccountIfEmpty(
std::tuple<TER, STAmount, STAmount, std::optional<STAmount>>
AMMWithdraw::equalWithdrawTokens(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const account,
std::optional<AccountID> const& clawbackIssuer,
AccountID const& ammAccount,
@@ -1018,7 +1019,7 @@ AMMWithdraw::equalWithdrawTokens(
std::pair<TER, STAmount>
AMMWithdraw::equalWithdrawLimit(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
STAmount const& amount2Balance,
@@ -1089,7 +1090,7 @@ AMMWithdraw::equalWithdrawLimit(
std::pair<TER, STAmount>
AMMWithdraw::singleWithdraw(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
STAmount const& lptAMMBalance,
@@ -1141,7 +1142,7 @@ AMMWithdraw::singleWithdraw(
std::pair<TER, STAmount>
AMMWithdraw::singleWithdrawTokens(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
STAmount const& lptAMMBalance,
@@ -1195,7 +1196,7 @@ AMMWithdraw::singleWithdrawTokens(
std::pair<TER, STAmount>
AMMWithdraw::singleWithdrawEPrice(
Sandbox& view,
SLE const& ammSle,
AMMEntryR const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
STAmount const& lptAMMBalance,

View File

@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -205,7 +206,7 @@ TrustSet::preclaim(PreclaimContext const& ctx)
{
// pass
}
else if (auto const ammSle = ctx.view.read({ltAMM, sleDst->getFieldH256(sfAMMID)}))
else if (auto const ammSle = AMMEntryR(sleDst->getFieldH256(sfAMMID), ctx.view))
{
auto const lpTokens = ammSle->getFieldAmount(sfLPTokenBalance);
if (lpTokens == beast::kZero)

View File

@@ -252,7 +252,10 @@ class TheoreticalQuality_test : public beast::unit_test::Suite
std::shared_ptr<ReadView const> closed,
std::optional<Quality> const& expectedQ = {})
{
PaymentSandbox const sb(closed.get(), TapNone);
// Not const: read-only ledger entries peek() through an ApplyView, which
// is undefined behavior on a const object (see SLEBase.h).
// NOLINTNEXTLINE(misc-const-correctness)
PaymentSandbox sb(closed.get(), TapNone);
AMMContext ammContext(rcp.srcAccount, false);
auto const sendMaxIssue = [&rcp]() -> std::optional<Asset> {

View File

@@ -11,6 +11,7 @@
#include <xrpl/basics/safe_cast.h>
#include <xrpl/json/json_value.h>
#include <xrpl/json/to_string.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AMMCore.h>
@@ -258,7 +259,7 @@ AMM::balances(Asset const& asset1, Asset const& asset2, std::optional<AccountID>
AuthHandling::IgnoreAuth,
env_.journal);
auto const lptAMMBalance = account
? ammLPHolds(*env_.current(), *amm, *account, env_.journal)
? ammLPHolds(*env_.current(), AMMEntryR(amm, *env_.current()), *account, env_.journal)
: amm->getFieldAmount(sfLPTokenBalance);
return {asset1Balance, asset2Balance, lptAMMBalance};
}
@@ -297,7 +298,8 @@ AMM::expectLPTokens(AccountID const& account, IOUAmount const& expTokens) const
{
if (auto const amm = env_.current()->read(keylet::amm(asset1_.asset(), asset2_.asset())))
{
auto const lptAMMBalance = ammLPHolds(*env_.current(), *amm, account, env_.journal);
auto const lptAMMBalance =
ammLPHolds(*env_.current(), AMMEntryR(amm, *env_.current()), account, env_.journal);
return lptAMMBalance == STAmount{expTokens, lptIssue_};
}
return false;

View File

@@ -11,6 +11,7 @@
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/json/json_value.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AMMEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AMMCore.h>
@@ -191,8 +192,9 @@ doAMMInfo(rpc::JsonContext& context)
FreezeHandling::IgnoreFreeze,
AuthHandling::IgnoreAuth,
context.j);
auto const lptAMMBalance =
accountID ? ammLPHolds(*ledger, *amm, *accountID, context.j) : (*amm)[sfLPTokenBalance];
auto const lptAMMBalance = accountID
? ammLPHolds(*ledger, AMMEntryR(amm, *ledger), *accountID, context.j)
: (*amm)[sfLPTokenBalance];
json::Value ammResult;
asset1Balance.setJson(ammResult[jss::amount]);