mirror of
https://github.com/XRPLF/rippled.git
synced 2026-02-10 17:02:29 +00:00
Compare commits
5 Commits
ximinez/fi
...
tapanito/l
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a43f5abede | ||
|
|
c5d7ebe93d | ||
|
|
d0b5ca9dab | ||
|
|
5e51893e9b | ||
|
|
3422c11d02 |
@@ -16,6 +16,7 @@
|
||||
// Add new amendments to the top of this list.
|
||||
// Keep it sorted in reverse chronological order.
|
||||
|
||||
XRPL_FIX (LendingProtocolV1_1, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (ExpiredNFTokenOfferRemoval, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (BatchInnerSigs, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(LendingProtocol, Supported::yes, VoteBehavior::DefaultNo)
|
||||
|
||||
@@ -1701,10 +1701,21 @@ class LoanBroker_test : public beast::unit_test::suite
|
||||
testRIPD4274MPT();
|
||||
}
|
||||
|
||||
void
|
||||
testFixAmendmentEnabled()
|
||||
{
|
||||
using namespace jtx;
|
||||
testcase("testFixAmendmentEnabled");
|
||||
Env env{*this};
|
||||
|
||||
BEAST_EXPECT(env.enabled(fixLendingProtocolV1_1));
|
||||
}
|
||||
|
||||
public:
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testFixAmendmentEnabled();
|
||||
testLoanBrokerSetDebtMaximum();
|
||||
testLoanBrokerCoverDepositNullVault();
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@ struct PreflightContext;
|
||||
bool
|
||||
checkLendingProtocolDependencies(PreflightContext const& ctx);
|
||||
|
||||
NotTEC
|
||||
temInvalidToMalformed(PreflightContext const& ctx);
|
||||
|
||||
static constexpr std::uint32_t secondsInYear = 365 * 24 * 60 * 60;
|
||||
|
||||
Number
|
||||
|
||||
@@ -10,6 +10,12 @@ checkLendingProtocolDependencies(PreflightContext const& ctx)
|
||||
return ctx.rules.enabled(featureSingleAssetVault) && VaultCreate::checkExtraFeatures(ctx);
|
||||
}
|
||||
|
||||
NotTEC
|
||||
temInvalidToMalformed(PreflightContext const& ctx)
|
||||
{
|
||||
return ctx.rules.enabled(fixLendingProtocolV1_1) ? temMALFORMED : temINVALID;
|
||||
}
|
||||
|
||||
LoanPaymentParts&
|
||||
LoanPaymentParts::operator+=(LoanPaymentParts const& other)
|
||||
{
|
||||
|
||||
@@ -33,14 +33,9 @@ DIDSet::preflight(PreflightContext const& ctx)
|
||||
ctx.tx[sfDIDDocument].empty() && ctx.tx.isFieldPresent(sfData) && ctx.tx[sfData].empty())
|
||||
return temEMPTY_DID;
|
||||
|
||||
auto isTooLong = [&](auto const& sField, std::size_t length) -> bool {
|
||||
if (auto field = ctx.tx[~sField])
|
||||
return field->length() > length;
|
||||
return false;
|
||||
};
|
||||
|
||||
if (isTooLong(sfURI, maxDIDURILength) || isTooLong(sfDIDDocument, maxDIDDocumentLength) ||
|
||||
isTooLong(sfData, maxDIDAttestationLength))
|
||||
if (!validDataLength(ctx.tx[~sfURI], maxDIDURILength) ||
|
||||
!validDataLength(ctx.tx[~sfDIDDocument], maxDIDDocumentLength) ||
|
||||
!validDataLength(ctx.tx[~sfData], maxDIDAttestationLength))
|
||||
return temMALFORMED;
|
||||
|
||||
return tesSUCCESS;
|
||||
|
||||
@@ -19,10 +19,10 @@ LoanBrokerCoverClawback::preflight(PreflightContext const& ctx)
|
||||
auto const amount = ctx.tx[~sfAmount];
|
||||
|
||||
if (!brokerID && !amount)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
if (brokerID && *brokerID == beast::zero)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
if (amount)
|
||||
{
|
||||
@@ -41,7 +41,7 @@ LoanBrokerCoverClawback::preflight(PreflightContext const& ctx)
|
||||
if (!brokerID)
|
||||
{
|
||||
if (amount->holds<MPTIssue>())
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
auto const account = ctx.tx[sfAccount];
|
||||
// Since we don't have a LoanBrokerID, holder _should_ be the loan
|
||||
@@ -49,7 +49,7 @@ LoanBrokerCoverClawback::preflight(PreflightContext const& ctx)
|
||||
// use a generic placeholder name.
|
||||
auto const holder = amount->getIssuer();
|
||||
if (holder == account || holder == beast::zero)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ NotTEC
|
||||
LoanBrokerCoverDeposit::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
if (ctx.tx[sfLoanBrokerID] == beast::zero)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
auto const dstAmount = ctx.tx[sfAmount];
|
||||
if (dstAmount <= beast::zero)
|
||||
|
||||
@@ -18,7 +18,7 @@ NotTEC
|
||||
LoanBrokerCoverWithdraw::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
if (ctx.tx[sfLoanBrokerID] == beast::zero)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
auto const dstAmount = ctx.tx[sfAmount];
|
||||
if (dstAmount <= beast::zero)
|
||||
|
||||
@@ -16,7 +16,7 @@ NotTEC
|
||||
LoanBrokerDelete::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
if (ctx.tx[sfLoanBrokerID] == beast::zero)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
@@ -18,16 +18,16 @@ LoanBrokerSet::preflight(PreflightContext const& ctx)
|
||||
using namespace Lending;
|
||||
|
||||
auto const& tx = ctx.tx;
|
||||
if (auto const data = tx[~sfData]; data && !data->empty() && !validDataLength(tx[~sfData], maxDataPayloadLength))
|
||||
return temINVALID;
|
||||
if (auto const data = tx[~sfData]; data && !validDataLength(tx[~sfData], maxDataPayloadLength))
|
||||
return temInvalidToMalformed(ctx);
|
||||
if (!validNumericRange(tx[~sfManagementFeeRate], maxManagementFeeRate))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
if (!validNumericRange(tx[~sfCoverRateMinimum], maxCoverRate))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
if (!validNumericRange(tx[~sfCoverRateLiquidation], maxCoverRate))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
if (!validNumericRange(tx[~sfDebtMaximum], Number(maxMPTokenAmount), Number(0)))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
if (tx.isFieldPresent(sfLoanBrokerID))
|
||||
{
|
||||
@@ -35,16 +35,16 @@ LoanBrokerSet::preflight(PreflightContext const& ctx)
|
||||
// LoanBroker Object
|
||||
if (tx.isFieldPresent(sfManagementFeeRate) || tx.isFieldPresent(sfCoverRateMinimum) ||
|
||||
tx.isFieldPresent(sfCoverRateLiquidation))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
if (tx[sfLoanBrokerID] == beast::zero)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
}
|
||||
|
||||
if (auto const vaultID = tx.at(~sfVaultID))
|
||||
{
|
||||
if (*vaultID == beast::zero)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -53,7 +53,7 @@ LoanBrokerSet::preflight(PreflightContext const& ctx)
|
||||
// Both must be zero or non-zero.
|
||||
if (minimumZero != liquidationZero)
|
||||
{
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ NotTEC
|
||||
LoanDelete::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
if (ctx.tx[sfLoanID] == beast::zero)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ NotTEC
|
||||
LoanManage::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
if (ctx.tx[sfLoanID] == beast::zero)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
// Flags are mutually exclusive
|
||||
if (auto const flagField = ctx.tx[~sfFlags]; flagField && *flagField)
|
||||
|
||||
@@ -28,7 +28,7 @@ NotTEC
|
||||
LoanPay::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
if (ctx.tx[sfLoanID] == beast::zero)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
if (ctx.tx[sfAmount] <= beast::zero)
|
||||
return temBAD_AMOUNT;
|
||||
|
||||
@@ -53,40 +53,40 @@ LoanSet::preflight(PreflightContext const& ctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (auto const data = tx[~sfData]; data && !data->empty() && !validDataLength(tx[~sfData], maxDataPayloadLength))
|
||||
return temINVALID;
|
||||
if (auto const data = tx[~sfData]; data && !validDataLength(tx[~sfData], maxDataPayloadLength))
|
||||
return temInvalidToMalformed(ctx);
|
||||
for (auto const& field : {&sfLoanServiceFee, &sfLatePaymentFee, &sfClosePaymentFee})
|
||||
{
|
||||
if (!validNumericMinimum(tx[~*field]))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
}
|
||||
// Principal Requested is required
|
||||
if (auto const p = tx[sfPrincipalRequested]; p <= 0)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
else if (!validNumericRange(tx[~sfLoanOriginationFee], p))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
if (!validNumericRange(tx[~sfInterestRate], maxInterestRate))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
if (!validNumericRange(tx[~sfOverpaymentFee], maxOverpaymentFee))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
if (!validNumericRange(tx[~sfLateInterestRate], maxLateInterestRate))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
if (!validNumericRange(tx[~sfCloseInterestRate], maxCloseInterestRate))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
if (!validNumericRange(tx[~sfOverpaymentInterestRate], maxOverpaymentInterestRate))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
if (auto const paymentTotal = tx[~sfPaymentTotal]; paymentTotal && *paymentTotal <= 0)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
if (auto const paymentInterval = tx[~sfPaymentInterval];
|
||||
!validNumericMinimum(paymentInterval, LoanSet::minPaymentInterval))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
// Grace period is between min default value and payment interval
|
||||
else if (auto const gracePeriod = tx[~sfGracePeriod]; //
|
||||
!validNumericRange(
|
||||
gracePeriod, paymentInterval.value_or(LoanSet::defaultPaymentInterval), defaultGracePeriod))
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
// Copied from preflight2
|
||||
if (counterPartySig)
|
||||
@@ -96,7 +96,7 @@ LoanSet::preflight(PreflightContext const& ctx)
|
||||
}
|
||||
|
||||
if (auto const brokerID = ctx.tx[~sfLoanBrokerID]; brokerID && *brokerID == beast::zero)
|
||||
return temINVALID;
|
||||
return temInvalidToMalformed(ctx);
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user