rippled
Loading...
Searching...
No Matches
NFTokenBurn.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2021 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/app/tx/detail/NFTokenBurn.h>
21#include <xrpld/app/tx/detail/NFTokenUtils.h>
22
23#include <xrpl/protocol/Feature.h>
24#include <xrpl/protocol/Protocol.h>
25#include <xrpl/protocol/TxFlags.h>
26
27namespace ripple {
28
31{
32 return tesSUCCESS;
33}
34
35TER
37{
38 auto const owner = [&ctx]() {
39 if (ctx.tx.isFieldPresent(sfOwner))
40 return ctx.tx.getAccountID(sfOwner);
41
42 return ctx.tx[sfAccount];
43 }();
44
45 if (!nft::findToken(ctx.view, owner, ctx.tx[sfNFTokenID]))
46 return tecNO_ENTRY;
47
48 // The owner of a token can always burn it, but the issuer can only
49 // do so if the token is marked as burnable.
50 if (auto const account = ctx.tx[sfAccount]; owner != account)
51 {
52 if (!(nft::getFlags(ctx.tx[sfNFTokenID]) & nft::flagBurnable))
53 return tecNO_PERMISSION;
54
55 if (auto const issuer = nft::getIssuer(ctx.tx[sfNFTokenID]);
56 issuer != account)
57 {
58 if (auto const sle = ctx.view.read(keylet::account(issuer)); sle)
59 {
60 if (auto const minter = (*sle)[~sfNFTokenMinter];
61 minter != account)
62 return tecNO_PERMISSION;
63 }
64 }
65 }
66
67 return tesSUCCESS;
68}
69
70TER
72{
73 // Remove the token, effectively burning it:
74 auto const ret = nft::removeToken(
75 view(),
76 ctx_.tx.isFieldPresent(sfOwner) ? ctx_.tx.getAccountID(sfOwner)
77 : ctx_.tx.getAccountID(sfAccount),
78 ctx_.tx[sfNFTokenID]);
79
80 // Should never happen since preclaim() verified the token is present.
81 if (!isTesSuccess(ret))
82 return ret;
83
84 if (auto issuer =
86 {
87 (*issuer)[~sfBurnedNFTokens] =
88 (*issuer)[~sfBurnedNFTokens].value_or(0) + 1;
89 view().update(issuer);
90 }
91
92 // Delete up to 500 offers in total.
93 // Because the number of sell offers is likely to be less than
94 // the number of buy offers, we prioritize the deletion of sell
95 // offers in order to clean up sell offer directory
96 std::size_t const deletedSellOffers = nft::removeTokenOffersWithLimit(
97 view(),
98 keylet::nft_sells(ctx_.tx[sfNFTokenID]),
100
101 if (maxDeletableTokenOfferEntries > deletedSellOffers)
102 {
104 view(),
105 keylet::nft_buys(ctx_.tx[sfNFTokenID]),
106 maxDeletableTokenOfferEntries - deletedSellOffers);
107 }
108
109 return tesSUCCESS;
110}
111
112} // namespace ripple
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
static TER preclaim(PreclaimContext const &ctx)
TER doApply() override
static NotTEC preflight(PreflightContext const &ctx)
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
AccountID getAccountID(SField const &field) const
Definition STObject.cpp:657
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:484
ApplyView & view()
Definition Transactor.h:163
ApplyContext & ctx_
Definition Transactor.h:143
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:184
Keylet nft_buys(uint256 const &id) noexcept
The directory of buy offers for the specified NFT.
Definition Indexes.cpp:434
Keylet nft_sells(uint256 const &id) noexcept
The directory of sell offers for the specified NFT.
Definition Indexes.cpp:440
constexpr std::uint16_t const flagBurnable
Definition nft.h:53
std::uint16_t getFlags(uint256 const &id)
Definition nft.h:60
TER removeToken(ApplyView &view, AccountID const &owner, uint256 const &nftokenID)
Remove the token from the owner's token directory.
AccountID getIssuer(uint256 const &id)
Definition nft.h:120
std::optional< STObject > findToken(ReadView const &view, AccountID const &owner, uint256 const &nftokenID)
Finds the specified token in the owner's token directory.
std::size_t removeTokenOffersWithLimit(ApplyView &view, Keylet const &directory, std::size_t maxDeletableOffers)
Delete up to a specified number of offers from the specified token offer directory.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::size_t constexpr maxDeletableTokenOfferEntries
The maximum number of offers in an offer directory for NFT to be burnable.
Definition Protocol.h:74
@ tecNO_ENTRY
Definition TER.h:307
@ tecNO_PERMISSION
Definition TER.h:306
@ tesSUCCESS
Definition TER.h:245
bool isTesSuccess(TER x) noexcept
Definition TER.h:678
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:609
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:80
ReadView const & view
Definition Transactor.h:83
State information when preflighting a tx.
Definition Transactor.h:35