mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
Change tecFROZEN to tecLOCKED for locked MPT.
Replace checkMPTTxAllowed() with canMPTTradeAndTransfer().
This commit is contained in:
@@ -495,6 +495,22 @@ canTrade(ReadView const& view, Asset const& asset)
|
||||
});
|
||||
}
|
||||
|
||||
TER
|
||||
canMPTTradeAndTransfer(
|
||||
ReadView const& view,
|
||||
Asset const& asset,
|
||||
AccountID const& from,
|
||||
AccountID const& to)
|
||||
{
|
||||
if (!asset.holds<MPTIssue>())
|
||||
return tesSUCCESS;
|
||||
|
||||
if (auto const ter = canTrade(view, asset); !isTesSuccess(ter))
|
||||
return ter;
|
||||
|
||||
return canTransfer(view, asset, from, to);
|
||||
}
|
||||
|
||||
TER
|
||||
lockEscrowMPT(ApplyView& view, AccountID const& sender, STAmount const& amount, beast::Journal j)
|
||||
{
|
||||
@@ -862,65 +878,4 @@ issuerSelfDebitHookMPT(ApplyView& view, MPTIssue const& issue, std::uint64_t amo
|
||||
view.issuerSelfDebitHookMPT(issue, amount, available);
|
||||
}
|
||||
|
||||
static TER
|
||||
checkMPTAllowed(ReadView const& view, TxType txType, Asset const& asset, AccountID const& accountID)
|
||||
{
|
||||
if (!asset.holds<MPTIssue>())
|
||||
return tesSUCCESS;
|
||||
|
||||
auto const& issuanceID = asset.get<MPTIssue>().getMptID();
|
||||
auto const validTx = txType == ttAMM_CREATE || txType == ttAMM_DEPOSIT ||
|
||||
txType == ttAMM_WITHDRAW || txType == ttOFFER_CREATE || txType == ttCHECK_CREATE ||
|
||||
txType == ttCHECK_CASH || txType == ttPAYMENT;
|
||||
XRPL_ASSERT(validTx, "xrpl::checkMPTAllowed : all MPT tx or DEX");
|
||||
if (!validTx)
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const& issuer = asset.getIssuer();
|
||||
if (!view.exists(keylet::account(issuer)))
|
||||
return tecNO_ISSUER; // LCOV_EXCL_LINE
|
||||
|
||||
auto const issuanceKey = keylet::mptIssuance(issuanceID);
|
||||
auto const issuanceSle = view.read(issuanceKey);
|
||||
if (!issuanceSle)
|
||||
return tecOBJECT_NOT_FOUND; // LCOV_EXCL_LINE
|
||||
|
||||
auto const flags = issuanceSle->getFlags();
|
||||
|
||||
if ((flags & lsfMPTLocked) != 0u)
|
||||
return tecLOCKED; // LCOV_EXCL_LINE
|
||||
// Offer crossing and Payment
|
||||
if ((flags & lsfMPTCanTrade) == 0)
|
||||
return tecNO_PERMISSION;
|
||||
|
||||
if (accountID != issuer)
|
||||
{
|
||||
if ((flags & lsfMPTCanTransfer) == 0)
|
||||
return tecNO_PERMISSION;
|
||||
|
||||
auto const mptSle = view.read(keylet::mptoken(issuanceKey.key, accountID));
|
||||
// Allow to succeed since some tx create MPToken if it doesn't exist.
|
||||
// Tx's have their own check for missing MPToken.
|
||||
if (!mptSle)
|
||||
return tesSUCCESS;
|
||||
|
||||
if (mptSle->isFlag(lsfMPTLocked))
|
||||
return tecLOCKED;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
checkMPTTxAllowed(
|
||||
ReadView const& view,
|
||||
TxType txType,
|
||||
Asset const& asset,
|
||||
AccountID const& accountID)
|
||||
{
|
||||
// use isDEXAllowed for payment/offer crossing
|
||||
XRPL_ASSERT(txType != ttPAYMENT, "xrpl::checkMPTTxAllowed : not payment");
|
||||
return checkMPTAllowed(view, txType, asset, accountID);
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -40,6 +40,14 @@ isGlobalFrozen(ReadView const& view, Asset const& asset)
|
||||
[&](MPTIssue const& issue) { return isGlobalFrozen(view, issue); });
|
||||
}
|
||||
|
||||
TER
|
||||
checkGlobalFrozen(ReadView const& view, Asset const& asset)
|
||||
{
|
||||
if (isGlobalFrozen(view, asset))
|
||||
return asset.holds<MPTIssue>() ? tecLOCKED : tecFROZEN;
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
bool
|
||||
isIndividualFrozen(ReadView const& view, AccountID const& account, Asset const& asset)
|
||||
{
|
||||
@@ -47,6 +55,14 @@ isIndividualFrozen(ReadView const& view, AccountID const& account, Asset const&
|
||||
[&](auto const& issue) { return isIndividualFrozen(view, account, issue); }, asset.value());
|
||||
}
|
||||
|
||||
TER
|
||||
checkIndividualFrozen(ReadView const& view, AccountID const& account, Asset const& asset)
|
||||
{
|
||||
if (isIndividualFrozen(view, account, asset))
|
||||
return asset.holds<MPTIssue>() ? tecLOCKED : tecFROZEN;
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
bool
|
||||
isFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int depth)
|
||||
{
|
||||
|
||||
@@ -94,10 +94,10 @@ CheckCreate::preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
// The currency may not be globally frozen
|
||||
AccountID const& issuerId{sendMax.getIssuer()};
|
||||
if (isGlobalFrozen(ctx.view, sendMax.asset()))
|
||||
if (auto const ter = checkGlobalFrozen(ctx.view, sendMax.asset()); !isTesSuccess(ter))
|
||||
{
|
||||
JLOG(ctx.j.warn()) << "Creating a check for frozen asset";
|
||||
return sendMax.asset().holds<MPTIssue>() ? tecLOCKED : tecFROZEN;
|
||||
JLOG(ctx.j.warn()) << "Creating a check for frozen or locked asset";
|
||||
return ter;
|
||||
}
|
||||
auto const err = sendMax.asset().visit(
|
||||
[&](Issue const& issue) -> std::optional<TER> {
|
||||
|
||||
@@ -94,11 +94,16 @@ AMMCreate::preclaim(PreclaimContext const& ctx)
|
||||
}
|
||||
|
||||
// Globally or individually frozen
|
||||
if (isFrozen(ctx.view, accountID, amount.asset()) ||
|
||||
isFrozen(ctx.view, accountID, amount2.asset()))
|
||||
if (auto const ter = checkFrozen(ctx.view, accountID, amount.asset()); !isTesSuccess(ter))
|
||||
|
||||
{
|
||||
JLOG(ctx.j.debug()) << "AMM Instance: involves frozen asset.";
|
||||
return tecFROZEN;
|
||||
JLOG(ctx.j.debug()) << "AMM Instance: involves frozen or locked asset.";
|
||||
return ter;
|
||||
}
|
||||
if (auto const ter = checkFrozen(ctx.view, accountID, amount2.asset()); !isTesSuccess(ter))
|
||||
{
|
||||
JLOG(ctx.j.debug()) << "AMM Instance: involves frozen or locked asset.";
|
||||
return ter;
|
||||
}
|
||||
|
||||
auto noDefaultRipple = [](ReadView const& view, Asset const& asset) {
|
||||
@@ -165,10 +170,10 @@ AMMCreate::preclaim(PreclaimContext const& ctx)
|
||||
return terADDRESS_COLLISION;
|
||||
}
|
||||
|
||||
if (auto const ter = checkMPTTxAllowed(ctx.view, ttAMM_CREATE, amount.asset(), accountID);
|
||||
if (auto const ter = canMPTTradeAndTransfer(ctx.view, amount.asset(), accountID, accountID);
|
||||
!isTesSuccess(ter))
|
||||
return ter;
|
||||
if (auto const ter = checkMPTTxAllowed(ctx.view, ttAMM_CREATE, amount2.asset(), accountID);
|
||||
if (auto const ter = canMPTTradeAndTransfer(ctx.view, amount2.asset(), accountID, accountID);
|
||||
!isTesSuccess(ter))
|
||||
return ter;
|
||||
|
||||
|
||||
@@ -243,12 +243,12 @@ AMMDeposit::preclaim(PreclaimContext const& ctx)
|
||||
return ter;
|
||||
}
|
||||
|
||||
if (isFrozen(ctx.view, accountID, asset))
|
||||
if (auto const ter = checkFrozen(ctx.view, accountID, asset); !isTesSuccess(ter))
|
||||
{
|
||||
JLOG(ctx.j.debug()) << "AMM Deposit: account or currency is frozen, "
|
||||
JLOG(ctx.j.debug()) << "AMM Deposit: account or currency is frozen or locked, "
|
||||
<< to_string(accountID) << " " << to_string(asset);
|
||||
|
||||
return tecFROZEN;
|
||||
return ter;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
@@ -280,18 +280,20 @@ AMMDeposit::preclaim(PreclaimContext const& ctx)
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
// AMM account or currency frozen
|
||||
if (isFrozen(ctx.view, ammAccountID, amount->asset()))
|
||||
if (auto const ter = checkFrozen(ctx.view, ammAccountID, amount->asset());
|
||||
!isTesSuccess(ter))
|
||||
{
|
||||
JLOG(ctx.j.debug())
|
||||
<< "AMM Deposit: AMM account or currency is frozen, " << to_string(accountID);
|
||||
return tecFROZEN;
|
||||
JLOG(ctx.j.debug()) << "AMM Deposit: AMM account or currency is frozen or locked, "
|
||||
<< to_string(accountID);
|
||||
return ter;
|
||||
}
|
||||
// Account frozen
|
||||
if (isIndividualFrozen(ctx.view, accountID, amount->asset()))
|
||||
if (auto const ter = checkIndividualFrozen(ctx.view, accountID, amount->asset());
|
||||
!isTesSuccess(ter))
|
||||
{
|
||||
JLOG(ctx.j.debug()) << "AMM Deposit: account is frozen, " << to_string(accountID)
|
||||
<< " " << to_string(amount->asset());
|
||||
return tecFROZEN;
|
||||
JLOG(ctx.j.debug()) << "AMM Deposit: account is frozen or locked, "
|
||||
<< to_string(accountID) << " " << to_string(amount->asset());
|
||||
return ter;
|
||||
}
|
||||
if (checkBalance)
|
||||
{
|
||||
@@ -344,10 +346,10 @@ AMMDeposit::preclaim(PreclaimContext const& ctx)
|
||||
}
|
||||
}
|
||||
|
||||
if (auto const ter = checkMPTTxAllowed(ctx.view, ttAMM_DEPOSIT, ctx.tx[sfAsset], accountID);
|
||||
if (auto const ter = canMPTTradeAndTransfer(ctx.view, ctx.tx[sfAsset], accountID, accountID);
|
||||
!isTesSuccess(ter))
|
||||
return ter;
|
||||
if (auto const ter = checkMPTTxAllowed(ctx.view, ttAMM_DEPOSIT, ctx.tx[sfAsset2], accountID);
|
||||
if (auto const ter = canMPTTradeAndTransfer(ctx.view, ctx.tx[sfAsset2], accountID, accountID);
|
||||
!isTesSuccess(ter))
|
||||
return ter;
|
||||
|
||||
|
||||
@@ -211,22 +211,24 @@ AMMWithdraw::preclaim(PreclaimContext const& ctx)
|
||||
return ter;
|
||||
}
|
||||
// AMM account or currency frozen
|
||||
if (isFrozen(ctx.view, ammAccountID, amount->asset()))
|
||||
if (auto const ter = checkFrozen(ctx.view, ammAccountID, amount->asset());
|
||||
!isTesSuccess(ter))
|
||||
{
|
||||
JLOG(ctx.j.debug())
|
||||
<< "AMM Withdraw: AMM account or currency is frozen, " << to_string(accountID);
|
||||
return tecFROZEN;
|
||||
JLOG(ctx.j.debug()) << "AMM Withdraw: AMM account or currency is frozen or locked, "
|
||||
<< to_string(accountID);
|
||||
return ter;
|
||||
}
|
||||
// Account frozen
|
||||
if (isIndividualFrozen(ctx.view, accountID, amount->asset()))
|
||||
if (auto const ter = checkIndividualFrozen(ctx.view, accountID, amount->asset());
|
||||
!isTesSuccess(ter))
|
||||
{
|
||||
JLOG(ctx.j.debug()) << "AMM Withdraw: account is frozen, " << to_string(accountID)
|
||||
<< " " << to_string(amount->asset());
|
||||
return tecFROZEN;
|
||||
JLOG(ctx.j.debug()) << "AMM Withdraw: account is frozen or locked, "
|
||||
<< to_string(accountID) << " " << to_string(amount->asset());
|
||||
return ter;
|
||||
}
|
||||
|
||||
if (auto const ter =
|
||||
checkMPTTxAllowed(ctx.view, ttAMM_WITHDRAW, amount->asset(), accountID);
|
||||
canMPTTradeAndTransfer(ctx.view, amount->asset(), accountID, accountID);
|
||||
!isTesSuccess(ter))
|
||||
return ter;
|
||||
}
|
||||
|
||||
@@ -146,11 +146,15 @@ OfferCreate::preclaim(PreclaimContext const& ctx)
|
||||
|
||||
auto viewJ = ctx.registry.get().getJournal("View");
|
||||
|
||||
if (isGlobalFrozen(ctx.view, saTakerPays.asset()) ||
|
||||
isGlobalFrozen(ctx.view, saTakerGets.asset()))
|
||||
if (auto const ter = checkGlobalFrozen(ctx.view, saTakerPays.asset()); !isTesSuccess(ter))
|
||||
{
|
||||
JLOG(ctx.j.debug()) << "Offer involves frozen asset";
|
||||
return tecFROZEN;
|
||||
return ter;
|
||||
}
|
||||
if (auto const ter = checkGlobalFrozen(ctx.view, saTakerGets.asset()); !isTesSuccess(ter))
|
||||
{
|
||||
JLOG(ctx.j.debug()) << "Offer involves frozen asset";
|
||||
return ter;
|
||||
}
|
||||
|
||||
// Allow unfunded MPT for issuer (OutstandingAmount >= MaximumAmount)
|
||||
@@ -281,7 +285,13 @@ OfferCreate::checkAcceptAsset(
|
||||
[&](MPTIssue const& issue) -> TER {
|
||||
// WeakAuth - don't check if MPToken exists since it's created
|
||||
// if needed.
|
||||
return requireAuth(view, issue, id, AuthType::WeakAuth);
|
||||
if (auto const ter = requireAuth(view, issue, id, AuthType::WeakAuth);
|
||||
!isTesSuccess(ter))
|
||||
{
|
||||
return ter;
|
||||
}
|
||||
|
||||
return checkFrozen(view, id, issue);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3063,10 +3063,8 @@ private:
|
||||
BTC.set({.holder = bob, .flags = tfMPTLock});
|
||||
|
||||
{
|
||||
// different from IOU. The offer is created but not crossed.
|
||||
env(offer(bob, BTC(5), XRP(25)));
|
||||
env(offer(bob, BTC(5), XRP(25)), ter(tecLOCKED));
|
||||
env.close();
|
||||
BEAST_EXPECT(expectOffers(env, bob, 1, {{{BTC(5), XRP(25)}}}));
|
||||
BEAST_EXPECT(ammAlice.expectBalances(XRP(500), BTC(105), ammAlice.tokens()));
|
||||
}
|
||||
|
||||
@@ -3169,7 +3167,7 @@ private:
|
||||
BTC.set({.flags = tfMPTLock});
|
||||
|
||||
// assets can't be bought on the market
|
||||
AMM const ammA3(env, A3, BTC(1), XRP(1), ter(tecFROZEN));
|
||||
AMM const ammA3(env, A3, BTC(1), XRP(1), ter(tecLOCKED));
|
||||
|
||||
// direct issues can be sent
|
||||
env(pay(G1, A2, BTC(1)));
|
||||
|
||||
@@ -99,7 +99,7 @@ private:
|
||||
.pay = 30'000,
|
||||
.flags = tfMPTCanLock | MPTDEXFlags});
|
||||
USD.set({.flags = tfMPTLock});
|
||||
AMM const ammAliceFail(env, alice, XRP(10'000), USD(10'000), ter(tecFROZEN));
|
||||
AMM const ammAliceFail(env, alice, XRP(10'000), USD(10'000), ter(tecLOCKED));
|
||||
USD.set({.flags = tfMPTUnlock});
|
||||
AMM const ammAlice(env, alice, XRP(10'000), USD(10'000));
|
||||
}
|
||||
@@ -303,7 +303,7 @@ private:
|
||||
.pay = 30'000,
|
||||
.flags = tfMPTCanLock | MPTDEXFlags});
|
||||
BTC.set({.flags = tfMPTLock});
|
||||
AMM const ammAlice(env, alice, USD(10'000), BTC(10'000), ter(tecFROZEN));
|
||||
AMM const ammAlice(env, alice, USD(10'000), BTC(10'000), ter(tecLOCKED));
|
||||
BEAST_EXPECT(!ammAlice.ammExists());
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ private:
|
||||
BTC.set({.holder = alice, .flags = tfMPTLock});
|
||||
|
||||
// alice's token is locked
|
||||
AMM const ammAlice(env, alice, USD(10'000), BTC(10'000), ter(tecFROZEN));
|
||||
AMM const ammAlice(env, alice, USD(10'000), BTC(10'000), ter(tecLOCKED));
|
||||
BEAST_EXPECT(!ammAlice.ammExists());
|
||||
|
||||
// bob can create
|
||||
@@ -645,14 +645,14 @@ private:
|
||||
BTC.set({.flags = tfMPTLock});
|
||||
|
||||
ammAlice.deposit(
|
||||
carol, BTC(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
carol, BTC(100), std::nullopt, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
|
||||
ammAlice.deposit(
|
||||
carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
|
||||
ammAlice.deposit(carol, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
ammAlice.deposit(carol, 1'000, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
|
||||
ammAlice.deposit(carol, USD(100), BTC(100), std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
ammAlice.deposit(carol, USD(100), BTC(100), std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
}
|
||||
|
||||
// Individually lock MPT or freeze IOU (AMM) with IOU/MPT AMM
|
||||
@@ -673,20 +673,19 @@ private:
|
||||
|
||||
// Carol can not deposit locked mpt
|
||||
ammAlice.deposit(
|
||||
carol, BTC(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
carol, BTC(100), std::nullopt, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
|
||||
ammAlice.deposit(carol, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
ammAlice.deposit(carol, 1'000, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
|
||||
if (!features[featureAMMClawback])
|
||||
{
|
||||
ammAlice.deposit(
|
||||
carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
ammAlice.deposit(carol, USD(100), std::nullopt, std::nullopt, std::nullopt);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Carol can not deposit non-forzen token either
|
||||
// Carol can not deposit non-frozen token either
|
||||
ammAlice.deposit(
|
||||
carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
}
|
||||
|
||||
// Alice can deposit because she's not individually locked
|
||||
@@ -727,9 +726,9 @@ private:
|
||||
ammAlice.deposit(carol, USD(100), std::nullopt, std::nullopt, std::nullopt);
|
||||
|
||||
// Can not deposit locked token
|
||||
ammAlice.deposit(carol, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
ammAlice.deposit(carol, 1'000, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
ammAlice.deposit(
|
||||
carol, BTC(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
carol, BTC(100), std::nullopt, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
|
||||
// Unlock AMM MPT
|
||||
BTC.set({.holder = ammAlice.ammAccount(), .flags = tfMPTUnlock});
|
||||
@@ -761,10 +760,10 @@ private:
|
||||
// Carol's BTC is locked
|
||||
BTC.set({.holder = carol, .flags = tfMPTLock});
|
||||
ammAlice.deposit(
|
||||
carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
|
||||
ammAlice.deposit(
|
||||
carol, BTC(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
carol, BTC(100), std::nullopt, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
|
||||
// Unlock carol's BTC
|
||||
BTC.set({.holder = carol, .flags = tfMPTUnlock});
|
||||
@@ -780,9 +779,9 @@ private:
|
||||
ammAlice.deposit(carol, USD(100), std::nullopt, std::nullopt, std::nullopt);
|
||||
|
||||
// Can not deposit locked token BTC
|
||||
ammAlice.deposit(carol, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
ammAlice.deposit(carol, 1'000, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
ammAlice.deposit(
|
||||
carol, BTC(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
carol, BTC(100), std::nullopt, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
|
||||
// Unlock AMM MPT BTC
|
||||
BTC.set({.holder = ammAlice.ammAccount(), .flags = tfMPTUnlock});
|
||||
@@ -797,9 +796,9 @@ private:
|
||||
ammAlice.deposit(carol, BTC(100), std::nullopt, std::nullopt, std::nullopt);
|
||||
|
||||
// Can not deposit locked token USD
|
||||
ammAlice.deposit(carol, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
ammAlice.deposit(carol, 1'000, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
ammAlice.deposit(
|
||||
carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
|
||||
// Unlock AMM MPT USD
|
||||
USD.set({.holder = ammAlice.ammAccount(), .flags = tfMPTUnlock});
|
||||
@@ -853,7 +852,7 @@ private:
|
||||
|
||||
AMM amm(env, gw, XRP(10'000), BTC(10'000));
|
||||
|
||||
amm.deposit({.account = alice, .asset1In = BTC(10), .err = ter(tecNO_PERMISSION)});
|
||||
amm.deposit({.account = alice, .asset1In = BTC(10), .err = ter(tecNO_AUTH)});
|
||||
}
|
||||
|
||||
// Insufficient XRP balance
|
||||
@@ -2211,7 +2210,7 @@ private:
|
||||
.account = alice,
|
||||
.asset1Out = BTC(100),
|
||||
.assets = {{XRP, BTC}},
|
||||
.err = ter(tecNO_PERMISSION)});
|
||||
.err = ter(tecNO_AUTH)});
|
||||
}
|
||||
|
||||
// Globally locked MPT
|
||||
@@ -2232,8 +2231,8 @@ private:
|
||||
BTC.set({.flags = tfMPTLock});
|
||||
|
||||
ammAlice.withdraw(
|
||||
alice, MPT(ammAlice[1])(100), std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
ammAlice.withdraw(alice, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
alice, MPT(ammAlice[1])(100), std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
ammAlice.withdraw(alice, 1'000, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
|
||||
// can single withdraw the other asset
|
||||
ammAlice.withdraw({.account = alice, .asset1Out = XRP(100)});
|
||||
@@ -2261,8 +2260,8 @@ private:
|
||||
|
||||
// Alice's BTC is locked
|
||||
BTC.set({.holder = alice, .flags = tfMPTLock});
|
||||
ammAlice.withdraw(alice, 1000, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
ammAlice.withdraw(alice, BTC(100), std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
ammAlice.withdraw(alice, 1000, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
ammAlice.withdraw(alice, BTC(100), std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
|
||||
// can withdraw the other asset
|
||||
ammAlice.withdraw(alice, USD(100), std::nullopt, std::nullopt);
|
||||
@@ -2290,8 +2289,8 @@ private:
|
||||
// Alice's BTC is locked
|
||||
BTC.set({.holder = alice, .flags = tfMPTLock});
|
||||
|
||||
ammAlice.withdraw(alice, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
ammAlice.withdraw(alice, BTC(100), std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
ammAlice.withdraw(alice, 1'000, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
ammAlice.withdraw(alice, BTC(100), std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
// can still single withdraw the unlocked other asset
|
||||
ammAlice.withdraw(alice, USD(100), std::nullopt, std::nullopt);
|
||||
|
||||
@@ -2310,8 +2309,8 @@ private:
|
||||
ammAlice.withdraw(alice, USD(100), std::nullopt, std::nullopt);
|
||||
|
||||
// Can not withdraw locked token BTC
|
||||
ammAlice.withdraw(alice, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
ammAlice.withdraw(alice, BTC(100), std::nullopt, std::nullopt, ter(tecFROZEN));
|
||||
ammAlice.withdraw(alice, 1'000, std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
ammAlice.withdraw(alice, BTC(100), std::nullopt, std::nullopt, ter(tecLOCKED));
|
||||
|
||||
// Unlock AMM MPT
|
||||
BTC.set({.holder = ammAlice.ammAccount(), .flags = tfMPTUnlock});
|
||||
@@ -6807,33 +6806,33 @@ private:
|
||||
cb(amm, BTC);
|
||||
};
|
||||
|
||||
// Deposit two assets, one of which is frozen,
|
||||
// then we should get tecFROZEN error.
|
||||
// Deposit two assets, one of which is locked,
|
||||
// then we should get tecLOCKED error.
|
||||
{
|
||||
Env env(*this);
|
||||
testAMMDeposit(env, [&](AMM& amm, MPTTester& BTC) {
|
||||
amm.deposit(alice, BTC(100), XRP(100), std::nullopt, tfTwoAsset, ter(tecFROZEN));
|
||||
amm.deposit(alice, BTC(100), XRP(100), std::nullopt, tfTwoAsset, ter(tecLOCKED));
|
||||
});
|
||||
}
|
||||
|
||||
// Deposit one asset, which is the frozen token,
|
||||
// then we should get tecFROZEN error.
|
||||
// Deposit one asset, which is the frozen locked,
|
||||
// then we should get tecLOCKED error.
|
||||
{
|
||||
Env env(*this);
|
||||
testAMMDeposit(env, [&](AMM& amm, MPTTester& BTC) {
|
||||
amm.deposit(
|
||||
alice, BTC(100), std::nullopt, std::nullopt, tfSingleAsset, ter(tecFROZEN));
|
||||
alice, BTC(100), std::nullopt, std::nullopt, tfSingleAsset, ter(tecLOCKED));
|
||||
});
|
||||
}
|
||||
|
||||
// Deposit one asset which is not the frozen token,
|
||||
// but the other asset is frozen. We should get tecFROZEN error
|
||||
// but the other asset is frozen. We should get tecLOCKED error
|
||||
// when feature AMMClawback is enabled.
|
||||
{
|
||||
Env env(*this);
|
||||
testAMMDeposit(env, [&](AMM& amm, MPTTester& BTC) {
|
||||
amm.deposit(
|
||||
alice, XRP(100), std::nullopt, std::nullopt, tfSingleAsset, ter(tecFROZEN));
|
||||
alice, XRP(100), std::nullopt, std::nullopt, tfSingleAsset, ter(tecLOCKED));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1813,10 +1813,10 @@ class CheckMPT_test : public beast::unit_test::suite
|
||||
// Use offers to automatically create MPT.
|
||||
MPT const OF4 = gw1["OF4"];
|
||||
gw1.set(OF4, tfMPTLock);
|
||||
env(offer(gw1, XRP(92), OF4(92)), ter(tecFROZEN));
|
||||
env(offer(gw1, XRP(92), OF4(92)), ter(tecLOCKED));
|
||||
env.close();
|
||||
BEAST_EXPECT(env.le(keylet::mptoken(OF4, alice)) == nullptr);
|
||||
env(offer(alice, OF4(92), XRP(92)), ter(tecFROZEN));
|
||||
env(offer(alice, OF4(92), XRP(92)), ter(tecLOCKED));
|
||||
env.close();
|
||||
|
||||
// No one's owner count should have changed.
|
||||
@@ -1904,10 +1904,10 @@ class CheckMPT_test : public beast::unit_test::suite
|
||||
// Use offers to automatically create MPT.
|
||||
MPT const OF4 = gw1["OF4"];
|
||||
gw1.set(OF4, tfMPTLock);
|
||||
env(offer(alice, XRP(91), OF4(91)), ter(tecFROZEN));
|
||||
env(offer(alice, XRP(91), OF4(91)), ter(tecLOCKED));
|
||||
env.close();
|
||||
BEAST_EXPECT(env.le(keylet::mptoken(OF4, alice)) == nullptr);
|
||||
env(offer(bob, OF4(91), XRP(91)), ter(tecFROZEN));
|
||||
env(offer(bob, OF4(91), XRP(91)), ter(tecLOCKED));
|
||||
env.close();
|
||||
|
||||
// No one's owner count should have changed.
|
||||
|
||||
@@ -3395,10 +3395,10 @@ class MPToken_test : public beast::unit_test::suite
|
||||
auto const [errBuy, errSell] = [&]() -> std::pair<TER, TER> {
|
||||
// Global lock
|
||||
if (lockMPTIssue)
|
||||
return std::make_pair(tecFROZEN, tecFROZEN);
|
||||
return std::make_pair(tecLOCKED, tecLOCKED);
|
||||
// Local lock
|
||||
if (lockMPToken)
|
||||
return std::make_pair(tesSUCCESS, error(tecUNFUNDED_OFFER));
|
||||
return std::make_pair(error(tecLOCKED), error(tecUNFUNDED_OFFER));
|
||||
// MPToken doesn't exist
|
||||
if (requireAuth)
|
||||
return std::make_pair(error(tecNO_AUTH), error(tecUNFUNDED_OFFER));
|
||||
@@ -3496,10 +3496,9 @@ class MPToken_test : public beast::unit_test::suite
|
||||
else
|
||||
{
|
||||
auto const err = flag == tfMPTLock ? ter(tecUNFUNDED_OFFER) : ter(tesSUCCESS);
|
||||
auto const err1 = flag == tfMPTLock ? ter(tecLOCKED) : ter(tesSUCCESS);
|
||||
env(offer(alice, ETH(1), BTC(1)), err);
|
||||
// Offer created by not crossed
|
||||
env(offer(carol, BTC(1), ETH(1)));
|
||||
BEAST_EXPECT(expectOffers(env, carol, 1, {{BTC(1), ETH(1)}}));
|
||||
env(offer(carol, BTC(1), ETH(1)), err1);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6126,8 +6125,7 @@ class MPToken_test : public beast::unit_test::suite
|
||||
AMM amm(env, gw, BTC(100), USD(100));
|
||||
env.close();
|
||||
// alice can't deposit since MPTCanTransfer is not set
|
||||
amm.deposit(
|
||||
DepositArg{.account = alice, .tokens = 1'000, .err = ter(tecNO_PERMISSION)});
|
||||
amm.deposit(DepositArg{.account = alice, .tokens = 1'000, .err = ter(tecNO_AUTH)});
|
||||
env.close();
|
||||
|
||||
// can't clawback since alice is not an LP
|
||||
@@ -6360,8 +6358,8 @@ class MPToken_test : public beast::unit_test::suite
|
||||
|
||||
// alice and issuer can't create
|
||||
USD.set({.flags = tfMPTLock});
|
||||
createFail(alice, tecFROZEN);
|
||||
createFail(gw, tecFROZEN);
|
||||
createFail(alice, tecLOCKED);
|
||||
createFail(gw, tecLOCKED);
|
||||
|
||||
// MPTRequireAuth is set
|
||||
|
||||
@@ -6381,7 +6379,7 @@ class MPToken_test : public beast::unit_test::suite
|
||||
USD.set({.mutableFlags = tmfMPTClearRequireAuth});
|
||||
USD.set({.mutableFlags = tmfMPTClearCanTransfer});
|
||||
// alice can't create
|
||||
createFail(alice, tecNO_PERMISSION);
|
||||
createFail(alice, tecNO_AUTH);
|
||||
// issuer can create
|
||||
createDeleteAMM(gw);
|
||||
USD.set({.mutableFlags = tmfMPTSetCanTransfer});
|
||||
@@ -6427,12 +6425,12 @@ class MPToken_test : public beast::unit_test::suite
|
||||
{.account = account,
|
||||
.asset1In = USD(1),
|
||||
.asset2In = EUR(1),
|
||||
.err = ter(tecFROZEN)});
|
||||
.err = ter(tecLOCKED)});
|
||||
amm.deposit(
|
||||
{.account = account,
|
||||
.asset1In = EUR(1),
|
||||
.assets = std::make_pair(EUR, USD),
|
||||
.err = ter(tecFROZEN)});
|
||||
.err = ter(tecLOCKED)});
|
||||
}
|
||||
USD.set({.flags = tfMPTUnlock});
|
||||
|
||||
@@ -6467,15 +6465,12 @@ class MPToken_test : public beast::unit_test::suite
|
||||
USD.set({.mutableFlags = tmfMPTClearCanTransfer});
|
||||
// carol can't deposit
|
||||
amm.deposit(
|
||||
{.account = carol,
|
||||
.asset1In = USD(1),
|
||||
.asset2In = EUR(1),
|
||||
.err = ter(tecNO_PERMISSION)});
|
||||
{.account = carol, .asset1In = USD(1), .asset2In = EUR(1), .err = ter(tecNO_AUTH)});
|
||||
amm.deposit(
|
||||
{.account = carol,
|
||||
.asset1In = EUR(1),
|
||||
.assets = std::make_pair(EUR, USD),
|
||||
.err = ter(tecNO_PERMISSION)});
|
||||
.err = ter(tecNO_AUTH)});
|
||||
// issuer can deposit
|
||||
amm.deposit({.account = gw, .tokens = 1'000});
|
||||
// carol can deposit
|
||||
@@ -6517,8 +6512,8 @@ class MPToken_test : public beast::unit_test::suite
|
||||
{.account = account,
|
||||
.asset1Out = USD(1),
|
||||
.asset2Out = EUR(1),
|
||||
.err = ter(tecFROZEN)});
|
||||
amm.withdraw({.account = account, .tokens = 1'000, .err = ter(tecFROZEN)});
|
||||
.err = ter(tecLOCKED)});
|
||||
amm.withdraw({.account = account, .tokens = 1'000, .err = ter(tecLOCKED)});
|
||||
// can single withdraw another asset
|
||||
amm.withdraw(
|
||||
{.account = account, .asset1Out = EUR(1), .assets = std::make_pair(EUR, USD)});
|
||||
@@ -6544,7 +6539,7 @@ class MPToken_test : public beast::unit_test::suite
|
||||
USD.authorize({.account = gw, .holder = carol});
|
||||
amm.withdraw({.account = carol, .asset1Out = USD(1), .asset2Out = EUR(1)});
|
||||
|
||||
// MPTCanTransfer is set
|
||||
// MPTCanTransfer is not set
|
||||
|
||||
USD.set({.mutableFlags = tmfMPTClearRequireAuth});
|
||||
USD.set({.mutableFlags = tmfMPTClearCanTransfer});
|
||||
@@ -6553,7 +6548,7 @@ class MPToken_test : public beast::unit_test::suite
|
||||
{.account = carol,
|
||||
.asset1Out = USD(1),
|
||||
.asset2Out = EUR(1),
|
||||
.err = ter(tecNO_PERMISSION)});
|
||||
.err = ter(tecNO_AUTH)});
|
||||
// can withdraw another asset
|
||||
amm.withdraw(
|
||||
{.account = carol, .asset1Out = EUR(1), .assets = std::make_pair(EUR, USD)});
|
||||
@@ -6564,6 +6559,9 @@ class MPToken_test : public beast::unit_test::suite
|
||||
amm.withdraw({.account = carol, .asset1Out = USD(1), .asset2Out = EUR(1)});
|
||||
|
||||
USD.set({.mutableFlags = tmfMPTSetCanTransfer});
|
||||
|
||||
// MPTCanTrade is not set
|
||||
|
||||
USD.set({.mutableFlags = tmfMPTClearCanTrade});
|
||||
amm.withdraw({.account = gw, .tokens = 1'000, .err = ter(tecNO_PERMISSION)});
|
||||
amm.withdraw({.account = carol, .tokens = 1'000, .err = ter(tecNO_PERMISSION)});
|
||||
|
||||
Reference in New Issue
Block a user