mirror of
https://github.com/XRPLF/rippled.git
synced 2026-09-28 07:48:01 +00:00
featureTokenIssuance
This commit is contained in:
@@ -338,6 +338,17 @@ adjustLoanBrokerOwnerCount(
|
||||
[[nodiscard]] Rate
|
||||
transferRate(ReadView const& view, AccountID const& issuer);
|
||||
|
||||
/**
|
||||
* Returns the transfer fee charged for a specific currency of the issuer.
|
||||
* A per-currency TransferFee on the currency's TokenIssuance overrides the
|
||||
* account-wide TransferRate.
|
||||
*/
|
||||
[[nodiscard]] Rate
|
||||
transferRate(ReadView const& view, AccountID const& issuer, Currency const& currency);
|
||||
|
||||
[[nodiscard]] Rate
|
||||
transferRate(ReadView const& view, Issue const& issue);
|
||||
|
||||
/**
|
||||
* Generate a pseudo-account address from a pseudo owner key.
|
||||
* @param pseudoOwnerKey The key to generate the address from
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/helpers/TokenIssuanceHelpers.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
@@ -391,7 +392,8 @@ directSendNoFee(
|
||||
AccountID const& uReceiverID,
|
||||
STAmount const& saAmount,
|
||||
bool bCheckIssuer,
|
||||
beast::Journal j);
|
||||
beast::Journal j,
|
||||
EnforceSupplyCap enforceSupplyCap = EnforceSupplyCap::Yes);
|
||||
|
||||
/**
|
||||
* Calls static accountSendIOU if saAmount represents Issue.
|
||||
|
||||
109
include/xrpl/ledger/helpers/TokenIssuanceHelpers.h
Normal file
109
include/xrpl/ledger/helpers/TokenIssuanceHelpers.h
Normal file
@@ -0,0 +1,109 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* ceil(value * 10^scale), exact.
|
||||
*
|
||||
* The shift is a pure exponent adjustment; the +1 for a fractional
|
||||
* positive value is exact because a fractional Number is < 10^16.
|
||||
* Truncation toward zero already is the ceiling for negative values.
|
||||
*/
|
||||
[[nodiscard]] Number
|
||||
tokenScaledCeil(Number const& value, std::uint8_t scale);
|
||||
|
||||
/**
|
||||
* floor(value * 10^scale) as integer base units; nullopt if it does not
|
||||
* fit in a non-negative int64.
|
||||
*/
|
||||
[[nodiscard]] std::optional<std::int64_t>
|
||||
tokenBaseUnits(Number const& value, std::uint8_t scale);
|
||||
|
||||
/**
|
||||
* True if the issuance violates
|
||||
* ceil(IssuedAmount * 10^TokenScale) + MPT OutstandingAmount > MaximumAmount.
|
||||
* Always false for an uncapped issuance.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
tokenSupplyExceeded(ReadView const& view, SLE::const_ref sleIssuance);
|
||||
|
||||
/**
|
||||
* Controls whether an IOU credit hard-fails when a capped TokenIssuance
|
||||
* would exceed its MaximumAmount. Flow-engine steps pass No: their send
|
||||
* results are advisory (return values ignored, reverse-pass execution can
|
||||
* legitimately overshoot transiently) and the supply-cap invariant checker
|
||||
* gates the final state instead.
|
||||
*/
|
||||
enum class EnforceSupplyCap : bool { No = false, Yes = true };
|
||||
|
||||
/**
|
||||
* Maintain IssuedAmount on the issuer's TokenIssuance for a trust-line
|
||||
* balance move of `amount` from `sender` to `receiver`. Only the amount's
|
||||
* issuer is adjusted: balance moving away from the issuer increases its
|
||||
* net issuance, balance returning decreases it.
|
||||
*
|
||||
* No-op when the amendment is disabled, neither party is the issuer, or no
|
||||
* TokenIssuance exists. Returns tecSUPPLY_EXCEEDED when the cap is enforced
|
||||
* and a capped issuer would exceed MaximumAmount.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
adjustTokenIssuance(
|
||||
ApplyView& view,
|
||||
AccountID const& sender,
|
||||
AccountID const& receiver,
|
||||
STAmount const& amount,
|
||||
EnforceSupplyCap enforceCap,
|
||||
beast::Journal j);
|
||||
|
||||
/**
|
||||
* Remaining IOU the issuer can issue under the supply cap, floored to the
|
||||
* representable amount; nullopt when there is no TokenIssuance or no cap.
|
||||
*/
|
||||
[[nodiscard]] std::optional<STAmount>
|
||||
tokenIssuanceHeadroom(ReadView const& view, Issue const& issue);
|
||||
|
||||
/**
|
||||
* True when the issue's TokenIssuance carries the per-currency lock
|
||||
* (lsfTokenLocked). The per-currency analog of lsfGlobalFreeze.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
isTokenLocked(ReadView const& view, Issue const& issue);
|
||||
|
||||
/**
|
||||
* For an MPT issuance bound to a capped TokenIssuance: the additional MPT
|
||||
* base units that can be minted under the shared cap
|
||||
* (MaximumAmount - OutstandingAmount - ceil(IssuedAmount * 10^TokenScale)).
|
||||
* nullopt when unbound or uncapped.
|
||||
*/
|
||||
[[nodiscard]] std::optional<std::int64_t>
|
||||
mptBoundHeadroom(ReadView const& view, SLE::const_ref sleMptIssuance);
|
||||
|
||||
/**
|
||||
* Validate binding an MPTokenIssuance to a TokenIssuance: the MPT issuance
|
||||
* exists, is issued by `account`, is not already bound, and its
|
||||
* MaximumAmount/AssetScale equal the TokenIssuance's MaximumAmount/
|
||||
* TokenScale.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
validateTokenBinding(
|
||||
ReadView const& view,
|
||||
MPTID const& mptId,
|
||||
AccountID const& account,
|
||||
std::optional<std::uint64_t> const& maximumAmount,
|
||||
std::uint8_t tokenScale);
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -342,6 +342,15 @@ mptokenIssuance(uint256 const& issuanceKey)
|
||||
return {ltMPTOKEN_ISSUANCE, issuanceKey};
|
||||
}
|
||||
|
||||
Keylet
|
||||
tokenIssuance(AccountID const& issuer, Currency const& currency) noexcept;
|
||||
|
||||
inline Keylet
|
||||
tokenIssuance(uint256 const& key)
|
||||
{
|
||||
return {ltTOKEN_ISSUANCE, key};
|
||||
}
|
||||
|
||||
Keylet
|
||||
mptoken(MPTID const& issuanceID, AccountID const& holder) noexcept;
|
||||
|
||||
|
||||
@@ -208,7 +208,13 @@ enum LedgerEntryType : std::uint16_t {
|
||||
\
|
||||
LEDGER_OBJECT(Sponsorship, \
|
||||
LSF_FLAG(lsfSponsorshipRequireSignForFee, 0x00010000) \
|
||||
LSF_FLAG(lsfSponsorshipRequireSignForReserve, 0x00020000))
|
||||
LSF_FLAG(lsfSponsorshipRequireSignForReserve, 0x00020000)) \
|
||||
\
|
||||
LEDGER_OBJECT(TokenIssuance, \
|
||||
LSF_FLAG(lsfTokenLocked, 0x00000001) /* True, per-currency global freeze */ \
|
||||
LSF_FLAG(lsfTokenCannotLock, 0x00000002) /* True, issuer renounced the per-currency lock */ \
|
||||
LSF_FLAG(lsfTokenWrapped, 0x00000004) /* True, owned by a pseudo-account (blackholed issuer) */ \
|
||||
LSF_FLAG(lsfTokenVerifiedSupply, 0x00000008)) /* True, IssuedAmount reflects verified legacy supply */
|
||||
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -376,6 +376,20 @@ constexpr std::uint32_t kMaxInvestmentPeriod = std::chrono::seconds{std::chrono:
|
||||
*/
|
||||
constexpr std::uint8_t kMaxAssetCheckDepth = 5;
|
||||
|
||||
/**
|
||||
* Maximum MaximumAmount of a TokenIssuance, in base units (10^15). Bounded
|
||||
* to what Number/STAmount arithmetic represents exactly, so the supply-cap
|
||||
* comparison can never be affected by mantissa rounding.
|
||||
*/
|
||||
constexpr std::uint64_t kMaxTokenIssuanceAmount = 1'000'000'000'000'000ull;
|
||||
static_assert(kMaxTokenIssuanceAmount <= kMaxMpTokenAmount);
|
||||
|
||||
/**
|
||||
* Maximum TokenScale of a TokenIssuance: 10^scale must stay in exact int64
|
||||
* range. 10^19 > 2^63-1 > 10^18
|
||||
*/
|
||||
constexpr std::uint8_t kMaxTokenIssuanceScale = 18;
|
||||
|
||||
/**
|
||||
* A ledger index.
|
||||
*/
|
||||
|
||||
@@ -377,6 +377,7 @@ enum TECcodes : TERUnderlyingType {
|
||||
tecNO_SPONSOR_PERMISSION = 200,
|
||||
tecOUT_OF_GAS = 201,
|
||||
tecBYTECODE_REJECTED = 202,
|
||||
tecSUPPLY_EXCEEDED = 203,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -162,6 +162,16 @@ inline constexpr FlagValue tfUniversalMask = ~tfUniversal;
|
||||
TF_FLAG(tfMPTSetCanHoldConfidentialBalance, 0x00000100), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(TokenIssuanceCreate, \
|
||||
TF_FLAG(tfTokenCannotLock, 0x00000001), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(TokenIssuanceSet, \
|
||||
TF_FLAG2(tfTokenCannotLock, 0x00000001) \
|
||||
TF_FLAG(tfTokenLock, 0x00000002) \
|
||||
TF_FLAG(tfTokenUnlock, 0x00000004), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(NFTokenCreateOffer, \
|
||||
TF_FLAG(tfSellNFToken, 0x00000001), \
|
||||
MASK_ADJ(0)) \
|
||||
|
||||
@@ -17,25 +17,27 @@ enum class Delegation { Delegable, NotDelegable };
|
||||
* TxSettings::privileges) and enforced in InvariantCheck.cpp.
|
||||
*/
|
||||
enum class Privilege : std::uint16_t {
|
||||
NoPriv = 0x0000, // The transaction can not do any of the enumerated operations
|
||||
CreateAcct = 0x0001, // The transaction can create a new ACCOUNT_ROOT object.
|
||||
CreatePseudoAcct = 0x0002, // The transaction can create a pseudo account,
|
||||
// which implies createAcct
|
||||
MustDeleteAcct = 0x0004, // The transaction must delete an ACCOUNT_ROOT object
|
||||
MayDeleteAcct = 0x0008, // The transaction may delete an ACCOUNT_ROOT
|
||||
// object, but does not have to
|
||||
OverrideFreeze = 0x0010, // The transaction can override some freeze rules
|
||||
ChangeNftCounts = 0x0020, // The transaction can mint or burn an NFT
|
||||
CreateMptIssuance = 0x0040, // The transaction can create a new MPT issuance
|
||||
DestroyMptIssuance = 0x0080, // The transaction can destroy an MPT issuance
|
||||
MustAuthorizeMpt = 0x0100, // The transaction MUST create or delete an MPT
|
||||
// object (except by issuer)
|
||||
MayAuthorizeMpt = 0x0200, // The transaction MAY create or delete an MPT
|
||||
// object (except by issuer)
|
||||
MayDeleteMpt = 0x0400, // The transaction MAY delete an MPT object. May not create.
|
||||
MustModifyVault = 0x0800, // The transaction must modify, delete or create, a vault
|
||||
MayModifyVault = 0x1000, // The transaction MAY modify, delete or create, a vault
|
||||
MayCreateMpt = 0x2000, // The transaction MAY create an MPT object, except for issuer.
|
||||
NoPriv = 0x0000, // The transaction can not do any of the enumerated operations
|
||||
CreateAcct = 0x0001, // The transaction can create a new ACCOUNT_ROOT object.
|
||||
CreatePseudoAcct = 0x0002, // The transaction can create a pseudo account,
|
||||
// which implies createAcct
|
||||
MustDeleteAcct = 0x0004, // The transaction must delete an ACCOUNT_ROOT object
|
||||
MayDeleteAcct = 0x0008, // The transaction may delete an ACCOUNT_ROOT
|
||||
// object, but does not have to
|
||||
OverrideFreeze = 0x0010, // The transaction can override some freeze rules
|
||||
ChangeNftCounts = 0x0020, // The transaction can mint or burn an NFT
|
||||
CreateMptIssuance = 0x0040, // The transaction can create a new MPT issuance
|
||||
DestroyMptIssuance = 0x0080, // The transaction can destroy an MPT issuance
|
||||
MustAuthorizeMpt = 0x0100, // The transaction MUST create or delete an MPT
|
||||
// object (except by issuer)
|
||||
MayAuthorizeMpt = 0x0200, // The transaction MAY create or delete an MPT
|
||||
// object (except by issuer)
|
||||
MayDeleteMpt = 0x0400, // The transaction MAY delete an MPT object. May not create.
|
||||
MustModifyVault = 0x0800, // The transaction must modify, delete or create, a vault
|
||||
MayModifyVault = 0x1000, // The transaction MAY modify, delete or create, a vault
|
||||
MayCreateMpt = 0x2000, // The transaction MAY create an MPT object, except for issuer.
|
||||
CreateTokenIssuance = 0x4000, // The transaction can create a new token issuance
|
||||
DestroyTokenIssuance = 0x8000, // The transaction can destroy a token issuance
|
||||
};
|
||||
|
||||
// The inner static_cast is not redundant: the underlying type is narrower than
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
// Add new amendments to the top of this list.
|
||||
// Keep it sorted in reverse chronological order.
|
||||
|
||||
XRPL_FEATURE(TokenIssuance, Supported::No, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(SmartEscrow, Supported::No, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(LendingProtocolV1_2, Supported::No, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (Cleanup3_5_0, Supported::Yes, VoteBehavior::DefaultNo)
|
||||
|
||||
@@ -418,6 +418,7 @@ LEDGER_ENTRY(ltMPTOKEN_ISSUANCE, 0x007e, MPTokenIssuance, mpt_issuance, ({
|
||||
{sfIssuerKeyEpoch, SoeOptional},
|
||||
{sfAuditorKeyEpoch, SoeOptional},
|
||||
{sfConfidentialOutstandingAmount, SoeDefault},
|
||||
{sfTokenIssuanceID, SoeOptional},
|
||||
}))
|
||||
|
||||
/** A ledger object which tracks MPToken
|
||||
@@ -649,5 +650,22 @@ LEDGER_ENTRY(ltSPONSORSHIP, 0x0090, Sponsorship, sponsorship, ({
|
||||
{sfSponseeNode, SoeRequired},
|
||||
}))
|
||||
|
||||
/** A ledger object which describes an IOU token issuance.
|
||||
\sa keylet::tokenIssuance
|
||||
*/
|
||||
LEDGER_ENTRY(ltTOKEN_ISSUANCE, 0x0091, TokenIssuance, token_issuance, ({
|
||||
{sfIssuer, SoeRequired},
|
||||
{sfCurrency, SoeRequired},
|
||||
{sfMaximumAmount, SoeOptional},
|
||||
{sfIssuedAmount, SoeDefault},
|
||||
{sfTokenScale, SoeDefault},
|
||||
{sfMPTokenIssuanceID, SoeOptional},
|
||||
{sfTransferFee, SoeOptional},
|
||||
{sfMPTokenMetadata, SoeOptional},
|
||||
{sfOwnerNode, SoeRequired},
|
||||
{sfPreviousTxnID, SoeRequired},
|
||||
{sfPreviousTxnLgrSeq, SoeRequired},
|
||||
}))
|
||||
|
||||
#undef EXPAND
|
||||
#undef LEDGER_ENTRY_DUPLICATE
|
||||
|
||||
@@ -19,6 +19,7 @@ TYPED_SFIELD(sfTransactionResult, UINT8, 3)
|
||||
TYPED_SFIELD(sfScale, UINT8, 4)
|
||||
TYPED_SFIELD(sfAssetScale, UINT8, 5)
|
||||
TYPED_SFIELD(sfLEVersion, UINT8, 6)
|
||||
TYPED_SFIELD(sfTokenScale, UINT8, 7)
|
||||
|
||||
// 8-bit integers (uncommon)
|
||||
TYPED_SFIELD(sfTickSize, UINT8, 16)
|
||||
@@ -220,6 +221,7 @@ TYPED_SFIELD(sfLoanID, UINT256, 38)
|
||||
TYPED_SFIELD(sfReferenceHolding, UINT256, 39)
|
||||
TYPED_SFIELD(sfBlindingFactor, UINT256, 40)
|
||||
TYPED_SFIELD(sfObjectID, UINT256, 41)
|
||||
TYPED_SFIELD(sfTokenIssuanceID, UINT256, 42)
|
||||
|
||||
// number (common)
|
||||
TYPED_SFIELD(sfNumber, NUMBER, 1)
|
||||
@@ -239,6 +241,7 @@ TYPED_SFIELD(sfPrincipalRequested, NUMBER, 14)
|
||||
TYPED_SFIELD(sfTotalValueOutstanding, NUMBER, 15, SField::kSmdNeedsAsset | SField::kSmdDefault)
|
||||
TYPED_SFIELD(sfPeriodicPayment, NUMBER, 16)
|
||||
TYPED_SFIELD(sfManagementFeeOutstanding, NUMBER, 17, SField::kSmdNeedsAsset | SField::kSmdDefault)
|
||||
TYPED_SFIELD(sfIssuedAmount, NUMBER, 18, SField::kSmdNeedsAsset | SField::kSmdDefault)
|
||||
|
||||
// 32-bit signed (common)
|
||||
TYPED_SFIELD(sfLoanScale, INT32, 1)
|
||||
@@ -374,6 +377,7 @@ UNTYPED_SFIELD(sfPaths, PATHSET, 1)
|
||||
// currency
|
||||
TYPED_SFIELD(sfBaseAsset, CURRENCY, 1)
|
||||
TYPED_SFIELD(sfQuoteAsset, CURRENCY, 2)
|
||||
TYPED_SFIELD(sfCurrency, CURRENCY, 3)
|
||||
|
||||
// issue
|
||||
TYPED_SFIELD(sfLockingChainIssue, ISSUE, 1)
|
||||
|
||||
@@ -1134,6 +1134,60 @@ TRANSACTION(ttSPONSORSHIP_SET, 91, SponsorshipSet,
|
||||
{sfRemainingOwnerCountDelta, SoeOptional},
|
||||
}))
|
||||
|
||||
/** This transaction type creates a TokenIssuance object. */
|
||||
#if TRANSACTION_INCLUDE
|
||||
# include <xrpl/tx/transactors/token/TokenIssuanceCreate.h>
|
||||
#endif
|
||||
TRANSACTION(ttTOKEN_ISSUANCE_CREATE, 92, TokenIssuanceCreate,
|
||||
({
|
||||
.amendment = featureTokenIssuance,
|
||||
.privileges = Privilege::CreateTokenIssuance,
|
||||
}),
|
||||
({
|
||||
{sfCurrency, SoeRequired},
|
||||
{sfMaximumAmount, SoeOptional},
|
||||
{sfTokenScale, SoeOptional},
|
||||
{sfMPTokenIssuanceID, SoeOptional},
|
||||
{sfTransferFee, SoeOptional},
|
||||
{sfMPTokenMetadata, SoeOptional},
|
||||
}))
|
||||
|
||||
/** This transaction type modifies a TokenIssuance object. */
|
||||
#if TRANSACTION_INCLUDE
|
||||
# include <xrpl/tx/transactors/token/TokenIssuanceSet.h>
|
||||
#endif
|
||||
TRANSACTION(ttTOKEN_ISSUANCE_SET, 93, TokenIssuanceSet,
|
||||
({.amendment = featureTokenIssuance}),
|
||||
({
|
||||
{sfCurrency, SoeRequired},
|
||||
{sfMPTokenIssuanceID, SoeOptional},
|
||||
{sfTransferFee, SoeOptional},
|
||||
{sfMPTokenMetadata, SoeOptional},
|
||||
}))
|
||||
|
||||
/** This transaction type destroys a TokenIssuance object. */
|
||||
#if TRANSACTION_INCLUDE
|
||||
# include <xrpl/tx/transactors/token/TokenIssuanceDestroy.h>
|
||||
#endif
|
||||
TRANSACTION(ttTOKEN_ISSUANCE_DESTROY, 94, TokenIssuanceDestroy,
|
||||
({
|
||||
.amendment = featureTokenIssuance,
|
||||
.privileges = Privilege::DestroyTokenIssuance,
|
||||
}),
|
||||
({
|
||||
{sfCurrency, SoeRequired},
|
||||
}))
|
||||
|
||||
/** This transaction type converts between an IOU and its bound MPT. */
|
||||
#if TRANSACTION_INCLUDE
|
||||
# include <xrpl/tx/transactors/token/TokenConvert.h>
|
||||
#endif
|
||||
TRANSACTION(ttTOKEN_CONVERT, 95, TokenConvert,
|
||||
({.amendment = featureTokenIssuance}),
|
||||
({
|
||||
{sfAmount, SoeRequired, SoeMptSupported},
|
||||
}))
|
||||
|
||||
/** This system-generated transaction type is used to update the status of the various amendments.
|
||||
|
||||
For details, see: https://xrpl.org/amendments.html
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <xrpl/tx/invariants/PermissionedDEXInvariant.h>
|
||||
#include <xrpl/tx/invariants/PermissionedDomainInvariant.h>
|
||||
#include <xrpl/tx/invariants/SponsorshipInvariant.h>
|
||||
#include <xrpl/tx/invariants/TokenIssuanceInvariant.h>
|
||||
#include <xrpl/tx/invariants/VaultInvariant.h>
|
||||
|
||||
#include <cstdint>
|
||||
@@ -463,7 +464,8 @@ using InvariantChecks = std::tuple<
|
||||
ValidMPTTransfer,
|
||||
ObjectHasPseudoAccount,
|
||||
SponsorshipOwnerCountsMatch,
|
||||
SponsorshipAccountCountMatchesField>;
|
||||
SponsorshipAccountCountMatchesField,
|
||||
ValidTokenIssuance>;
|
||||
|
||||
/**
|
||||
* @brief get a tuple of all invariant checks
|
||||
|
||||
48
include/xrpl/tx/invariants/TokenIssuanceInvariant.h
Normal file
48
include/xrpl/tx/invariants/TokenIssuanceInvariant.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* Invariants for TokenIssuance objects:
|
||||
*
|
||||
* - created/deleted only by transactions carrying the matching privilege,
|
||||
* and the privileged transactions create/delete exactly one
|
||||
* - MaximumAmount, TokenScale, Issuer, and Currency never change; the
|
||||
* MPT binding is write-once
|
||||
* - a capped issuance never exceeds
|
||||
* ceil(IssuedAmount * 10^TokenScale) + MPT OutstandingAmount
|
||||
* <= MaximumAmount after application
|
||||
* - deletion only with IssuedAmount == 0
|
||||
*/
|
||||
class ValidTokenIssuance
|
||||
{
|
||||
std::uint32_t created_ = 0;
|
||||
std::uint32_t deleted_ = 0;
|
||||
bool immutableChanged_ = false;
|
||||
std::vector<SLE::const_pointer> after_;
|
||||
std::vector<SLE::const_pointer> deletedIssuances_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after);
|
||||
|
||||
[[nodiscard]] bool
|
||||
finalize(
|
||||
STTx const& tx,
|
||||
TER const result,
|
||||
XRPAmount const fee,
|
||||
ReadView const& view,
|
||||
beast::Journal const& j);
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/helpers/TokenIssuanceHelpers.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
@@ -33,6 +34,13 @@ checkFreeze(
|
||||
}
|
||||
}
|
||||
|
||||
// The per-currency lock behaves like a global freeze scoped to one
|
||||
// currency of the issuer.
|
||||
if (isTokenLocked(view, Issue{currency, dst}))
|
||||
{
|
||||
return terNO_LINE;
|
||||
}
|
||||
|
||||
if (auto sle = view.read(keylet::trustLine(src, dst, currency)))
|
||||
{
|
||||
if (sle->isFlag((dst > src) ? lsfHighFreeze : lsfLowFreeze))
|
||||
|
||||
47
include/xrpl/tx/transactors/token/TokenConvert.h
Normal file
47
include/xrpl/tx/transactors/token/TokenConvert.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/tx/ApplyContext.h>
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class TokenConvert : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr auto kConsequencesFactory = ConsequencesFactoryType::Normal;
|
||||
|
||||
explicit TokenConvert(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
checkExtraFeatures(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
|
||||
void
|
||||
visitInvariantEntry(bool, SLE::const_ref, SLE::const_ref) override
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
52
include/xrpl/tx/transactors/token/TokenIssuanceCreate.h
Normal file
52
include/xrpl/tx/transactors/token/TokenIssuanceCreate.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/tx/ApplyContext.h>
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class TokenIssuanceCreate : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr auto kConsequencesFactory = ConsequencesFactoryType::Normal;
|
||||
|
||||
explicit TokenIssuanceCreate(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
checkExtraFeatures(PreflightContext const& ctx);
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
|
||||
void
|
||||
visitInvariantEntry(bool, SLE::const_ref, SLE::const_ref) override
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
44
include/xrpl/tx/transactors/token/TokenIssuanceDestroy.h
Normal file
44
include/xrpl/tx/transactors/token/TokenIssuanceDestroy.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/tx/ApplyContext.h>
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class TokenIssuanceDestroy : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr auto kConsequencesFactory = ConsequencesFactoryType::Normal;
|
||||
|
||||
explicit TokenIssuanceDestroy(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
|
||||
void
|
||||
visitInvariantEntry(bool, SLE::const_ref, SLE::const_ref) override
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
52
include/xrpl/tx/transactors/token/TokenIssuanceSet.h
Normal file
52
include/xrpl/tx/transactors/token/TokenIssuanceSet.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/tx/ApplyContext.h>
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class TokenIssuanceSet : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr auto kConsequencesFactory = ConsequencesFactoryType::Normal;
|
||||
|
||||
explicit TokenIssuanceSet(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
checkExtraFeatures(PreflightContext const& ctx);
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
|
||||
void
|
||||
visitInvariantEntry(bool, SLE::const_ref, SLE::const_ref) override
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
Reference in New Issue
Block a user