mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-30 02:20:39 +00:00
Merge remote-tracking branch 'origin/tapanito/lending-fix-amendment' into tapanito/vault-donation
# Conflicts: # src/libxrpl/tx/transactors/vault/VaultDeposit.cpp
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
#include <test/jtx/Env.h>
|
||||
#include <test/jtx/amount.h>
|
||||
#include <test/jtx/mpt.h>
|
||||
#include <test/jtx/testline.h>
|
||||
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/unit_test/suite.h>
|
||||
@@ -67,15 +66,23 @@ class Vault_test : public beast::unit_test::suite
|
||||
auto const vault = env.le(keylet);
|
||||
BEAST_EXPECT(vault != nullptr);
|
||||
if (!asset.integral())
|
||||
{
|
||||
BEAST_EXPECT(vault->at(sfScale) == 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
BEAST_EXPECT(vault->at(sfScale) == 0);
|
||||
}
|
||||
auto const shares = env.le(keylet::mptIssuance(vault->at(sfShareMPTID)));
|
||||
BEAST_EXPECT(shares != nullptr);
|
||||
if (!asset.integral())
|
||||
{
|
||||
BEAST_EXPECT(shares->at(sfAssetScale) == 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
BEAST_EXPECT(shares->at(sfAssetScale) == 0);
|
||||
}
|
||||
return {MPTIssue(vault->at(sfShareMPTID)), Account("vault", vault->at(sfAccount))};
|
||||
}();
|
||||
auto const shares = share.raw().get<MPTIssue>();
|
||||
@@ -1332,11 +1339,17 @@ class Vault_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(asset1 <= toFund1 && asset2 <= toFund2);
|
||||
|
||||
if (!asset1.native() && !asset2.native())
|
||||
{
|
||||
fund(env, gw, {alice, carol}, {toFund1, toFund2}, Fund::All);
|
||||
}
|
||||
else if (asset1.native())
|
||||
{
|
||||
fund(env, gw, {alice, carol}, toFund1, {toFund2}, Fund::All);
|
||||
}
|
||||
else if (asset2.native())
|
||||
{
|
||||
fund(env, gw, {alice, carol}, toFund2, {toFund1}, Fund::All);
|
||||
}
|
||||
|
||||
AMM ammAlice(env, alice, asset1, asset2, CreateArg{.log = false, .tfee = 0});
|
||||
|
||||
@@ -2278,7 +2291,9 @@ class Vault_test : public beast::unit_test::suite
|
||||
env(fset(issuer, asfDefaultRipple));
|
||||
}
|
||||
else
|
||||
{
|
||||
env.trust(asset(1000), charlie);
|
||||
}
|
||||
env.close();
|
||||
env(rate(issuer, args.transferRate));
|
||||
env.close();
|
||||
@@ -2624,13 +2639,13 @@ class Vault_test : public beast::unit_test::suite
|
||||
|
||||
// Turn on noripple on the pseudo account's trust line.
|
||||
// Charlie's is already set.
|
||||
env(trust(issuer, vaultAccount(keylet)["IOU"], tfSetNoRipple), THISLINE);
|
||||
env(trust(issuer, vaultAccount(keylet)["IOU"], tfSetNoRipple));
|
||||
|
||||
{
|
||||
// Charlie cannot deposit
|
||||
auto tx = vault.deposit(
|
||||
{.depositor = charlie, .id = keylet.key, .amount = asset(100)});
|
||||
env(tx, ter{terNO_RIPPLE}, THISLINE);
|
||||
env(tx, ter{terNO_RIPPLE});
|
||||
env.close();
|
||||
}
|
||||
|
||||
@@ -2638,14 +2653,14 @@ class Vault_test : public beast::unit_test::suite
|
||||
PrettyAsset shares = issuanceId(keylet);
|
||||
auto tx1 =
|
||||
vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(100)});
|
||||
env(tx1, THISLINE);
|
||||
env(tx1);
|
||||
env.close();
|
||||
|
||||
// Charlie cannot receive funds
|
||||
auto tx2 = vault.withdraw(
|
||||
{.depositor = owner, .id = keylet.key, .amount = shares(100)});
|
||||
tx2[sfDestination] = charlie.human();
|
||||
env(tx2, ter{terNO_RIPPLE}, THISLINE);
|
||||
env(tx2, ter{terNO_RIPPLE});
|
||||
env.close();
|
||||
|
||||
{
|
||||
@@ -2658,7 +2673,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
env(tx);
|
||||
env.close();
|
||||
}
|
||||
env(pay(owner, charlie, shares(100)), THISLINE);
|
||||
env(pay(owner, charlie, shares(100)));
|
||||
env.close();
|
||||
|
||||
// Charlie cannot withdraw
|
||||
@@ -2667,16 +2682,16 @@ class Vault_test : public beast::unit_test::suite
|
||||
env(tx3, ter{terNO_RIPPLE});
|
||||
env.close();
|
||||
|
||||
env(pay(charlie, owner, shares(100)), THISLINE);
|
||||
env(pay(charlie, owner, shares(100)));
|
||||
env.close();
|
||||
}
|
||||
|
||||
tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(100)});
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
// Delete vault with zero balance
|
||||
env(vault.del({.owner = owner, .id = keylet.key}), THISLINE);
|
||||
env(vault.del({.owner = owner, .id = keylet.key}));
|
||||
},
|
||||
{.charlieRipple = false});
|
||||
|
||||
@@ -3350,7 +3365,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
MPTIssue shares(issuanceId);
|
||||
env.memoize(vaultAccount);
|
||||
|
||||
auto const peek = [=, &env, this](std::function<bool(SLE&, SLE&)> fn) -> bool {
|
||||
auto const peek = [keylet, &env, this](std::function<bool(SLE&, SLE&)> fn) -> bool {
|
||||
return env.app().openLedger().modify([&](OpenView& view, beast::Journal j) -> bool {
|
||||
Sandbox sb(&view, tapNONE);
|
||||
auto vault = sb.peek(keylet::vault(keylet.key));
|
||||
@@ -4501,131 +4516,6 @@ class Vault_test : public beast::unit_test::suite
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testDelegate()
|
||||
{
|
||||
using namespace test::jtx;
|
||||
|
||||
Env env(*this, testable_amendments());
|
||||
Account alice{"alice"};
|
||||
Account bob{"bob"};
|
||||
Account carol{"carol"};
|
||||
|
||||
struct CaseArgs
|
||||
{
|
||||
PrettyAsset asset = xrpIssue();
|
||||
};
|
||||
|
||||
auto const xrpBalance = [this](
|
||||
Env const& env, Account const& account) -> std::optional<long> {
|
||||
auto sle = env.le(keylet::account(account.id()));
|
||||
if (BEAST_EXPECT(sle != nullptr))
|
||||
return sle->getFieldAmount(sfBalance).xrp().drops();
|
||||
return std::nullopt;
|
||||
};
|
||||
|
||||
auto testCase = [&, this](auto test, CaseArgs args = {}) {
|
||||
Env env{*this, testable_amendments() | featureSingleAssetVault};
|
||||
|
||||
Vault vault{env};
|
||||
|
||||
// use different initial amount to distinguish the source balance
|
||||
env.fund(XRP(10000), alice);
|
||||
env.fund(XRP(20000), bob);
|
||||
env.fund(XRP(30000), carol);
|
||||
env.close();
|
||||
|
||||
env(delegate::set(
|
||||
carol,
|
||||
alice,
|
||||
{"Payment",
|
||||
"VaultCreate",
|
||||
"VaultSet",
|
||||
"VaultDelete",
|
||||
"VaultDeposit",
|
||||
"VaultWithdraw",
|
||||
"VaultClawback"}));
|
||||
|
||||
test(env, vault, args.asset);
|
||||
};
|
||||
|
||||
testCase([&, this](Env& env, Vault& vault, PrettyAsset const& asset) {
|
||||
testcase("delegated vault creation");
|
||||
auto startBalance = xrpBalance(env, carol);
|
||||
if (!BEAST_EXPECT(startBalance.has_value()))
|
||||
return;
|
||||
|
||||
auto [tx, keylet] = vault.create({.owner = carol, .asset = asset});
|
||||
env(tx, delegate::as(alice));
|
||||
env.close();
|
||||
BEAST_EXPECT(xrpBalance(env, carol) == *startBalance);
|
||||
});
|
||||
|
||||
testCase([&, this](Env& env, Vault& vault, PrettyAsset const& asset) {
|
||||
testcase("delegated deposit and withdrawal");
|
||||
auto [tx, keylet] = vault.create({.owner = carol, .asset = asset});
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
auto const amount = 1513;
|
||||
auto const baseFee = env.current()->fees().base;
|
||||
|
||||
auto startBalance = xrpBalance(env, carol);
|
||||
if (!BEAST_EXPECT(startBalance.has_value()))
|
||||
return;
|
||||
|
||||
tx = vault.deposit({.depositor = carol, .id = keylet.key, .amount = asset(amount)});
|
||||
env(tx, delegate::as(alice));
|
||||
env.close();
|
||||
BEAST_EXPECT(xrpBalance(env, carol) == *startBalance - amount);
|
||||
|
||||
tx =
|
||||
vault.withdraw({.depositor = carol, .id = keylet.key, .amount = asset(amount - 1)});
|
||||
env(tx, delegate::as(alice));
|
||||
env.close();
|
||||
BEAST_EXPECT(xrpBalance(env, carol) == *startBalance - 1);
|
||||
|
||||
tx = vault.withdraw({.depositor = carol, .id = keylet.key, .amount = asset(1)});
|
||||
env(tx);
|
||||
env.close();
|
||||
BEAST_EXPECT(xrpBalance(env, carol) == *startBalance - baseFee);
|
||||
});
|
||||
|
||||
testCase([&, this](Env& env, Vault& vault, PrettyAsset const& asset) {
|
||||
testcase("delegated withdrawal same as base fee and deletion");
|
||||
auto [tx, keylet] = vault.create({.owner = carol, .asset = asset});
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
auto const amount = 25537;
|
||||
auto const baseFee = env.current()->fees().base;
|
||||
|
||||
auto startBalance = xrpBalance(env, carol);
|
||||
if (!BEAST_EXPECT(startBalance.has_value()))
|
||||
return;
|
||||
|
||||
tx = vault.deposit({.depositor = carol, .id = keylet.key, .amount = asset(amount)});
|
||||
env(tx);
|
||||
env.close();
|
||||
BEAST_EXPECT(xrpBalance(env, carol) == *startBalance - amount - baseFee);
|
||||
|
||||
tx = vault.withdraw({.depositor = carol, .id = keylet.key, .amount = asset(baseFee)});
|
||||
env(tx, delegate::as(alice));
|
||||
env.close();
|
||||
BEAST_EXPECT(xrpBalance(env, carol) == *startBalance - amount);
|
||||
|
||||
tx = vault.withdraw(
|
||||
{.depositor = carol, .id = keylet.key, .amount = asset(amount - baseFee)});
|
||||
env(tx, delegate::as(alice));
|
||||
env.close();
|
||||
BEAST_EXPECT(xrpBalance(env, carol) == *startBalance - baseFee);
|
||||
|
||||
tx = vault.del({.owner = carol, .id = keylet.key});
|
||||
env(tx, delegate::as(alice));
|
||||
env.close();
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
testVaultClawbackBurnShares()
|
||||
{
|
||||
@@ -4657,7 +4547,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
Vault vault{env};
|
||||
|
||||
auto const& [tx, vaultKeylet] = vault.create({.owner = owner, .asset = asset});
|
||||
env(tx, ter(tesSUCCESS), THISLINE);
|
||||
env(tx, ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
auto const& vaultSle = env.le(vaultKeylet);
|
||||
@@ -4667,8 +4557,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
|
||||
env(vault.deposit(
|
||||
{.depositor = depositor, .id = vaultKeylet.key, .amount = asset(100)}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
auto const& [availablePreDefault, totalPreDefault] = vaultAssetBalance(vaultKeylet);
|
||||
@@ -4681,14 +4570,13 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = vaultKeylet.key,
|
||||
.holder = depositor,
|
||||
.amount = share(0).value()}),
|
||||
ter(tecNO_PERMISSION),
|
||||
THISLINE);
|
||||
ter(tecNO_PERMISSION));
|
||||
env.close();
|
||||
|
||||
auto const& sharesAvailable = vaultShareBalance(vaultKeylet);
|
||||
auto const& brokerKeylet = keylet::loanbroker(owner.id(), env.seq(owner));
|
||||
|
||||
env(set(owner, vaultKeylet.key), THISLINE);
|
||||
env(set(owner, vaultKeylet.key));
|
||||
env.close();
|
||||
|
||||
auto const& loanKeylet = keylet::loan(brokerKeylet.key, 1);
|
||||
@@ -4701,8 +4589,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
paymentTotal(10),
|
||||
sig(sfCounterpartySignature, owner),
|
||||
fee(env.current()->fees().base * 2),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
// attempt to clawback shares while there assetsAvailable == 0 and
|
||||
@@ -4712,13 +4599,12 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = vaultKeylet.key,
|
||||
.holder = depositor,
|
||||
.amount = share(0).value()}),
|
||||
ter(tecNO_PERMISSION),
|
||||
THISLINE);
|
||||
ter(tecNO_PERMISSION));
|
||||
env.close();
|
||||
|
||||
env.close(std::chrono::seconds{120 + 60});
|
||||
|
||||
env(manage(owner, loanKeylet.key, tfLoanDefault), ter(tesSUCCESS), THISLINE);
|
||||
env(manage(owner, loanKeylet.key, tfLoanDefault), ter(tesSUCCESS));
|
||||
|
||||
auto const& [availablePostDefault, totalPostDefault] = vaultAssetBalance(vaultKeylet);
|
||||
|
||||
@@ -4736,19 +4622,23 @@ class Vault_test : public beast::unit_test::suite
|
||||
{
|
||||
testcase("VaultClawback (share) - " + prefix + " owner asset clawback fails");
|
||||
auto [vault, vaultKeylet] = setupVault(asset, owner, depositor);
|
||||
// when asset is XRP or owner is not issuer clawback fail
|
||||
// when owner is issuer precision loss occurs as vault is
|
||||
// empty
|
||||
auto const expectedTer = [&]() {
|
||||
if (asset.native())
|
||||
return ter(temMALFORMED);
|
||||
if (asset.raw().getIssuer() != owner.id())
|
||||
return ter(tecNO_PERMISSION);
|
||||
return ter(tecPRECISION_LOSS);
|
||||
}();
|
||||
env(vault.clawback({
|
||||
.issuer = owner,
|
||||
.id = vaultKeylet.key,
|
||||
.holder = depositor,
|
||||
.amount = asset(100).value(),
|
||||
}),
|
||||
// when asset is XRP or owner is not issuer clawback fail
|
||||
// when owner is issuer precision loss occurs as vault is
|
||||
// empty
|
||||
asset.native() ? ter(temMALFORMED)
|
||||
: asset.raw().getIssuer() != owner.id() ? ter(tecNO_PERMISSION)
|
||||
: ter(tecPRECISION_LOSS),
|
||||
THISLINE);
|
||||
expectedTer);
|
||||
env.close();
|
||||
}
|
||||
|
||||
@@ -4767,8 +4657,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.holder = depositor,
|
||||
.amount = share(1).value(),
|
||||
}),
|
||||
ter(tecLIMIT_EXCEEDED),
|
||||
THISLINE);
|
||||
ter(tecLIMIT_EXCEEDED));
|
||||
env.close();
|
||||
}
|
||||
|
||||
@@ -4784,8 +4673,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
}),
|
||||
// when owner is issuer implicit clawback fails
|
||||
asset.native() || asset.raw().getIssuer() != owner.id() ? ter(tesSUCCESS)
|
||||
: ter(tecWRONG_ASSET),
|
||||
THISLINE);
|
||||
: ter(tecWRONG_ASSET));
|
||||
env.close();
|
||||
}
|
||||
|
||||
@@ -4805,8 +4693,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.holder = depositor,
|
||||
.amount = share(vaultShareBalance(vaultKeylet)).value(),
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
}
|
||||
{
|
||||
@@ -4823,8 +4710,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.holder = owner,
|
||||
.amount = share(vaultShareBalance(vaultKeylet)).value(),
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
}
|
||||
|
||||
@@ -4841,8 +4727,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.holder = owner,
|
||||
.amount = share(vaultShareBalance(vaultKeylet)).value(),
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
|
||||
// Now the vault is empty, clawback again fails
|
||||
env(vault.clawback({
|
||||
@@ -4850,8 +4735,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = vaultKeylet.key,
|
||||
.holder = owner,
|
||||
}),
|
||||
ter(tecNO_PERMISSION),
|
||||
THISLINE);
|
||||
ter(tecNO_PERMISSION));
|
||||
env.close();
|
||||
}
|
||||
};
|
||||
@@ -4909,15 +4793,14 @@ class Vault_test : public beast::unit_test::suite
|
||||
Vault vault{env};
|
||||
|
||||
auto const& [tx, vaultKeylet] = vault.create({.owner = owner, .asset = asset});
|
||||
env(tx, ter(tesSUCCESS), THISLINE);
|
||||
env(tx, ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
auto const& vaultSle = env.le(vaultKeylet);
|
||||
BEAST_EXPECT(vaultSle != nullptr);
|
||||
env(vault.deposit(
|
||||
{.depositor = depositor, .id = vaultKeylet.key, .amount = asset(100)}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
return std::make_pair(vault, vaultKeylet);
|
||||
@@ -4940,16 +4823,14 @@ class Vault_test : public beast::unit_test::suite
|
||||
.holder = issuer,
|
||||
.amount = asset(1).value(),
|
||||
}),
|
||||
ter(temMALFORMED),
|
||||
THISLINE);
|
||||
ter(temMALFORMED));
|
||||
// When asset is implicit, clawback fails as no permission.
|
||||
env(vault.clawback({
|
||||
.issuer = issuer,
|
||||
.id = vaultKeylet.key,
|
||||
.holder = issuer,
|
||||
}),
|
||||
ter(tecNO_PERMISSION),
|
||||
THISLINE);
|
||||
ter(tecNO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4966,8 +4847,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.holder = depositor,
|
||||
.amount = asset2(1).value(),
|
||||
}),
|
||||
ter(tecWRONG_ASSET),
|
||||
THISLINE);
|
||||
ter(tecWRONG_ASSET));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -4980,8 +4860,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = vaultKeylet.key,
|
||||
.holder = issuer,
|
||||
}),
|
||||
ter(tecWRONG_ASSET),
|
||||
THISLINE);
|
||||
ter(tecWRONG_ASSET));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -4993,8 +4872,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = vaultKeylet.key,
|
||||
.holder = depositor,
|
||||
}),
|
||||
ter(tecNO_PERMISSION),
|
||||
THISLINE);
|
||||
ter(tecNO_PERMISSION));
|
||||
|
||||
env(vault.clawback({
|
||||
.issuer = owner,
|
||||
@@ -5002,8 +4880,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.holder = depositor,
|
||||
.amount = asset(1).value(),
|
||||
}),
|
||||
ter(tecNO_PERMISSION),
|
||||
THISLINE);
|
||||
ter(tecNO_PERMISSION));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -5014,8 +4891,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = vaultKeylet.key,
|
||||
.holder = issuer,
|
||||
}),
|
||||
ter(tecNO_PERMISSION),
|
||||
THISLINE);
|
||||
ter(tecNO_PERMISSION));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -5033,8 +4909,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.holder = depositor,
|
||||
.amount = share(1).value(),
|
||||
}),
|
||||
ter(tecNO_PERMISSION),
|
||||
THISLINE);
|
||||
ter(tecNO_PERMISSION));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -5049,8 +4924,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.holder = depositor,
|
||||
.amount = asset(1).value(),
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -5064,8 +4938,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.holder = depositor,
|
||||
.amount = asset(100).value(),
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -5079,8 +4952,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
.id = vaultKeylet.key,
|
||||
.holder = depositor,
|
||||
}),
|
||||
ter(tesSUCCESS),
|
||||
THISLINE);
|
||||
ter(tesSUCCESS));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5155,19 +5027,19 @@ class Vault_test : public beast::unit_test::suite
|
||||
tx[sfData] = "4D65746144617461";
|
||||
|
||||
tx[sfAssetsMaximum] = maxInt64;
|
||||
env(tx, ter(tefEXCEPTION), THISLINE);
|
||||
env(tx, ter(tefEXCEPTION));
|
||||
env.close();
|
||||
|
||||
tx[sfAssetsMaximum] = initialXRPPlus1;
|
||||
env(tx, ter(tefEXCEPTION), THISLINE);
|
||||
env(tx, ter(tefEXCEPTION));
|
||||
env.close();
|
||||
|
||||
tx[sfAssetsMaximum] = initialXRP;
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
tx[sfAssetsMaximum] = maxInt64Plus1;
|
||||
env(tx, ter(tefEXCEPTION), THISLINE);
|
||||
env(tx, ter(tefEXCEPTION));
|
||||
env.close();
|
||||
|
||||
// This value will be rounded
|
||||
@@ -5177,7 +5049,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(decimalTest == "9223372036854775.808");
|
||||
tx[sfAssetsMaximum] = decimalTest;
|
||||
auto const newKeylet = keylet::vault(owner.id(), env.seq(owner));
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
auto const vaultSle = env.le(newKeylet);
|
||||
@@ -5200,26 +5072,26 @@ class Vault_test : public beast::unit_test::suite
|
||||
return mptAsset;
|
||||
}();
|
||||
|
||||
env(pay(issuer, owner, mptAsset(100'000)), THISLINE);
|
||||
env(pay(issuer, owner, mptAsset(100'000)));
|
||||
env.close();
|
||||
|
||||
auto [tx, keylet] = vault.create({.owner = owner, .asset = mptAsset});
|
||||
tx[sfData] = "4D65746144617461";
|
||||
|
||||
tx[sfAssetsMaximum] = maxInt64;
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
tx[sfAssetsMaximum] = initialXRPPlus1;
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
tx[sfAssetsMaximum] = initialXRP;
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
tx[sfAssetsMaximum] = maxInt64Plus1;
|
||||
env(tx, ter(tefEXCEPTION), THISLINE);
|
||||
env(tx, ter(tefEXCEPTION));
|
||||
env.close();
|
||||
|
||||
// This value will be rounded
|
||||
@@ -5229,7 +5101,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(decimalTest == "922337203685477580.8");
|
||||
tx[sfAssetsMaximum] = decimalTest;
|
||||
auto const newKeylet = keylet::vault(owner.id(), env.seq(owner));
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
auto const vaultSle = env.le(newKeylet);
|
||||
@@ -5252,19 +5124,19 @@ class Vault_test : public beast::unit_test::suite
|
||||
tx[sfData] = "4D65746144617461";
|
||||
|
||||
tx[sfAssetsMaximum] = maxInt64;
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
tx[sfAssetsMaximum] = initialXRPPlus1;
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
tx[sfAssetsMaximum] = initialXRP;
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
tx[sfAssetsMaximum] = maxInt64Plus1;
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
tx[sfAssetsMaximum] = "1000000000000000e80";
|
||||
@@ -5281,7 +5153,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(decimalTest == "922337203685477580.8");
|
||||
tx[sfAssetsMaximum] = decimalTest;
|
||||
auto const newKeylet = keylet::vault(owner.id(), env.seq(owner));
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
auto const vaultSle = env.le(newKeylet);
|
||||
@@ -5295,7 +5167,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
{
|
||||
tx[sfAssetsMaximum] = "9223372036854775807e40"; // max int64 * 10^40
|
||||
auto const newKeylet = keylet::vault(owner.id(), env.seq(owner));
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
auto const vaultSle = env.le(newKeylet);
|
||||
@@ -5309,7 +5181,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
{
|
||||
tx[sfAssetsMaximum] = "9223372036854775807e-40"; // max int64 * 10^-40
|
||||
auto const newKeylet = keylet::vault(owner.id(), env.seq(owner));
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
auto const vaultSle = env.le(newKeylet);
|
||||
@@ -5323,7 +5195,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
{
|
||||
tx[sfAssetsMaximum] = "9223372036854775807e-100"; // max int64 * 10^-100
|
||||
auto const newKeylet = keylet::vault(owner.id(), env.seq(owner));
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
// Field 'AssetsMaximum' may not be explicitly set to default.
|
||||
@@ -5337,7 +5209,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
// What _can't_ IOUs do?
|
||||
// 1. Exceed maximum exponent / offset
|
||||
tx[sfAssetsMaximum] = "1000000000000000e81";
|
||||
env(tx, ter(tefEXCEPTION), THISLINE);
|
||||
env(tx, ter(tefEXCEPTION));
|
||||
env.close();
|
||||
|
||||
// 2. Mantissa larger than uint64 max
|
||||
@@ -5345,7 +5217,7 @@ class Vault_test : public beast::unit_test::suite
|
||||
try
|
||||
{
|
||||
tx[sfAssetsMaximum] = "18446744073709551617e5"; // uint64 max + 1
|
||||
env(tx, THISLINE);
|
||||
env(tx);
|
||||
BEAST_EXPECTS(false, "Expected parse_error for mantissa larger than uint64 max");
|
||||
}
|
||||
catch (parse_error const& e)
|
||||
@@ -5374,20 +5246,20 @@ class Vault_test : public beast::unit_test::suite
|
||||
auto const keylet = keylet::vault(owner.id(), 1);
|
||||
auto delTx = vault.del({.owner = owner, .id = keylet.key});
|
||||
|
||||
// Test VaultDelete with fixLendingProtocolV1_1 disabled
|
||||
// Test VaultDelete with featureLendingProtocolV1_1 disabled
|
||||
// Transaction fails if the data field is provided
|
||||
{
|
||||
testcase("VaultDelete data fixLendingProtocolV1_1 disabled");
|
||||
env.disableFeature(fixLendingProtocolV1_1);
|
||||
testcase("VaultDelete data featureLendingProtocolV1_1 disabled");
|
||||
env.disableFeature(featureLendingProtocolV1_1);
|
||||
delTx[sfMemoData] = strHex(std::string(maxDataPayloadLength, 'A'));
|
||||
env(delTx, ter(temDISABLED), THISLINE);
|
||||
env.close();
|
||||
env.enableFeature(fixLendingProtocolV1_1);
|
||||
env.enableFeature(featureLendingProtocolV1_1);
|
||||
}
|
||||
|
||||
// Transaction fails if the data field is too large
|
||||
{
|
||||
testcase("VaultDelete data fixLendingProtocolV1_1 enabled data too large");
|
||||
testcase("VaultDelete data featureLendingProtocolV1_1 enabled data too large");
|
||||
delTx[sfMemoData] = strHex(std::string(maxDataPayloadLength + 1, 'A'));
|
||||
env(delTx, ter(temMALFORMED), THISLINE);
|
||||
env.close();
|
||||
@@ -5395,14 +5267,14 @@ class Vault_test : public beast::unit_test::suite
|
||||
|
||||
// Transaction fails if the data field is set, but is empty
|
||||
{
|
||||
testcase("VaultDelete data fixLendingProtocolV1_1 enabled data empty");
|
||||
testcase("VaultDelete data featureLendingProtocolV1_1 enabled data empty");
|
||||
delTx[sfMemoData] = strHex(std::string(0, 'A'));
|
||||
env(delTx, ter(temMALFORMED), THISLINE);
|
||||
env.close();
|
||||
}
|
||||
|
||||
{
|
||||
testcase("VaultDelete data fixLendingProtocolV1_1 enabled data valid");
|
||||
testcase("VaultDelete data featureLendingProtocolV1_1 enabled data valid");
|
||||
PrettyAsset const xrpAsset = xrpIssue();
|
||||
auto [tx, keylet] = vault.create({.owner = owner, .asset = xrpAsset});
|
||||
env(tx, ter(tesSUCCESS), THISLINE);
|
||||
@@ -5582,7 +5454,6 @@ public:
|
||||
testFailedPseudoAccount();
|
||||
testScaleIOU();
|
||||
testRPC();
|
||||
testDelegate();
|
||||
testVaultClawbackBurnShares();
|
||||
testVaultClawbackAssets();
|
||||
testAssetsMaximum();
|
||||
|
||||
Reference in New Issue
Block a user