Skip to content

Commit

Permalink
Fixed NFT deep freeze offer acceptance
Browse files Browse the repository at this point in the history
  • Loading branch information
vvysokikh1 committed Jan 20, 2025
1 parent 9f21f5d commit 8c40ab9
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 26 deletions.
49 changes: 23 additions & 26 deletions src/test/app/Freeze_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1818,21 +1818,20 @@ class Freeze_test : public beast::unit_test::suite
}

// Testing A2 nft offer sell when A2 deep frozen by issuer
// if (features[featureDeepFreeze])
// {
// auto const sellOfferIndex = createNFTOffer(env, A2, USD(10));
if (features[featureDeepFreeze])
{
auto const sellOfferIndex = createNFTOffer(env, A2, USD(10));

// env(trust(G1, A2["USD"](0), tfSetFreeze | tfSetDeepFreeze));
// env.close();
env(trust(G1, A2["USD"](0), tfSetFreeze | tfSetDeepFreeze));
env.close();

// // test: A2 cannot receive USD for his NFT
// env(token::acceptSellOffer(A1, sellOfferIndex),
// ter(tecINSUFFICIENT_FUNDS));
// env.close();
// test: A2 cannot receive USD for his NFT
env(token::acceptSellOffer(A1, sellOfferIndex), ter(tecFROZEN));
env.close();

// env(trust(G1, A2["USD"](0), tfClearFreeze | tfClearDeepFreeze));
// env.close();
// }
env(trust(G1, A2["USD"](0), tfClearFreeze | tfClearDeepFreeze));
env.close();
}

// Testing A1 nft offer sell when A2 frozen by issuer
{
Expand Down Expand Up @@ -1872,30 +1871,28 @@ class Freeze_test : public beast::unit_test::suite
// env.close();

// // test: A2 cannot receive USD for his NFT
// env(token::acceptSellOffer(A1, sellOfferIndex),
// ter(tecINSUFFICIENT_FUNDS));
// env(token::acceptSellOffer(A1, sellOfferIndex), ter(tecFROZEN));
// env.close();

// env(trust(A2, G1["USD"](0), tfClearFreeze));
// env.close();
// }

// // Testing A2 nft offer sell when A2 deep frozen by currency holder
// if (features[featureDeepFreeze])
// {
// auto const sellOfferIndex = createNFTOffer(env, A2, USD(10));
if (features[featureDeepFreeze])
{
auto const sellOfferIndex = createNFTOffer(env, A2, USD(10));

// env(trust(A2, G1["USD"](0), tfSetFreeze | tfSetDeepFreeze));
// env.close();
env(trust(A2, G1["USD"](0), tfSetFreeze | tfSetDeepFreeze));
env.close();

// // test: A2 cannot receive USD for his NFT
// env(token::acceptSellOffer(A1, sellOfferIndex),
// ter(tecINSUFFICIENT_FUNDS));
// env.close();
// test: A2 cannot receive USD for his NFT
env(token::acceptSellOffer(A1, sellOfferIndex), ter(tecFROZEN));
env.close();

// env(trust(A2, G1["USD"](0), tfClearFreeze | tfClearDeepFreeze));
// env.close();
// }
env(trust(A2, G1["USD"](0), tfClearFreeze | tfClearDeepFreeze));
env.close();
}

// Testing A1 nft offer sell when A2 frozen by currency holder
{
Expand Down
68 changes: 68 additions & 0 deletions src/xrpld/app/tx/detail/NFTokenAcceptOffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,21 @@ NFTokenAcceptOffer::preclaim(PreclaimContext const& ctx)
ctx.j) < needed)
return tecINSUFFICIENT_FUNDS;
}

// Make sure that we are allowed to hold what the taker will pay us.
// This is the same approach taken by usual offers except we don't check
// trust line authorization at the moment.
if (!needed.native())
{
auto const result = checkAcceptAsset(
ctx.view,
ctx.flags,
(*so)[sfOwner],
ctx.j,
Issue(needed.getCurrency(), needed.getIssuer()));
if (result != tesSUCCESS)
return result;
}
}

// Fix a bug where the transfer of an NFToken with a transfer fee could
Expand Down Expand Up @@ -510,4 +525,57 @@ NFTokenAcceptOffer::doApply()
return tecINTERNAL;
}

TER
NFTokenAcceptOffer::checkAcceptAsset(
ReadView const& view,
ApplyFlags const flags,
AccountID const id,
beast::Journal const j,
Issue const& issue)
{
// Only valid for custom currencies
XRPL_ASSERT(
!isXRP(issue.currency),
"ripple::CreateOffer::checkAcceptAsset : input is not XRP");

auto const issuerAccount = view.read(keylet::account(issue.account));

if (!issuerAccount)
{
JLOG(j.debug())
<< "delay: can't receive IOUs from non-existent issuer: "
<< to_string(issue.account);

return (flags & tapRETRY) ? TER{terNO_ACCOUNT} : TER{tecNO_ISSUER};
}

// An account can not create a trustline to itself, so no line can exist
// to be frozen. Additionally, an issuer can always accept its own
// issuance.
if (issue.account == id)
{
return tesSUCCESS;
}

auto const trustLine =
view.read(keylet::line(id, issue.account, issue.currency));

if (!trustLine)
{
return tesSUCCESS;
}

// There's no difference which side enacted deep freeze, accepting
// tokens shouldn't be possible.
bool const deepFrozen =
(*trustLine)[sfFlags] & (lsfLowDeepFreeze | lsfHighDeepFreeze);

if (deepFrozen)
{
return tecFROZEN;
}

return tesSUCCESS;
}

} // namespace ripple
8 changes: 8 additions & 0 deletions src/xrpld/app/tx/detail/NFTokenAcceptOffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ class NFTokenAcceptOffer : public Transactor
AccountID const& seller,
uint256 const& nfTokenID);

static TER
checkAcceptAsset(
ReadView const& view,
ApplyFlags const flags,
AccountID const id,
beast::Journal const j,
Issue const& issue);

public:
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};

Expand Down

0 comments on commit 8c40ab9

Please sign in to comment.