mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-21 11:35:53 +00:00
LoanBrokerSet will charge a reserve increment when creating
- Refactor: Add a Transactor base function to make it easier to get the owner reserve increment as a fee. - Refactor: Add an overload jtx::fee(increment) to pay an owner reserve.
This commit is contained in:
@@ -72,7 +72,7 @@ class LoanBroker_test : public beast::unit_test::suite
|
|||||||
|
|
||||||
using namespace loanBroker;
|
using namespace loanBroker;
|
||||||
// Can't create a loan broker regardless of whether the vault exists
|
// Can't create a loan broker regardless of whether the vault exists
|
||||||
env(set(alice, keylet.key), ter(temDISABLED));
|
env(set(alice, keylet.key), fee(increment), ter(temDISABLED));
|
||||||
};
|
};
|
||||||
failAll(all - featureMPTokensV1);
|
failAll(all - featureMPTokensV1);
|
||||||
failAll(all - featureSingleAssetVault - featureLendingProtocol);
|
failAll(all - featureSingleAssetVault - featureLendingProtocol);
|
||||||
@@ -153,62 +153,80 @@ class LoanBroker_test : public beast::unit_test::suite
|
|||||||
{
|
{
|
||||||
auto badKeylet = keylet::vault(alice.id(), env.seq(alice));
|
auto badKeylet = keylet::vault(alice.id(), env.seq(alice));
|
||||||
// Try some failure cases
|
// Try some failure cases
|
||||||
|
// insufficient fee
|
||||||
|
env(set(evan, vault.vaultID), ter(telINSUF_FEE_P));
|
||||||
// not the vault owner
|
// not the vault owner
|
||||||
env(set(evan, vault.vaultID), ter(tecNO_PERMISSION));
|
env(set(evan, vault.vaultID),
|
||||||
|
fee(increment),
|
||||||
|
ter(tecNO_PERMISSION));
|
||||||
// not a vault
|
// not a vault
|
||||||
env(set(alice, badKeylet.key), ter(tecNO_ENTRY));
|
env(set(alice, badKeylet.key),
|
||||||
|
fee(increment),
|
||||||
|
ter(tecNO_ENTRY));
|
||||||
// flags are checked first
|
// flags are checked first
|
||||||
env(set(evan, vault.vaultID, ~tfUniversal),
|
env(set(evan, vault.vaultID, ~tfUniversal),
|
||||||
|
fee(increment),
|
||||||
ter(temINVALID_FLAG));
|
ter(temINVALID_FLAG));
|
||||||
// field length validation
|
// field length validation
|
||||||
// sfData: good length, bad account
|
// sfData: good length, bad account
|
||||||
env(set(evan, vault.vaultID),
|
env(set(evan, vault.vaultID),
|
||||||
|
fee(increment),
|
||||||
data(std::string(maxDataPayloadLength, 'X')),
|
data(std::string(maxDataPayloadLength, 'X')),
|
||||||
ter(tecNO_PERMISSION));
|
ter(tecNO_PERMISSION));
|
||||||
// sfData: too long
|
// sfData: too long
|
||||||
env(set(evan, vault.vaultID),
|
env(set(evan, vault.vaultID),
|
||||||
|
fee(increment),
|
||||||
data(std::string(maxDataPayloadLength + 1, 'Y')),
|
data(std::string(maxDataPayloadLength + 1, 'Y')),
|
||||||
ter(temINVALID));
|
ter(temINVALID));
|
||||||
// sfManagementFeeRate: good value, bad account
|
// sfManagementFeeRate: good value, bad account
|
||||||
env(set(evan, vault.vaultID),
|
env(set(evan, vault.vaultID),
|
||||||
managementFeeRate(maxFeeRate),
|
managementFeeRate(maxFeeRate),
|
||||||
|
fee(increment),
|
||||||
ter(tecNO_PERMISSION));
|
ter(tecNO_PERMISSION));
|
||||||
// sfManagementFeeRate: too big
|
// sfManagementFeeRate: too big
|
||||||
env(set(evan, vault.vaultID),
|
env(set(evan, vault.vaultID),
|
||||||
managementFeeRate(maxFeeRate + 1),
|
managementFeeRate(maxFeeRate + 1),
|
||||||
|
fee(increment),
|
||||||
ter(temINVALID));
|
ter(temINVALID));
|
||||||
// sfCoverRateMinimum: good value, bad account
|
// sfCoverRateMinimum: good value, bad account
|
||||||
env(set(evan, vault.vaultID),
|
env(set(evan, vault.vaultID),
|
||||||
coverRateMinimum(maxCoverRate),
|
coverRateMinimum(maxCoverRate),
|
||||||
|
fee(increment),
|
||||||
ter(tecNO_PERMISSION));
|
ter(tecNO_PERMISSION));
|
||||||
// sfCoverRateMinimum: too big
|
// sfCoverRateMinimum: too big
|
||||||
env(set(evan, vault.vaultID),
|
env(set(evan, vault.vaultID),
|
||||||
coverRateMinimum(maxCoverRate + 1),
|
coverRateMinimum(maxCoverRate + 1),
|
||||||
|
fee(increment),
|
||||||
ter(temINVALID));
|
ter(temINVALID));
|
||||||
// sfCoverRateLiquidation: good value, bad account
|
// sfCoverRateLiquidation: good value, bad account
|
||||||
env(set(evan, vault.vaultID),
|
env(set(evan, vault.vaultID),
|
||||||
coverRateLiquidation(maxCoverRate),
|
coverRateLiquidation(maxCoverRate),
|
||||||
|
fee(increment),
|
||||||
ter(tecNO_PERMISSION));
|
ter(tecNO_PERMISSION));
|
||||||
// sfCoverRateLiquidation: too big
|
// sfCoverRateLiquidation: too big
|
||||||
env(set(evan, vault.vaultID),
|
env(set(evan, vault.vaultID),
|
||||||
coverRateLiquidation(maxCoverRate + 1),
|
coverRateLiquidation(maxCoverRate + 1),
|
||||||
|
fee(increment),
|
||||||
ter(temINVALID));
|
ter(temINVALID));
|
||||||
// sfDebtMaximum: good value, bad account
|
// sfDebtMaximum: good value, bad account
|
||||||
env(set(evan, vault.vaultID),
|
env(set(evan, vault.vaultID),
|
||||||
debtMaximum(Number(0)),
|
debtMaximum(Number(0)),
|
||||||
|
fee(increment),
|
||||||
ter(tecNO_PERMISSION));
|
ter(tecNO_PERMISSION));
|
||||||
// sfDebtMaximum: overflow
|
// sfDebtMaximum: overflow
|
||||||
env(set(evan, vault.vaultID),
|
env(set(evan, vault.vaultID),
|
||||||
debtMaximum(Number(1, 100)),
|
debtMaximum(Number(1, 100)),
|
||||||
|
fee(increment),
|
||||||
ter(temINVALID));
|
ter(temINVALID));
|
||||||
// sfDebtMaximum: negative
|
// sfDebtMaximum: negative
|
||||||
env(set(evan, vault.vaultID),
|
env(set(evan, vault.vaultID),
|
||||||
debtMaximum(Number(-1)),
|
debtMaximum(Number(-1)),
|
||||||
|
fee(increment),
|
||||||
ter(temINVALID));
|
ter(temINVALID));
|
||||||
|
|
||||||
auto keylet = keylet::loanbroker(alice.id(), env.seq(alice));
|
auto keylet = keylet::loanbroker(alice.id(), env.seq(alice));
|
||||||
// Successfully create a Loan Broker with all default values.
|
// Successfully create a Loan Broker with all default values.
|
||||||
env(set(alice, vault.vaultID));
|
env(set(alice, vault.vaultID), fee(increment));
|
||||||
env.close();
|
env.close();
|
||||||
if (auto broker = env.le(keylet); BEAST_EXPECT(broker))
|
if (auto broker = env.le(keylet); BEAST_EXPECT(broker))
|
||||||
{
|
{
|
||||||
@@ -339,7 +357,8 @@ class LoanBroker_test : public beast::unit_test::suite
|
|||||||
managementFeeRate(123),
|
managementFeeRate(123),
|
||||||
debtMaximum(Number(9)),
|
debtMaximum(Number(9)),
|
||||||
coverRateMinimum(100),
|
coverRateMinimum(100),
|
||||||
coverRateLiquidation(200));
|
coverRateLiquidation(200),
|
||||||
|
fee(increment));
|
||||||
env.close();
|
env.close();
|
||||||
if (auto broker = env.le(keylet2); BEAST_EXPECT(broker))
|
if (auto broker = env.le(keylet2); BEAST_EXPECT(broker))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class fee
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool manual_ = true;
|
bool manual_ = true;
|
||||||
|
bool increment_ = false;
|
||||||
std::optional<STAmount> amount_;
|
std::optional<STAmount> amount_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -44,6 +45,10 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit fee(increment_t) : increment_(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
explicit fee(none_t)
|
explicit fee(none_t)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,13 +26,15 @@ namespace test {
|
|||||||
namespace jtx {
|
namespace jtx {
|
||||||
|
|
||||||
void
|
void
|
||||||
fee::operator()(Env&, JTx& jt) const
|
fee::operator()(Env& env, JTx& jt) const
|
||||||
{
|
{
|
||||||
if (!manual_)
|
if (!manual_)
|
||||||
return;
|
return;
|
||||||
jt.fill_fee = false;
|
jt.fill_fee = false;
|
||||||
|
if (increment_)
|
||||||
|
jt[sfFee] = STAmount(env.current()->fees().increment).getJson();
|
||||||
if (amount_)
|
if (amount_)
|
||||||
jt[jss::Fee] = amount_->getJson(JsonOptions::none);
|
jt[sfFee] = amount_->getJson(JsonOptions::none);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace jtx
|
} // namespace jtx
|
||||||
|
|||||||
@@ -49,6 +49,16 @@ struct disabled_t
|
|||||||
};
|
};
|
||||||
static disabled_t const disabled;
|
static disabled_t const disabled;
|
||||||
|
|
||||||
|
/** Used for fee() calls that use an owner reserve increment */
|
||||||
|
struct increment_t
|
||||||
|
{
|
||||||
|
increment_t()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static increment_t const increment;
|
||||||
|
|
||||||
} // namespace jtx
|
} // namespace jtx
|
||||||
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
|
|||||||
@@ -1319,21 +1319,16 @@ class Invariants_test : public beast::unit_test::suite
|
|||||||
auto [tx, vKeylet] =
|
auto [tx, vKeylet] =
|
||||||
vault.create({.owner = a, .asset = xrpAsset});
|
vault.create({.owner = a, .asset = xrpAsset});
|
||||||
env(tx);
|
env(tx);
|
||||||
env.close();
|
|
||||||
BEAST_EXPECT(env.le(vKeylet));
|
BEAST_EXPECT(env.le(vKeylet));
|
||||||
|
|
||||||
vaultID = vKeylet.key;
|
vaultID = vKeylet.key;
|
||||||
|
|
||||||
env(vault.deposit(
|
|
||||||
{.depositor = a, .id = vaultID, .amount = xrpAsset(50)}));
|
|
||||||
env.close();
|
|
||||||
|
|
||||||
// Create Loan Broker
|
// Create Loan Broker
|
||||||
using namespace loanBroker;
|
using namespace loanBroker;
|
||||||
|
|
||||||
loanBrokerKeylet = keylet::loanbroker(a.id(), env.seq(a));
|
loanBrokerKeylet = keylet::loanbroker(a.id(), env.seq(a));
|
||||||
// Create a Loan Broker with all default values.
|
// Create a Loan Broker with all default values.
|
||||||
env(set(a, vaultID));
|
env(set(a, vaultID), fee(increment));
|
||||||
|
|
||||||
return BEAST_EXPECT(env.le(loanBrokerKeylet));
|
return BEAST_EXPECT(env.le(loanBrokerKeylet));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ XRPAmount
|
|||||||
AMMCreate::calculateBaseFee(ReadView const& view, STTx const& tx)
|
AMMCreate::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||||
{
|
{
|
||||||
// The fee required for AMMCreate is one owner reserve.
|
// The fee required for AMMCreate is one owner reserve.
|
||||||
return view.fees().increment;
|
return calculateOwnerReserveFee(view, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ XRPAmount
|
|||||||
DeleteAccount::calculateBaseFee(ReadView const& view, STTx const& tx)
|
DeleteAccount::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||||
{
|
{
|
||||||
// The fee required for AccountDelete is one owner reserve.
|
// The fee required for AccountDelete is one owner reserve.
|
||||||
return view.fees().increment;
|
return calculateOwnerReserveFee(view, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ LedgerStateFix::calculateBaseFee(ReadView const& view, STTx const& tx)
|
|||||||
{
|
{
|
||||||
// The fee required for LedgerStateFix is one owner reserve, just like
|
// The fee required for LedgerStateFix is one owner reserve, just like
|
||||||
// the fee for AccountDelete.
|
// the fee for AccountDelete.
|
||||||
return view.fees().increment;
|
return calculateOwnerReserveFee(view, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
|
|||||||
@@ -92,6 +92,15 @@ LoanBrokerSet::doPreflight(PreflightContext const& ctx)
|
|||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XRPAmount
|
||||||
|
LoanBrokerSet::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||||
|
{
|
||||||
|
// One reserve increment is typically much greater than one base fee.
|
||||||
|
if (!tx.isFieldPresent(sfLoanBrokerID))
|
||||||
|
return calculateOwnerReserveFee(view, tx);
|
||||||
|
return Transactor::calculateBaseFee(view, tx);
|
||||||
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
LoanBrokerSet::preclaim(PreclaimContext const& ctx)
|
LoanBrokerSet::preclaim(PreclaimContext const& ctx)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ public:
|
|||||||
static NotTEC
|
static NotTEC
|
||||||
doPreflight(PreflightContext const& ctx);
|
doPreflight(PreflightContext const& ctx);
|
||||||
|
|
||||||
|
static XRPAmount
|
||||||
|
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||||
|
|
||||||
static TER
|
static TER
|
||||||
preclaim(PreclaimContext const& ctx);
|
preclaim(PreclaimContext const& ctx);
|
||||||
|
|
||||||
|
|||||||
@@ -233,6 +233,18 @@ Transactor::calculateBaseFee(ReadView const& view, STTx const& tx)
|
|||||||
return baseFee + (signerCount * baseFee);
|
return baseFee + (signerCount * baseFee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the fee in fee units, not scaled for load.
|
||||||
|
XRPAmount
|
||||||
|
Transactor::calculateOwnerReserveFee(ReadView const& view, STTx const& tx)
|
||||||
|
{
|
||||||
|
// One reserve increment is typically much greater than one base fee.
|
||||||
|
XRPL_ASSERT(
|
||||||
|
view.fees().increment > view.fees().base * 100,
|
||||||
|
"ripple::Transactor::calculateOwnerReserveFee : Owner reserve is much "
|
||||||
|
"greater than base fee");
|
||||||
|
return view.fees().increment;
|
||||||
|
}
|
||||||
|
|
||||||
XRPAmount
|
XRPAmount
|
||||||
Transactor::minimumFee(
|
Transactor::minimumFee(
|
||||||
Application& app,
|
Application& app,
|
||||||
|
|||||||
@@ -208,6 +208,10 @@ protected:
|
|||||||
Fees const& fees,
|
Fees const& fees,
|
||||||
ApplyFlags flags);
|
ApplyFlags flags);
|
||||||
|
|
||||||
|
// Returns the fee in fee units, not scaled for load.
|
||||||
|
static XRPAmount
|
||||||
|
calculateOwnerReserveFee(ReadView const& view, STTx const& tx);
|
||||||
|
|
||||||
// Base class always returns true
|
// Base class always returns true
|
||||||
static bool
|
static bool
|
||||||
isEnabled(PreflightContext const& ctx);
|
isEnabled(PreflightContext const& ctx);
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ XRPAmount
|
|||||||
VaultCreate::calculateBaseFee(ReadView const& view, STTx const& tx)
|
VaultCreate::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||||
{
|
{
|
||||||
// One reserve increment is typically much greater than one base fee.
|
// One reserve increment is typically much greater than one base fee.
|
||||||
return view.fees().increment;
|
return calculateOwnerReserveFee(view, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
|
|||||||
Reference in New Issue
Block a user