-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Expand file tree
/
Copy pathMPTokenHelpers.h
More file actions
278 lines (233 loc) · 8.66 KB
/
MPTokenHelpers.h
File metadata and controls
278 lines (233 loc) · 8.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
#pragma once
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/MPTIssue.h>
#include <xrpl/protocol/Rate.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/TER.h>
#include <initializer_list>
#include <optional>
namespace xrpl {
class MPTokenIssuance : public virtual TokenBase
{
public:
MPTokenIssuance(ReadView const& view, MPTIssue const& mptIssue)
: ReadOnlySLE(view.read(keylet::mptIssuance(mptIssue.getMptID())), view)
, TokenBase(view, view.read(keylet::mptIssuance(mptIssue.getMptID())))
, mptID_(mptIssue.getMptID())
, mptIssue_(mptIssue)
{
}
MPTokenIssuance(ReadView const& view, MPTID const& mptID)
: ReadOnlySLE(view.read(keylet::mptIssuance(mptID)), view)
, TokenBase(view, view.read(keylet::mptIssuance(mptID)))
, mptID_(mptID)
, mptIssue_(MPTIssue(mptID_))
{
}
MPTID const&
getMptID() const
{
return mptID_;
}
MPTIssue const&
getMptIssue() const
{
return mptIssue_;
}
AccountID const&
getIssuer() const
{
return mptIssue_.getIssuer();
}
//------------------------------------------------------------------------------
//
// Freeze checking (MPT-specific)
//
//------------------------------------------------------------------------------
[[nodiscard]] bool
isGlobalFrozen() const override;
[[nodiscard]] bool
isIndividualFrozen(AccountID const& account) const override;
[[nodiscard]] bool
isFrozen(AccountID const& account, int depth = 0) const override;
[[nodiscard]] TER
checkFrozen(AccountID const& account) const override;
[[nodiscard]] bool
isAnyFrozen(std::initializer_list<AccountID> const& accounts, int depth = 0) const override;
[[nodiscard]] bool
isDeepFrozen(AccountID const& account, int depth = 0) const override;
[[nodiscard]] TER
checkDeepFrozen(AccountID const& account) const override;
//------------------------------------------------------------------------------
//
// Transfer rate (MPT-specific)
//
//------------------------------------------------------------------------------
/** Returns MPT transfer fee as Rate. Rate specifies
* the fee as fractions of 1 billion. For example, 1% transfer rate
* is represented as 1,010,000,000.
* @param issuanceID MPTokenIssuanceID of MPTTokenIssuance object
*/
[[nodiscard]] Rate
transferRate() const override;
//------------------------------------------------------------------------------
//
// Holding checks (MPT-specific)
//
//------------------------------------------------------------------------------
[[nodiscard]] TER
canAddHolding() const override;
/** Check if the account lacks required authorization for MPT.
*
* requireAuth check is recursive for MPT shares in a vault, descending to
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is
* purely defensive, as we currently do not allow such vaults to be created.
*/
[[nodiscard]] TER
requireAuth(AccountID const& account, AuthType authType = AuthType::Legacy, int depth = 0)
const override;
/** Check if the destination account is allowed
* to receive MPT. Return tecNO_AUTH if it doesn't
* and tesSUCCESS otherwise.
*/
[[nodiscard]] TER
canTransfer(AccountID const& from, AccountID const& to) const override;
//------------------------------------------------------------------------------
//
// Token capability checks (MPT-specific)
//
//------------------------------------------------------------------------------
[[nodiscard]] bool
canClawback() const override;
[[nodiscard]] bool
requiresAuth() const override;
[[nodiscard]] bool
hasHolder(AccountID const& holder) const override
{
return readView_.exists(keylet::mptoken(mptID_, holder));
}
STAmount
accountHolds(
AccountID const& account,
FreezeHandling zeroIfFrozen,
beast::Journal j,
SpendableHandling includeFullBalance = shSIMPLE_BALANCE) const override;
[[nodiscard]] STAmount
accountHolds(
AccountID const& account,
FreezeHandling zeroIfFrozen,
AuthHandling zeroIfUnauthorized,
beast::Journal j,
SpendableHandling includeFullBalance = shSIMPLE_BALANCE) const override;
protected:
MPTID const mptID_;
MPTIssue const mptIssue_;
};
class WritableMPTokenIssuance : public virtual WritableTokenBase, public virtual MPTokenIssuance
{
public:
WritableMPTokenIssuance(ApplyView& view, MPTIssue const& mptIssue)
: ReadOnlySLE(view.peek(keylet::mptIssuance(mptIssue.getMptID())), view)
, TokenBase(view, view.peek(keylet::mptIssuance(mptIssue.getMptID())))
, WritableSLE(view.peek(keylet::mptIssuance(mptIssue.getMptID())), view)
, WritableTokenBase(view, view.peek(keylet::mptIssuance(mptIssue.getMptID())))
, MPTokenIssuance(view, mptIssue)
{
}
WritableMPTokenIssuance(ApplyView& view, MPTID const& mptID)
: ReadOnlySLE(view.peek(keylet::mptIssuance(mptID)), view)
, TokenBase(view, view.peek(keylet::mptIssuance(mptID)))
, WritableSLE(view.peek(keylet::mptIssuance(mptID)), view)
, WritableTokenBase(view, view.peek(keylet::mptIssuance(mptID)))
, MPTokenIssuance(view, mptID)
{
}
// Resolve ambiguity: use writable operator-> for non-const, read-only for const
using WritableSLE::operator->;
using MPTokenIssuance::operator->;
using WritableSLE::operator*;
using MPTokenIssuance::operator*;
//------------------------------------------------------------------------------
//
// Authorization (MPT-specific)
//
//------------------------------------------------------------------------------
[[nodiscard]] TER
authorizeMPToken(
XRPAmount const& priorBalance,
AccountID const& account,
beast::Journal journal,
std::uint32_t flags = 0,
std::optional<AccountID> holderID = std::nullopt);
/** Enforce account has MPToken to match its authorization.
*
* Called from doApply - it will check for expired (and delete if found any)
* credentials matching DomainID set in MPTokenIssuance. Must be called if
* requireAuth(...MPTIssue...) returned tesSUCCESS or tecEXPIRED in preclaim.
*/
[[nodiscard]] TER
enforceMPTokenAuthorization(
AccountID const& account,
XRPAmount const& priorBalance,
beast::Journal j);
//------------------------------------------------------------------------------
//
// Empty holding operations (MPT-specific)
//
//------------------------------------------------------------------------------
[[nodiscard]] TER
addEmptyHolding(AccountID const& accountID, XRPAmount priorBalance, beast::Journal journal)
override;
[[nodiscard]] TER
removeEmptyHolding(AccountID const& accountID, beast::Journal journal) override;
/** Create a WritableMPTokenIssuance backed by a brand-new SLE
* (not yet inserted into the view).
*/
[[nodiscard]] static WritableMPTokenIssuance
makeNew(MPTID const& mptID, ApplyView& view)
{
return WritableMPTokenIssuance(
mptID, std::make_shared<SLE>(keylet::mptIssuance(mptID)), view);
}
[[nodiscard]] static WritableMPTokenIssuance
makeNew(std::uint32_t const seq, AccountID const& issuer, ApplyView& view)
{
auto const mptID = makeMptID(seq, issuer);
return WritableMPTokenIssuance(
mptID, std::make_shared<SLE>(keylet::mptIssuance(mptID)), view);
}
private:
// This is a private constructor only used by `makeNew`
WritableMPTokenIssuance(MPTID const& mptID, std::shared_ptr<SLE> sle, ApplyView& view)
: ReadOnlySLE(sle, view)
, TokenBase(view, sle)
, WritableSLE(sle, view)
, WritableTokenBase(view, sle)
, MPTokenIssuance(view, mptID)
{
insert();
}
};
//------------------------------------------------------------------------------
//
// Escrow operations (MPT-specific)
//
//------------------------------------------------------------------------------
TER
rippleLockEscrowMPT(
ApplyView& view,
AccountID const& uGrantorID,
STAmount const& saAmount,
beast::Journal j);
TER
rippleUnlockEscrowMPT(
ApplyView& view,
AccountID const& uGrantorID,
AccountID const& uGranteeID,
STAmount const& netAmount,
STAmount const& grossAmount,
beast::Journal j);
} // namespace xrpl