#include #include #include #include #include #include #include // IWYU pragma: keep #include #include #include #include #include // IWYU pragma: keep #include #include #include namespace xrpl { [[nodiscard]] std::optional assetsToSharesDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount const& assets) { XRPL_ASSERT(!assets.negative(), "xrpl::assetsToSharesDeposit : non-negative assets"); XRPL_ASSERT( assets.asset() == vault->at(sfAsset), "xrpl::assetsToSharesDeposit : assets and vault match"); if (assets.negative() || assets.asset() != vault->at(sfAsset)) return std::nullopt; // LCOV_EXCL_LINE Number const assetTotal = vault->at(sfAssetsTotal); STAmount shares{vault->at(sfShareMPTID)}; if (assetTotal == 0) { return STAmount{ shares.asset(), Number(assets.mantissa(), assets.exponent() + vault->at(sfScale)).truncate()}; } Number const shareTotal = issuance->at(sfOutstandingAmount); shares = ((shareTotal * assets) / assetTotal).truncate(); return shares; } [[nodiscard]] std::optional sharesToAssetsDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount const& shares) { XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsDeposit : non-negative shares"); XRPL_ASSERT( shares.asset() == vault->at(sfShareMPTID), "xrpl::sharesToAssetsDeposit : shares and vault match"); if (shares.negative() || shares.asset() != vault->at(sfShareMPTID)) return std::nullopt; // LCOV_EXCL_LINE Number const assetTotal = vault->at(sfAssetsTotal); STAmount assets{vault->at(sfAsset)}; if (assetTotal == 0) { return STAmount{ assets.asset(), shares.mantissa(), shares.exponent() - vault->at(sfScale), false}; } Number const shareTotal = issuance->at(sfOutstandingAmount); assets = (assetTotal * shares) / shareTotal; return assets; } [[nodiscard]] std::optional assetsToSharesWithdraw( SLE::const_ref vault, SLE::const_ref issuance, STAmount const& assets, TruncateShares truncate, WaiveUnrealizedLoss waive) { XRPL_ASSERT(!assets.negative(), "xrpl::assetsToSharesWithdraw : non-negative assets"); XRPL_ASSERT( assets.asset() == vault->at(sfAsset), "xrpl::assetsToSharesWithdraw : assets and vault match"); if (assets.negative() || assets.asset() != vault->at(sfAsset)) return std::nullopt; // LCOV_EXCL_LINE Number assetTotal = vault->at(sfAssetsTotal); if (waive == WaiveUnrealizedLoss::No) assetTotal -= vault->at(sfLossUnrealized); STAmount shares{vault->at(sfShareMPTID)}; if (assetTotal == 0) return shares; Number const shareTotal = issuance->at(sfOutstandingAmount); Number result = (shareTotal * assets) / assetTotal; if (truncate == TruncateShares::Yes) result = result.truncate(); shares = result; return shares; } [[nodiscard]] std::optional sharesToAssetsWithdraw( SLE::const_ref vault, SLE::const_ref issuance, STAmount const& shares, WaiveUnrealizedLoss waive) { XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsWithdraw : non-negative shares"); XRPL_ASSERT( shares.asset() == vault->at(sfShareMPTID), "xrpl::sharesToAssetsWithdraw : shares and vault match"); if (shares.negative() || shares.asset() != vault->at(sfShareMPTID)) return std::nullopt; // LCOV_EXCL_LINE Number assetTotal = vault->at(sfAssetsTotal); if (waive == WaiveUnrealizedLoss::No) assetTotal -= vault->at(sfLossUnrealized); STAmount assets{vault->at(sfAsset)}; if (assetTotal == 0) return assets; Number const shareTotal = issuance->at(sfOutstandingAmount); assets = (assetTotal * shares) / shareTotal; return assets; } [[nodiscard]] bool isSoleShareholder(ReadView const& view, AccountID const& account, SLE::const_ref issuance) { XRPL_ASSERT( issuance && issuance->getType() == ltMPTOKEN_ISSUANCE, "xrpl::isSoleShareholder : valid issuance SLE"); std::uint64_t const outstanding = issuance->at(sfOutstandingAmount); if (outstanding == 0) return false; auto const shareMPTID = makeMptID(issuance->getFieldU32(sfSequence), issuance->getAccountID(sfIssuer)); auto const sleToken = view.read(keylet::mptoken(shareMPTID, account)); if (!sleToken) return false; // LCOV_EXCL_LINE return sleToken->getFieldU64(sfMPTAmount) == outstanding; } [[nodiscard]] VaultVersion getVaultVersion(SLE::const_ref vault) { XRPL_ASSERT(vault && vault->getType() == ltVAULT, "xrpl::getVaultVersion : valid Vault sle"); if (!vault->isFieldPresent(sfLEVersion)) return VaultVersion::Legacy; auto const version = vault->at(sfLEVersion); if (version > std::to_underlying(VaultVersion::CashBasis)) { // LCOV_EXCL_START UNREACHABLE("xrpl::getVaultVersion : invalid vault version"); return VaultVersion::Legacy; // LCOV_EXCL_STOP } return static_cast(version); } } // namespace xrpl