rippled
Loading...
Searching...
No Matches
MPTokenAuthorize.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2024 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/MPTokenAuthorize.h>
21
22#include <xrpl/ledger/View.h>
23#include <xrpl/protocol/Feature.h>
24#include <xrpl/protocol/TxFlags.h>
25#include <xrpl/protocol/st.h>
26
27namespace ripple {
28
34
37{
38 if (ctx.tx[sfAccount] == ctx.tx[~sfHolder])
39 return temMALFORMED;
40
41 return tesSUCCESS;
42}
43
44TER
46{
47 auto const accountID = ctx.tx[sfAccount];
48 auto const holderID = ctx.tx[~sfHolder];
49
50 // if non-issuer account submits this tx, then they are trying either:
51 // 1. Unauthorize/delete MPToken
52 // 2. Use/create MPToken
53 //
54 // Note: `accountID` is holder's account
55 // `holderID` is NOT used
56 if (!holderID)
57 {
59 keylet::mptoken(ctx.tx[sfMPTokenIssuanceID], accountID));
60
61 // There is an edge case where all holders have zero balance, issuance
62 // is legally destroyed, then outstanding MPT(s) are deleted afterwards.
63 // Thus, there is no need to check for the existence of the issuance if
64 // the MPT is being deleted with a zero balance. Check for unauthorize
65 // before fetching the MPTIssuance object.
66
67 // if holder wants to delete/unauthorize a mpt
68 if (ctx.tx.getFlags() & tfMPTUnauthorize)
69 {
70 if (!sleMpt)
72
73 if ((*sleMpt)[sfMPTAmount] != 0)
74 {
75 auto const sleMptIssuance = ctx.view.read(
76 keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID]));
77 if (!sleMptIssuance)
78 return tefINTERNAL;
79
80 return tecHAS_OBLIGATIONS;
81 }
82
83 if ((*sleMpt)[~sfLockedAmount].value_or(0) != 0)
84 {
85 auto const sleMptIssuance = ctx.view.read(
86 keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID]));
87 if (!sleMptIssuance)
88 return tefINTERNAL; // LCOV_EXCL_LINE
89
90 return tecHAS_OBLIGATIONS;
91 }
92 if (ctx.view.rules().enabled(featureSingleAssetVault) &&
93 sleMpt->isFlag(lsfMPTLocked))
94 return tecNO_PERMISSION;
95
96 return tesSUCCESS;
97 }
98
99 // Now test when the holder wants to hold/create/authorize a new MPT
100 auto const sleMptIssuance =
101 ctx.view.read(keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID]));
102
103 if (!sleMptIssuance)
104 return tecOBJECT_NOT_FOUND;
105
106 if (accountID == (*sleMptIssuance)[sfIssuer])
107 return tecNO_PERMISSION;
108
109 // if holder wants to use and create a mpt
110 if (sleMpt)
111 return tecDUPLICATE;
112
113 return tesSUCCESS;
114 }
115
116 if (!ctx.view.exists(keylet::account(*holderID)))
117 return tecNO_DST;
118
119 auto const sleMptIssuance =
120 ctx.view.read(keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID]));
121 if (!sleMptIssuance)
122 return tecOBJECT_NOT_FOUND;
123
124 std::uint32_t const mptIssuanceFlags = sleMptIssuance->getFieldU32(sfFlags);
125
126 // If tx is submitted by issuer, they would either try to do the following
127 // for allowlisting:
128 // 1. authorize an account
129 // 2. unauthorize an account
130 //
131 // Note: `accountID` is issuer's account
132 // `holderID` is holder's account
133 if (accountID != (*sleMptIssuance)[sfIssuer])
134 return tecNO_PERMISSION;
135
136 // If tx is submitted by issuer, it only applies for MPT with
137 // lsfMPTRequireAuth set
138 if (!(mptIssuanceFlags & lsfMPTRequireAuth))
139 return tecNO_AUTH;
140
141 // The holder must create the MPT before the issuer can authorize it.
142 if (!ctx.view.exists(
143 keylet::mptoken(ctx.tx[sfMPTokenIssuanceID], *holderID)))
144 return tecOBJECT_NOT_FOUND;
145
146 return tesSUCCESS;
147}
148
149TER
151 ApplyView& view,
152 MPTID const& mptIssuanceID,
153 AccountID const& account,
154 std::uint32_t const flags)
155{
156 auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
157
158 auto const ownerNode = view.dirInsert(
159 keylet::ownerDir(account), mptokenKey, describeOwnerDir(account));
160
161 if (!ownerNode)
162 return tecDIR_FULL; // LCOV_EXCL_LINE
163
164 auto mptoken = std::make_shared<SLE>(mptokenKey);
165 (*mptoken)[sfAccount] = account;
166 (*mptoken)[sfMPTokenIssuanceID] = mptIssuanceID;
167 (*mptoken)[sfFlags] = flags;
168 (*mptoken)[sfOwnerNode] = *ownerNode;
169
170 view.insert(mptoken);
171
172 return tesSUCCESS;
173}
174
175TER
177{
178 auto const& tx = ctx_.tx;
179 return authorizeMPToken(
180 ctx_.view(),
182 tx[sfMPTokenIssuanceID],
183 account_,
185 tx.getFlags(),
186 tx[~sfHolder]);
187}
188
189} // namespace ripple
ApplyView & view()
beast::Journal const journal
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:143
virtual void insert(std::shared_ptr< SLE > const &sle)=0
Insert a new state SLE.
std::optional< std::uint64_t > dirInsert(Keylet const &directory, uint256 const &key, std::function< void(std::shared_ptr< SLE > const &)> const &describe)
Insert an entry to a directory.
Definition ApplyView.h:319
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
static TER createMPToken(ApplyView &view, MPTID const &mptIssuanceID, AccountID const &account, std::uint32_t const flags)
static NotTEC preflight(PreflightContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:130
std::uint32_t getFlags() const
Definition STObject.cpp:537
AccountID const account_
Definition Transactor.h:147
ApplyView & view()
Definition Transactor.h:163
XRPAmount mPriorBalance
Definition Transactor.h:148
ApplyContext & ctx_
Definition Transactor.h:143
T is_same_v
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Definition Indexes.cpp:540
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:526
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:184
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:374
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
@ lsfMPTRequireAuth
constexpr std::uint32_t const tfMPTokenAuthorizeMask
Definition TxFlags.h:173
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition View.cpp:1050
@ tefINTERNAL
Definition TER.h:173
constexpr std::uint32_t const tfMPTUnauthorize
Definition TxFlags.h:172
@ tecNO_DST
Definition TER.h:290
@ tecOBJECT_NOT_FOUND
Definition TER.h:326
@ tecDIR_FULL
Definition TER.h:287
@ tecDUPLICATE
Definition TER.h:315
@ tecNO_PERMISSION
Definition TER.h:305
@ tecHAS_OBLIGATIONS
Definition TER.h:317
@ tecNO_AUTH
Definition TER.h:300
@ tesSUCCESS
Definition TER.h:244
TER authorizeMPToken(ApplyView &view, XRPAmount const &priorBalance, MPTID const &mptIssuanceID, AccountID const &account, beast::Journal journal, std::uint32_t flags=0, std::optional< AccountID > holderID=std::nullopt)
Definition View.cpp:1284
@ temMALFORMED
Definition TER.h:87
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