diff --git a/include/xrpl/protocol/Asset.h b/include/xrpl/protocol/Asset.h index ba706dd609..23b2360277 100644 --- a/include/xrpl/protocol/Asset.h +++ b/include/xrpl/protocol/Asset.h @@ -21,12 +21,14 @@ #define RIPPLE_PROTOCOL_ASSET_H_INCLUDED #include +#include #include #include namespace ripple { class Asset; +class STAmount; template concept ValidIssueType = @@ -92,6 +94,8 @@ public: void setJson(Json::Value& jv) const; + STAmount operator() (Number const&) const; + bool native() const { diff --git a/include/xrpl/protocol/STAmount.h b/include/xrpl/protocol/STAmount.h index 4a78004000..ea049be62a 100644 --- a/include/xrpl/protocol/STAmount.h +++ b/include/xrpl/protocol/STAmount.h @@ -153,6 +153,11 @@ public: template STAmount(A const& asset, int mantissa, int exponent = 0); + template + STAmount(A const& asset, Number const& number) + : STAmount(asset, number.mantissa(), number.exponent()) + {} + // Legacy support for new-style amounts STAmount(IOUAmount const& amount, Issue const& issue); STAmount(XRPAmount const& amount); diff --git a/src/libxrpl/protocol/Asset.cpp b/src/libxrpl/protocol/Asset.cpp index 67323f8614..e9ece21186 100644 --- a/src/libxrpl/protocol/Asset.cpp +++ b/src/libxrpl/protocol/Asset.cpp @@ -43,6 +43,11 @@ Asset::setJson(Json::Value& jv) const std::visit([&](auto&& issue) { issue.setJson(jv); }, issue_); } +STAmount Asset::operator() (Number const& number) const +{ + return STAmount{*this, number}; +} + std::string to_string(Asset const& asset) { diff --git a/src/libxrpl/protocol/TER.cpp b/src/libxrpl/protocol/TER.cpp index e414f642e0..b79917ac79 100644 --- a/src/libxrpl/protocol/TER.cpp +++ b/src/libxrpl/protocol/TER.cpp @@ -118,6 +118,7 @@ transResults() MAKE_ERROR(tecLOCKED, "Fund is locked."), MAKE_ERROR(tecBAD_CREDENTIALS, "Bad credentials."), MAKE_ERROR(tecWRONG_ASSET, "Wrong asset given."), + MAKE_ERROR(tecLIMIT_EXCEEDED, "Limit exceeded."), MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."), MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."), diff --git a/src/test/app/Vault_test.cpp b/src/test/app/Vault_test.cpp index b0ed08c777..36fd6eeecd 100644 --- a/src/test/app/Vault_test.cpp +++ b/src/test/app/Vault_test.cpp @@ -37,7 +37,8 @@ class Vault_test : public beast::unit_test::suite Account issuer{"issuer"}; Account owner{"owner"}; - env.fund(XRP(1000), issuer, owner); + Account depositor{"depositor"}; + env.fund(XRP(1000), issuer, owner, depositor); env.close(); auto vault = env.vault(); @@ -205,6 +206,25 @@ class Vault_test : public beast::unit_test::suite env(tx, ter(tecLOCKED)); } + SUBCASE("transfer IOU") + { + Asset asset = issuer["IOU"]; + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); + env.trust(asset(1000), depositor); + env(pay(issuer, depositor, asset(1000))); + env(tx); + env.close(); + + { + auto tx = vault.deposit({ + .depositor = depositor, + .id = keylet.key, + .amount = asset(123)}); + env(tx); + env.close(); + } + } + // TODO: VaultSet (update) succeed // TODO: VaultSet (update) fail: wrong owner // TODO: VaultSet (update) fail: Data too large diff --git a/src/test/jtx/amount.h b/src/test/jtx/amount.h index 9990c77c38..8281c0186b 100644 --- a/src/test/jtx/amount.h +++ b/src/test/jtx/amount.h @@ -21,7 +21,6 @@ #define RIPPLE_TEST_JTX_AMOUNT_H_INCLUDED #include -#include #include #include #include diff --git a/src/test/jtx/impl/vault.cpp b/src/test/jtx/impl/vault.cpp index 17b796ca42..8cea759216 100644 --- a/src/test/jtx/impl/vault.cpp +++ b/src/test/jtx/impl/vault.cpp @@ -64,6 +64,17 @@ Vault::del(DeleteArgs const& args) return jv; } +Json::Value +Vault::deposit(DepositArgs const& args) +{ + Json::Value jv; + jv[jss::TransactionType] = jss::VaultDeposit; + jv[jss::Account] = args.depositor.human(); + jv[jss::VaultID] = to_string(args.id); + jv[jss::Amount] = to_json(args.amount); + return jv; +} + } // namespace jtx } // namespace test } // namespace ripple diff --git a/src/test/jtx/vault.h b/src/test/jtx/vault.h index 788d4ce9f0..777adaf181 100644 --- a/src/test/jtx/vault.h +++ b/src/test/jtx/vault.h @@ -21,9 +21,10 @@ #define RIPPLE_TEST_JTX_VAULT_H_INCLUDED #include -#include +#include #include +#include #include #include @@ -68,6 +69,17 @@ struct Vault Json::Value del(DeleteArgs const& args); + + struct DepositArgs + { + Account depositor; + uint256 id; + STAmount amount; + }; + + Json::Value + deposit(DepositArgs const& args); + }; } // namespace jtx diff --git a/src/xrpld/app/tx/detail/VaultDeposit.cpp b/src/xrpld/app/tx/detail/VaultDeposit.cpp index a97cdd41a6..b0671e8819 100644 --- a/src/xrpld/app/tx/detail/VaultDeposit.cpp +++ b/src/xrpld/app/tx/detail/VaultDeposit.cpp @@ -74,8 +74,11 @@ VaultDeposit::doApply() return tecINSUFFICIENT_FUNDS; } - Number assetTotalNew = vault->at(sfAssetTotal) + amount; - if (assetTotalNew > vault->at(sfAssetMaximum)) + vault->at(sfAssetTotal) += amount; + vault->at(sfAssetAvailable) += amount; + + auto maximum = *vault->at(sfAssetMaximum); + if (maximum != 0 && *vault->at(sfAssetTotal) > maximum) return tecLIMIT_EXCEEDED; // TODO: Check credentials. @@ -87,9 +90,6 @@ VaultDeposit::doApply() if (auto ter = accountSend(view(), account_, vaultAccount, amount, j_)) return ter; - vault->at(sfAssetTotal) += amount; - vault->at(sfAssetAvailable) += amount; - auto shares = assetsToSharesDeposit(view(), vault, amount); if (!shares) return shares.error(); diff --git a/src/xrpld/ledger/detail/View.cpp b/src/xrpld/ledger/detail/View.cpp index 4791c765bf..c8b49324cc 100644 --- a/src/xrpld/ledger/detail/View.cpp +++ b/src/xrpld/ledger/detail/View.cpp @@ -2247,7 +2247,7 @@ assetsToSharesDeposit( return assets; Number shareTotal = getShareTotal(view, vault); auto shares = shareTotal * (assets / assetTotal); - STAmount amount{MPTAmount{shares}, MPTIssue{vault->at(sfMPTokenIssuanceID)}}; + STAmount amount{vault->at(sfMPTokenIssuanceID), shares}; return amount; }