mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Compare commits
3 Commits
ximinez/le
...
vlntb/RIPD
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a913a791aa | ||
|
|
933447ce48 | ||
|
|
5fe00e32a3 |
@@ -5243,6 +5243,46 @@ class Vault_test : public beast::unit_test::suite
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testFrozenWithdrawToIssuer()
|
||||||
|
{
|
||||||
|
using namespace test::jtx;
|
||||||
|
|
||||||
|
testcase("frozen IOU can be withdrawn to issuer");
|
||||||
|
|
||||||
|
Env env{*this, testable_amendments() | featureSingleAssetVault};
|
||||||
|
Account issuer{"issuer"};
|
||||||
|
Account owner{"owner"};
|
||||||
|
Account depositor{"depositor"};
|
||||||
|
env.fund(XRP(1000), issuer, owner, depositor);
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
PrettyAsset asset = issuer["IOU"];
|
||||||
|
env.trust(asset(1000), owner);
|
||||||
|
env.trust(asset(1000), depositor);
|
||||||
|
env(pay(issuer, owner, asset(100)));
|
||||||
|
env(pay(issuer, depositor, asset(200)));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
Vault vault{env};
|
||||||
|
auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
|
||||||
|
env(tx);
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
env(vault.deposit(
|
||||||
|
{.depositor = depositor, .id = keylet.key, .amount = asset(50)}));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
env(fset(issuer, asfGlobalFreeze));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
auto withdraw = vault.withdraw(
|
||||||
|
{.depositor = depositor, .id = keylet.key, .amount = asset(10)});
|
||||||
|
withdraw[sfDestination] = issuer.human();
|
||||||
|
env(withdraw, ter{tesSUCCESS});
|
||||||
|
env.close();
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void
|
void
|
||||||
run() override
|
run() override
|
||||||
@@ -5261,6 +5301,7 @@ public:
|
|||||||
testScaleIOU();
|
testScaleIOU();
|
||||||
testRPC();
|
testRPC();
|
||||||
testDelegate();
|
testDelegate();
|
||||||
|
testFrozenWithdrawToIssuer();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -80,13 +80,23 @@ VaultWithdraw::preclaim(PreclaimContext const& ctx)
|
|||||||
return ter;
|
return ter;
|
||||||
|
|
||||||
// Cannot withdraw from a Vault an Asset frozen for the destination account
|
// Cannot withdraw from a Vault an Asset frozen for the destination account
|
||||||
|
if (!vaultAsset.holds<Issue>() ||
|
||||||
|
(dstAcct != vaultAsset.getIssuer() &&
|
||||||
|
account != vaultAsset.getIssuer()))
|
||||||
|
{
|
||||||
if (auto const ret = checkFrozen(ctx.view, dstAcct, vaultAsset))
|
if (auto const ret = checkFrozen(ctx.view, dstAcct, vaultAsset))
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// Cannot return shares to the vault, if the underlying asset was frozen for
|
// Cannot return shares to the vault, if the underlying asset was frozen for
|
||||||
// the submitter
|
// the submitter
|
||||||
|
if (!vaultAsset.holds<Issue>() ||
|
||||||
|
(dstAcct != vaultAsset.getIssuer() &&
|
||||||
|
account != vaultAsset.getIssuer()))
|
||||||
|
{
|
||||||
if (auto const ret = checkFrozen(ctx.view, account, vaultShare))
|
if (auto const ret = checkFrozen(ctx.view, account, vaultShare))
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
@@ -115,6 +125,7 @@ VaultWithdraw::doApply()
|
|||||||
|
|
||||||
auto const amount = ctx_.tx[sfAmount];
|
auto const amount = ctx_.tx[sfAmount];
|
||||||
Asset const vaultAsset = vault->at(sfAsset);
|
Asset const vaultAsset = vault->at(sfAsset);
|
||||||
|
auto const dstAcct = ctx_.tx[~sfDestination].value_or(account_);
|
||||||
MPTIssue const share{mptIssuanceID};
|
MPTIssue const share{mptIssuanceID};
|
||||||
STAmount sharesRedeemed = {share};
|
STAmount sharesRedeemed = {share};
|
||||||
STAmount assetsWithdrawn;
|
STAmount assetsWithdrawn;
|
||||||
@@ -165,11 +176,21 @@ VaultWithdraw::doApply()
|
|||||||
return tecPATH_DRY;
|
return tecPATH_DRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When withdrawing IOU to the issuer, ignore freeze since spec allows
|
||||||
|
// returning frozen IOU assets to their issuer. MPTs don't have this
|
||||||
|
// exemption - MPT locks function like "deep freeze" with no issuer
|
||||||
|
// exception.
|
||||||
|
FreezeHandling const freezeHandling = (vaultAsset.holds<Issue>() &&
|
||||||
|
(dstAcct == vaultAsset.getIssuer() ||
|
||||||
|
account_ == vaultAsset.getIssuer()))
|
||||||
|
? FreezeHandling::fhIGNORE_FREEZE
|
||||||
|
: FreezeHandling::fhZERO_IF_FROZEN;
|
||||||
|
|
||||||
if (accountHolds(
|
if (accountHolds(
|
||||||
view(),
|
view(),
|
||||||
account_,
|
account_,
|
||||||
share,
|
share,
|
||||||
FreezeHandling::fhZERO_IF_FROZEN,
|
freezeHandling,
|
||||||
AuthHandling::ahIGNORE_AUTH,
|
AuthHandling::ahIGNORE_AUTH,
|
||||||
j_) < sharesRedeemed)
|
j_) < sharesRedeemed)
|
||||||
{
|
{
|
||||||
@@ -237,8 +258,6 @@ VaultWithdraw::doApply()
|
|||||||
// else quietly ignore, account balance is not zero
|
// else quietly ignore, account balance is not zero
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const dstAcct = ctx_.tx[~sfDestination].value_or(account_);
|
|
||||||
|
|
||||||
return doWithdraw(
|
return doWithdraw(
|
||||||
view(),
|
view(),
|
||||||
ctx_.tx,
|
ctx_.tx,
|
||||||
|
|||||||
Reference in New Issue
Block a user