1#include <xrpl/ledger/helpers/VaultHelpers.h>
3#include <xrpl/basics/Number.h>
4#include <xrpl/beast/utility/Zero.h>
5#include <xrpl/beast/utility/instrumentation.h>
6#include <xrpl/ledger/ReadView.h>
7#include <xrpl/ledger/View.h>
8#include <xrpl/ledger/helpers/CredentialHelpers.h>
9#include <xrpl/protocol/AccountID.h>
10#include <xrpl/protocol/Indexes.h>
11#include <xrpl/protocol/LedgerFormats.h>
12#include <xrpl/protocol/Protocol.h>
13#include <xrpl/protocol/SField.h>
14#include <xrpl/protocol/STAmount.h>
15#include <xrpl/protocol/STLedgerEntry.h>
16#include <xrpl/protocol/STNumber.h>
17#include <xrpl/protocol/STTx.h>
18#include <xrpl/protocol/TER.h>
27[[nodiscard]] std::optional<STAmount>
30 XRPL_ASSERT(!assets.
negative(),
"xrpl::assetsToSharesDeposit : non-negative assets");
32 assets.
asset() == vault->at(sfAsset),
33 "xrpl::assetsToSharesDeposit : assets and vault match");
34 if (assets.
negative() || assets.
asset() != vault->at(sfAsset))
37 Number const assetTotal = vault->at(sfAssetsTotal);
38 STAmount shares{vault->at(sfShareMPTID)};
46 Number const shareTotal = issuance->at(sfOutstandingAmount);
47 shares = ((shareTotal * assets) / assetTotal).truncate();
54 XRPL_ASSERT(!shares.
negative(),
"xrpl::sharesToAssetsDeposit : non-negative shares");
56 shares.
asset() == vault->at(sfShareMPTID),
57 "xrpl::sharesToAssetsDeposit : shares and vault match");
58 if (shares.
negative() || shares.
asset() != vault->at(sfShareMPTID))
61 Number const assetTotal = vault->at(sfAssetsTotal);
69 Number const shareTotal = issuance->at(sfOutstandingAmount);
70 assets = (assetTotal * shares) / shareTotal;
74[[nodiscard]] std::expected<STAmount, TER>
78 delta.
asset() == vault->at(sfAsset),
79 "xrpl::clampToAssetsTotalScale : delta and vault asset match");
81 Asset const asset = vault->at(sfAsset);
88 Number const assetsTotal = vault->at(sfAssetsTotal);
92 int const postScale = [&] {
94 return scale(assetsTotal + delta, asset);
111 Number const posterior = [&] {
113 return assetsTotal + magnitude;
116 Number const roundedPosterior =
118 actualDelta =
STAmount{asset, roundedPosterior - assetsTotal};
122 abs(actualDelta) <=
abs(delta),
123 "xrpl::clampToAssetsTotalScale : actual delta smaller or equal to calculated delta");
136 Number assetTotal = vault->at(sfAssetsTotal);
138 assetTotal -= vault->at(sfLossUnrealized);
158 XRPL_ASSERT(!assets.
negative(),
"xrpl::assetsToSharesWithdraw : non-negative assets");
160 assets.
asset() == vault->at(sfAsset),
161 "xrpl::assetsToSharesWithdraw : assets and vault match");
162 if (assets.
negative() || assets.
asset() != vault->at(sfAsset))
166 STAmount shares{vault->at(sfShareMPTID)};
169 Number const shareTotal = issuance->at(sfOutstandingAmount);
170 Number result = (shareTotal * assets) / assetTotal;
184 XRPL_ASSERT(!shares.
negative(),
"xrpl::sharesToAssetsWithdraw : non-negative shares");
186 shares.
asset() == vault->at(sfShareMPTID),
187 "xrpl::sharesToAssetsWithdraw : shares and vault match");
188 if (shares.
negative() || shares.
asset() != vault->at(sfShareMPTID))
192 STAmount assets{vault->at(sfAsset)};
195 Number const shareTotal = issuance->at(sfOutstandingAmount);
196 assets = (assetTotal * shares) / shareTotal;
204 issuance && issuance->getType() == ltMPTOKEN_ISSUANCE,
205 "xrpl::isSoleShareholder : valid issuance SLE");
207 std::uint64_t const outstanding = issuance->at(sfOutstandingAmount);
208 if (outstanding == 0)
211 auto const shareMPTID =
212 makeMptID(issuance->getFieldU32(sfSequence), issuance->getAccountID(sfIssuer));
217 return sleToken->getFieldU64(sfMPTAmount) == outstanding;
223 XRPL_ASSERT(vault && vault->getType() == ltVAULT,
"xrpl::getVaultVersion : valid Vault sle");
224 if (!vault->isFieldPresent(sfLEVersion))
227 auto const version = vault->at(sfLEVersion);
231 UNREACHABLE(
"xrpl::getVaultVersion : invalid vault version");
253 XRPL_ASSERT(vault && vault->getType() == ltVAULT,
"xrpl::getVaultKind : valid Vault sle");
254 return decodeVaultKind(vault->at(~sfVaultKind));
260 return decodeVaultKind(tx[~sfVaultKind]);
266 auto const kindField = tx[~sfVaultKind];
284 XRPL_ASSERT(vault && vault->getType() == ltVAULT,
"xrpl::getVaultPhase : valid Vault sle");
286 view, (*vault)[~sfVaultKind], (*vault)[~sfSubscriptionDate], (*vault)[~sfRedemptionDate]);
316 issuance && issuance->getType() == ltMPTOKEN_ISSUANCE,
317 "xrpl::checkVaultDomain : valid issuance SLE");
319 auto const maybeDomainID = issuance->at(~sfDomainID);
Number is a floating point type that can represent a wide range of values.
Number truncate() const noexcept
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
std::uint64_t mantissa() const noexcept
bool negative() const noexcept
Asset const & asset() const
int exponent() const noexcept
std::shared_ptr< STLedgerEntry const > const & ConstRef
TER validDomain(ReadView const &view, UInt256 domainID, AccountID const &subject)
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
VaultPhase
Lifecycle phase of a vault.
std::optional< STAmount > sharesToAssetsWithdraw(SLE::ConstRef vault, SLE::ConstRef issuance, STAmount const &shares, WaiveUnrealizedLoss waive=WaiveUnrealizedLoss::No)
From the perspective of a vault, return the number of assets to give the depositor when they redeem a...
bool isSoleShareholder(ReadView const &view, AccountID const &account, SLE::ConstRef issuance)
Returns true iff account holds all of the vault's outstanding shares — i.e.
bool debitIsNonZeroDust(Asset const &asset, Number const &total, Number const &amount)
Returns true if debiting amount from total (the current value of a vault's sfAssetsTotal or sfAssetsA...
TER checkVaultDomain(ReadView const &view, SLE::ConstRef issuance, AccountID const &subject, SuppressExpired suppressExpired)
Checks that subject belongs to the permissioned domain governing a vault's shares.
std::optional< STAmount > assetsToSharesWithdraw(SLE::ConstRef vault, SLE::ConstRef issuance, STAmount const &assets, TruncateShares truncate=TruncateShares::No, WaiveUnrealizedLoss waive=WaiveUnrealizedLoss::No)
From the perspective of a vault, return the number of shares to demand from the depositor when they a...
bool hasExpired(ReadView const &view, std::optional< std::uint32_t > const &exp, ExpiryComparison comparison=ExpiryComparison::Inclusive)
Determines whether the given expiration time has passed.
bool isValidClosedEndedGap(std::uint32_t sub, std::uint32_t red)
Returns true iff the (SubscriptionDate, RedemptionDate) gap of a closed-ended vault satisfies kMinInv...
std::optional< STAmount > sharesToAssetsDeposit(SLE::ConstRef vault, SLE::ConstRef issuance, STAmount const &shares)
From the perspective of a vault, return the number of assets to take from depositor when they receive...
int scale(Number const &number, Asset const &asset)
Get the scale of a Number for a given asset.
Number assetsTotalForWithdrawal(SLE::ConstRef vault, WaiveUnrealizedLoss waive)
Returns the assets backing outstanding shares for a withdrawal: sfAssetsTotal minus sfLossUnrealized,...
constexpr std::uint32_t kMaxInvestmentPeriod
std::expected< STAmount, TER > clampToAssetsTotalScale(SLE::ConstRef vault, STAmount const &delta)
Adjusts a requested asset change (delta) to match the decimal scale of the updated total vault assets...
TruncateShares
Controls whether to truncate shares instead of rounding.
STAmount roundToScale(STAmount const &value, std::int32_t scale, Number::RoundingMode rounding=Number::getround())
Round an arbitrary precision Amount to the precision of an STAmount that has a given exponent.
VaultVersion
Vault ledger-entry schema versions.
std::optional< STAmount > assetsToSharesDeposit(SLE::ConstRef vault, SLE::ConstRef issuance, STAmount const &assets)
From the perspective of a vault, return the number of shares to give depositor when they offer a fixe...
VaultPhase getVaultPhase(ReadView const &view, SLE::ConstRef vault)
Returns the current lifecycle phase of a vault.
MPTID makeMptID(std::uint32_t const sequence, AccountID const &account)
constexpr Number abs(Number x) noexcept
VaultKind getVaultKind(SLE::ConstRef vault)
Resolves the VaultKind of a vault SLE.
void roundToAsset(A const &asset, Number &value)
Round an arbitrary precision Number IN PLACE to the precision of a given Asset.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
TERSubset< CanCvtToTER > TER
SuppressExpired
Controls whether checkVaultDomain reports an expired credential as an error.
bool isValidVaultKind(STTx const &tx)
Returns true iff sfVaultKind is either absent from tx or is present and equal to a recognised VaultKi...
VaultVersion getVaultVersion(SLE::ConstRef vault)
Resolves a Vault's LEVersion, the single point every accounting touch point should call to determine ...
constexpr std::uint32_t kMinInvestmentPeriod
Bounds on the length of a closed-ended vault's Investment phase (RedemptionDate - SubscriptionDate).
WaiveUnrealizedLoss
Controls whether the withdraw conversion helpers (assetsToSharesWithdraw and sharesToAssetsWithdraw) ...