mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
Check that the borrower has sufficient funds to make the LoanPay
This commit is contained in:
@@ -594,7 +594,7 @@ class Loan_test : public beast::unit_test::suite
|
||||
{
|
||||
// Need to account for fees if the loan is in XRP
|
||||
PrettyAmount adjustment = broker.asset(0);
|
||||
if (broker.asset.raw().native())
|
||||
if (broker.asset.native())
|
||||
{
|
||||
adjustment = 2 * env.current()->fees().base;
|
||||
}
|
||||
@@ -757,7 +757,7 @@ class Loan_test : public beast::unit_test::suite
|
||||
if (deleter == borrower)
|
||||
{
|
||||
// Need to account for fees if the loan is in XRP
|
||||
if (broker.asset.raw().native())
|
||||
if (broker.asset.native())
|
||||
{
|
||||
adjustment = env.current()->fees().base;
|
||||
}
|
||||
@@ -1061,12 +1061,12 @@ class Loan_test : public beast::unit_test::suite
|
||||
TER> {
|
||||
// Freeze / lock the asset
|
||||
std::function<void(Account const& holder)> empty;
|
||||
if (broker.asset.raw().native())
|
||||
if (broker.asset.native())
|
||||
{
|
||||
// XRP can't be frozen
|
||||
return std::make_tuple(empty, empty, empty, tesSUCCESS);
|
||||
}
|
||||
else if (broker.asset.raw().holds<Issue>())
|
||||
else if (broker.asset.holds<Issue>())
|
||||
{
|
||||
auto freeze = [&](Account const& holder) {
|
||||
env(trust(issuer, holder[iouCurrency](0), tfSetFreeze));
|
||||
@@ -1365,15 +1365,24 @@ class Loan_test : public beast::unit_test::suite
|
||||
// taken
|
||||
auto const transactionAmount = payoffAmount + broker.asset(10);
|
||||
|
||||
// Send a transaction that tries to pay more than the borrowers's
|
||||
// balance
|
||||
env(pay(borrower,
|
||||
loanKeylet.key,
|
||||
STAmount{
|
||||
broker.asset,
|
||||
borrowerBalanceBeforePayment.number() * 2}),
|
||||
ter(tecINSUFFICIENT_FUNDS));
|
||||
|
||||
env(pay(borrower, loanKeylet.key, transactionAmount));
|
||||
|
||||
env.close();
|
||||
|
||||
// Need to account for fees if the loan is in XRP
|
||||
PrettyAmount adjustment = broker.asset(0);
|
||||
if (broker.asset.raw().native())
|
||||
if (broker.asset.native())
|
||||
{
|
||||
adjustment = env.current()->fees().base;
|
||||
adjustment = env.current()->fees().base * 2;
|
||||
}
|
||||
|
||||
state.paymentRemaining = 0;
|
||||
@@ -1814,7 +1823,7 @@ class Loan_test : public beast::unit_test::suite
|
||||
|
||||
// Need to account for fees if the loan is in XRP
|
||||
PrettyAmount adjustment = broker.asset(0);
|
||||
if (broker.asset.raw().native())
|
||||
if (broker.asset.native())
|
||||
{
|
||||
adjustment = env.current()->fees().base;
|
||||
}
|
||||
@@ -2730,7 +2739,6 @@ class Loan_test : public beast::unit_test::suite
|
||||
|
||||
env(trust(broker, IOU(20'000'000)));
|
||||
env(pay(issuer, broker, IOU(10'000'000)));
|
||||
env(trust(borrower, IOU(20'000'000)));
|
||||
env.close();
|
||||
|
||||
auto const brokerInfo = createVaultAndBroker(env, IOU, broker);
|
||||
@@ -2745,6 +2753,13 @@ class Loan_test : public beast::unit_test::suite
|
||||
paymentInterval(100),
|
||||
fee(XRP(100)));
|
||||
env.close();
|
||||
|
||||
env(trust(borrower, IOU(20'000'000)));
|
||||
// The borrower increases their limit and acquires some IOU so they
|
||||
// can pay interest
|
||||
env(pay(issuer, borrower, IOU(500)));
|
||||
env.close();
|
||||
|
||||
if (auto const le = env.le(keylet::loan(keylet.key));
|
||||
BEAST_EXPECT(le))
|
||||
{
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <xrpld/app/misc/LendingHelpers.h>
|
||||
#include <xrpld/app/tx/detail/LoanManage.h>
|
||||
|
||||
#include <xrpl/json/to_string.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
bool
|
||||
@@ -203,6 +205,27 @@ LoanPay::preclaim(PreclaimContext const& ctx)
|
||||
<< "Vault pseudo-account can not receive funds (deep frozen).";
|
||||
return ret;
|
||||
}
|
||||
// Make sure the borrower has enough funds to make the payment!
|
||||
// Do not support "partial payments" - if the transaction says to pay X,
|
||||
// then the account must have X available, even if the loan payment takes
|
||||
// less.
|
||||
// Also assume that anybody taking loans is not using "community credit",
|
||||
// which would let an IOU balance go negative up to the other side's limit.
|
||||
// This may change in a later version.
|
||||
if (auto const balance = accountHolds(
|
||||
ctx.view,
|
||||
account,
|
||||
asset,
|
||||
fhZERO_IF_FROZEN,
|
||||
ahZERO_IF_UNAUTHORIZED,
|
||||
ctx.j);
|
||||
balance < amount)
|
||||
{
|
||||
JLOG(ctx.j.warn()) << "Payment amount too large. Amount: "
|
||||
<< to_string(amount.getJson())
|
||||
<< ". Balance: " << to_string(balance.getJson());
|
||||
return tecINSUFFICIENT_FUNDS;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
@@ -480,20 +503,36 @@ LoanPay::doApply()
|
||||
: accountHolds(
|
||||
view, brokerPayee, asset, fhIGNORE_FREEZE, ahIGNORE_AUTH, j_);
|
||||
|
||||
/*
|
||||
auto const balanceScale = std::max(
|
||||
{accountBalanceBefore.exponent(),
|
||||
vaultBalanceBefore.exponent(),
|
||||
brokerBalanceBefore.exponent(),
|
||||
accountBalanceAfter.exponent(),
|
||||
vaultBalanceAfter.exponent(),
|
||||
brokerBalanceAfter.exponent()});
|
||||
*/
|
||||
XRPL_ASSERT_PARTS(
|
||||
accountBalanceBefore + vaultBalanceBefore + brokerBalanceBefore ==
|
||||
accountBalanceAfter + vaultBalanceAfter + brokerBalanceAfter,
|
||||
"ripple::LoanPay::doApply",
|
||||
"funds are conserved (with rounding)");
|
||||
XRPL_ASSERT_PARTS(
|
||||
accountBalanceAfter >= beast::zero,
|
||||
"ripple::LoanPay::doApply",
|
||||
"positive account balance");
|
||||
XRPL_ASSERT_PARTS(
|
||||
accountBalanceAfter < accountBalanceBefore,
|
||||
"ripple::LoanPay::doApply",
|
||||
"account balance decreased");
|
||||
XRPL_ASSERT_PARTS(
|
||||
vaultBalanceAfter >= beast::zero && brokerBalanceAfter >= beast::zero,
|
||||
"ripple::LoanPay::doApply",
|
||||
"positive vault and broker balances");
|
||||
XRPL_ASSERT_PARTS(
|
||||
vaultBalanceAfter >= vaultBalanceBefore,
|
||||
"ripple::LoanPay::doApply",
|
||||
"vault balance did not decrease");
|
||||
XRPL_ASSERT_PARTS(
|
||||
brokerBalanceAfter >= brokerBalanceBefore,
|
||||
"ripple::LoanPay::doApply",
|
||||
"broker balance did not decrease");
|
||||
XRPL_ASSERT_PARTS(
|
||||
vaultBalanceAfter > vaultBalanceBefore ||
|
||||
brokerBalanceAfter > brokerBalanceBefore,
|
||||
"ripple::LoanPay::doApply",
|
||||
"vault and/or broker balance increased");
|
||||
#endif
|
||||
|
||||
return tesSUCCESS;
|
||||
|
||||
Reference in New Issue
Block a user