rippled
Loading...
Searching...
No Matches
MPTokenIssuanceCreate.cpp
1#include <xrpld/app/tx/detail/MPTokenIssuanceCreate.h>
2
3#include <xrpl/ledger/View.h>
4#include <xrpl/protocol/Feature.h>
5#include <xrpl/protocol/TxFlags.h>
6
7namespace xrpl {
8
9bool
11{
12 if (ctx.tx.isFieldPresent(sfDomainID) &&
13 !(ctx.rules.enabled(featurePermissionedDomains) && ctx.rules.enabled(featureSingleAssetVault)))
14 return false;
15
16 if (ctx.tx.isFieldPresent(sfMutableFlags) && !ctx.rules.enabled(featureDynamicMPT))
17 return false;
18
19 return true;
20}
21
24{
25 // This mask is only compared against sfFlags
27}
28
31{
32 // If the mutable flags field is included, at least one flag must be
33 // specified.
34 if (auto const mutableFlags = ctx.tx[~sfMutableFlags];
35 mutableFlags && (!*mutableFlags || *mutableFlags & tmfMPTokenIssuanceCreateMutableMask))
36 return temINVALID_FLAG;
37
38 if (auto const fee = ctx.tx[~sfTransferFee])
39 {
40 if (fee > maxTransferFee)
42
43 // If a non-zero TransferFee is set then the tfTransferable flag
44 // must also be set.
45 if (fee > 0u && !ctx.tx.isFlag(tfMPTCanTransfer))
46 return temMALFORMED;
47 }
48
49 if (auto const domain = ctx.tx[~sfDomainID])
50 {
51 if (*domain == beast::zero)
52 return temMALFORMED;
53
54 // Domain present implies that MPTokenIssuance is not public
55 if ((ctx.tx.getFlags() & tfMPTRequireAuth) == 0)
56 return temMALFORMED;
57 }
58
59 if (auto const metadata = ctx.tx[~sfMPTokenMetadata])
60 {
61 if (metadata->length() == 0 || metadata->length() > maxMPTokenMetadataLength)
62 return temMALFORMED;
63 }
64
65 // Check if maximumAmount is within unsigned 63 bit range
66 if (auto const maxAmt = ctx.tx[~sfMaximumAmount])
67 {
68 if (maxAmt == 0)
69 return temMALFORMED;
70
71 if (maxAmt > maxMPTokenAmount)
72 return temMALFORMED;
73 }
74 return tesSUCCESS;
75}
76
79{
80 auto const acct = view.peek(keylet::account(args.account));
81 if (!acct)
82 return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE
83
84 if (args.priorBalance && *(args.priorBalance) < view.fees().accountReserve((*acct)[sfOwnerCount] + 1))
86
87 auto const mptId = makeMptID(args.sequence, args.account);
88 auto const mptIssuanceKeylet = keylet::mptIssuance(mptId);
89
90 // create the MPTokenIssuance
91 {
92 auto const ownerNode =
93 view.dirInsert(keylet::ownerDir(args.account), mptIssuanceKeylet, describeOwnerDir(args.account));
94
95 if (!ownerNode)
96 return Unexpected(tecDIR_FULL); // LCOV_EXCL_LINE
97
98 auto mptIssuance = std::make_shared<SLE>(mptIssuanceKeylet);
99 (*mptIssuance)[sfFlags] = args.flags & ~tfUniversal;
100 (*mptIssuance)[sfIssuer] = args.account;
101 (*mptIssuance)[sfOutstandingAmount] = 0;
102 (*mptIssuance)[sfOwnerNode] = *ownerNode;
103 (*mptIssuance)[sfSequence] = args.sequence;
104
105 if (args.maxAmount)
106 (*mptIssuance)[sfMaximumAmount] = *args.maxAmount;
107
108 if (args.assetScale)
109 (*mptIssuance)[sfAssetScale] = *args.assetScale;
110
111 if (args.transferFee)
112 (*mptIssuance)[sfTransferFee] = *args.transferFee;
113
114 if (args.metadata)
115 (*mptIssuance)[sfMPTokenMetadata] = *args.metadata;
116
117 if (args.domainId)
118 (*mptIssuance)[sfDomainID] = *args.domainId;
119
120 if (args.mutableFlags)
121 (*mptIssuance)[sfMutableFlags] = *args.mutableFlags;
122
123 view.insert(mptIssuance);
124 }
125
126 // Update owner count.
127 adjustOwnerCount(view, acct, 1, journal);
128
129 return mptId;
130}
131
132TER
134{
135 auto const& tx = ctx_.tx;
136 auto const result = create(
137 view(),
138 j_,
139 {
140 .priorBalance = mPriorBalance,
141 .account = account_,
142 .sequence = tx.getSeqValue(),
143 .flags = tx.getFlags(),
144 .maxAmount = tx[~sfMaximumAmount],
145 .assetScale = tx[~sfAssetScale],
146 .transferFee = tx[~sfTransferFee],
147 .metadata = tx[~sfMPTokenMetadata],
148 .domainId = tx[~sfDomainID],
149 .mutableFlags = tx[~sfMutableFlags],
150 });
151 return result ? tesSUCCESS : result.error();
152}
153
154} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:40
STTx const & tx
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:114
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:283
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
static bool checkExtraFeatures(PreflightContext const &ctx)
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
static Expected< MPTID, TER > create(ApplyView &view, beast::Journal journal, MPTCreateArgs const &args)
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:118
bool isFlag(std::uint32_t) const
Definition STObject.cpp:486
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:439
std::uint32_t getFlags() const
Definition STObject.cpp:492
AccountID const account_
Definition Transactor.h:112
beast::Journal const j_
Definition Transactor.h:110
ApplyView & view()
Definition Transactor.h:128
XRPAmount mPriorBalance
Definition Transactor.h:113
ApplyContext & ctx_
Definition Transactor.h:108
T is_same_v
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:325
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:462
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:160
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
constexpr std::uint32_t const tmfMPTokenIssuanceCreateMutableMask
Definition TxFlags.h:147
constexpr std::uint32_t const tfMPTCanTransfer
Definition TxFlags.h:132
constexpr std::uint32_t const tfMPTRequireAuth
Definition TxFlags.h:129
std::uint64_t constexpr maxMPTokenAmount
The maximum amount of MPTokenIssuance.
Definition Protocol.h:233
std::size_t constexpr maxMPTokenMetadataLength
The maximum length of MPTokenMetadata.
Definition Protocol.h:230
void adjustOwnerCount(ApplyView &view, std::shared_ptr< SLE > const &sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
Definition View.cpp:941
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition View.cpp:955
constexpr std::uint32_t const tfMPTokenIssuanceCreateMask
Definition TxFlags.h:134
@ temINVALID_FLAG
Definition TER.h:91
@ temMALFORMED
Definition TER.h:67
@ temBAD_TRANSFER_FEE
Definition TER.h:122
@ tecDIR_FULL
Definition TER.h:268
@ tecINTERNAL
Definition TER.h:291
@ tecINSUFFICIENT_RESERVE
Definition TER.h:288
std::uint16_t constexpr maxTransferFee
The maximum token transfer fee allowed.
Definition Protocol.h:66
MPTID makeMptID(std::uint32_t sequence, AccountID const &account)
Definition Indexes.cpp:146
@ tesSUCCESS
Definition TER.h:225
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
std::optional< std::uint32_t > mutableFlags
AccountID const & account
std::optional< std::uint64_t > maxAmount
std::optional< std::uint16_t > transferFee
std::optional< uint256 > domainId
std::optional< XRPAmount > priorBalance
std::optional< Slice > const & metadata
std::optional< std::uint8_t > assetScale
State information when preflighting a tx.
Definition Transactor.h:15