rippled
Loading...
Searching...
No Matches
MPTokenIssuanceCreate.cpp
1#include <xrpl/ledger/View.h>
2#include <xrpl/ledger/helpers/AccountRootHelpers.h>
3#include <xrpl/ledger/helpers/DirectoryHelpers.h>
4#include <xrpl/protocol/Feature.h>
5#include <xrpl/protocol/TxFlags.h>
6#include <xrpl/tx/transactors/token/MPTokenIssuanceCreate.h>
7
8namespace xrpl {
9
10bool
12{
13 if (ctx.tx.isFieldPresent(sfDomainID) &&
14 !(ctx.rules.enabled(featurePermissionedDomains) &&
15 ctx.rules.enabled(featureSingleAssetVault)))
16 return false;
17
18 if (ctx.tx.isFieldPresent(sfMutableFlags) && !ctx.rules.enabled(featureDynamicMPT))
19 return false;
20
21 return true;
22}
23
26{
27 // This mask is only compared against sfFlags
28 return tfMPTokenIssuanceCreateMask;
29}
30
33{
34 // If the mutable flags field is included, at least one flag must be
35 // specified.
36 if (auto const mutableFlags = ctx.tx[~sfMutableFlags]; mutableFlags &&
37 ((*mutableFlags == 0u) || ((*mutableFlags & tmfMPTokenIssuanceCreateMutableMask) != 0u)))
38 return temINVALID_FLAG;
39
40 if (auto const fee = ctx.tx[~sfTransferFee])
41 {
42 if (fee > maxTransferFee)
44
45 // If a non-zero TransferFee is set then the tfTransferable flag
46 // must also be set.
47 if (fee > 0u && !ctx.tx.isFlag(tfMPTCanTransfer))
48 return temMALFORMED;
49 }
50
51 if (auto const domain = ctx.tx[~sfDomainID])
52 {
53 if (*domain == beast::zero)
54 return temMALFORMED;
55
56 // Domain present implies that MPTokenIssuance is not public
57 if ((ctx.tx.getFlags() & tfMPTRequireAuth) == 0)
58 return temMALFORMED;
59 }
60
61 if (auto const metadata = ctx.tx[~sfMPTokenMetadata])
62 {
63 if (metadata->empty() || metadata->length() > maxMPTokenMetadataLength)
64 return temMALFORMED;
65 }
66
67 // Check if maximumAmount is within unsigned 63 bit range
68 if (auto const maxAmt = ctx.tx[~sfMaximumAmount])
69 {
70 if (maxAmt == 0)
71 return temMALFORMED;
72
73 if (maxAmt > maxMPTokenAmount)
74 return temMALFORMED;
75 }
76 return tesSUCCESS;
77}
78
81{
82 auto const acct = view.peek(keylet::account(args.account));
83 if (!acct)
84 return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE
85
86 if (args.priorBalance &&
87 *(args.priorBalance) < view.fees().accountReserve((*acct)[sfOwnerCount] + 1))
89
90 auto const mptId = makeMptID(args.sequence, args.account);
91 auto const mptIssuanceKeylet = keylet::mptIssuance(mptId);
92
93 // create the MPTokenIssuance
94 {
95 auto const ownerNode = view.dirInsert(
96 keylet::ownerDir(args.account), mptIssuanceKeylet, describeOwnerDir(args.account));
97
98 if (!ownerNode)
99 return Unexpected(tecDIR_FULL); // LCOV_EXCL_LINE
100
101 auto mptIssuance = std::make_shared<SLE>(mptIssuanceKeylet);
102 (*mptIssuance)[sfFlags] = args.flags & ~tfUniversal;
103 (*mptIssuance)[sfIssuer] = args.account;
104 (*mptIssuance)[sfOutstandingAmount] = 0;
105 (*mptIssuance)[sfOwnerNode] = *ownerNode;
106 (*mptIssuance)[sfSequence] = args.sequence;
107
108 if (args.maxAmount)
109 (*mptIssuance)[sfMaximumAmount] = *args.maxAmount;
110
111 if (args.assetScale)
112 (*mptIssuance)[sfAssetScale] = *args.assetScale;
113
114 if (args.transferFee)
115 (*mptIssuance)[sfTransferFee] = *args.transferFee;
116
117 if (args.metadata)
118 (*mptIssuance)[sfMPTokenMetadata] = *args.metadata;
119
120 if (args.domainId)
121 (*mptIssuance)[sfDomainID] = *args.domainId;
122
123 if (args.mutableFlags)
124 (*mptIssuance)[sfMutableFlags] = *args.mutableFlags;
125
126 view.insert(mptIssuance);
127 }
128
129 // Update owner count.
130 adjustOwnerCount(view, acct, 1, journal);
131
132 return mptId;
133}
134
135TER
137{
138 auto const& tx = ctx_.tx;
139 auto const result = create(
140 view(),
141 j_,
142 {
143 .priorBalance = preFeeBalance_,
144 .account = account_,
145 .sequence = tx.getSeqValue(),
146 .flags = tx.getFlags(),
147 .maxAmount = tx[~sfMaximumAmount],
148 .assetScale = tx[~sfAssetScale],
149 .transferFee = tx[~sfTransferFee],
150 .metadata = tx[~sfMPTokenMetadata],
151 .domainId = tx[~sfDomainID],
152 .mutableFlags = tx[~sfMutableFlags],
153 });
154 return result ? tesSUCCESS : result.error();
155}
156
157} // 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:116
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:289
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:120
bool isFlag(std::uint32_t) const
Definition STObject.cpp:503
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:456
std::uint32_t getFlags() const
Definition STObject.cpp:509
AccountID const account_
Definition Transactor.h:116
beast::Journal const j_
Definition Transactor.h:114
ApplyView & view()
Definition Transactor.h:132
XRPAmount preFeeBalance_
Definition Transactor.h:117
ApplyContext & ctx_
Definition Transactor.h:112
T is_same_v
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:336
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:474
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:165
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
constexpr FlagValue tmfMPTokenIssuanceCreateMutableMask
Definition TxFlags.h:350
std::uint64_t constexpr maxMPTokenAmount
The maximum amount of MPTokenIssuance.
Definition Protocol.h:234
std::size_t constexpr maxMPTokenMetadataLength
The maximum length of MPTokenMetadata.
Definition Protocol.h:231
void adjustOwnerCount(ApplyView &view, std::shared_ptr< SLE > const &sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Returns a function that sets the owner on a directory SLE.
@ 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:151
@ 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
std::optional< std::uint16_t > transferFee
State information when preflighting a tx.
Definition Transactor.h:14