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 ripple {
8
9bool
11{
12 if (ctx.tx.isFieldPresent(sfDomainID) &&
13 !(ctx.rules.enabled(featurePermissionedDomains) &&
14 ctx.rules.enabled(featureSingleAssetVault)))
15 return false;
16
17 if (ctx.tx.isFieldPresent(sfMutableFlags) &&
18 !ctx.rules.enabled(featureDynamicMPT))
19 return false;
20
21 return true;
22}
23
26{
27 // This mask is only compared against sfFlags
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 || *mutableFlags & tmfMPTokenIssuanceCreateMutableMask))
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->length() == 0 ||
64 metadata->length() > maxMPTokenMetadataLength)
65 return temMALFORMED;
66 }
67
68 // Check if maximumAmount is within unsigned 63 bit range
69 if (auto const maxAmt = ctx.tx[~sfMaximumAmount])
70 {
71 if (maxAmt == 0)
72 return temMALFORMED;
73
74 if (maxAmt > maxMPTokenAmount)
75 return temMALFORMED;
76 }
77 return tesSUCCESS;
78}
79
82 ApplyView& view,
83 beast::Journal journal,
84 MPTCreateArgs const& args)
85{
86 auto const acct = view.peek(keylet::account(args.account));
87 if (!acct)
88 return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE
89
90 if (args.priorBalance &&
91 *(args.priorBalance) <
92 view.fees().accountReserve((*acct)[sfOwnerCount] + 1))
94
95 auto const mptId = makeMptID(args.sequence, args.account);
96 auto const mptIssuanceKeylet = keylet::mptIssuance(mptId);
97
98 // create the MPTokenIssuance
99 {
100 auto const ownerNode = view.dirInsert(
102 mptIssuanceKeylet,
104
105 if (!ownerNode)
106 return Unexpected(tecDIR_FULL); // LCOV_EXCL_LINE
107
108 auto mptIssuance = std::make_shared<SLE>(mptIssuanceKeylet);
109 (*mptIssuance)[sfFlags] = args.flags & ~tfUniversal;
110 (*mptIssuance)[sfIssuer] = args.account;
111 (*mptIssuance)[sfOutstandingAmount] = 0;
112 (*mptIssuance)[sfOwnerNode] = *ownerNode;
113 (*mptIssuance)[sfSequence] = args.sequence;
114
115 if (args.maxAmount)
116 (*mptIssuance)[sfMaximumAmount] = *args.maxAmount;
117
118 if (args.assetScale)
119 (*mptIssuance)[sfAssetScale] = *args.assetScale;
120
121 if (args.transferFee)
122 (*mptIssuance)[sfTransferFee] = *args.transferFee;
123
124 if (args.metadata)
125 (*mptIssuance)[sfMPTokenMetadata] = *args.metadata;
126
127 if (args.domainId)
128 (*mptIssuance)[sfDomainID] = *args.domainId;
129
130 if (args.mutableFlags)
131 (*mptIssuance)[sfMutableFlags] = *args.mutableFlags;
132
133 view.insert(mptIssuance);
134 }
135
136 // Update owner count.
137 adjustOwnerCount(view, acct, 1, journal);
138
139 return mptId;
140}
141
142TER
144{
145 auto const& tx = ctx_.tx;
146 auto const result = create(
147 view(),
148 j_,
149 {
150 .priorBalance = mPriorBalance,
151 .account = account_,
152 .sequence = tx.getSeqValue(),
153 .flags = tx.getFlags(),
154 .maxAmount = tx[~sfMaximumAmount],
155 .assetScale = tx[~sfAssetScale],
156 .transferFee = tx[~sfTransferFee],
157 .metadata = tx[~sfMPTokenMetadata],
158 .domainId = tx[~sfDomainID],
159 .mutableFlags = tx[~sfMutableFlags],
160 });
161 return result ? tesSUCCESS : result.error();
162}
163
164} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:41
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:124
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:300
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 Expected< MPTID, TER > create(ApplyView &view, beast::Journal journal, MPTCreateArgs const &args)
static NotTEC preflight(PreflightContext const &ctx)
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
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:111
bool isFlag(std::uint32_t) const
Definition STObject.cpp:512
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:465
std::uint32_t getFlags() const
Definition STObject.cpp:518
AccountID const account_
Definition Transactor.h:128
ApplyView & view()
Definition Transactor.h:144
beast::Journal const j_
Definition Transactor.h:126
XRPAmount mPriorBalance
Definition Transactor.h:129
ApplyContext & ctx_
Definition Transactor.h:124
T is_same_v
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:507
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:165
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:355
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
constexpr std::uint32_t const tfMPTCanTransfer
Definition TxFlags.h:133
std::uint64_t constexpr maxMPTokenAmount
The maximum amount of MPTokenIssuance.
Definition Protocol.h:100
constexpr std::uint32_t const tfMPTokenIssuanceCreateMask
Definition TxFlags.h:135
std::uint16_t constexpr maxTransferFee
The maximum token transfer fee allowed.
Definition Protocol.h:66
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:1013
constexpr std::uint32_t const tmfMPTokenIssuanceCreateMutableMask
Definition TxFlags.h:148
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition View.cpp:1031
std::size_t constexpr maxMPTokenMetadataLength
The maximum length of MPTokenMetadata.
Definition Protocol.h:97
@ tecDIR_FULL
Definition TER.h:269
@ tecINTERNAL
Definition TER.h:292
@ tecINSUFFICIENT_RESERVE
Definition TER.h:289
@ tesSUCCESS
Definition TER.h:226
MPTID makeMptID(std::uint32_t sequence, AccountID const &account)
Definition Indexes.cpp:151
constexpr std::uint32_t const tfMPTRequireAuth
Definition TxFlags.h:130
@ temBAD_TRANSFER_FEE
Definition TER.h:123
@ temMALFORMED
Definition TER.h:68
@ temINVALID_FLAG
Definition TER.h:92
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
std::optional< std::uint16_t > transferFee
std::optional< XRPAmount > priorBalance
std::optional< std::uint32_t > mutableFlags
std::optional< std::uint8_t > assetScale
std::optional< uint256 > domainId
std::optional< std::uint64_t > maxAmount
std::optional< Slice > const & metadata
State information when preflighting a tx.
Definition Transactor.h:16