xrpld
Loading...
Searching...
No Matches
LoanValidation_test.cpp
1#include <test/app/lending/LoanTestBase.h>
2#include <test/jtx/Account.h>
3#include <test/jtx/Env.h>
4#include <test/jtx/TestHelpers.h>
5#include <test/jtx/amount.h>
6#include <test/jtx/envconfig.h>
7#include <test/jtx/fee.h>
8#include <test/jtx/flags.h>
9#include <test/jtx/jtx_json.h>
10#include <test/jtx/mpt.h>
11#include <test/jtx/pay.h>
12#include <test/jtx/sponsor.h>
13#include <test/jtx/ter.h>
14#include <test/jtx/trust.h>
15#include <test/jtx/txflags.h>
16
17#include <xrpl/basics/Number.h>
18#include <xrpl/basics/base_uint.h>
19#include <xrpl/basics/strHex.h>
20#include <xrpl/beast/unit_test/suite.h>
21#include <xrpl/beast/utility/Journal.h>
22#include <xrpl/beast/utility/Zero.h>
23#include <xrpl/json/json_value.h>
24#include <xrpl/json/to_string.h>
25#include <xrpl/ledger/helpers/AccountRootHelpers.h>
26#include <xrpl/protocol/Feature.h>
27#include <xrpl/protocol/Indexes.h>
28#include <xrpl/protocol/Issue.h>
29#include <xrpl/protocol/Protocol.h>
30#include <xrpl/protocol/SField.h>
31#include <xrpl/protocol/STTx.h>
32#include <xrpl/protocol/SeqProxy.h>
33#include <xrpl/protocol/TER.h>
34#include <xrpl/protocol/TxFlags.h>
35#include <xrpl/protocol/jss.h>
36#include <xrpl/tx/transactors/lending/LoanSet.h>
37
38#include <cstdint>
39#include <optional>
40
41namespace xrpl::test {
42
44{
45private:
46 void
48 {
49 testcase("Disabled");
50 // Lending Protocol depends on Single Asset Vault (SAV). Test
51 // combinations of the two amendments.
52 // Single Asset Vault depends on MPTokensV1, but don't test every combo
53 // of that.
54 using namespace jtx;
55 auto failAll = [this](FeatureBitset features) {
56 Env env(*this, features);
57
58 Account const alice{"alice"};
59 Account const bob{"bob"};
60 env.fund(XRP(10000), alice, bob);
61
62 auto const keylet = keylet::loanBroker(alice, SeqProxy::rawSequence(env.seq(alice)));
63
64 using namespace std::chrono_literals;
65 using namespace loan;
66
67 // counter party signature is optional on LoanSet. Confirm that by
68 // sending transaction without one.
69 auto setTx = env.jt(set(alice, keylet.key, Number(10000)), Ter(temDISABLED));
70 env(setTx);
71
72 // All loan transactions are disabled.
73 // 1. LoanSet
74 setTx = env.jt(setTx, Sig(sfCounterpartySignature, bob), Ter(temDISABLED));
75 env(setTx);
76 // Actual sequence will be based off the loan broker, but we
77 // obviously don't have one of those if the amendment is disabled
78 auto const loanKeylet = keylet::loan(keylet.key, SeqProxy::rawSequence(env.seq(alice)));
79 // Other Loan transactions are disabled, too.
80 // 2. LoanDelete
81 env(del(alice, loanKeylet.key), Ter(temDISABLED));
82 // 3. LoanManage
83 env(manage(alice, loanKeylet.key, tfLoanImpair), Ter(temDISABLED));
84 // 4. LoanPay
85 env(pay(alice, loanKeylet.key, XRP(500)), Ter(temDISABLED));
86 };
87 failAll(all_ - featureMPTokensV1);
88 failAll(all_ - featureSingleAssetVault - featureLendingProtocol);
89 failAll(all_ - featureSingleAssetVault);
90 failAll(all_ - featureLendingProtocol);
91 }
92
93 void
95 {
97 std::string("Invalid LoanSet (") +
98 (vaultKind == VaultKind::OpenEnded ? "open-ended" : "closed-ended") + " vault)");
99 using namespace jtx;
100 using namespace loan;
101 Account const lender{"lender"};
102 Account const issuer{"issuer"};
103 Account const borrower{"borrower"};
104 Account const sponsor{"sponsor"};
105 auto const iou = issuer["IOU"];
106
107 auto testWrapper = [&](auto&& test) {
108 Env env(*this);
109 env.fund(XRP(1'000), lender, issuer, borrower, sponsor);
110 env(trust(lender, iou(10'000'000)));
111 env(pay(issuer, lender, iou(5'000'000)));
112 BrokerInfo const brokerInfo{
113 createVaultAndBroker(env, issuer["IOU"], lender, {.vaultKind = vaultKind})};
114
115 auto const loanSetFee = Fee(env.current()->fees().base * 2);
116 Number const debtMaximumRequest = brokerInfo.asset(1'000).value();
117 test(env, brokerInfo, loanSetFee, debtMaximumRequest);
118 };
119
120 // preflight:
121 testWrapper([&](Env& env,
122 BrokerInfo const& brokerInfo,
123 jtx::Fee const& loanSetFee,
124 Number const& debtMaximumRequest) {
125 for (auto const sponsorFlags : {spfSponsorReserve, spfSponsorReserve | spfSponsorFee})
126 {
127 env(set(borrower, brokerInfo.brokerID, debtMaximumRequest),
128 sponsor::As(sponsor, sponsorFlags),
129 Sig(sfCounterpartySignature, lender),
130 loanSetFee,
132 }
133
134 // first temBAD_SIGNER: TODO
135 // invalid grace period
136 {
137 // zero grace period
138 env(set(borrower, brokerInfo.brokerID, debtMaximumRequest),
139 Sig(sfCounterpartySignature, lender),
140 kGracePeriod(0),
141 loanSetFee,
142 Ter(temINVALID));
143
144 // grace period less than default minimum
145 env(set(borrower, brokerInfo.brokerID, debtMaximumRequest),
146 Sig(sfCounterpartySignature, lender),
147 kGracePeriod(LoanSet::kDefaultGracePeriod - 1),
148 loanSetFee,
149 Ter(temINVALID));
150
151 // grace period greater than payment interval
152 env(set(borrower, brokerInfo.brokerID, debtMaximumRequest),
153 Sig(sfCounterpartySignature, lender),
154 kPaymentInterval(120),
155 kGracePeriod(121),
156 loanSetFee,
157 Ter(temINVALID));
158 }
159 // empty/zero broker ID
160 {
161 auto jv = set(borrower, uint256{}, debtMaximumRequest);
162
163 auto testZeroBrokerID = [&](std::string const& id, std::uint32_t flags = 0) {
164 // empty broker ID
165 jv[sfLoanBrokerID] = id;
166 env(jv,
167 Sig(sfCounterpartySignature, lender),
168 loanSetFee,
169 Txflags(flags),
170 Ter(temINVALID));
171 };
172 // empty broker ID
173 testZeroBrokerID(std::string(""));
174 // zero broker ID
175 // needs a flag to distinguish the parsed STTx from the prior
176 // test
177 testZeroBrokerID(to_string(uint256{}), tfFullyCanonicalSig);
178 }
179
180 // preflightCheckSigningKey() failure:
181 // can it happen? the signature is checked before transactor
182 // executes
183
184 JTx const tx = env.jt(
185 set(borrower, brokerInfo.brokerID, debtMaximumRequest),
186 Sig(sfCounterpartySignature, lender),
187 loanSetFee);
188 STTx local = *(tx.stx);
189 auto counterpartySig = local.getFieldObject(sfCounterpartySignature);
190 auto badPubKey = counterpartySig.getFieldVL(sfSigningPubKey);
191 badPubKey[20] ^= 0xAA;
192 counterpartySig.setFieldVL(sfSigningPubKey, badPubKey);
193 local.setFieldObject(sfCounterpartySignature, counterpartySig);
194 json::Value jvResult;
195 jvResult[jss::tx_blob] = strHex(local.getSerializer().slice());
196 auto res = env.rpc("json", "submit", to_string(jvResult))["result"];
197 BEAST_EXPECT(
198 res[jss::error] == "invalidTransaction" &&
199 res[jss::error_exception] ==
200 "fails local checks: Counterparty: Invalid signature.");
201 });
202
203 // preclaim:
204 testWrapper([&](Env& env,
205 BrokerInfo const& brokerInfo,
206 jtx::Fee const& loanSetFee,
207 Number const& debtMaximumRequest) {
208 // canAddHoldingFailure (IOU only, if MPT doesn't have
209 // MPTCanTransfer set, then can't create Vault/LoanBroker,
210 // and LoanSet will fail with different error
211 env(fclear(issuer, asfDefaultRipple));
212 env.close();
213 env(set(borrower, brokerInfo.brokerID, debtMaximumRequest),
214 Sig(sfCounterpartySignature, lender),
215 loanSetFee,
217 });
218
219 // doApply:
220 testWrapper([&](Env& env,
221 BrokerInfo const& brokerInfo,
222 jtx::Fee const& loanSetFee,
223 Number const& debtMaximumRequest) {
224 auto const amt =
225 env.balance(borrower) - accountReserve(*env.current(), borrower.id(), env.journal);
226 env(pay(borrower, issuer, amt));
227
228 // tecINSUFFICIENT_RESERVE
229 env(set(borrower, brokerInfo.brokerID, debtMaximumRequest),
230 Sig(sfCounterpartySignature, lender),
231 loanSetFee,
233
234 // addEmptyHolding failure
235 env(pay(issuer, borrower, amt));
236 env(fset(issuer, asfGlobalFreeze));
237 env.close();
238
239 env(set(borrower, brokerInfo.brokerID, debtMaximumRequest),
240 Sig(sfCounterpartySignature, lender),
241 loanSetFee,
242 Ter(tecFROZEN));
243 });
244 }
245
246 void
248 {
249 testcase("Invalid LoanDelete");
250 using namespace jtx;
251 using namespace loan;
252
253 // preflight: temINVALID, LoanID == zero
254 {
255 Account const alice{"alice"};
256 Env env(*this);
257 env.fund(XRP(1'000), alice);
258 env.close();
259 env(del(alice, beast::kZero), Ter(temINVALID));
260 }
261 }
262
263 void
265 {
266 testcase("Invalid LoanManage");
267 using namespace jtx;
268 using namespace loan;
269
270 // preflight: temINVALID, LoanID == zero
271 {
272 Account const alice{"alice"};
273 Env env(*this);
274 env.fund(XRP(1'000), alice);
275 env.close();
276 env(manage(alice, beast::kZero, tfLoanDefault), Ter(temINVALID));
277 }
278 }
279
280 void
282 {
283 testcase("Invalid LoanPay");
284 using namespace jtx;
285 using namespace loan;
286 Account const lender{"lender"};
287 Account const issuer{"issuer"};
288 Account const borrower{"borrower"};
289 auto const iou = issuer["IOU"];
290
291 // preclaim
292 Env env(*this);
293 env.fund(XRP(1'000), lender, issuer, borrower);
294 env(trust(lender, iou(10'000'000)));
295 env(pay(issuer, lender, iou(5'000'000)));
296 BrokerInfo brokerInfo{createVaultAndBroker(env, issuer["IOU"], lender)};
297
298 auto const loanSetFee = Fee(env.current()->fees().base * 2);
299 STAmount const debtMaximumRequest = brokerInfo.asset(1'000).value();
300
301 env(set(borrower, brokerInfo.brokerID, debtMaximumRequest),
302 Sig(sfCounterpartySignature, lender),
303 loanSetFee);
304
305 env.close();
306
307 std::uint32_t const loanSequence = 1;
308 auto const loanKeylet =
309 keylet::loan(brokerInfo.brokerID, SeqProxy::rawSequence(loanSequence));
310
311 env(fset(issuer, asfGlobalFreeze));
312 env.close();
313
314 // preclaim: tecFROZEN
315 env(pay(borrower, loanKeylet.key, debtMaximumRequest), Ter(tecFROZEN));
316 env.close();
317
318 env(fclear(issuer, asfGlobalFreeze));
319 env.close();
320
321 auto const pseudoBroker = [&]() -> std::optional<Account> {
322 if (auto brokerSle = env.le(keylet::loanBroker(brokerInfo.brokerID));
323 BEAST_EXPECT(brokerSle))
324 {
325 return Account{"pseudo", brokerSle->at(sfAccount)};
326 }
327
328 return std::nullopt;
329 }();
330 if (!pseudoBroker)
331 return;
332
333 // Lender and pseudoaccount must both be frozen
334 env(trust(issuer, lender["IOU"](1'000), lender, tfSetFreeze | tfSetDeepFreeze));
335 env(trust(
336 issuer, (*pseudoBroker)["IOU"](1'000), *pseudoBroker, tfSetFreeze | tfSetDeepFreeze));
337 env.close();
338
339 // preclaim: tecFROZEN due to deep frozen
340 env(pay(borrower, loanKeylet.key, debtMaximumRequest), Ter(tecFROZEN));
341 env.close();
342
343 // Only one needs to be unfrozen
344 env(trust(issuer, lender["IOU"](1'000), tfClearFreeze | tfClearDeepFreeze));
345 env.close();
346
347 // The payment is late by this point
348 env(pay(borrower, loanKeylet.key, debtMaximumRequest), Ter(tecEXPIRED));
349 env.close();
350 env(pay(borrower, loanKeylet.key, debtMaximumRequest, tfLoanLatePayment));
351 env.close();
352
353 // preclaim: tecKILLED
354 // note that tecKILLED in loanMakePayment()
355 // doesn't happen because of the preclaim check.
356 env(pay(borrower, loanKeylet.key, debtMaximumRequest), Ter(tecKILLED));
357 }
358
359 void
361 {
362 testcase("Require Auth - Implicit Pseudo-account authorization");
363 using namespace jtx;
364 using namespace loan;
365 Account const lender{"lender"};
366 Account const issuer{"issuer"};
367 Account const borrower{"borrower"};
368 Env env(*this);
369
370 env.fund(XRP(100'000), issuer, lender, borrower);
371 env.close();
372
373 auto asset = MPTTester({
374 .env = env,
375 .issuer = issuer,
376 .holders = {lender, borrower},
377 .flags = kMptDexFlags | tfMPTRequireAuth | tfMPTCanClawback | tfMPTCanLock,
378 .authHolder = true,
379 });
380
381 env(pay(issuer, lender, asset(5'000'000)));
382 BrokerInfo brokerInfo{createVaultAndBroker(env, asset, lender)};
383
384 auto const loanSetFee = Fee(env.current()->fees().base * 2);
385 STAmount const debtMaximumRequest = brokerInfo.asset(1'000).value();
386
387 auto forUnauthAuth = [&](auto&& doTx) {
388 for (auto const flag : {tfMPTUnauthorize, 0u})
389 {
390 asset.authorize({.account = issuer, .holder = borrower, .flags = flag});
391 env.close();
392 doTx(flag == 0);
393 env.close();
394 }
395 };
396
397 // Can't create a loan if the borrower is not authorized
398 forUnauthAuth([&](bool authorized) {
399 auto const err = !authorized ? Ter(tecNO_AUTH) : Ter(tesSUCCESS);
400 env(set(borrower, brokerInfo.brokerID, debtMaximumRequest),
401 Sig(sfCounterpartySignature, lender),
402 loanSetFee,
403 err);
404 });
405
406 static constexpr std::uint32_t kLoanSequence = 1;
407 auto const loanKeylet =
408 keylet::loan(brokerInfo.brokerID, SeqProxy::rawSequence(kLoanSequence));
409
410 // Can't loan pay if the borrower is not authorized
411 forUnauthAuth([&](bool authorized) {
412 auto const err = !authorized ? Ter(tecNO_AUTH) : Ter(tesSUCCESS);
413 env(pay(borrower, loanKeylet.key, debtMaximumRequest), err);
414 });
415 }
416
417 void
419 {
420 testcase("RIPD-4125 - overpayment");
421
422 using namespace jtx;
423
424 Account const issuer("issuer");
425 Account const lender("lender");
426 Account const borrower("borrower");
427
428 BrokerParameters const brokerParams{
429 .vaultDeposit = 100'000,
430 .debtMax = 0,
431 .coverRateMin = TenthBips32{0},
432 .managementFeeRate = TenthBips16{0},
433 .coverRateLiquidation = TenthBips32{0}};
434 LoanParameters const loanParams{
435 .account = lender,
436 .counter = borrower,
437 .principalRequest = Number{200000, -6},
438 .interest = TenthBips32{50000},
439 .payTotal = 3,
440 .payInterval = 200,
441 .gracePd = 60,
442 .flags = tfLoanOverpayment,
443 };
444
445 auto const assetType = AssetType::XRP;
446
447 Env env(*this, makeConfig(), all_, nullptr, beast::Severity::Warning);
448
449 auto loanResult =
450 createLoan(env, assetType, brokerParams, loanParams, issuer, lender, borrower);
451
452 if (BEAST_EXPECT(loanResult); !loanResult.has_value())
453 return;
454
455 auto broker = std::get<BrokerInfo>(*loanResult);
456 auto loanKeylet = std::get<Keylet>(*loanResult);
457 auto pseudoAcct = std::get<Account>(*loanResult);
458
459 VerifyLoanStatus const verifyLoanStatus(env, broker, pseudoAcct, loanKeylet);
460
461 auto const state = getCurrentState(env, broker, loanKeylet);
462
463 env(loan::pay(
464 borrower,
465 loanKeylet.key,
466 STAmount{broker.asset, state.periodicPayment * 3 / 2 + 1},
467 tfLoanOverpayment));
468 env.close();
469
470 PaymentParameters const paymentParams{
471 .showStepBalances = false,
472 .validateBalances = true,
473 };
474
476 env,
477 broker,
478 loanParams,
479 loanKeylet,
480 verifyLoanStatus,
481 issuer,
482 lender,
483 borrower,
484 paymentParams);
485 }
486
487 void
489 {
490 // From FIND-003
491 testcase << "Wrong Max Debt Behavior";
492
493 using namespace jtx;
494 using namespace std::chrono_literals;
495 Env env(*this, features);
496
497 Account const issuer{"issuer"};
498 Account const lender{"lender"};
499
500 BrokerParameters const brokerParams{.debtMax = 0};
501 env.fund(XRP(brokerParams.vaultDeposit * 100), issuer, noripple(lender));
502 env.close();
503
504 PrettyAsset const xrpAsset{xrpIssue(), 1'000'000};
505
506 BrokerInfo const broker{createVaultAndBroker(env, xrpAsset, lender, brokerParams)};
507
508 if (auto const brokerSle = env.le(keylet::loanBroker(broker.brokerID));
509 BEAST_EXPECT(brokerSle))
510 {
511 BEAST_EXPECT(brokerSle->at(sfDebtMaximum) == 0);
512 }
513
514 using namespace loan;
515
516 auto const loanSetFee = Fee(env.current()->fees().base * 2);
517 Number const principalRequest{1, 3};
518
519 auto createJson = env.json(set(lender, broker.brokerID, principalRequest), Fee(loanSetFee));
520
521 json::Value counterpartyJson{json::ValueType::Object};
522 counterpartyJson[sfTxnSignature] = createJson[sfTxnSignature];
523 counterpartyJson[sfSigningPubKey] = createJson[sfSigningPubKey];
524 if (!BEAST_EXPECT(!createJson.isMember(jss::Signers)))
525 counterpartyJson[sfSigners] = createJson[sfSigners];
526
527 createJson = env.json(createJson, Json(sfCounterpartySignature, counterpartyJson));
528 env(createJson);
529
530 env.close();
531 }
532
533 void
545
546 // Tests run under each entry in amendmentCombinations().
547 void
552
553public:
554 void
555 run() override
556 {
558 for (auto const& features : jtx::amendmentCombinations(
559 {fixCleanup3_1_3, fixCleanup3_2_0, featureMPTokensV2}, all_))
560 runAmendmentSensitive(features);
561 }
562};
563
564BEAST_DEFINE_TESTSUITE(LoanValidation, tx, xrpl);
565
566} // namespace xrpl::test
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:155
Represents a JSON value.
Definition json_value.h:117
static constexpr std::uint32_t kDefaultGracePeriod
Number is a floating point type that can represent a wide range of values.
Definition Number.h:351
Blob getFieldVL(SField const &field) const
Definition STObject.cpp:649
Serializer getSerializer() const
Definition STObject.h:1003
void setFieldObject(SField const &field, STObject const &v)
Definition STObject.cpp:839
STObject getFieldObject(SField const &field) const
Definition STObject.cpp:678
static constexpr SeqProxy rawSequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
Definition SeqProxy.h:62
Slice slice() const noexcept
Definition Serializer.h:45
FeatureBitset const all_
BrokerInfo createVaultAndBroker(jtx::Env &env, jtx::PrettyAsset const &asset, jtx::Account const &lender, BrokerParameters const &params=BrokerParameters::defaults())
LoanState getCurrentState(jtx::Env const &env, BrokerInfo const &broker, Keylet const &loanKeylet)
Get the state without checking anything.
void makeLoanPayments(jtx::Env &env, BrokerInfo const &broker, LoanParameters const &loanParams, Keylet const &loanKeylet, VerifyLoanStatus const &verifyLoanStatus, jtx::Account const &issuer, jtx::Account const &lender, jtx::Account const &borrower, PaymentParameters const &paymentParams=PaymentParameters::defaults())
std::optional< std::tuple< BrokerInfo, Keylet, jtx::Account > > createLoan(jtx::Env &env, AssetType assetType, BrokerParameters const &brokerParams, LoanParameters const &loanParams, jtx::Account const &issuer, jtx::Account const &lender, jtx::Account const &borrower)
void runAmendmentSensitive(FeatureBitset features)
void run() override
Runs the suite.
void testWrongMaxDebtBehavior(FeatureBitset features)
void testInvalidLoanSet(VaultKind vaultKind)
Immutable cryptographic account descriptor.
Definition jtx/Account.h:21
AccountID id() const
Returns the Account ID.
A transaction testing environment.
Definition Env.h:161
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:133
json::Value json(JsonValue &&jv, FN const &... fN)
Create JSON from parameters.
Definition Env.h:750
SLE::const_pointer le(Account const &account) const
Return an account root.
Definition Env.cpp:311
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:323
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Definition Env.cpp:302
json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition Env.h:1056
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
Definition Env.h:721
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
Definition Env.cpp:201
beast::Journal const journal
Definition Env.h:204
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition Env.h:377
Set the fee on a JTx.
Definition fee.h:20
Inject raw JSON.
Definition jtx_json.h:16
Test helper for creating, mutating, and asserting MPT and confidential MPT ledger state.
Definition mpt.h:447
Set the regular signature on a JTx.
Definition sig.h:19
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition ter.h:18
Set the flags on a JTx.
Definition txflags.h:14
constexpr Zero kZero
Definition Zero.h:30
@ Object
object value (collection of name/value pairs).
Definition json_value.h:29
Keylet computation functions.
Definition Indexes.h:40
Keylet loan(uint256 const &loanBrokerID, SeqProxy const &loanSeq) noexcept
Definition Indexes.cpp:573
Keylet loanBroker(AccountID const &owner, SeqProxy const &seq) noexcept
Definition Indexes.cpp:567
json::Value pay(AccountID const &account, uint256 const &loanID, STAmount const &amount, std::uint32_t flags)
auto const kMptDexFlags
Definition mpt.h:45
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition pay.cpp:14
std::vector< FeatureBitset > amendmentCombinations(std::initializer_list< uint256 > features, FeatureBitset seed)
Returns all 2^N permutations of a seed FeatureBitset with each subset of the given features excluded.
Definition Env.h:123
XrpT const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:92
std::unique_ptr< Config > makeConfig(std::map< std::string, std::string > extraTxQ={}, std::map< std::string, std::string > extraVoting={})
json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition flags.h:110
std::array< Account, 1+sizeof...(Args)> noripple(Account const &account, Args const &... args)
Designate accounts as no-ripple in Env::fund.
Definition Env.h:86
json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition trust.cpp:18
json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition flags.cpp:15
static STAmount accountReserve(jtx::Env &env, std::uint32_t count=1)
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
constexpr FlagValue spfSponsorFee
Definition TxFlags.h:459
@ terNO_RIPPLE
Definition TER.h:220
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
Definition Issue.h:108
std::string strHex(FwdIt begin, FwdIt end)
Definition strHex.h:13
static bool authorized(Port const &port, std::map< std::string, std::string > const &h)
TenthBips< std::uint32_t > TenthBips32
Definition Units.h:454
TenthBips< std::uint16_t > TenthBips16
Definition Units.h:453
VaultKind
Vault kind.
Definition Protocol.h:335
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:651
@ temINVALID
Definition TER.h:98
@ temINVALID_FLAG
Definition TER.h:99
@ temDISABLED
Definition TER.h:102
@ tecNO_AUTH
Definition TER.h:303
@ tecFROZEN
Definition TER.h:306
@ tecEXPIRED
Definition TER.h:317
@ tecINSUFFICIENT_RESERVE
Definition TER.h:310
@ tecKILLED
Definition TER.h:319
BaseUInt< 256 > uint256
Definition base_uint.h:580
constexpr FlagValue spfSponsorReserve
Definition TxFlags.h:460
@ tesSUCCESS
Definition TER.h:245
constexpr FlagValue tfFullyCanonicalSig
Definition TxFlags.h:43
Helper class to compare the expected state of a loan and loan broker against the data in the ledger.
Execution context for applying a JSON transaction.
Definition JTx.h:27
std::shared_ptr< STTx const > stx
Definition JTx.h:37