refactor: Retire InnerObjTemplate fix (#7368)

This commit is contained in:
Timothy Banks
2026-07-01 11:36:28 -04:00
committed by GitHub
parent 0d149ba5b6
commit c53aafa6bf
8 changed files with 15 additions and 58 deletions

View File

@@ -58,7 +58,6 @@ XRPL_FIX (XChainRewardRounding, Supported::Yes, VoteBehavior::DefaultNo
XRPL_FIX (EmptyDID, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(PriceOracle, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (AMMOverflowOffer, Supported::Yes, VoteBehavior::DefaultYes)
XRPL_FIX (InnerObjTemplate, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (FillOrKill, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(DID, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (DisallowIncomingV1, Supported::Yes, VoteBehavior::DefaultNo)
@@ -101,6 +100,7 @@ XRPL_RETIRE_FIX(1623)
XRPL_RETIRE_FIX(1781)
XRPL_RETIRE_FIX(AmendmentMajorityCalc)
XRPL_RETIRE_FIX(CheckThreading)
XRPL_RETIRE_FIX(InnerObjTemplate)
XRPL_RETIRE_FIX(MasterKeyAsRegularKey)
XRPL_RETIRE_FIX(NonFungibleTokensV1_2)
XRPL_RETIRE_FIX(NFTokenRemint)

View File

@@ -602,9 +602,7 @@ std::uint16_t
getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account)
{
using namespace std::chrono;
XRPL_ASSERT(
!view.rules().enabled(fixInnerObjTemplate) || ammSle.isFieldPresent(sfAuctionSlot),
"xrpl::getTradingFee : auction present");
XRPL_ASSERT(ammSle.isFieldPresent(sfAuctionSlot), "xrpl::getTradingFee : auction present");
if (ammSle.isFieldPresent(sfAuctionSlot))
{
auto const& auctionSlot = safeDowncast<STObject const&>(ammSle.peekAtField(sfAuctionSlot));
@@ -822,7 +820,7 @@ initializeFeeAuctionVote(
// AMM creator gets the auction slot for free.
// AuctionSlot is created on AMMCreate and updated on AMMDeposit
// when AMM is in an empty state
if (rules.enabled(fixInnerObjTemplate) && !ammSle->isFieldPresent(sfAuctionSlot))
if (!ammSle->isFieldPresent(sfAuctionSlot))
{
STObject auctionSlot = STObject::makeInnerObject(sfAuctionSlot);
ammSle->set(std::move(auctionSlot));

View File

@@ -78,12 +78,10 @@ STObject::makeInnerObject(SField const& name)
// The if is complicated because inner object templates were added in
// two phases:
// 1. If there are no available Rules, then always apply the template.
// 2. fixInnerObjTemplate added templates to two AMM inner objects.
// 3. fixInnerObjTemplate2 added templates to all remaining inner objects.
// 2. fixInnerObjTemplate2 added templates to all remaining inner objects.
std::optional<Rules> const& rules = getCurrentTransactionRules();
bool const isAMMObj = name == sfAuctionSlot || name == sfVoteEntry;
if (!rules || (rules->enabled(fixInnerObjTemplate) && isAMMObj) ||
(rules->enabled(fixInnerObjTemplate2) && !isAMMObj))
if (!rules || isAMMObj || rules->enabled(fixInnerObjTemplate2))
{
if (SOTemplate const* elements =
InnerObjectFormats::getInstance().findSOTemplateBySField(name))

View File

@@ -184,18 +184,11 @@ applyBid(ApplyContext& ctx, Sandbox& sb, AccountID const& account, beast::Journa
return {tecINTERNAL, false};
STAmount const lptAMMBalance = (*ammSle)[sfLPTokenBalance];
auto const lpTokens = ammLPHolds(sb, *ammSle, account, ctx.journal);
auto const& rules = ctx.view().rules();
if (!rules.enabled(fixInnerObjTemplate))
{
if (!ammSle->isFieldPresent(sfAuctionSlot))
ammSle->makeFieldPresent(sfAuctionSlot);
}
else
{
XRPL_ASSERT(ammSle->isFieldPresent(sfAuctionSlot), "xrpl::applyBid : has auction slot");
if (!ammSle->isFieldPresent(sfAuctionSlot))
return {tecINTERNAL, false};
}
XRPL_ASSERT(ammSle->isFieldPresent(sfAuctionSlot), "xrpl::applyBid : has auction slot");
if (!ammSle->isFieldPresent(sfAuctionSlot))
return {tecINTERNAL, false};
auto& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);
auto const current =
duration_cast<seconds>(ctx.view().header().parentCloseTime.time_since_epoch()).count();

View File

@@ -195,9 +195,7 @@ applyVote(ApplyContext& ctx, Sandbox& sb, AccountID const& accountID, beast::Jou
}
}
XRPL_ASSERT(
!ctx.view().rules().enabled(fixInnerObjTemplate) || ammSle->isFieldPresent(sfAuctionSlot),
"xrpl::applyVote : has auction slot");
XRPL_ASSERT(ammSle->isFieldPresent(sfAuctionSlot), "xrpl::applyVote : has auction slot");
// Update the vote entries and the trading/discounted fee.
ammSle->setFieldArray(sfVoteSlots, updatedVoteSlots);

View File

@@ -5747,38 +5747,16 @@ private:
};
// ledger is closed after each transaction, vote/withdraw don't fail
// regardless whether the amendment is enabled or not
test(all, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 0, true);
test(all - fixInnerObjTemplate, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 0, true);
// ledger is not closed after each transaction
// vote/withdraw don't fail if the amendment is enabled
test(all, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 0, false);
// vote/withdraw fail if the amendment is not enabled
// second vote/withdraw still fail: second vote fails because
// the initial trading fee is 0, consequently second withdraw fails
// because the second vote fails
test(
all - fixInnerObjTemplate,
tefEXCEPTION,
tefEXCEPTION,
tefEXCEPTION,
tefEXCEPTION,
0,
false);
// if non-zero trading/discounted fee then vote/withdraw
// don't fail whether the ledger is closed or not and
// the amendment is enabled or not
// don't fail whether the ledger is closed or not
test(all, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 10, true);
test(all - fixInnerObjTemplate, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 10, true);
test(all, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 10, false);
test(all - fixInnerObjTemplate, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 10, false);
// non-zero trading fee but discounted fee is 0, vote doesn't fail
// but withdraw fails
test(all, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 9, false);
// second vote sets the trading fee to non-zero, consequently
// second withdraw doesn't fail even if the amendment is not
// enabled and the ledger is not closed
test(all - fixInnerObjTemplate, tesSUCCESS, tefEXCEPTION, tesSUCCESS, tesSUCCESS, 9, false);
}
void

View File

@@ -738,8 +738,7 @@ AMM::bid(BidArg const& arg)
{
if (auto const amm = env_.current()->read(keylet::amm(asset1_.asset(), asset2_.asset())))
{
if (env_.current()->rules().enabled(fixInnerObjTemplate) &&
!amm->isFieldPresent(sfAuctionSlot))
if (!amm->isFieldPresent(sfAuctionSlot))
Throw<std::runtime_error>("AMM::Bid");
if (amm->isFieldPresent(sfAuctionSlot))
{
@@ -867,8 +866,7 @@ AMM::expectAuctionSlot(auto&& cb) const
{
if (auto const amm = env_.current()->read(keylet::amm(asset1_.asset(), asset2_.asset())))
{
if (env_.current()->rules().enabled(fixInnerObjTemplate) &&
!amm->isFieldPresent(sfAuctionSlot))
if (!amm->isFieldPresent(sfAuctionSlot))
Throw<std::runtime_error>("AMM::expectAuctionSlot");
if (amm->isFieldPresent(sfAuctionSlot))
{
@@ -876,10 +874,6 @@ AMM::expectAuctionSlot(auto&& cb) const
safeDowncast<STObject const&>(amm->peekAtField(sfAuctionSlot));
if (auctionSlot.isFieldPresent(sfAccount))
{
// This could fail in pre-fixInnerObjTemplate tests
// if the submitted transactions recreate one of
// the failure scenarios. Access as optional
// to avoid the failure.
auto const slotFee = auctionSlot[~sfDiscountedFee].value_or(0);
auto const slotInterval = ammAuctionTimeSlot(
env_.app().getTimeKeeper().now().time_since_epoch().count(), auctionSlot);

View File

@@ -214,9 +214,7 @@ doAMMInfo(RPC::JsonContext& context)
}
if (voteSlots.size() > 0)
ammResult[jss::vote_slots] = std::move(voteSlots);
XRPL_ASSERT(
!ledger->rules().enabled(fixInnerObjTemplate) || amm->isFieldPresent(sfAuctionSlot),
"xrpl::doAMMInfo : auction slot is set");
XRPL_ASSERT(amm->isFieldPresent(sfAuctionSlot), "xrpl::doAMMInfo : auction slot is present");
if (amm->isFieldPresent(sfAuctionSlot))
{
auto const& auctionSlot = safeDowncast<STObject const&>(amm->peekAtField(sfAuctionSlot));