1#include <test/jtx/Account.h>
2#include <test/jtx/CaptureLogs.h>
3#include <test/jtx/Env.h>
4#include <test/jtx/TestHelpers.h>
5#include <test/jtx/acctdelete.h>
6#include <test/jtx/amount.h>
7#include <test/jtx/balance.h>
8#include <test/jtx/batch.h>
9#include <test/jtx/delegate.h>
10#include <test/jtx/delivermin.h>
11#include <test/jtx/did.h>
12#include <test/jtx/domain.h>
13#include <test/jtx/fee.h>
14#include <test/jtx/flags.h>
15#include <test/jtx/mpt.h>
16#include <test/jtx/multisign.h>
17#include <test/jtx/noop.h>
18#include <test/jtx/offer.h>
19#include <test/jtx/paths.h>
20#include <test/jtx/pay.h>
21#include <test/jtx/permissioned_domains.h>
22#include <test/jtx/rate.h>
23#include <test/jtx/regkey.h>
24#include <test/jtx/sendmax.h>
25#include <test/jtx/sig.h>
26#include <test/jtx/sponsor.h>
27#include <test/jtx/ter.h>
28#include <test/jtx/trust.h>
29#include <test/jtx/txflags.h>
30#include <test/jtx/vault.h>
32#include <xrpl/basics/Number.h>
33#include <xrpl/basics/Slice.h>
34#include <xrpl/basics/base_uint.h>
35#include <xrpl/basics/strHex.h>
36#include <xrpl/beast/unit_test/suite.h>
37#include <xrpl/json/json_value.h>
38#include <xrpl/json/to_string.h>
39#include <xrpl/ledger/Dir.h>
40#include <xrpl/ledger/helpers/DelegateHelpers.h>
41#include <xrpl/protocol/Feature.h>
42#include <xrpl/protocol/Indexes.h>
43#include <xrpl/protocol/Issue.h>
44#include <xrpl/protocol/KeyType.h>
45#include <xrpl/protocol/Permissions.h>
46#include <xrpl/protocol/SField.h>
47#include <xrpl/protocol/STObject.h>
48#include <xrpl/protocol/STTx.h>
49#include <xrpl/protocol/SecretKey.h>
50#include <xrpl/protocol/TER.h>
51#include <xrpl/protocol/TxFlags.h>
52#include <xrpl/protocol/TxSettings.h>
53#include <xrpl/protocol/XRPAmount.h>
54#include <xrpl/protocol/jss.h>
73 testcase(
"test feature not enabled");
76 Env env{*
this, features};
80 env.
fund(
XRP(1000000), gw, alice, bob);
96 testcase(
"test valid request creating, updating, deleting permissions");
102 env.
fund(
XRP(100000), gw, alice);
111 "Payment",
"EscrowCreate",
"EscrowFinish",
"TrustlineAuthorize",
"CheckCreate"};
117 auto comparePermissions = [&](
json::Value const& jle,
122 !jle[jss::result].isMember(jss::error) && jle[jss::result].isMember(jss::node));
123 BEAST_EXPECT(jle[jss::result][jss::node][
"LedgerEntryType"] == jss::Delegate);
124 BEAST_EXPECT(jle[jss::result][jss::node][jss::Account] == account.human());
125 BEAST_EXPECT(jle[jss::result][jss::node][sfAuthorize.jsonName] == authorize.human());
127 auto const& jPermissions = jle[jss::result][jss::node][sfPermissions.jsonName];
129 for (
auto const& permission : permissions)
132 jPermissions[i][sfPermission.jsonName][sfPermissionValue.jsonName] ==
139 comparePermissions(
delegate::entry(env, gw, alice), permissions, gw, alice);
142 auto const newPermissions =
149 comparePermissions(
delegate::entry(env, gw, alice), newPermissions, gw, alice);
155 BEAST_EXPECT(jle[jss::result][jss::error] ==
"entryNotFound");
160 comparePermissions(
delegate::entry(env, alice, gw), permissions, alice, gw);
163 BEAST_EXPECT(response[jss::result][jss::error] ==
"entryNotFound");
169 testcase(
"test invalid DelegateSet");
172 Env env(*
this, features);
176 env.
fund(
XRP(100000), gw, alice, bob);
207 jv[jss::TransactionType] = jss::DelegateSet;
208 jv[jss::Account] = gw.
human();
209 jv[sfAuthorize.jsonName] = alice.
human();
212 permissionValue[sfPermissionValue.jsonName] =
"Payment";
214 permissionObj[sfPermission.jsonName] = permissionValue;
215 permissionsJson.
append(permissionObj);
216 jv[sfPermissions.jsonName] = permissionsJson;
217 jv[sfFee.jsonName] = -1;
230 "TrustlineAuthorize",
232 "TrustlineAuthorize"}),
244 Vault const vault{env};
245 auto [tx,
keylet] = vault.create({.owner = gw, .asset =
xrpIssue()});
249 auto const sleVault = env.
le(
keylet);
250 BEAST_EXPECT(sleVault);
251 Account const vaultPseudo{
"vault", sleVault->at(sfAccount)};
299 env.
fund(
XRP(100000), bob, carol);
349 auto setup = [&](
Env& env) {
353 env.fund(
XRP(1000), alice, bob, carol);
361 auto [alice, bob, carol] = setup(env);
363 auto const aliceBalance = env.
balance(alice);
364 auto const bobBalance = env.
balance(bob);
365 auto const carolBalance = env.
balance(carol);
369 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
370 BEAST_EXPECT(env.
balance(bob) == bobBalance);
371 BEAST_EXPECT(env.
balance(carol) == carolBalance);
377 auto [alice, bob, carol] = setup(env);
381 auto const aliceBalance = env.
balance(alice);
382 auto const bobBalance = env.
balance(bob);
383 auto const carolBalance = env.
balance(carol);
385 auto const sendAmt =
XRP(100);
386 auto const feeAmt =
XRP(10);
389 BEAST_EXPECT(env.
balance(alice) == aliceBalance - sendAmt);
390 BEAST_EXPECT(env.
balance(bob) == bobBalance - feeAmt);
391 BEAST_EXPECT(env.
balance(carol) == carolBalance + sendAmt);
397 auto [alice, bob, carol] = setup(env);
401 auto const aliceBalance = env.
balance(alice);
402 auto const bobBalance = env.
balance(bob);
403 auto const carolBalance = env.
balance(carol);
405 env(
pay(alice, carol,
XRP(100)),
410 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
411 BEAST_EXPECT(env.
balance(bob) == bobBalance);
412 BEAST_EXPECT(env.
balance(carol) == carolBalance);
422 auto setup = [&](
Env& env) {
427 auto const baseFee = env.current()->fees().base;
428 auto const reserve = env.current()->fees().accountReserve(1, 1);
429 auto const paymentAmount =
XRP(1);
430 auto const highFee =
reserve + baseFee;
431 BEAST_EXPECT(highFee >
reserve);
433 env.fund(paymentAmount +
reserve + baseFee, alice);
434 env.fund(
XRP(1000), bob);
435 env.fund(
XRP(1000), carol);
454 auto [alice, bob, carol, paymentAmount, highFee,
reserve] = setup(env);
455 auto const aliceBalance = env.
balance(alice);
456 auto const bobBalance = env.
balance(bob);
457 auto const carolBalance = env.
balance(carol);
462 BEAST_EXPECT(env.
balance(alice) == aliceBalance - highFee);
463 BEAST_EXPECT(env.
balance(bob) == bobBalance);
464 BEAST_EXPECT(env.
balance(carol) == carolBalance);
471 auto [alice, bob, carol, paymentAmount, highFee,
reserve] = setup(env);
473 auto const alicePrePay = env.
balance(alice,
XRP);
475 auto const carolPrePay = env.
balance(carol,
XRP);
493 auto const baseFee = env.
current()->fees().base;
494 auto const baseReserve = env.
current()->fees().accountReserve(0, 1);
496 env.
fund(env.
current()->fees().accountReserve(1, 1) + baseFee +
XRP(1), alice);
497 env.
fund(baseReserve, bob);
504 auto const alicePreTx = env.
balance(alice,
XRP);
513 BEAST_EXPECT(env.
balance(bob,
XRP) < baseReserve);
528 auto const baseFee = env.
current()->fees().base;
542 auto const alicePrePay = env.
balance(alice,
XRP);
544 auto const carolPrePay = env.
balance(carol,
XRP);
565 env.
fund(
XRP(10000), alice, bob, carol);
568 auto aliceSeq = env.
seq(alice);
569 auto bobSeq = env.
seq(bob);
573 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
574 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
575 aliceSeq = env.
seq(alice);
576 bobSeq = env.
seq(bob);
578 for (
auto i = 0; i < 20; ++i)
583 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
584 BEAST_EXPECT(env.
seq(bob) == bobSeq);
585 aliceSeq = env.
seq(alice);
589 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
590 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
591 bobSeq = env.
seq(bob);
596 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
597 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
598 bobSeq = env.
seq(bob);
602 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
603 BEAST_EXPECT(env.
seq(bob) == bobSeq);
604 aliceSeq = env.
seq(alice);
621 env.
fund(
XRP(100000), alice, bob, carol);
628 BEAST_EXPECT(env.
closed()->exists(delegateKey));
632 dir.
begin(), dir.
end(), [&](
auto const& sle) { return sle->key() == key; });
644 auto const aliceBalance = env.
balance(alice);
645 auto const carolBalance = env.
balance(carol);
649 auto const deleteFee =
drops(env.
current()->fees().increment);
655 BEAST_EXPECT(!env.
closed()->exists(delegateKey));
659 BEAST_EXPECT(env.
balance(carol) == carolBalance + aliceBalance - deleteFee);
670 env.
fund(
XRP(100000), alice, bob, carol);
677 BEAST_EXPECT(env.
closed()->exists(delegateKey));
681 dir.
begin(), dir.
end(), [&](
auto const& sle) { return sle->key() == key; });
691 BEAST_EXPECT(sleAlice);
692 BEAST_EXPECT(sleAlice->getFieldU32(sfOwnerCount) == 1);
697 auto const bobBalance = env.
balance(bob);
698 auto const carolBalance = env.
balance(carol);
704 auto const deleteFee =
drops(env.
current()->fees().increment);
710 BEAST_EXPECT(!env.
closed()->exists(delegateKey));
714 BEAST_EXPECT(env.
balance(carol) == carolBalance + bobBalance - deleteFee);
718 BEAST_EXPECT(sleAlice2);
719 BEAST_EXPECT(sleAlice2->getFieldU32(sfOwnerCount) == 0);
721 auto const aliceDeleteFee =
drops(env.
current()->fees().increment);
737 env.
fund(
XRP(100000), alice, bob, carol, dave);
750 dir.
begin(), dir.
end(), [&](
auto const& sle) { return sle->key() == key; });
754 BEAST_EXPECT(env.
closed()->exists(aliceBobKey));
755 BEAST_EXPECT(env.
closed()->exists(carolBobKey));
764 auto const bobBalance = env.
balance(bob);
765 auto const daveBalance = env.
balance(dave);
767 auto const deleteFee =
drops(env.
current()->fees().increment);
776 BEAST_EXPECT(!env.
closed()->exists(aliceBobKey));
777 BEAST_EXPECT(!env.
closed()->exists(carolBobKey));
785 BEAST_EXPECT(env.
balance(dave) == daveBalance + bobBalance - deleteFee);
792 testcase(
"test delegate transaction");
866 auto const usd = gw[
"USD"];
867 auto const eur = gw2[
"EUR"];
872 env.
trust(usd(200), alice);
873 env.
trust(eur(400), gw);
918 BEAST_EXPECT(env.
balance(bob, usd) == usd(0));
928 BEAST_EXPECT(env.
balance(bob, usd) == usd(0));
946 env(
pay(gw2, gw, eur(200)));
970 auto const usd = gw[
"USD"];
975 env.
trust(usd(200), alice);
1010 BEAST_EXPECT(env.
balance(bob, usd) == usd(0));
1016 Env env(*
this, features);
1021 auto const usd = gw[
"USD"];
1023 env.
fund(
XRP(10000), alice, bob, carol, gw);
1025 env.
trust(usd(50000), alice);
1026 env.
trust(usd(50000), bob);
1027 env.
trust(usd(50000), carol);
1028 env(
pay(gw, alice, usd(10000)));
1029 env(
pay(gw, bob, usd(10000)));
1030 env(
pay(gw, carol, usd(10000)));
1035 env(
offer(carol,
XRP(100), usd(501)));
1043 env(
pay(gw, alice, usd(500)),
1051 env(
pay(gw, alice, usd(5000)),
1058 env(
pay(gw, alice, usd(5000)),
1072 env(
offer(bob,
XRP(100), usd(501)));
1080 env(
pay(alice, gw, usd(500)),
1088 env(
pay(alice, gw, usd(5000)),
1095 env(
pay(alice, gw, usd(5000)),
1111 Env env(*
this, features);
1115 auto const usd = gw[
"USD"];
1116 env.
fund(
XRP(10000), alice, bob, gw);
1117 env.
trust(usd(200), alice);
1141 auto const gwUSD = gw[
"USD"];
1142 auto const aliceUSD = alice[
"USD"];
1144 env.
fund(
XRP(10000), alice, bob, gw);
1145 env.
trust(gwUSD(200), alice);
1148 env(
pay(gw, alice, gwUSD(50)));
1155 env.
trust(gwUSD(0), alice);
1157 BEAST_EXPECT(env.
limit(alice, gwUSD.issue()) == gwUSD(0));
1159 env(
trust(gw, aliceUSD(200)));
1170 Env env(*
this, features);
1174 auto const gwUSD = gw[
"USD"];
1175 auto const aliceUSD = alice[
"USD"];
1177 env.
fund(
XRP(10000), alice, bob, gw);
1178 env.
trust(gwUSD(200), alice);
1181 env(
pay(gw, alice, gwUSD(50)));
1187 env(
trust(gw, aliceUSD(200)));
1193 if (!features[fixCleanup3_4_0])
1226 Env env(*
this, features);
1230 auto const gwUSD = gw[
"USD"];
1231 auto const aliceUSD = alice[
"USD"];
1233 env.
fund(
XRP(10000), alice, bob, gw);
1234 env.
trust(gwUSD(200), alice);
1237 env(
pay(gw, alice, gwUSD(50)));
1238 env(
trust(gw, aliceUSD(200)));
1241 env(
delegate::set(alice, bob, {
"PaymentBurn",
"PaymentMint"}));
1251 Env env(*
this, features);
1255 auto const usd = gw[
"USD"];
1256 env.
fund(
XRP(10000), alice, bob, gw);
1257 env.
trust(usd(200), alice);
1266 env(
pay(gw, alice, usd(100)),
1271 env(
pay(alice, gw, usd(50)),
1278 env(
pay(gw, alice, usd(100)),
1282 env(
pay(alice, gw, usd(50)),
1288 env(
pay(gw, alice, usd(100)),
1292 env(
pay(alice, gw, usd(50)),
1298 for (
auto const flag : {tfPartialPayment, tfNoRippleDirect, tfLimitQuality})
1300 env(
pay(gw, alice, usd(100)),
1304 env(
pay(alice, gw, usd(50)),
1319 Env env(*
this, features);
1323 auto const usd = gw[
"USD"];
1324 env.
fund(
XRP(10000), alice, bob, gw);
1325 env.
trust(usd(200), alice);
1346 MPTTester mpt(env, gw, {.holders = {alice, bob}});
1347 mpt.
create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer});
1349 mpt.authorize({.account = alice});
1350 mpt.authorize({.account = bob});
1352 auto const gwMPT = mpt[
"MPT"];
1353 env(
pay(gw, alice, gwMPT(500)));
1354 env(
pay(gw, bob, gwMPT(500)));
1356 auto aliceMPT = env.
balance(alice, gwMPT);
1357 auto bobMPT = env.
balance(bob, gwMPT);
1365 BEAST_EXPECT(env.
balance(alice, gwMPT) == aliceMPT + gwMPT(50));
1366 BEAST_EXPECT(env.
balance(bob, gwMPT) == bobMPT);
1367 aliceMPT = env.
balance(alice, gwMPT);
1376 BEAST_EXPECT(env.
balance(alice, gwMPT) == aliceMPT - gwMPT(50));
1377 BEAST_EXPECT(env.
balance(bob, gwMPT) == bobMPT);
1378 aliceMPT = env.
balance(alice, gwMPT);
1383 env(
delegate::set(alice, bob, {
"PaymentBurn",
"PaymentMint",
"Payment"}));
1386 BEAST_EXPECT(env.
balance(alice, gwMPT) == aliceMPT - gwMPT(50));
1387 BEAST_EXPECT(env.
balance(bob, gwMPT) == bobMPT);
1388 aliceMPT = env.
balance(alice, gwMPT);
1390 BEAST_EXPECT(env.
balance(alice, gwMPT) == aliceMPT - gwMPT(100));
1391 BEAST_EXPECT(env.
balance(bob, gwMPT) == bobMPT + gwMPT(100));
1405 auto const gwUSD = gw[
"USD"];
1406 auto const aliceUSD = alice[
"USD"];
1408 env.
fund(
XRP(10000), alice, bob, gw);
1409 env.
trust(gwUSD(200), alice);
1413 env(
pay(gw, alice, gwUSD(100)));
1426 env(
pay(gw, alice, aliceUSD(50)),
1445 env(
pay(alice, gw, aliceUSD(50)),
1465 Account const gw2{
"gateway2"};
1466 auto const gwUSD = gw[
"USD"];
1468 env.
fund(
XRP(10000), alice, bob, gw, gw2);
1471 env.
trust(gwUSD(200), alice);
1474 env(
pay(gw, alice, gwUSD(100)));
1477 env(
delegate::set(alice, bob, {
"PaymentMint",
"PaymentBurn"}));
1480 env(
pay(alice, gw, gw2[
"USD"](50)),
1487 Env env(*
this, features);
1491 Account const gw2{
"gateway2"};
1496 MPTTester mpt(env, gw, {.holders = {alice, bob}});
1497 mpt.
create({.ownerCount = 1, .flags = tfMPTCanTransfer});
1499 mpt.authorize({.account = alice});
1500 mpt.authorize({.account = bob});
1502 auto const gwMPT = mpt[
"MPT"];
1503 env(
pay(gw, alice, gwMPT(500)));
1504 env(
pay(gw, bob, gwMPT(500)));
1507 env(
delegate::set(alice, bob, {
"PaymentMint",
"PaymentBurn"}));
1521 env.
fund(
XRP(10000), alice, bob, gw);
1524 env(
delegate::set(alice, bob, {
"PaymentMint",
"PaymentBurn"}));
1527 env(
pay(alice, gw, alice[
"USD"](50)),
1539 auto const gwUSD = gw[
"USD"];
1540 auto const aliceUSD = alice[
"USD"];
1542 env.
fund(
XRP(10000), alice, bob, gw);
1548 env.
trust(gwUSD(200), alice);
1556 env(
pay(alice, gw, aliceUSD(50)),
1566 env(
trust(gw, aliceUSD(200)));
1570 env(
pay(alice, gw, aliceUSD(100)));
1579 env(
pay(gw, alice, aliceUSD(50)),
1591 env.
fund(
XRP(10000), alice, bob, gw);
1592 env.
trust(gw[
"USD"](200), alice);
1599 env(
pay(alice, gw, alice[
"USD"](50)),
1611 auto const usd = gw[
"USD"];
1612 env.
fund(
XRP(10000), alice, bob, gw);
1613 env.
trust(usd(200), alice);
1617 env(
delegate::set(alice, bob, {
"AccountDomainSet",
"PaymentMint"}));
1625 auto jt =
noop(alice);
1626 jt[sfDomain] =
strHex(domain);
1627 jt[sfDelegate] = bob.
human();
1629 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
1642 testcase(
"test TrustSet granular permissions");
1643 using namespace jtx;
1651 env.
fund(
XRP(10000), gw, alice, bob);
1652 env(
fset(gw, asfRequireAuth));
1663 env(
trust(alice, gw[
"USD"](50)));
1671 env(
trust(alice, gw[
"USD"](50), tfSetNoRipple),
1674 env(
trust(alice, gw[
"USD"](50), tfClearNoRipple),
1677 env(
trust(gw, gw[
"USD"](0), alice, tfSetDeepFreeze),
1680 env(
trust(gw, gw[
"USD"](0), alice, tfClearDeepFreeze),
1686 env(
trust(gw, gw[
"USD"](0), alice, tfSetfAuth),
1689 env(
trust(gw, gw[
"USD"](0), alice, tfSetFreeze),
1696 env(
trust(gw, gw[
"USD"](0), alice, tfClearFreeze),
1702 env(
trust(gw, gw[
"USD"](50), alice, tfSetfAuth),
1710 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
1714 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustlineUnfreeze"}));
1720 env(
trust(gw, gw[
"USD"](0), alice, tfSetFreeze),
1730 auto tx =
trust(alice, gw[
"USD"](50));
1731 tx[
"QualityIn"] =
"1000";
1733 auto tx2 =
trust(alice, gw[
"USD"](50));
1734 tx2[
"QualityOut"] =
"1000";
1736 auto tx3 =
trust(gw, alice[
"USD"](50));
1737 tx3[
"QualityIn"] =
"1000";
1739 auto tx4 =
trust(gw, alice[
"USD"](50));
1740 tx4[
"QualityOut"] =
"1000";
1746 auto tx5 =
trust(gw, alice[
"USD"](50));
1747 tx5[
"QualityOut"] =
"1000";
1749 auto tx6 =
trust(alice, gw[
"USD"](50));
1750 tx6[
"QualityOut"] =
"1000";
1763 env.
fund(
XRP(10000), gw, alice, bob);
1764 env(
fset(gw, asfRequireAuth));
1769 env(
delegate::set(alice, bob, {
"TrustlineUnfreeze",
"NFTokenCreateOffer"}));
1778 {
"TrustlineUnfreeze",
"NFTokenCreateOffer",
"TrustSet",
"AccountTransferRateSet"}));
1786 {
"TrustlineUnfreeze",
"NFTokenCreateOffer",
"TrustSet",
"AccountTransferRateSet"}));
1808 env.
fund(
XRP(10000), gw, alice, bob);
1809 env(
fset(gw, asfRequireAuth));
1811 env(
trust(alice, gw[
"USD"](50)));
1825 env.
fund(
XRP(10000), gw, alice, bob);
1827 env(
fset(gw, asfRequireAuth));
1829 env(
trust(alice, gw[
"USD"](50)));
1839 txJson[sfQualityOut.jsonName] = 100;
1843 env(
trust(gw, gw[
"USD"](0), alice, tfSetfAuth | tfSetNoRipple),
1852 testcase(
"test AccountSet granular permissions");
1853 using namespace jtx;
1860 auto const alice =
Account{
"alice"};
1861 auto const bob =
Account{
"bob"};
1862 env.
fund(
XRP(10000), alice, bob);
1873 auto jt =
noop(alice);
1874 jt[sfDomain] =
strHex(domain);
1875 jt[sfDelegate] = bob.human();
1879 env(
delegate::set(alice, bob, {
"TrustlineUnfreeze",
"AccountEmailHashSet"}));
1889 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
1894 BEAST_EXPECT(!env.
le(alice)->isFieldPresent(sfDomain));
1897 std::string const failDomain =
"fail_domain_update";
1898 jt[sfFlags] = tfRequireAuth;
1899 jt[sfDomain] =
strHex(failDomain);
1906 jt[sfDomain] =
strHex(domain);
1907 std::string const mh(
"5F31A79367DC3137FADA860C05742EE6");
1908 jt[sfEmailHash] = mh;
1912 env(
delegate::set(alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet"}));
1915 BEAST_EXPECT(
to_string((*env.
le(alice))[sfEmailHash]) == mh);
1916 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
1920 jt[sfMessageKey] =
strHex(rkp.first.slice());
1925 alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet",
"AccountMessageKeySet"}));
1930 BEAST_EXPECT(
strHex((*env.
le(alice))[sfMessageKey]) ==
strHex(rkp.first.slice()));
1931 jt[sfMessageKey] =
"";
1933 BEAST_EXPECT(!env.
le(alice)->isFieldPresent(sfMessageKey));
1942 {
"AccountDomainSet",
1943 "AccountEmailHashSet",
1944 "AccountMessageKeySet",
1945 "AccountTransferRateSet"}));
1947 auto jtRate =
rate(alice, 2.0);
1948 jtRate[sfDelegate] = bob.human();
1950 BEAST_EXPECT((*env.
le(alice))[sfTransferRate] == 2000000000);
1960 {
"AccountDomainSet",
1961 "AccountEmailHashSet",
1962 "AccountMessageKeySet",
1963 "AccountTransferRateSet",
1964 "AccountTickSizeSet"}));
1967 BEAST_EXPECT((*env.
le(alice))[sfTickSize] == 8);
1979 env(
fset(alice, asfRequireAuth));
1988 alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet",
"AccountMessageKeySet"}));
1993 "9633EC8AF54F16B5286DB1D7B519EF49EEFC050C0C8AC4384F1D88ACD1BFDF"
1995 auto jv2 =
noop(alice);
1996 jv2[sfDomain] =
strHex(domain);
1997 jv2[sfDelegate] = bob.human();
1998 jv2[sfWalletLocator] = locator;
2007 auto const alice =
Account{
"alice"};
2008 auto const bob =
Account{
"bob"};
2009 env.
fund(
XRP(10000), alice, bob);
2016 env(
fset(alice, flag));
2024 testSetClearFlag(asfRequireAuth);
2025 testSetClearFlag(asfAllowTrustLineClawback);
2029 alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet",
"AccountMessageKeySet"}));
2032 testSetClearFlag(asfDefaultRipple);
2033 testSetClearFlag(asfDepositAuth);
2034 testSetClearFlag(asfDisallowIncomingCheck);
2035 testSetClearFlag(asfDisallowIncomingNFTokenOffer);
2036 testSetClearFlag(asfDisallowIncomingPayChan);
2037 testSetClearFlag(asfDisallowIncomingTrustline);
2038 testSetClearFlag(asfDisallowXRP);
2039 testSetClearFlag(asfRequireDest);
2040 testSetClearFlag(asfGlobalFreeze);
2044 env(
fset(alice, asfAccountTxnID));
2046 BEAST_EXPECT(env.
le(alice)->isFieldPresent(sfAccountTxnID));
2051 jt[sfDelegate] = bob.human();
2052 jt[sfNFTokenMinter] = bob.human();
2057 bob, alice, {
"AccountDomainSet",
"AccountEmailHashSet",
"AccountMessageKeySet"}));
2064 env(
fset(bob, asfNoFreeze));
2072 env(
regkey(bob, bobKey));
2074 env(
fset(alice, asfDisableMaster),
2085 env.
fund(
XRP(10000), alice, bob);
2088 env(
delegate::set(alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet"}));
2092 auto jt =
noop(alice);
2093 jt[sfDomain] =
strHex(domain);
2094 jt[sfDelegate] = bob.
human();
2098 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
2104 auto const alice =
Account{
"alice"};
2105 auto const bob =
Account{
"bob"};
2106 env.
fund(
XRP(10000), alice, bob);
2114 auto txJson =
noop(alice);
2115 txJson[sfDomain] =
strHex(domain);
2116 txJson[sfDelegate] = bob.human();
2120 txJson[sfNFTokenMinter] = bob.human();
2131 env.
fund(
XRP(10000), alice, bob);
2137 auto jt =
noop(alice);
2138 jt[sfDelegate] = bob.
human();
2147 env.
fund(
XRP(10000), alice, bob);
2154 auto jt =
noop(alice);
2155 jt[sfDomain] =
strHex(domain);
2156 jt[sfDelegate] = bob.
human();
2170 testcase(
"test MPTokenIssuanceSet granular");
2171 using namespace jtx;
2178 env.
fund(
XRP(100000), alice, bob);
2181 MPTTester mpt(env, alice, {.fund =
false});
2183 mpt.create({.flags = tfMPTCanLock});
2205 mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob});
2208 .flags = tfMPTUnlock,
2213 env(
delegate::set(alice, bob, {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"}));
2215 mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob});
2216 mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob});
2225 env.
fund(
XRP(100000), alice, bob);
2228 MPTTester mpt(env, alice, {.fund =
false});
2230 mpt.create({.flags = tfMPTCanLock});
2236 mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob});
2240 .flags = tfMPTUnlock,
2246 env(
delegate::set(alice, bob, {
"NFTokenMint",
"MPTokenIssuanceLock",
"NFTokenBurn"}));
2251 .flags = tfMPTUnlock,
2259 {
"NFTokenMint",
"MPTokenIssuanceLock",
"NFTokenBurn",
"MPTokenIssuanceSet"}));
2260 mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob});
2262 mpt.set({.account = alice, .flags = tfMPTLock});
2263 mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob});
2264 mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob});
2272 env.
fund(
XRP(100000), alice, bob);
2275 MPTTester mpt(env, alice, {.fund =
false});
2277 mpt.create({.flags = tfMPTCanLock});
2291 env.
fund(
XRP(100000), alice, bob);
2293 MPTTester mpt(env, alice, {.fund =
false});
2294 mpt.
create({.flags = tfMPTCanLock});
2306 .flags = tfMPTSetCanLock,
2323 Account const credIssuer{
"credIssuer"};
2324 env.
fund(
XRP(100000), alice, bob, credIssuer);
2327 env(
pdomain::setTx(credIssuer, {{.issuer = credIssuer, .credType =
"credential"}}));
2331 MPTTester mpt(env, alice, {.fund =
false});
2332 mpt.
create({.flags = tfMPTCanLock | tfMPTCanTransfer});
2336 env(
delegate::set(alice, bob, {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"}));
2342 {.transferFee = 100},
2343 {.metadata =
"test"},
2344 {.domainID = domainID},
2345 {.flags = tfMPTSetCanTrade},
2346 {.flags = tfMPTSetCanClawback},
2349 {.flags = tfMPTLock, .domainID = domainID},
2352 for (
auto arg : args)
2354 arg.account = alice;
2366 testcase(
"test granular permission with sponsor common fields");
2367 using namespace jtx;
2373 auto const usd = gw[
"USD"];
2374 auto const feeAmt =
XRP(10);
2380 env.
trust(usd(200), alice);
2387 auto const gwBalance = env.
balance(gw);
2388 auto const bobBalance = env.
balance(bob);
2390 env(
pay(gw, alice, usd(50)),
2397 BEAST_EXPECT(env.
balance(gw) == gwBalance);
2398 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2405 env(
pay(gw, alice, usd(50)),
2411 BEAST_EXPECT(env.
balance(gw) == gwBalance);
2412 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2424 using namespace jtx;
2430 env.
fund(
XRP(100000), alice, bob, carol);
2436 auto aliceBalance = env.
balance(alice);
2437 auto bobBalance = env.
balance(bob);
2438 auto carolBalance = env.
balance(carol);
2442 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(100));
2443 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
2444 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(100));
2450 testcase(
"test single sign with bad secret");
2451 using namespace jtx;
2458 env.
fund(
XRP(100000), alice, bob, carol);
2464 auto aliceBalance = env.
balance(alice);
2465 auto bobBalance = env.
balance(bob);
2466 auto carolBalance = env.
balance(carol);
2468 env(
pay(alice, carol,
XRP(100)),
2474 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2475 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2476 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2484 env.
fund(
XRP(100000), alice, bob, carol);
2490 auto aliceBalance = env.
balance(alice);
2491 auto bobBalance = env.
balance(bob);
2492 auto carolBalance = env.
balance(carol);
2494 env(
pay(alice, carol,
XRP(100)),
2500 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2501 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2502 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2504 env(
pay(alice, carol,
XRP(100)),
2510 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2511 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2512 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2520 env.
fund(
XRP(100000), alice, bob, carol);
2523 auto aliceBalance = env.
balance(alice);
2524 auto bobBalance = env.
balance(bob);
2525 auto carolBalance = env.
balance(carol);
2527 env(
pay(alice, carol,
XRP(100)),
2533 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2534 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2535 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2537 env(
pay(alice, carol,
XRP(100)),
2543 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2544 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2545 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2553 using namespace jtx;
2560 Account const edward{
"edward"};
2561 env.
fund(
XRP(100000), alice, bob, carol, daria, edward);
2564 env(
signers(bob, 2, {{daria, 1}, {edward, 1}}));
2570 auto aliceBalance = env.
balance(alice);
2571 auto bobBalance = env.
balance(bob);
2572 auto carolBalance = env.
balance(carol);
2573 auto dariaBalance = env.
balance(daria);
2574 auto edwardBalance = env.
balance(edward);
2578 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(100));
2579 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
2580 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(100));
2581 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
2582 BEAST_EXPECT(env.
balance(edward) == edwardBalance);
2588 testcase(
"test multi sign which does not meet quorum");
2589 using namespace jtx;
2596 Account const edward{
"edward"};
2598 env.
fund(
XRP(100000), alice, bob, carol, daria, edward, fred);
2601 env(
signers(bob, 3, {{daria, 1}, {edward, 1}, {fred, 1}}));
2607 auto aliceBalance = env.
balance(alice);
2608 auto bobBalance = env.
balance(bob);
2609 auto carolBalance = env.
balance(carol);
2610 auto dariaBalance = env.
balance(daria);
2611 auto edwardBalance = env.
balance(edward);
2613 env(
pay(alice, carol,
XRP(100)),
2616 Msig(daria, edward),
2619 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2620 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2621 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2622 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
2623 BEAST_EXPECT(env.
balance(edward) == edwardBalance);
2632 testcase(
"test delegator as multisigner in delegate's signer list");
2633 using namespace jtx;
2640 env.
fund(
XRP(100000), alice, bob, carol, daria);
2647 env(
signers(bob, 2, {{alice, 1}, {daria, 1}}));
2650 auto aliceBalance = env.
balance(alice);
2651 auto bobBalance = env.
balance(bob);
2652 auto carolBalance = env.
balance(carol);
2653 auto const amt = 100;
2659 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(amt));
2660 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
2661 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(amt));
2668 aliceBalance = env.
balance(alice);
2669 bobBalance = env.
balance(bob);
2670 carolBalance = env.
balance(carol);
2675 env(
pay(alice, carol,
XRP(50)),
2681 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2682 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2683 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2691 testcase(
"test sign_for with delegated transaction");
2692 using namespace jtx;
2699 env.
fund(
XRP(100000), alice, bob, carol, daria);
2706 env(
signers(bob, 2, {{alice, 1}, {daria, 1}}));
2709 auto const baseFee = env.
current()->fees().base;
2711 auto const sendAmt = 1'000'000;
2714 jv[jss::tx_json][jss::Account] = alice.
human();
2715 jv[jss::tx_json][sfDelegate.jsonName] = bob.
human();
2716 jv[jss::tx_json][jss::TransactionType] = jss::Payment;
2717 jv[jss::tx_json][jss::Destination] = carol.
human();
2718 jv[jss::tx_json][jss::Amount] = sendAmt;
2720 jv[jss::tx_json][jss::Sequence] = env.
seq(alice);
2721 jv[jss::tx_json][jss::SigningPubKey] =
"";
2727 auto const aliceBalance = env.
balance(alice);
2728 auto const bobBalance = env.
balance(bob);
2729 auto const dariaBalance = env.
balance(daria);
2730 auto const carolBalance = env.
balance(carol);
2733 jv[jss::account] = alice.
human();
2734 jv[jss::secret] = alice.
name();
2735 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv))[jss::result];
2736 BEAST_EXPECT(jrr[jss::status] ==
"success");
2739 jv2[jss::tx_json] = jrr[jss::tx_json];
2740 jv2[jss::account] = daria.
human();
2741 jv2[jss::secret] = daria.
name();
2742 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv2))[jss::result];
2743 BEAST_EXPECT(jrr[jss::status] ==
"success");
2746 jvSubmit[jss::tx_json] = jrr[jss::tx_json];
2747 jrr = env.
rpc(
"json",
"submit_multisigned",
to_string(jvSubmit))[jss::result];
2748 BEAST_EXPECT(jrr[jss::status] ==
"success");
2751 BEAST_EXPECT(env.
balance(bob) == bobBalance - (10 * baseFee));
2752 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
2759 jv[jss::account] = bob.
human();
2760 jv[jss::secret] = bob.
name();
2761 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv))[jss::result];
2762 BEAST_EXPECT(jrr[jss::status] ==
"error");
2764 jrr[jss::error_message].asString().contains(
2765 "A Signer may not be the transaction's Account"));
2773 using namespace jtx;
2775 Env env(*
this, features);
2779 env.
fund(
XRP(100000), alice, bob);
2782 auto buildRequest = [&](
auto value) ->
json::Value {
2784 jv[jss::TransactionType] = jss::DelegateSet;
2785 jv[jss::Account] = alice.
human();
2786 jv[sfAuthorize.jsonName] = bob.
human();
2790 permissionValue[sfPermissionValue.jsonName] = value;
2792 permissionObj[sfPermission.jsonName] = permissionValue;
2793 permissionsJson.
append(permissionObj);
2794 jv[sfPermissions.jsonName] = permissionsJson;
2801 for (
auto value : {0, 100000, 54321})
2803 auto jv = buildRequest(value);
2811 testcase(
"test delegate disabled tx");
2812 using namespace jtx;
2819 {
"AMMClawback", featureAMMClawback},
2820 {
"AMMCreate", featureAMM},
2821 {
"AMMDeposit", featureAMM},
2822 {
"AMMWithdraw", featureAMM},
2823 {
"AMMVote", featureAMM},
2824 {
"AMMBid", featureAMM},
2825 {
"AMMDelete", featureAMM},
2826 {
"XChainCreateClaimID", featureXChainBridge},
2827 {
"XChainCommit", featureXChainBridge},
2828 {
"XChainClaim", featureXChainBridge},
2829 {
"XChainAccountCreateCommit", featureXChainBridge},
2830 {
"XChainAddClaimAttestation", featureXChainBridge},
2831 {
"XChainAddAccountCreateAttestation", featureXChainBridge},
2832 {
"XChainModifyBridge", featureXChainBridge},
2833 {
"XChainCreateBridge", featureXChainBridge},
2834 {
"DIDSet", featureDID},
2835 {
"DIDDelete", featureDID},
2836 {
"OracleSet", featurePriceOracle},
2837 {
"OracleDelete", featurePriceOracle},
2838 {
"LedgerStateFix", fixNFTokenPageLinks},
2839 {
"MPTokenIssuanceCreate", featureMPTokensV1},
2840 {
"MPTokenIssuanceDestroy", featureMPTokensV1},
2841 {
"MPTokenIssuanceSet", featureMPTokensV1},
2842 {
"MPTokenAuthorize", featureMPTokensV1},
2843 {
"CredentialCreate", featureCredentials},
2844 {
"CredentialAccept", featureCredentials},
2845 {
"CredentialDelete", featureCredentials},
2846 {
"NFTokenModify", featureDynamicNFT},
2847 {
"PermissionedDomainSet", featurePermissionedDomains},
2848 {
"PermissionedDomainDelete", featurePermissionedDomains},
2849 {
"SponsorshipSet", featureSponsor},
2855 BEAST_EXPECT(txRequiredFeatures.
contains(tx));
2857 Env env(*
this, features - txRequiredFeatures[tx]);
2861 env.
fund(
XRP(100000), alice, bob);
2867 for (
auto const& tx : txRequiredFeatures)
2868 txAmendmentDisabled(features, tx.first);
2874 auto txAmendmentEnabled = [&](
std::string const& tx) {
2875 Env env(*
this, features);
2879 env.
fund(
XRP(100000), alice, bob);
2885 for (
auto const& tx : txRequiredFeatures)
2886 txAmendmentEnabled(tx.first);
2892 for (
auto const permission : {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"})
2894 Env env(*
this, features - featureMPTokensV1);
2898 env.
fund(
XRP(100000), alice, bob);
2909 testcase(
"Make sure GranularSandbox is checked after transaction-level permission");
2911 using namespace jtx;
2917 env.
fund(
XRP(10000), gw, alice, bob);
2919 env(
fset(gw, asfRequireAuth));
2921 env(
trust(alice, gw[
"USD"](50)));
2931 txJson[sfQualityOut.jsonName] = 100;
2935 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustSet"}));
2949 testcase(
"Delegable Transactions Completeness");
2953#pragma push_macro("UNWRAP")
2955#pragma push_macro("TRANSACTION")
2958#define UNWRAP(...) __VA_ARGS__
2959#define TRANSACTION(tag, value, name, settings, ...) \
2960 if ((xrpl::TxSettings UNWRAP settings).delegable == xrpl::Delegation::Delegable) \
2965#include <xrpl/protocol/detail/transactions.macro>
2968#pragma pop_macro("TRANSACTION")
2970#pragma pop_macro("UNWRAP")
2993 delegableCount == expectedDelegableCount,
2994 "\n[SECURITY] New delegable transaction detected!"
2998 "\n Action: Verify security requirements to interact with Delegation feature");
3004 testcase(
"non-delegable tx with sfDelegate is rejected at preflight");
3005 using namespace jtx;
3007 Env env(*
this, features);
3010 env.
fund(
XRP(10000), alice, bob);
3027 Vault const vault{env};
3031 env(vault.set({.owner = alice, .id = keylet.key}),
3034 env(vault.del({.owner = alice, .id = keylet.key}),
3037 env(vault.deposit({.depositor = alice, .id = keylet.key, .amount = XRP(1)}),
3040 env(vault.withdraw({.depositor = alice, .id = keylet.key, .amount = XRP(1)}),
3043 env(vault.clawback({.issuer = alice, .id = keylet.key, .holder = bob}),
3050 auto const seq = env.seq(alice);
3052 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
3060 Vault const vault{env};
3092 testcase(
"DelegateUtils nullptr check");
3100 BEAST_EXPECT(granularPermissions.empty());
3106 testcase(
"test Permission to Tx type");
3122 for (
auto const gp : {
3123#pragma push_macro("GRANULAR_PERMISSION")
3124#undef GRANULAR_PERMISSION
3125#define GRANULAR_PERMISSION(type, txType, value, ...) GranularPermissionType::type,
3126#include <xrpl/protocol/detail/permissions.macro>
3127#undef GRANULAR_PERMISSION
3128#pragma pop_macro("GRANULAR_PERMISSION")
TestcaseT testcase
Memberspace for declaring test cases.
std::string const & arg() const
Return the argument associated with the runner.
Value & append(Value const &value)
Append value to array at the end.
A class that simplifies iterating ledger directory pages.
ConstIterator begin() const
ConstIterator end() const
Number is a floating point type that can represent a wide range of values.
static std::optional< TxType > permissionToTxType(std::uint32_t value)
void testNonDelegableTxWithDelegate(FeatureBitset features)
void testMultiSignDelegatorAsSigner()
void testMultiSignQuorumNotMet()
void testGranularSandboxCheckOrder()
void testSignForDelegated()
void testTrustSetGranular()
void testFeatureDisabled(FeatureBitset features)
void testInvalidRequest(FeatureBitset features)
void run() override
Runs the suite.
void testMPTokenIssuanceSetGranular()
void testDelegateTransaction()
void testGranularPermissionWithSponsorCommonFields()
void testSingleSignBadSecret()
void testDelegateUtilsNullptrCheck()
void testPermissionToTxType()
void testTxDelegableCount()
void testPaymentGranular(FeatureBitset features)
void testPermissionValue(FeatureBitset features)
void testAccountSetGranular()
void testTxRequireFeatures(FeatureBitset features)
Immutable cryptographic account descriptor.
std::string const & human() const
Returns the human readable public key.
std::string const & name() const
Return the name.
AccountID id() const
Returns the Account ID.
Sets the DeliverMin on a JTx.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
SLE::const_pointer le(Account const &account) const
Return an account root.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
PrettyAmount limit(Account const &account, Issue const &issue) const
Returns the IOU limit on an account.
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
std::shared_ptr< STObject const > meta()
Return metadata for the last JTx.
void require(Args const &... args)
Check a set of requirements.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Test helper for creating, mutating, and asserting MPT and confidential MPT ledger state.
void create(MPTCreate const &arg=MPTCreate{}, std::source_location const &loc=std::source_location::current())
Set a multisignature on a JTx.
Sets the SendMax on a JTx.
Set the regular signature on a JTx.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Adds an inner Batch transaction to a JTx and autofills it.
Sets the optional URI on a DIDSet.
@ Array
array value (ordered list)
Keylet computation functions.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Keylet account(AccountID const &id) noexcept
AccountID root.
json::Value outer(jtx::Account const &account, uint32_t seq, STAmount const &fee, std::uint32_t flags)
Build an outer Batch transaction JSON object.
XRPAmount calcBatchFee(jtx::Env const &env, uint32_t const &numSigners, uint32_t const &txns=0)
Calculate the expected outer Batch transaction fee.
json::Value create(A const &account, A const &dest, STAmount const &sendMax)
Create a check.
json::Value entry(jtx::Env &env, jtx::Account const &account, jtx::Account const &authorize)
json::Value set(jtx::Account const &account, jtx::Account const &authorize, std::vector< std::string > const &permissions)
json::Value set(jtx::Account const &account)
json::Value set(AccountID const &account, UInt256 const &vaultId, uint32_t flags)
json::Value coverWithdraw(AccountID const &account, UInt256 const &brokerID, STAmount const &amount, uint32_t flags)
json::Value coverDeposit(AccountID const &account, UInt256 const &brokerID, STAmount const &amount, uint32_t flags)
json::Value del(AccountID const &account, UInt256 const &brokerID, uint32_t flags)
json::Value coverClawback(AccountID const &account, std::uint32_t flags)
json::Value manage(AccountID const &account, UInt256 const &loanID, std::uint32_t flags)
json::Value set(AccountID const &account, UInt256 const &loanBrokerID, Number principalRequested, std::uint32_t flags)
json::Value del(AccountID const &account, UInt256 const &loanID, std::uint32_t flags)
json::Value pay(AccountID const &account, UInt256 const &loanID, STAmount const &amount, std::uint32_t flags)
UInt256 getNewDomain(std::shared_ptr< STObject const > const &meta)
json::Value setTx(AccountID const &account, Credentials const &credentials, std::optional< UInt256 > domain)
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
json::Value regkey(Account const &account, DisabledT)
Disable the regular key.
bool expectOffers(Env &env, AccountID const &account, std::uint16_t size, std::vector< Amounts > const &toMatch)
XrpT const XRP
Converts to XRP Issue or STAmount.
json::Value noop(Account const &account)
The null transaction.
XRPAmount txFee(Env const &env, std::uint16_t n)
json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
FeatureBitset testableAmendments()
json::Value acctdelete(Account const &account, Account const &dest)
Delete account.
json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
json::Value signers(Account const &account, std::uint32_t quorum, std::vector< Signer > const &v)
json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
static XRPAmount reserve(jtx::Env &env, std::uint32_t count)
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
STTx createTx(bool disabling, LedgerIndex seq, PublicKey const &txKey)
Create ttUNL_MODIFY Tx.
constexpr XRPAmount
Convert XRP to drops (integral types).
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr FlagValue spfSponsorFee
@ terNO_DELEGATE_PERMISSION
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
std::unordered_set< GranularPermissionType > getGranularPermission(SLE::ConstRef delegate, TxType const &type)
Load the granular permissions granted to the delegate account for the specified transaction type.
std::string strHex(FwdIt begin, FwdIt end)
BaseUInt< 256 > Domain
Domain is a 256-bit hash representing a specific domain.
constexpr FlagValue tifMPTTransferFee
NotTEC checkTxPermission(SLE::ConstRef delegate, STTx const &tx)
Check if the delegate account has permission to execute the transaction.
std::string to_string(BaseUInt< Bits, Tag > const &a)
Slice makeSlice(std::array< T, N > const &a)
@ tecINSUFFICIENT_RESERVE
constexpr FlagValue tfFullyCanonicalSig