mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
initial implementation of token holders
This commit is contained in:
96
include/xrpl/ledger/helpers/MPToken.h
Normal file
96
include/xrpl/ledger/helpers/MPToken.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHolderBase.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class MPToken : public virtual TokenHolderBase
|
||||
{
|
||||
public:
|
||||
MPToken(ReadView const& view, MPTokenIssuance const& issuance, AccountID const& holder)
|
||||
: ReadOnlySLE(view.read(keylet::mptoken(issuance.getMptID(), holder)), view)
|
||||
, TokenHolderBase(
|
||||
view,
|
||||
view.read(keylet::mptoken(issuance.getMptID(), holder)),
|
||||
issuance,
|
||||
holder)
|
||||
, issuance_(issuance)
|
||||
{
|
||||
}
|
||||
|
||||
MPTokenIssuance const&
|
||||
getIssuance() const
|
||||
{
|
||||
return issuance_;
|
||||
}
|
||||
|
||||
protected:
|
||||
MPTokenIssuance const& issuance_;
|
||||
};
|
||||
|
||||
class WritableMPToken : public virtual WritableTokenHolderBase, public virtual MPToken
|
||||
{
|
||||
public:
|
||||
WritableMPToken(ApplyView& view, WritableMPTokenIssuance& issuance, AccountID const& holder)
|
||||
: ReadOnlySLE(view.peek(keylet::mptoken(issuance.getMptID(), holder)), view)
|
||||
, TokenHolderBase(
|
||||
view,
|
||||
view.peek(keylet::mptoken(issuance.getMptID(), holder)),
|
||||
issuance,
|
||||
holder)
|
||||
, WritableSLE(view.peek(keylet::mptoken(issuance.getMptID(), holder)), view)
|
||||
, WritableTokenHolderBase(
|
||||
view,
|
||||
view.peek(keylet::mptoken(issuance.getMptID(), holder)),
|
||||
issuance,
|
||||
holder)
|
||||
, MPToken(view, issuance, holder)
|
||||
, writableIssuance_(issuance)
|
||||
{
|
||||
}
|
||||
|
||||
// Resolve ambiguity: use writable operator-> for non-const, read-only for const
|
||||
using WritableSLE::operator->;
|
||||
using MPToken::operator->;
|
||||
using WritableSLE::operator*;
|
||||
using MPToken::operator*;
|
||||
|
||||
WritableMPTokenIssuance&
|
||||
getWritableIssuance()
|
||||
{
|
||||
return writableIssuance_;
|
||||
}
|
||||
|
||||
static TER
|
||||
createMPToken(
|
||||
ApplyView& view,
|
||||
WritableMPTokenIssuance& issuance,
|
||||
AccountID const& account,
|
||||
std::uint32_t const flags)
|
||||
{
|
||||
WritableMPToken mptoken(view, issuance, account);
|
||||
|
||||
auto const ownerNode =
|
||||
view.dirInsert(keylet::ownerDir(account), mptoken.key(), describeOwnerDir(account));
|
||||
|
||||
if (!ownerNode)
|
||||
return tecDIR_FULL; // LCOV_EXCL_LINE
|
||||
|
||||
mptoken.newSLE();
|
||||
|
||||
(*mptoken)[sfAccount] = account;
|
||||
(*mptoken)[sfMPTokenIssuanceID] = issuance.getMptID();
|
||||
(*mptoken)[sfFlags] = flags;
|
||||
(*mptoken)[sfOwnerNode] = *ownerNode;
|
||||
|
||||
mptoken.insert();
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
protected:
|
||||
WritableMPTokenIssuance& writableIssuance_;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
146
include/xrpl/ledger/helpers/RippleState.h
Normal file
146
include/xrpl/ledger/helpers/RippleState.h
Normal file
@@ -0,0 +1,146 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Expected.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHolderBase.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class RippleState : public virtual TokenHolderBase
|
||||
{
|
||||
public:
|
||||
RippleState(ReadView const& view, IOUToken const& token, AccountID const& holder)
|
||||
: ReadOnlySLE(view.read(keylet::line(holder, token.getIssuer(), token.getCurrency())), view)
|
||||
, TokenHolderBase(
|
||||
view,
|
||||
view.read(keylet::line(holder, token.getIssuer(), token.getCurrency())),
|
||||
token,
|
||||
holder)
|
||||
, iouToken_(token)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor with explicit SLE (for when SLE is already available) */
|
||||
RippleState(
|
||||
ReadView const& view,
|
||||
std::shared_ptr<SLE const> sle,
|
||||
IOUToken const& token,
|
||||
AccountID const& holder)
|
||||
: ReadOnlySLE(sle, view), TokenHolderBase(view, sle, token, holder), iouToken_(token)
|
||||
{
|
||||
}
|
||||
|
||||
IOUToken const&
|
||||
getIOUToken() const
|
||||
{
|
||||
return iouToken_;
|
||||
}
|
||||
|
||||
protected:
|
||||
IOUToken const& iouToken_;
|
||||
};
|
||||
|
||||
class WritableRippleState : public virtual WritableTokenHolderBase, public virtual RippleState
|
||||
{
|
||||
public:
|
||||
WritableRippleState(ApplyView& view, WritableIOUToken& token, AccountID const& holder)
|
||||
: ReadOnlySLE(view.peek(keylet::line(holder, token.getIssuer(), token.getCurrency())), view)
|
||||
, TokenHolderBase(
|
||||
view,
|
||||
view.peek(keylet::line(holder, token.getIssuer(), token.getCurrency())),
|
||||
token,
|
||||
holder)
|
||||
, WritableSLE(view.peek(keylet::line(holder, token.getIssuer(), token.getCurrency())), view)
|
||||
, WritableTokenHolderBase(
|
||||
view,
|
||||
view.peek(keylet::line(holder, token.getIssuer(), token.getCurrency())),
|
||||
token,
|
||||
holder)
|
||||
, RippleState(view, token, holder)
|
||||
, writableIOUToken_(token)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor with explicit SLE (for creation or when SLE is already available) */
|
||||
WritableRippleState(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> sle,
|
||||
WritableIOUToken& token,
|
||||
AccountID const& holder)
|
||||
: ReadOnlySLE(sle, view)
|
||||
, TokenHolderBase(view, sle, token, holder)
|
||||
, WritableSLE(sle, view)
|
||||
, WritableTokenHolderBase(view, sle, token, holder)
|
||||
, RippleState(view, sle, token, holder)
|
||||
, writableIOUToken_(token)
|
||||
{
|
||||
}
|
||||
|
||||
// Resolve ambiguity: use writable operator-> for non-const, read-only for const
|
||||
using WritableSLE::operator->;
|
||||
using RippleState::operator->;
|
||||
using WritableSLE::operator*;
|
||||
using RippleState::operator*;
|
||||
|
||||
WritableIOUToken&
|
||||
getWritableIOUToken()
|
||||
{
|
||||
return writableIOUToken_;
|
||||
}
|
||||
|
||||
static Expected<std::unique_ptr<WritableRippleState>, TER>
|
||||
createHolding(
|
||||
ApplyView& view,
|
||||
WritableIOUToken& token,
|
||||
AccountID const& accountID,
|
||||
beast::Journal journal)
|
||||
{
|
||||
auto const ter = token.addEmptyHolding(accountID, XRPAmount{0}, journal);
|
||||
if (ter != tesSUCCESS)
|
||||
return Unexpected(ter);
|
||||
return std::make_unique<WritableRippleState>(view, token, accountID);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Trust line operations
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Create a trust line
|
||||
|
||||
This can set an initial balance.
|
||||
*/
|
||||
[[nodiscard]] static TER
|
||||
trustCreate(
|
||||
ApplyView& view,
|
||||
bool const bSrcHigh,
|
||||
AccountID const& uSrcAccountID,
|
||||
AccountID const& uDstAccountID,
|
||||
uint256 const& uIndex, // ripple state entry
|
||||
WritableAccountRoot& wrappedAcct, // the account being set.
|
||||
bool const bAuth, // authorize account.
|
||||
bool const bNoRipple, // others cannot ripple through
|
||||
bool const bFreeze, // funds cannot leave
|
||||
bool bDeepFreeze, // can neither receive nor send funds
|
||||
STAmount const& saBalance, // balance of account being set.
|
||||
// Issuer should be noAccount()
|
||||
STAmount const& saLimit, // limit for account being set.
|
||||
// Issuer should be the account being set.
|
||||
std::uint32_t uQualityIn,
|
||||
std::uint32_t uQualityOut,
|
||||
beast::Journal j);
|
||||
|
||||
[[nodiscard]] static TER
|
||||
trustDelete(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> const& sleRippleState,
|
||||
AccountID const& uLowAccountID,
|
||||
AccountID const& uHighAccountID,
|
||||
beast::Journal j);
|
||||
|
||||
protected:
|
||||
WritableIOUToken& writableIOUToken_;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -216,44 +216,6 @@ creditBalance(
|
||||
Currency const& currency);
|
||||
/** @} */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Trust line operations
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Create a trust line
|
||||
|
||||
This can set an initial balance.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
trustCreate(
|
||||
ApplyView& view,
|
||||
bool const bSrcHigh,
|
||||
AccountID const& uSrcAccountID,
|
||||
AccountID const& uDstAccountID,
|
||||
uint256 const& uIndex, // ripple state entry
|
||||
WritableAccountRoot& wrappedAcct, // the account being set.
|
||||
bool const bAuth, // authorize account.
|
||||
bool const bNoRipple, // others cannot ripple through
|
||||
bool const bFreeze, // funds cannot leave
|
||||
bool bDeepFreeze, // can neither receive nor send funds
|
||||
STAmount const& saBalance, // balance of account being set.
|
||||
// Issuer should be noAccount()
|
||||
STAmount const& saLimit, // limit for account being set.
|
||||
// Issuer should be the account being set.
|
||||
std::uint32_t uQualityIn,
|
||||
std::uint32_t uQualityOut,
|
||||
beast::Journal j);
|
||||
|
||||
[[nodiscard]] TER
|
||||
trustDelete(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> const& sleRippleState,
|
||||
AccountID const& uLowAccountID,
|
||||
AccountID const& uHighAccountID,
|
||||
beast::Journal j);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// IOU issuance/redemption
|
||||
|
||||
155
include/xrpl/ledger/helpers/TokenHolderBase.h
Normal file
155
include/xrpl/ledger/helpers/TokenHolderBase.h
Normal file
@@ -0,0 +1,155 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/WrappedSLEBase.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class TokenHolderBase : public virtual ReadOnlySLE
|
||||
{
|
||||
public:
|
||||
TokenHolderBase(
|
||||
ReadView const& view,
|
||||
std::shared_ptr<SLE const> sle,
|
||||
TokenBase const& token,
|
||||
AccountID const& holder)
|
||||
: ReadOnlySLE(sle, view), token_(token), holder_(holder), holderAccount_(holder, view)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor with explicit keylet (for when SLE lookup is needed) */
|
||||
TokenHolderBase(
|
||||
ReadView const& view,
|
||||
Keylet const& key,
|
||||
TokenBase const& token,
|
||||
AccountID const& holder)
|
||||
: ReadOnlySLE(key, view), token_(token), holder_(holder), holderAccount_(holder, view)
|
||||
{
|
||||
}
|
||||
|
||||
TokenHolderBase() = delete;
|
||||
|
||||
AccountID const&
|
||||
getHolder() const
|
||||
{
|
||||
return holder_;
|
||||
}
|
||||
|
||||
TokenBase const&
|
||||
getToken() const
|
||||
{
|
||||
return token_;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
isFrozen(int depth = 0) const
|
||||
{
|
||||
return token_.isFrozen(holder_, depth);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
isDeepFrozen(int depth = 0) const
|
||||
{
|
||||
return token_.isDeepFrozen(holder_, depth);
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
checkFrozen() const
|
||||
{
|
||||
return token_.checkFrozen(holder_);
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
checkDeepFrozen() const
|
||||
{
|
||||
return token_.checkDeepFrozen(holder_);
|
||||
}
|
||||
|
||||
STAmount
|
||||
accountHolds(
|
||||
FreezeHandling zeroIfFrozen,
|
||||
beast::Journal j,
|
||||
SpendableHandling includeFullBalance = shSIMPLE_BALANCE) const
|
||||
{
|
||||
return token_.accountHolds(holder_, zeroIfFrozen, j, includeFullBalance);
|
||||
}
|
||||
|
||||
[[nodiscard]] STAmount
|
||||
accountHolds(
|
||||
FreezeHandling zeroIfFrozen,
|
||||
AuthHandling zeroIfUnauthorized,
|
||||
beast::Journal j,
|
||||
SpendableHandling includeFullBalance = shSIMPLE_BALANCE) const
|
||||
{
|
||||
return token_.accountHolds(
|
||||
holder_, zeroIfFrozen, zeroIfUnauthorized, j, includeFullBalance);
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
requireAuth(AuthType authType = AuthType::Legacy, int depth = 0) const
|
||||
{
|
||||
return token_.requireAuth(holder_, authType, depth);
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
canTransfer(AccountID const& to) const
|
||||
{
|
||||
return token_.canTransfer(holder_, to);
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
canTransfer(TokenHolderBase const& to) const
|
||||
{
|
||||
return token_.canTransfer(holder_, to.getHolder());
|
||||
}
|
||||
|
||||
protected:
|
||||
TokenBase const& token_;
|
||||
AccountID const holder_;
|
||||
AccountRoot holderAccount_;
|
||||
};
|
||||
|
||||
class WritableTokenHolderBase : public virtual TokenHolderBase, public virtual WritableSLE
|
||||
{
|
||||
public:
|
||||
WritableTokenHolderBase(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> sle,
|
||||
WritableTokenBase& token,
|
||||
AccountID const& holder)
|
||||
: ReadOnlySLE(sle, view)
|
||||
, TokenHolderBase(view, sle, token, holder)
|
||||
, WritableSLE(sle, view)
|
||||
, writableToken_(token)
|
||||
, writableHolderAccount_(holder, view)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor with explicit keylet (for creation or lookup by key) */
|
||||
WritableTokenHolderBase(
|
||||
ApplyView& view,
|
||||
Keylet const& key,
|
||||
WritableTokenBase& token,
|
||||
AccountID const& holder)
|
||||
: ReadOnlySLE(key, view)
|
||||
, TokenHolderBase(view, key, token, holder)
|
||||
, WritableSLE(key, view)
|
||||
, writableToken_(token)
|
||||
, writableHolderAccount_(holder, view)
|
||||
{
|
||||
}
|
||||
|
||||
WritableTokenBase&
|
||||
getWritableToken()
|
||||
{
|
||||
return writableToken_;
|
||||
}
|
||||
|
||||
protected:
|
||||
WritableTokenBase& writableToken_;
|
||||
WritableAccountRoot writableHolderAccount_;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -60,6 +60,12 @@ public:
|
||||
return readView_;
|
||||
}
|
||||
|
||||
Keylet const&
|
||||
key() const
|
||||
{
|
||||
return key_;
|
||||
}
|
||||
|
||||
STLedgerEntry const*
|
||||
operator->() const
|
||||
{
|
||||
@@ -80,12 +86,21 @@ protected:
|
||||
|
||||
/** Constructor for read-only context (ReadView) */
|
||||
explicit ReadOnlySLE(std::shared_ptr<SLE const> sle, ReadView const& view)
|
||||
: sle_(std::move(sle)), readView_(view)
|
||||
: sle_(std::move(sle))
|
||||
, readView_(view)
|
||||
, key_(sle_ ? Keylet(sle_->getType(), sle_->key()) : Keylet(ltANY, uint256{}))
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor for read-only context (ReadView) with explicit keylet */
|
||||
explicit ReadOnlySLE(Keylet const& key, ReadView const& view)
|
||||
: sle_(view.read(key)), readView_(view), key_(key)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<SLE const> sle_; // Always valid (const view)
|
||||
ReadView const& readView_; // Always valid
|
||||
Keylet key_; // Keylet for this entry
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -192,8 +207,8 @@ protected:
|
||||
{
|
||||
}
|
||||
|
||||
ApplyView& applyView_; // ApplyView for write contexts (first for init order)
|
||||
Keylet const key_;
|
||||
ApplyView& applyView_; // ApplyView for write contexts (first for init order)
|
||||
Keylet key_; // Keylet for this entry
|
||||
std::shared_ptr<SLE> mutableSle_; // Mutable SLE for write contexts
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleState.h>
|
||||
#include <xrpl/protocol/AmountConversions.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
@@ -301,7 +302,7 @@ IOUToken::transferRate() const
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
TER
|
||||
trustCreate(
|
||||
WritableRippleState::trustCreate(
|
||||
ApplyView& view,
|
||||
bool const bSrcHigh,
|
||||
AccountID const& uSrcAccountID,
|
||||
@@ -415,7 +416,7 @@ trustCreate(
|
||||
}
|
||||
|
||||
TER
|
||||
trustDelete(
|
||||
WritableRippleState::trustDelete(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> const& sleRippleState,
|
||||
AccountID const& uLowAccountID,
|
||||
@@ -551,7 +552,7 @@ issueIOU(
|
||||
state->setFieldAmount(sfBalance, final_balance);
|
||||
if (must_delete)
|
||||
{
|
||||
return trustDelete(
|
||||
return WritableRippleState::trustDelete(
|
||||
view,
|
||||
state,
|
||||
bSenderHigh ? account : issue.account,
|
||||
@@ -578,7 +579,7 @@ issueIOU(
|
||||
|
||||
bool noRipple = (receiverAccount->getFlags() & lsfDefaultRipple) == 0;
|
||||
|
||||
return trustCreate(
|
||||
return WritableRippleState::trustCreate(
|
||||
view,
|
||||
bSenderHigh,
|
||||
issue.account,
|
||||
@@ -644,7 +645,7 @@ redeemIOU(
|
||||
|
||||
if (must_delete)
|
||||
{
|
||||
return trustDelete(
|
||||
return WritableRippleState::trustDelete(
|
||||
applyView,
|
||||
state,
|
||||
bSenderHigh ? issue.account : account,
|
||||
@@ -792,7 +793,7 @@ WritableIOUToken::addEmptyHolding(
|
||||
if (priorBalance < readView_.fees().accountReserve(ownerCount + 1))
|
||||
return tecNO_LINE_INSUF_RESERVE;
|
||||
|
||||
return trustCreate(
|
||||
return WritableRippleState::trustCreate(
|
||||
applyView_,
|
||||
high,
|
||||
srcId,
|
||||
@@ -865,7 +866,7 @@ WritableIOUToken::removeEmptyHolding(AccountID const& accountID, beast::Journal
|
||||
line->clearFlag(lsfHighReserve);
|
||||
}
|
||||
|
||||
return trustDelete(
|
||||
return WritableRippleState::trustDelete(
|
||||
applyView_,
|
||||
line,
|
||||
line->at(sfLowLimit)->getIssuer(),
|
||||
@@ -906,7 +907,8 @@ deleteAMMTrustLine(
|
||||
if (ammAccountID && (low != *ammAccountID && high != *ammAccountID))
|
||||
return terNO_AMM;
|
||||
|
||||
if (auto const ter = trustDelete(view, sleState, low, high, j); !isTesSuccess(ter))
|
||||
if (auto const ter = WritableRippleState::trustDelete(view, sleState, low, high, j);
|
||||
!isTesSuccess(ter))
|
||||
{
|
||||
JLOG(j.error()) << "deleteAMMTrustLine: failed to delete the trustline.";
|
||||
return ter;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleState.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
@@ -385,7 +386,7 @@ rippleCreditIOU(
|
||||
|
||||
if (bDelete)
|
||||
{
|
||||
return trustDelete(
|
||||
return WritableRippleState::trustDelete(
|
||||
view,
|
||||
sleRippleState,
|
||||
bSenderHigh ? uReceiverID : uSenderID,
|
||||
@@ -413,7 +414,7 @@ rippleCreditIOU(
|
||||
|
||||
bool const noRipple = (wrappedAccount->getFlags() & lsfDefaultRipple) == 0;
|
||||
|
||||
return trustCreate(
|
||||
return WritableRippleState::trustCreate(
|
||||
view,
|
||||
bSenderHigh,
|
||||
uSenderID,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <xrpl/basics/scope.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleState.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
@@ -335,7 +336,7 @@ CheckCash::doApply()
|
||||
initialBalance.setIssuer(noAccount());
|
||||
|
||||
// clang-format off
|
||||
if (TER const ter = trustCreate(
|
||||
if (TER const ter = WritableRippleState::trustCreate(
|
||||
psb, // payment sandbox
|
||||
destLow, // is dest low?
|
||||
issuer, // source
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleState.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/MPTAmount.h>
|
||||
@@ -76,7 +77,7 @@ escrowUnlockApplyHelper<Issue>(
|
||||
initialBalance.setIssuer(noAccount());
|
||||
|
||||
// clang-format off
|
||||
if (TER const ter = trustCreate(
|
||||
if (TER const ter = WritableRippleState::trustCreate(
|
||||
view, // payment sandbox
|
||||
recvLow, // is dest low?
|
||||
issuer, // source
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPToken.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/TxFlags.h>
|
||||
@@ -28,6 +29,8 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
auto const accountID = ctx.tx[sfAccount];
|
||||
auto const holderID = ctx.tx[~sfHolder];
|
||||
MPTokenIssuance const mptIssuance(ctx.view, ctx.tx[sfMPTokenIssuanceID]);
|
||||
MPToken const mpt(ctx.view, mptIssuance, accountID);
|
||||
|
||||
// if non-issuer account submits this tx, then they are trying either:
|
||||
// 1. Unauthorize/delete MPToken
|
||||
@@ -37,9 +40,6 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx)
|
||||
// `holderID` is NOT used
|
||||
if (!holderID)
|
||||
{
|
||||
std::shared_ptr<SLE const> sleMpt =
|
||||
ctx.view.read(keylet::mptoken(ctx.tx[sfMPTokenIssuanceID], accountID));
|
||||
|
||||
// There is an edge case where all holders have zero balance, issuance
|
||||
// is legally destroyed, then outstanding MPT(s) are deleted afterwards.
|
||||
// Thus, there is no need to check for the existence of the issuance if
|
||||
@@ -49,36 +49,31 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx)
|
||||
// if holder wants to delete/unauthorize a mpt
|
||||
if (ctx.tx.getFlags() & tfMPTUnauthorize)
|
||||
{
|
||||
if (!sleMpt)
|
||||
if (!mpt)
|
||||
return tecOBJECT_NOT_FOUND;
|
||||
|
||||
if ((*sleMpt)[sfMPTAmount] != 0)
|
||||
if ((*mpt)[sfMPTAmount] != 0)
|
||||
{
|
||||
auto const sleMptIssuance =
|
||||
ctx.view.read(keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID]));
|
||||
if (!sleMptIssuance)
|
||||
if (!mptIssuance)
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
return tecHAS_OBLIGATIONS;
|
||||
}
|
||||
|
||||
if ((*sleMpt)[~sfLockedAmount].value_or(0) != 0)
|
||||
if ((*mpt)[~sfLockedAmount].value_or(0) != 0)
|
||||
{
|
||||
auto const sleMptIssuance =
|
||||
ctx.view.read(keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID]));
|
||||
if (!sleMptIssuance)
|
||||
if (!mptIssuance)
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
return tecHAS_OBLIGATIONS;
|
||||
}
|
||||
if (ctx.view.rules().enabled(featureSingleAssetVault) && sleMpt->isFlag(lsfMPTLocked))
|
||||
if (ctx.view.rules().enabled(featureSingleAssetVault) && mpt->isFlag(lsfMPTLocked))
|
||||
return tecNO_PERMISSION;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
// Now test when the holder wants to hold/create/authorize a new MPT
|
||||
MPTokenIssuance const mptIssuance(ctx.view, MPTIssue{ctx.tx[sfMPTokenIssuanceID]});
|
||||
|
||||
if (!mptIssuance)
|
||||
return tecOBJECT_NOT_FOUND;
|
||||
@@ -87,7 +82,7 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx)
|
||||
return tecNO_PERMISSION;
|
||||
|
||||
// if holder wants to use and create a mpt
|
||||
if (sleMpt)
|
||||
if (mpt)
|
||||
return tecDUPLICATE;
|
||||
|
||||
return tesSUCCESS;
|
||||
@@ -96,7 +91,6 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx)
|
||||
if (AccountRoot const acctHolder(*holderID, ctx.view); !acctHolder)
|
||||
return tecNO_DST;
|
||||
|
||||
MPTokenIssuance const mptIssuance(ctx.view, MPTIssue{ctx.tx[sfMPTokenIssuanceID]});
|
||||
if (!mptIssuance)
|
||||
return tecOBJECT_NOT_FOUND;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleState.h>
|
||||
#include <xrpl/protocol/AMMCore.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
@@ -581,7 +582,8 @@ TrustSet::doApply()
|
||||
{
|
||||
// Delete.
|
||||
|
||||
terResult = trustDelete(view(), sleRippleState, uLowAccountID, uHighAccountID, viewJ);
|
||||
terResult = WritableRippleState::trustDelete(
|
||||
view(), sleRippleState, uLowAccountID, uHighAccountID, viewJ);
|
||||
}
|
||||
// Reserve is not scaled by load.
|
||||
else if (bReserveIncrease && preFeeBalance_ < reserveCreate)
|
||||
@@ -632,7 +634,7 @@ TrustSet::doApply()
|
||||
JLOG(j_.trace()) << "doTrustSet: Creating ripple line: " << to_string(k.key);
|
||||
|
||||
// Create a new ripple line.
|
||||
terResult = trustCreate(
|
||||
terResult = WritableRippleState::trustCreate(
|
||||
view(),
|
||||
bHigh,
|
||||
accountID_,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <xrpl/beast/unit_test/suite.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/helpers/RippleState.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/InnerObjectFormats.h>
|
||||
@@ -404,7 +405,7 @@ class Invariants_test : public beast::unit_test::suite
|
||||
STAmount const lowLimit = line->at(sfLowLimit);
|
||||
STAmount const highLimit = line->at(sfHighLimit);
|
||||
BEAST_EXPECT(
|
||||
trustDelete(
|
||||
WritableRippleState::trustDelete(
|
||||
ac.view(),
|
||||
line,
|
||||
lowLimit.getIssuer(),
|
||||
|
||||
Reference in New Issue
Block a user