Skip to content

Commit

Permalink
Add the fixNFTokenTrustlineSurprise amendment:
Browse files Browse the repository at this point in the history
Fix bugs in interactions between NFTokenOffers and trust lines.

Since the NFTokenAcceptOffer does not check the trust line that
the issuer receives as a transfer fee in the NFTokenAcceptOffer,
if the issuer deletes the trust line after NFTokenCreateOffer,
the trust line is created for the issuer by the
NFTokenAcceptOffer.  That's fixed.

Also if Alice issues an IOU and also mints NFTokens with a
transfer fee, Alice's IOU cannot be used to pay for transfers
of those NFTokens.  That's fixed.

Resolves #4925.
Resolves #4941.
  • Loading branch information
scottschurr committed Mar 8, 2024
1 parent c28e005 commit b40d3fc
Show file tree
Hide file tree
Showing 6 changed files with 394 additions and 15 deletions.
28 changes: 28 additions & 0 deletions src/ripple/app/tx/impl/NFTokenAcceptOffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,34 @@ NFTokenAcceptOffer::preclaim(PreclaimContext const& ctx)
}
}

// Fix a bug where the transfer of an NFToken with a transfer fee could
// give the NFToken issuer an undesired trust line.
if (ctx.view.rules().enabled(fixNFTokenTrustlineSurprise))
{
std::shared_ptr<SLE const> const& offer = bo ? bo : so;
if (!offer)
// Should be caught in preflight.
return tecINTERNAL;

// - If the NFToken has a transfer fee, and
// - If the NFToken doesn't have the flagCreateTrustLines flag set, and
// - If the Amount is not XRP, and
// - If the NFToken issuer is not the Amount issuer, and
// - If the NFToken issuer does not have a trust line for the Amount
// - Then reject the token accept.
uint256 const& tokenID = offer->at(sfNFTokenID);
STAmount const& amount = offer->at(sfAmount);
if (nft::getTransferFee(tokenID) != 0 &&
(nft::getFlags(tokenID) & nft::flagCreateTrustLines) == 0 &&
!amount.native())
{
auto const issuer = nft::getIssuer(tokenID);
// Issuer doesn't need a trust line to accept their own currency.
if (issuer != amount.getIssuer() &&
!ctx.view.read(keylet::line(issuer, amount.issue())))
return tecNO_LINE;
}
}
return tesSUCCESS;
}

Expand Down
13 changes: 12 additions & 1 deletion src/ripple/app/tx/impl/NFTokenCreateOffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,19 @@ NFTokenCreateOffer::preclaim(PreclaimContext const& ctx)
if (!ctx.view.exists(keylet::account(issuer)))
return tecNO_ISSUER;

if (!ctx.view.exists(keylet::line(issuer, amount.issue())))
// There was a bug in a corner case that fixNFTokenTrustlineSurprise
// addresses. If the IOU issuer and the NFToken issuer are the same,
// then that issuer does not need a trust line to accept their fee.
if (ctx.view.rules().enabled(fixNFTokenTrustlineSurprise))
{
if (issuer != amount.getIssuer() &&
!ctx.view.read(keylet::line(issuer, amount.issue())))
return tecNO_LINE;
}
else if (!ctx.view.exists(keylet::line(issuer, amount.issue())))
{
return tecNO_LINE;
}

if (isFrozen(
ctx.view, issuer, amount.getCurrency(), amount.getIssuer()))
Expand Down
3 changes: 2 additions & 1 deletion src/ripple/protocol/Feature.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ namespace detail {
// Feature.cpp. Because it's only used to reserve storage, and determine how
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
// the actual number of amendments. A LogicError on startup will verify this.
static constexpr std::size_t numFeatures = 68;
static constexpr std::size_t numFeatures = 69;

/** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated
Expand Down Expand Up @@ -355,6 +355,7 @@ extern uint256 const fixFillOrKill;
extern uint256 const fixNFTokenReserve;
extern uint256 const fixInnerObjTemplate;
extern uint256 const featurePriceOracle;
extern uint256 const fixNFTokenTrustlineSurprise;

} // namespace ripple

Expand Down
3 changes: 2 additions & 1 deletion src/ripple/protocol/impl/Feature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,8 +460,9 @@ REGISTER_FIX (fixDisallowIncomingV1, Supported::yes, VoteBehavior::De
REGISTER_FEATURE(DID, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX(fixFillOrKill, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX (fixNFTokenReserve, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX(fixInnerObjTemplate, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX (fixInnerObjTemplate, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FEATURE(PriceOracle, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX (fixNFTokenTrustlineSurprise, Supported::yes, VoteBehavior::DefaultNo);

// The following amendments are obsolete, but must remain supported
// because they could potentially get enabled.
Expand Down

0 comments on commit b40d3fc

Please sign in to comment.