Add unit test

This commit is contained in:
Bronek Kozicki
2025-11-10 15:09:08 +00:00
parent 8499b9a8ff
commit 4b9f6bfafe
3 changed files with 54 additions and 22 deletions

View File

@@ -5556,11 +5556,11 @@ protected:
}); });
} }
#if LOANTODO
void void
testCoverDepositAllowsNonTransferableMPT() testCoverDepositWithdrawNonTransferableMPT()
{ {
testcase("CoverDeposit accepts MPT without CanTransfer"); testcase(
"CoverDeposit and CoverWithdraw reject MPT without CanTransfer");
using namespace jtx; using namespace jtx;
using namespace loanBroker; using namespace loanBroker;
@@ -5580,7 +5580,7 @@ protected:
env.close(); env.close();
PrettyAsset const asset = mpt["BUG"]; PrettyAsset const asset = mpt["MPT"];
mpt.authorize({.account = alice}); mpt.authorize({.account = alice});
env.close(); env.close();
@@ -5614,21 +5614,58 @@ protected:
env(pay(alice, pseudoAccount, asset(1)), ter(tecNO_AUTH)); env(pay(alice, pseudoAccount, asset(1)), ter(tecNO_AUTH));
env.close(); env.close();
// Cover cannot be transferred to broker account
auto const depositAmount = asset(1); auto const depositAmount = asset(1);
env(coverDeposit(alice, brokerKeylet.key, depositAmount)); env(coverDeposit(alice, brokerKeylet.key, depositAmount),
BEAST_EXPECT(env.ter() == tesSUCCESS); ter{tecNO_AUTH});
env.close(); env.close();
if (auto const refreshed = env.le(brokerKeylet); if (auto const refreshed = env.le(brokerKeylet);
BEAST_EXPECT(refreshed)) BEAST_EXPECT(refreshed))
{ {
// with an MPT that cannot be transferred the covrAvailable should
// remain zero
BEAST_EXPECT(refreshed->at(sfCoverAvailable) == 0); BEAST_EXPECT(refreshed->at(sfCoverAvailable) == 0);
env.require(balance(pseudoAccount, asset(0)));
}
// Set CanTransfer again and transfer some deposit
mpt.set({.mutableFlags = tmfMPTSetCanTransfer});
env.close();
env(coverDeposit(alice, brokerKeylet.key, depositAmount));
env.close();
if (auto const refreshed = env.le(brokerKeylet);
BEAST_EXPECT(refreshed))
{
BEAST_EXPECT(refreshed->at(sfCoverAvailable) == 1);
env.require(balance(pseudoAccount, depositAmount)); env.require(balance(pseudoAccount, depositAmount));
} }
// Remove CanTransfer after the deposit
mpt.set({.mutableFlags = tmfMPTClearCanTransfer});
env.close();
// Cover cannot be transferred from broker account
env(coverWithdraw(alice, brokerKeylet.key, depositAmount),
ter{tecNO_AUTH});
env.close();
// Set CanTransfer again and withdraw
mpt.set({.mutableFlags = tmfMPTSetCanTransfer});
env.close();
env(coverWithdraw(alice, brokerKeylet.key, depositAmount));
env.close();
if (auto const refreshed = env.le(brokerKeylet);
BEAST_EXPECT(refreshed))
{
BEAST_EXPECT(refreshed->at(sfCoverAvailable) == 0);
env.require(balance(pseudoAccount, asset(0)));
}
} }
#if LOANTODO
void void
testLoanPayLateFullPaymentBypassesPenalties() testLoanPayLateFullPaymentBypassesPenalties()
{ {
@@ -6504,11 +6541,11 @@ public:
run() override run() override
{ {
#if LOANTODO #if LOANTODO
testCoverDepositAllowsNonTransferableMPT();
testLoanPayLateFullPaymentBypassesPenalties(); testLoanPayLateFullPaymentBypassesPenalties();
testPoC_UnsignedUnderflowOnFullPayAfterEarlyPeriodic(); testPoC_UnsignedUnderflowOnFullPayAfterEarlyPeriodic();
testLoanCoverMinimumRoundingExploit(); testLoanCoverMinimumRoundingExploit();
#endif #endif
testCoverDepositWithdrawNonTransferableMPT();
testDustManipulation(); testDustManipulation();
testIssuerLoan(); testIssuerLoan();

View File

@@ -58,13 +58,10 @@ LoanBrokerCoverDeposit::preclaim(PreclaimContext const& ctx)
return tecWRONG_ASSET; return tecWRONG_ASSET;
auto const pseudoAccountID = sleBroker->at(sfAccount); auto const pseudoAccountID = sleBroker->at(sfAccount);
if (auto ter = canTransfer(ctx.view, vaultAsset, account, pseudoAccountID); // Cannot transfer a non-transferable Asset
!isTesSuccess(ter)) if (auto const ret =
{ canTransfer(ctx.view, vaultAsset, account, pseudoAccountID))
JLOG(ctx.j.warn()) << "Assets are non-transferable."; return ret;
return ter;
}
// Cannot transfer a frozen Asset // Cannot transfer a frozen Asset
if (auto const ret = checkFrozen(ctx.view, account, vaultAsset)) if (auto const ret = checkFrozen(ctx.view, account, vaultAsset))
return ret; return ret;

View File

@@ -67,12 +67,10 @@ LoanBrokerCoverWithdraw::preclaim(PreclaimContext const& ctx)
// The broker's pseudo-account is the source of funds. // The broker's pseudo-account is the source of funds.
auto const pseudoAccountID = sleBroker->at(sfAccount); auto const pseudoAccountID = sleBroker->at(sfAccount);
if (auto ter = canTransfer(ctx.view, vaultAsset, pseudoAccountID, dstAcct); // Cannot transfer a non-transferable Asset
!isTesSuccess(ter)) if (auto const ret =
{ canTransfer(ctx.view, vaultAsset, pseudoAccountID, dstAcct))
JLOG(ctx.j.warn()) << "Assets are non-transferable."; return ret;
return ter;
}
// Withdrawal to a 3rd party destination account is essentially a transfer. // Withdrawal to a 3rd party destination account is essentially a transfer.
// Enforce all the usual asset transfer checks. // Enforce all the usual asset transfer checks.