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/rate.h>
22#include <test/jtx/regkey.h>
23#include <test/jtx/sendmax.h>
24#include <test/jtx/sig.h>
25#include <test/jtx/ter.h>
26#include <test/jtx/trust.h>
27#include <test/jtx/txflags.h>
28#include <test/jtx/vault.h>
30#include <xrpl/basics/Number.h>
31#include <xrpl/basics/Slice.h>
32#include <xrpl/basics/base_uint.h>
33#include <xrpl/basics/strHex.h>
34#include <xrpl/beast/unit_test/suite.h>
35#include <xrpl/json/json_value.h>
36#include <xrpl/json/to_string.h>
37#include <xrpl/ledger/Dir.h>
38#include <xrpl/ledger/helpers/DelegateHelpers.h>
39#include <xrpl/protocol/Feature.h>
40#include <xrpl/protocol/Indexes.h>
41#include <xrpl/protocol/Issue.h>
42#include <xrpl/protocol/KeyType.h>
43#include <xrpl/protocol/Permissions.h>
44#include <xrpl/protocol/SField.h>
45#include <xrpl/protocol/STObject.h>
46#include <xrpl/protocol/STTx.h>
47#include <xrpl/protocol/SecretKey.h>
48#include <xrpl/protocol/TER.h>
49#include <xrpl/protocol/TxFlags.h>
50#include <xrpl/protocol/XRPAmount.h>
51#include <xrpl/protocol/jss.h>
70 testcase(
"test feature not enabled");
73 Env env{*
this, features};
77 env.
fund(
XRP(1000000), gw, alice, bob);
93 testcase(
"test valid request creating, updating, deleting permissions");
99 env.
fund(
XRP(100000), gw, alice);
108 "Payment",
"EscrowCreate",
"EscrowFinish",
"TrustlineAuthorize",
"CheckCreate"};
114 auto comparePermissions = [&](
json::Value const& jle,
119 !jle[jss::result].isMember(jss::error) && jle[jss::result].isMember(jss::node));
120 BEAST_EXPECT(jle[jss::result][jss::node][
"LedgerEntryType"] == jss::Delegate);
121 BEAST_EXPECT(jle[jss::result][jss::node][jss::Account] == account.human());
122 BEAST_EXPECT(jle[jss::result][jss::node][sfAuthorize.jsonName] == authorize.human());
124 auto const& jPermissions = jle[jss::result][jss::node][sfPermissions.jsonName];
126 for (
auto const& permission : permissions)
129 jPermissions[i][sfPermission.jsonName][sfPermissionValue.jsonName] ==
136 comparePermissions(
delegate::entry(env, gw, alice), permissions, gw, alice);
139 auto const newPermissions =
146 comparePermissions(
delegate::entry(env, gw, alice), newPermissions, gw, alice);
152 BEAST_EXPECT(jle[jss::result][jss::error] ==
"entryNotFound");
157 comparePermissions(
delegate::entry(env, alice, gw), permissions, alice, gw);
160 BEAST_EXPECT(response[jss::result][jss::error] ==
"entryNotFound");
166 testcase(
"test invalid DelegateSet");
169 Env env(*
this, features);
173 env.
fund(
XRP(100000), gw, alice, bob);
204 jv[jss::TransactionType] = jss::DelegateSet;
205 jv[jss::Account] = gw.
human();
206 jv[sfAuthorize.jsonName] = alice.
human();
209 permissionValue[sfPermissionValue.jsonName] =
"Payment";
211 permissionObj[sfPermission.jsonName] = permissionValue;
212 permissionsJson.
append(permissionObj);
213 jv[sfPermissions.jsonName] = permissionsJson;
214 jv[sfFee.jsonName] = -1;
227 "TrustlineAuthorize",
229 "TrustlineAuthorize"}),
241 Vault const vault{env};
242 auto [tx,
keylet] = vault.create({.owner = gw, .asset =
xrpIssue()});
246 auto const sleVault = env.
le(
keylet);
247 BEAST_EXPECT(sleVault);
248 Account const vaultPseudo{
"vault", sleVault->at(sfAccount)};
296 env.
fund(
XRP(100000), bob, carol);
346 auto setup = [&](
Env& env) {
350 env.fund(
XRP(1000), alice, bob, carol);
358 auto [alice, bob, carol] = setup(env);
360 auto const aliceBalance = env.
balance(alice);
361 auto const bobBalance = env.
balance(bob);
362 auto const carolBalance = env.
balance(carol);
366 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
367 BEAST_EXPECT(env.
balance(bob) == bobBalance);
368 BEAST_EXPECT(env.
balance(carol) == carolBalance);
374 auto [alice, bob, carol] = setup(env);
378 auto const aliceBalance = env.
balance(alice);
379 auto const bobBalance = env.
balance(bob);
380 auto const carolBalance = env.
balance(carol);
382 auto const sendAmt =
XRP(100);
383 auto const feeAmt =
XRP(10);
386 BEAST_EXPECT(env.
balance(alice) == aliceBalance - sendAmt);
387 BEAST_EXPECT(env.
balance(bob) == bobBalance - feeAmt);
388 BEAST_EXPECT(env.
balance(carol) == carolBalance + sendAmt);
394 auto [alice, bob, carol] = setup(env);
398 auto const aliceBalance = env.
balance(alice);
399 auto const bobBalance = env.
balance(bob);
400 auto const carolBalance = env.
balance(carol);
402 env(
pay(alice, carol,
XRP(100)),
407 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
408 BEAST_EXPECT(env.
balance(bob) == bobBalance);
409 BEAST_EXPECT(env.
balance(carol) == carolBalance);
419 auto setup = [&](
Env& env) {
424 auto const baseFee = env.current()->fees().base;
425 auto const reserve = env.current()->fees().accountReserve(1);
426 auto const paymentAmount =
XRP(1);
427 auto const highFee =
reserve + baseFee;
428 BEAST_EXPECT(highFee >
reserve);
430 env.fund(paymentAmount +
reserve + baseFee, alice);
431 env.fund(
XRP(1000), bob);
432 env.fund(
XRP(1000), carol);
451 auto [alice, bob, carol, paymentAmount, highFee,
reserve] = setup(env);
452 auto const aliceBalance = env.
balance(alice);
453 auto const bobBalance = env.
balance(bob);
454 auto const carolBalance = env.
balance(carol);
459 BEAST_EXPECT(env.
balance(alice) == aliceBalance - highFee);
460 BEAST_EXPECT(env.
balance(bob) == bobBalance);
461 BEAST_EXPECT(env.
balance(carol) == carolBalance);
468 auto [alice, bob, carol, paymentAmount, highFee,
reserve] = setup(env);
470 auto const alicePrePay = env.
balance(alice,
XRP);
472 auto const carolPrePay = env.
balance(carol,
XRP);
490 auto const baseFee = env.
current()->fees().base;
491 auto const baseReserve = env.
current()->fees().accountReserve(0);
493 env.
fund(env.
current()->fees().accountReserve(1) + baseFee +
XRP(1), alice);
494 env.
fund(baseReserve, bob);
501 auto const alicePreTx = env.
balance(alice,
XRP);
510 BEAST_EXPECT(env.
balance(bob,
XRP) < baseReserve);
525 auto const baseFee = env.
current()->fees().base;
539 auto const alicePrePay = env.
balance(alice,
XRP);
541 auto const carolPrePay = env.
balance(carol,
XRP);
562 env.
fund(
XRP(10000), alice, bob, carol);
565 auto aliceSeq = env.
seq(alice);
566 auto bobSeq = env.
seq(bob);
570 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
571 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
572 aliceSeq = env.
seq(alice);
573 bobSeq = env.
seq(bob);
575 for (
auto i = 0; i < 20; ++i)
580 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
581 BEAST_EXPECT(env.
seq(bob) == bobSeq);
582 aliceSeq = env.
seq(alice);
586 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
587 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
588 bobSeq = env.
seq(bob);
593 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
594 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
595 bobSeq = env.
seq(bob);
599 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
600 BEAST_EXPECT(env.
seq(bob) == bobSeq);
601 aliceSeq = env.
seq(alice);
618 env.
fund(
XRP(100000), alice, bob, carol);
625 BEAST_EXPECT(env.
closed()->exists(delegateKey));
629 dir.
begin(), dir.
end(), [&](
auto const& sle) { return sle->key() == key; });
641 auto const aliceBalance = env.
balance(alice);
642 auto const carolBalance = env.
balance(carol);
646 auto const deleteFee =
drops(env.
current()->fees().increment);
652 BEAST_EXPECT(!env.
closed()->exists(delegateKey));
656 BEAST_EXPECT(env.
balance(carol) == carolBalance + aliceBalance - deleteFee);
667 env.
fund(
XRP(100000), alice, bob, carol);
674 BEAST_EXPECT(env.
closed()->exists(delegateKey));
678 dir.
begin(), dir.
end(), [&](
auto const& sle) { return sle->key() == key; });
688 BEAST_EXPECT(sleAlice);
689 BEAST_EXPECT(sleAlice->getFieldU32(sfOwnerCount) == 1);
694 auto const bobBalance = env.
balance(bob);
695 auto const carolBalance = env.
balance(carol);
701 auto const deleteFee =
drops(env.
current()->fees().increment);
707 BEAST_EXPECT(!env.
closed()->exists(delegateKey));
711 BEAST_EXPECT(env.
balance(carol) == carolBalance + bobBalance - deleteFee);
715 BEAST_EXPECT(sleAlice2);
716 BEAST_EXPECT(sleAlice2->getFieldU32(sfOwnerCount) == 0);
718 auto const aliceDeleteFee =
drops(env.
current()->fees().increment);
734 env.
fund(
XRP(100000), alice, bob, carol, dave);
747 dir.
begin(), dir.
end(), [&](
auto const& sle) { return sle->key() == key; });
751 BEAST_EXPECT(env.
closed()->exists(aliceBobKey));
752 BEAST_EXPECT(env.
closed()->exists(carolBobKey));
761 auto const bobBalance = env.
balance(bob);
762 auto const daveBalance = env.
balance(dave);
764 auto const deleteFee =
drops(env.
current()->fees().increment);
773 BEAST_EXPECT(!env.
closed()->exists(aliceBobKey));
774 BEAST_EXPECT(!env.
closed()->exists(carolBobKey));
782 BEAST_EXPECT(env.
balance(dave) == daveBalance + bobBalance - deleteFee);
789 testcase(
"test delegate transaction");
863 auto const usd = gw[
"USD"];
864 auto const eur = gw2[
"EUR"];
869 env.
trust(usd(200), alice);
870 env.
trust(eur(400), gw);
915 BEAST_EXPECT(env.
balance(bob, usd) == usd(0));
925 BEAST_EXPECT(env.
balance(bob, usd) == usd(0));
943 env(
pay(gw2, gw, eur(200)));
967 auto const usd = gw[
"USD"];
972 env.
trust(usd(200), alice);
1007 BEAST_EXPECT(env.
balance(bob, usd) == usd(0));
1013 Env env(*
this, features);
1018 auto const usd = gw[
"USD"];
1020 env.
fund(
XRP(10000), alice, bob, carol, gw);
1022 env.
trust(usd(50000), alice);
1023 env.
trust(usd(50000), bob);
1024 env.
trust(usd(50000), carol);
1025 env(
pay(gw, alice, usd(10000)));
1026 env(
pay(gw, bob, usd(10000)));
1027 env(
pay(gw, carol, usd(10000)));
1032 env(
offer(carol,
XRP(100), usd(501)));
1039 env(
pay(gw, alice, usd(5000)),
1046 env(
pay(gw, alice, usd(5000)),
1060 env(
offer(bob,
XRP(100), usd(501)));
1067 env(
pay(alice, gw, usd(5000)),
1074 env(
pay(alice, gw, usd(5000)),
1090 Env env(*
this, features);
1094 auto const usd = gw[
"USD"];
1095 env.
fund(
XRP(10000), alice, bob, gw);
1096 env.
trust(usd(200), alice);
1120 auto const gwUSD = gw[
"USD"];
1121 auto const aliceUSD = alice[
"USD"];
1123 env.
fund(
XRP(10000), alice, bob, gw);
1124 env.
trust(gwUSD(200), alice);
1127 env(
pay(gw, alice, gwUSD(50)));
1134 env.
trust(gwUSD(0), alice);
1136 BEAST_EXPECT(env.
limit(alice, gwUSD.issue()) == gwUSD(0));
1138 env(
trust(gw, aliceUSD(200)));
1148 Env env(*
this, features);
1152 auto const usd = gw[
"USD"];
1153 env.
fund(
XRP(10000), alice, bob, gw);
1154 env.
trust(usd(200), alice);
1163 env(
pay(gw, alice, usd(100)),
1168 env(
pay(alice, gw, usd(50)),
1175 env(
pay(gw, alice, usd(100)),
1179 env(
pay(alice, gw, usd(50)),
1188 Env env(*
this, features);
1192 auto const usd = gw[
"USD"];
1193 env.
fund(
XRP(10000), alice, bob, gw);
1194 env.
trust(usd(200), alice);
1215 MPTTester mpt(env, gw, {.holders = {alice, bob}});
1216 mpt.
create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer});
1218 mpt.authorize({.account = alice});
1219 mpt.authorize({.account = bob});
1221 auto const gwMPT = mpt[
"MPT"];
1222 env(
pay(gw, alice, gwMPT(500)));
1223 env(
pay(gw, bob, gwMPT(500)));
1225 auto aliceMPT = env.
balance(alice, gwMPT);
1226 auto bobMPT = env.
balance(bob, gwMPT);
1234 BEAST_EXPECT(env.
balance(alice, gwMPT) == aliceMPT + gwMPT(50));
1235 BEAST_EXPECT(env.
balance(bob, gwMPT) == bobMPT);
1236 aliceMPT = env.
balance(alice, gwMPT);
1245 BEAST_EXPECT(env.
balance(alice, gwMPT) == aliceMPT - gwMPT(50));
1246 BEAST_EXPECT(env.
balance(bob, gwMPT) == bobMPT);
1247 aliceMPT = env.
balance(alice, gwMPT);
1252 env(
delegate::set(alice, bob, {
"PaymentBurn",
"PaymentMint",
"Payment"}));
1255 BEAST_EXPECT(env.
balance(alice, gwMPT) == aliceMPT - gwMPT(50));
1256 BEAST_EXPECT(env.
balance(bob, gwMPT) == bobMPT);
1257 aliceMPT = env.
balance(alice, gwMPT);
1259 BEAST_EXPECT(env.
balance(alice, gwMPT) == aliceMPT - gwMPT(100));
1260 BEAST_EXPECT(env.
balance(bob, gwMPT) == bobMPT + gwMPT(100));
1274 auto const gwUSD = gw[
"USD"];
1275 auto const aliceUSD = alice[
"USD"];
1277 env.
fund(
XRP(10000), alice, bob, gw);
1278 env.
trust(gwUSD(200), alice);
1282 env(
pay(gw, alice, gwUSD(100)));
1295 env(
pay(gw, alice, aliceUSD(50)),
1314 env(
pay(alice, gw, aliceUSD(50)),
1334 Account const gw2{
"gateway2"};
1335 auto const gwUSD = gw[
"USD"];
1337 env.
fund(
XRP(10000), alice, bob, gw, gw2);
1340 env.
trust(gwUSD(200), alice);
1343 env(
pay(gw, alice, gwUSD(100)));
1346 env(
delegate::set(alice, bob, {
"PaymentMint",
"PaymentBurn"}));
1349 env(
pay(alice, gw, gw2[
"USD"](50)),
1356 Env env(*
this, features);
1360 Account const gw2{
"gateway2"};
1365 MPTTester mpt(env, gw, {.holders = {alice, bob}});
1366 mpt.
create({.ownerCount = 1, .flags = tfMPTCanTransfer});
1368 mpt.authorize({.account = alice});
1369 mpt.authorize({.account = bob});
1371 auto const gwMPT = mpt[
"MPT"];
1372 env(
pay(gw, alice, gwMPT(500)));
1373 env(
pay(gw, bob, gwMPT(500)));
1376 env(
delegate::set(alice, bob, {
"PaymentMint",
"PaymentBurn"}));
1390 env.
fund(
XRP(10000), alice, bob, gw);
1393 env(
delegate::set(alice, bob, {
"PaymentMint",
"PaymentBurn"}));
1396 env(
pay(alice, gw, alice[
"USD"](50)),
1408 auto const gwUSD = gw[
"USD"];
1409 auto const aliceUSD = alice[
"USD"];
1411 env.
fund(
XRP(10000), alice, bob, gw);
1417 env.
trust(gwUSD(200), alice);
1425 env(
pay(alice, gw, aliceUSD(50)),
1435 env(
trust(gw, aliceUSD(200)));
1439 env(
pay(alice, gw, aliceUSD(100)));
1448 env(
pay(gw, alice, aliceUSD(50)),
1460 env.
fund(
XRP(10000), alice, bob, gw);
1461 env.
trust(gw[
"USD"](200), alice);
1468 env(
pay(alice, gw, alice[
"USD"](50)),
1480 auto const usd = gw[
"USD"];
1481 env.
fund(
XRP(10000), alice, bob, gw);
1482 env.
trust(usd(200), alice);
1486 env(
delegate::set(alice, bob, {
"AccountDomainSet",
"PaymentMint"}));
1494 auto jt =
noop(alice);
1495 jt[sfDomain] =
strHex(domain);
1496 jt[sfDelegate] = bob.
human();
1498 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
1511 testcase(
"test TrustSet granular permissions");
1512 using namespace jtx;
1520 env.
fund(
XRP(10000), gw, alice, bob);
1521 env(
fset(gw, asfRequireAuth));
1532 env(
trust(alice, gw[
"USD"](50)));
1540 env(
trust(alice, gw[
"USD"](50), tfSetNoRipple),
1543 env(
trust(alice, gw[
"USD"](50), tfClearNoRipple),
1546 env(
trust(gw, gw[
"USD"](0), alice, tfSetDeepFreeze),
1549 env(
trust(gw, gw[
"USD"](0), alice, tfClearDeepFreeze),
1555 env(
trust(gw, gw[
"USD"](0), alice, tfSetfAuth),
1558 env(
trust(gw, gw[
"USD"](0), alice, tfSetFreeze),
1565 env(
trust(gw, gw[
"USD"](0), alice, tfClearFreeze),
1571 env(
trust(gw, gw[
"USD"](50), alice, tfSetfAuth),
1579 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
1583 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustlineUnfreeze"}));
1589 env(
trust(gw, gw[
"USD"](0), alice, tfSetFreeze),
1599 auto tx =
trust(alice, gw[
"USD"](50));
1600 tx[
"QualityIn"] =
"1000";
1602 auto tx2 =
trust(alice, gw[
"USD"](50));
1603 tx2[
"QualityOut"] =
"1000";
1605 auto tx3 =
trust(gw, alice[
"USD"](50));
1606 tx3[
"QualityIn"] =
"1000";
1608 auto tx4 =
trust(gw, alice[
"USD"](50));
1609 tx4[
"QualityOut"] =
"1000";
1615 auto tx5 =
trust(gw, alice[
"USD"](50));
1616 tx5[
"QualityOut"] =
"1000";
1618 auto tx6 =
trust(alice, gw[
"USD"](50));
1619 tx6[
"QualityOut"] =
"1000";
1632 env.
fund(
XRP(10000), gw, alice, bob);
1633 env(
fset(gw, asfRequireAuth));
1638 env(
delegate::set(alice, bob, {
"TrustlineUnfreeze",
"NFTokenCreateOffer"}));
1647 {
"TrustlineUnfreeze",
"NFTokenCreateOffer",
"TrustSet",
"AccountTransferRateSet"}));
1655 {
"TrustlineUnfreeze",
"NFTokenCreateOffer",
"TrustSet",
"AccountTransferRateSet"}));
1677 env.
fund(
XRP(10000), gw, alice, bob);
1678 env(
fset(gw, asfRequireAuth));
1680 env(
trust(alice, gw[
"USD"](50)));
1694 env.
fund(
XRP(10000), gw, alice, bob);
1696 env(
fset(gw, asfRequireAuth));
1698 env(
trust(alice, gw[
"USD"](50)));
1708 txJson[sfQualityOut.jsonName] = 100;
1712 env(
trust(gw, gw[
"USD"](0), alice, tfSetfAuth | tfSetNoRipple),
1721 testcase(
"test AccountSet granular permissions");
1722 using namespace jtx;
1729 auto const alice =
Account{
"alice"};
1730 auto const bob =
Account{
"bob"};
1731 env.
fund(
XRP(10000), alice, bob);
1742 auto jt =
noop(alice);
1743 jt[sfDomain] =
strHex(domain);
1744 jt[sfDelegate] = bob.human();
1748 env(
delegate::set(alice, bob, {
"TrustlineUnfreeze",
"AccountEmailHashSet"}));
1758 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
1763 BEAST_EXPECT(!env.
le(alice)->isFieldPresent(sfDomain));
1766 std::string const failDomain =
"fail_domain_update";
1767 jt[sfFlags] = tfRequireAuth;
1768 jt[sfDomain] =
strHex(failDomain);
1775 jt[sfDomain] =
strHex(domain);
1776 std::string const mh(
"5F31A79367DC3137FADA860C05742EE6");
1777 jt[sfEmailHash] = mh;
1781 env(
delegate::set(alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet"}));
1784 BEAST_EXPECT(
to_string((*env.
le(alice))[sfEmailHash]) == mh);
1785 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
1789 jt[sfMessageKey] =
strHex(rkp.first.slice());
1794 alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet",
"AccountMessageKeySet"}));
1799 BEAST_EXPECT(
strHex((*env.
le(alice))[sfMessageKey]) ==
strHex(rkp.first.slice()));
1800 jt[sfMessageKey] =
"";
1802 BEAST_EXPECT(!env.
le(alice)->isFieldPresent(sfMessageKey));
1811 {
"AccountDomainSet",
1812 "AccountEmailHashSet",
1813 "AccountMessageKeySet",
1814 "AccountTransferRateSet"}));
1816 auto jtRate =
rate(alice, 2.0);
1817 jtRate[sfDelegate] = bob.human();
1819 BEAST_EXPECT((*env.
le(alice))[sfTransferRate] == 2000000000);
1829 {
"AccountDomainSet",
1830 "AccountEmailHashSet",
1831 "AccountMessageKeySet",
1832 "AccountTransferRateSet",
1833 "AccountTickSizeSet"}));
1836 BEAST_EXPECT((*env.
le(alice))[sfTickSize] == 8);
1848 env(
fset(alice, asfRequireAuth));
1857 alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet",
"AccountMessageKeySet"}));
1862 "9633EC8AF54F16B5286DB1D7B519EF49EEFC050C0C8AC4384F1D88ACD1BFDF"
1864 auto jv2 =
noop(alice);
1865 jv2[sfDomain] =
strHex(domain);
1866 jv2[sfDelegate] = bob.human();
1867 jv2[sfWalletLocator] = locator;
1876 auto const alice =
Account{
"alice"};
1877 auto const bob =
Account{
"bob"};
1878 env.
fund(
XRP(10000), alice, bob);
1885 env(
fset(alice, flag));
1893 testSetClearFlag(asfRequireAuth);
1894 testSetClearFlag(asfAllowTrustLineClawback);
1898 alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet",
"AccountMessageKeySet"}));
1901 testSetClearFlag(asfDefaultRipple);
1902 testSetClearFlag(asfDepositAuth);
1903 testSetClearFlag(asfDisallowIncomingCheck);
1904 testSetClearFlag(asfDisallowIncomingNFTokenOffer);
1905 testSetClearFlag(asfDisallowIncomingPayChan);
1906 testSetClearFlag(asfDisallowIncomingTrustline);
1907 testSetClearFlag(asfDisallowXRP);
1908 testSetClearFlag(asfRequireDest);
1909 testSetClearFlag(asfGlobalFreeze);
1913 env(
fset(alice, asfAccountTxnID));
1915 BEAST_EXPECT(env.
le(alice)->isFieldPresent(sfAccountTxnID));
1920 jt[sfDelegate] = bob.human();
1921 jt[sfNFTokenMinter] = bob.human();
1926 bob, alice, {
"AccountDomainSet",
"AccountEmailHashSet",
"AccountMessageKeySet"}));
1933 env(
fset(bob, asfNoFreeze));
1941 env(
regkey(bob, bobKey));
1943 env(
fset(alice, asfDisableMaster),
1954 env.
fund(
XRP(10000), alice, bob);
1957 env(
delegate::set(alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet"}));
1961 auto jt =
noop(alice);
1962 jt[sfDomain] =
strHex(domain);
1963 jt[sfDelegate] = bob.
human();
1967 BEAST_EXPECT((*env.
le(alice))[sfDomain] ==
makeSlice(domain));
1973 auto const alice =
Account{
"alice"};
1974 auto const bob =
Account{
"bob"};
1975 env.
fund(
XRP(10000), alice, bob);
1983 auto txJson =
noop(alice);
1984 txJson[sfDomain] =
strHex(domain);
1985 txJson[sfDelegate] = bob.human();
1989 txJson[sfNFTokenMinter] = bob.human();
2000 env.
fund(
XRP(10000), alice, bob);
2006 auto jt =
noop(alice);
2007 jt[sfDelegate] = bob.
human();
2016 env.
fund(
XRP(10000), alice, bob);
2023 auto jt =
noop(alice);
2024 jt[sfDomain] =
strHex(domain);
2025 jt[sfDelegate] = bob.
human();
2039 testcase(
"test MPTokenIssuanceSet granular");
2040 using namespace jtx;
2047 env.
fund(
XRP(100000), alice, bob);
2050 MPTTester mpt(env, alice, {.fund =
false});
2052 mpt.create({.flags = tfMPTCanLock});
2074 mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob});
2077 .flags = tfMPTUnlock,
2082 env(
delegate::set(alice, bob, {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"}));
2084 mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob});
2085 mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob});
2094 env.
fund(
XRP(100000), alice, bob);
2097 MPTTester mpt(env, alice, {.fund =
false});
2099 mpt.create({.flags = tfMPTCanLock});
2105 mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob});
2109 .flags = tfMPTUnlock,
2115 env(
delegate::set(alice, bob, {
"NFTokenMint",
"MPTokenIssuanceLock",
"NFTokenBurn"}));
2120 .flags = tfMPTUnlock,
2128 {
"NFTokenMint",
"MPTokenIssuanceLock",
"NFTokenBurn",
"MPTokenIssuanceSet"}));
2129 mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob});
2131 mpt.set({.account = alice, .flags = tfMPTLock});
2132 mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob});
2133 mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob});
2141 env.
fund(
XRP(100000), alice, bob);
2144 MPTTester mpt(env, alice, {.fund =
false});
2146 mpt.create({.flags = tfMPTCanLock});
2160 env.
fund(
XRP(100000), alice, bob);
2162 MPTTester mpt(env, alice, {.fund =
false});
2163 mpt.
create({.flags = tfMPTCanLock});
2191 using namespace jtx;
2197 env.
fund(
XRP(100000), alice, bob, carol);
2203 auto aliceBalance = env.
balance(alice);
2204 auto bobBalance = env.
balance(bob);
2205 auto carolBalance = env.
balance(carol);
2209 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(100));
2210 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
2211 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(100));
2217 testcase(
"test single sign with bad secret");
2218 using namespace jtx;
2225 env.
fund(
XRP(100000), alice, bob, carol);
2231 auto aliceBalance = env.
balance(alice);
2232 auto bobBalance = env.
balance(bob);
2233 auto carolBalance = env.
balance(carol);
2235 env(
pay(alice, carol,
XRP(100)),
2241 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2242 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2243 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2251 env.
fund(
XRP(100000), alice, bob, carol);
2257 auto aliceBalance = env.
balance(alice);
2258 auto bobBalance = env.
balance(bob);
2259 auto carolBalance = env.
balance(carol);
2261 env(
pay(alice, carol,
XRP(100)),
2267 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2268 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2269 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2271 env(
pay(alice, carol,
XRP(100)),
2277 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2278 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2279 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2287 env.
fund(
XRP(100000), alice, bob, carol);
2290 auto aliceBalance = env.
balance(alice);
2291 auto bobBalance = env.
balance(bob);
2292 auto carolBalance = env.
balance(carol);
2294 env(
pay(alice, carol,
XRP(100)),
2300 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2301 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2302 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2304 env(
pay(alice, carol,
XRP(100)),
2310 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2311 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2312 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2320 using namespace jtx;
2327 Account const edward{
"edward"};
2328 env.
fund(
XRP(100000), alice, bob, carol, daria, edward);
2331 env(
signers(bob, 2, {{daria, 1}, {edward, 1}}));
2337 auto aliceBalance = env.
balance(alice);
2338 auto bobBalance = env.
balance(bob);
2339 auto carolBalance = env.
balance(carol);
2340 auto dariaBalance = env.
balance(daria);
2341 auto edwardBalance = env.
balance(edward);
2345 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(100));
2346 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
2347 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(100));
2348 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
2349 BEAST_EXPECT(env.
balance(edward) == edwardBalance);
2355 testcase(
"test multi sign which does not meet quorum");
2356 using namespace jtx;
2363 Account const edward{
"edward"};
2365 env.
fund(
XRP(100000), alice, bob, carol, daria, edward, fred);
2368 env(
signers(bob, 3, {{daria, 1}, {edward, 1}, {fred, 1}}));
2374 auto aliceBalance = env.
balance(alice);
2375 auto bobBalance = env.
balance(bob);
2376 auto carolBalance = env.
balance(carol);
2377 auto dariaBalance = env.
balance(daria);
2378 auto edwardBalance = env.
balance(edward);
2380 env(
pay(alice, carol,
XRP(100)),
2383 Msig(daria, edward),
2386 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2387 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2388 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2389 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
2390 BEAST_EXPECT(env.
balance(edward) == edwardBalance);
2399 testcase(
"test delegator as multisigner in delegate's signer list");
2400 using namespace jtx;
2407 env.
fund(
XRP(100000), alice, bob, carol, daria);
2414 env(
signers(bob, 2, {{alice, 1}, {daria, 1}}));
2417 auto aliceBalance = env.
balance(alice);
2418 auto bobBalance = env.
balance(bob);
2419 auto carolBalance = env.
balance(carol);
2420 auto const amt = 100;
2426 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(amt));
2427 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
2428 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(amt));
2435 aliceBalance = env.
balance(alice);
2436 bobBalance = env.
balance(bob);
2437 carolBalance = env.
balance(carol);
2442 env(
pay(alice, carol,
XRP(50)),
2448 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
2449 BEAST_EXPECT(env.
balance(bob) == bobBalance);
2450 BEAST_EXPECT(env.
balance(carol) == carolBalance);
2458 testcase(
"test sign_for with delegated transaction");
2459 using namespace jtx;
2466 env.
fund(
XRP(100000), alice, bob, carol, daria);
2473 env(
signers(bob, 2, {{alice, 1}, {daria, 1}}));
2476 auto const baseFee = env.
current()->fees().base;
2478 auto const sendAmt = 1'000'000;
2481 jv[jss::tx_json][jss::Account] = alice.
human();
2482 jv[jss::tx_json][sfDelegate.jsonName] = bob.
human();
2483 jv[jss::tx_json][jss::TransactionType] = jss::Payment;
2484 jv[jss::tx_json][jss::Destination] = carol.
human();
2485 jv[jss::tx_json][jss::Amount] = sendAmt;
2487 jv[jss::tx_json][jss::Sequence] = env.
seq(alice);
2488 jv[jss::tx_json][jss::SigningPubKey] =
"";
2494 auto const aliceBalance = env.
balance(alice);
2495 auto const bobBalance = env.
balance(bob);
2496 auto const dariaBalance = env.
balance(daria);
2497 auto const carolBalance = env.
balance(carol);
2500 jv[jss::account] = alice.
human();
2501 jv[jss::secret] = alice.
name();
2502 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv))[jss::result];
2503 BEAST_EXPECT(jrr[jss::status] ==
"success");
2506 jv2[jss::tx_json] = jrr[jss::tx_json];
2507 jv2[jss::account] = daria.
human();
2508 jv2[jss::secret] = daria.
name();
2509 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv2))[jss::result];
2510 BEAST_EXPECT(jrr[jss::status] ==
"success");
2513 jvSubmit[jss::tx_json] = jrr[jss::tx_json];
2514 jrr = env.
rpc(
"json",
"submit_multisigned",
to_string(jvSubmit))[jss::result];
2515 BEAST_EXPECT(jrr[jss::status] ==
"success");
2518 BEAST_EXPECT(env.
balance(bob) == bobBalance - (10 * baseFee));
2519 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
2526 jv[jss::account] = bob.
human();
2527 jv[jss::secret] = bob.
name();
2528 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv))[jss::result];
2529 BEAST_EXPECT(jrr[jss::status] ==
"error");
2531 jrr[jss::error_message].asString().contains(
2532 "A Signer may not be the transaction's Account"));
2540 using namespace jtx;
2542 Env env(*
this, features);
2546 env.
fund(
XRP(100000), alice, bob);
2549 auto buildRequest = [&](
auto value) ->
json::Value {
2551 jv[jss::TransactionType] = jss::DelegateSet;
2552 jv[jss::Account] = alice.
human();
2553 jv[sfAuthorize.jsonName] = bob.
human();
2557 permissionValue[sfPermissionValue.jsonName] = value;
2559 permissionObj[sfPermission.jsonName] = permissionValue;
2560 permissionsJson.
append(permissionObj);
2561 jv[sfPermissions.jsonName] = permissionsJson;
2568 for (
auto value : {0, 100000, 54321})
2570 auto jv = buildRequest(value);
2578 testcase(
"test delegate disabled tx");
2579 using namespace jtx;
2586 {
"AMMClawback", featureAMMClawback},
2587 {
"AMMCreate", featureAMM},
2588 {
"AMMDeposit", featureAMM},
2589 {
"AMMWithdraw", featureAMM},
2590 {
"AMMVote", featureAMM},
2591 {
"AMMBid", featureAMM},
2592 {
"AMMDelete", featureAMM},
2593 {
"XChainCreateClaimID", featureXChainBridge},
2594 {
"XChainCommit", featureXChainBridge},
2595 {
"XChainClaim", featureXChainBridge},
2596 {
"XChainAccountCreateCommit", featureXChainBridge},
2597 {
"XChainAddClaimAttestation", featureXChainBridge},
2598 {
"XChainAddAccountCreateAttestation", featureXChainBridge},
2599 {
"XChainModifyBridge", featureXChainBridge},
2600 {
"XChainCreateBridge", featureXChainBridge},
2601 {
"DIDSet", featureDID},
2602 {
"DIDDelete", featureDID},
2603 {
"OracleSet", featurePriceOracle},
2604 {
"OracleDelete", featurePriceOracle},
2605 {
"LedgerStateFix", fixNFTokenPageLinks},
2606 {
"MPTokenIssuanceCreate", featureMPTokensV1},
2607 {
"MPTokenIssuanceDestroy", featureMPTokensV1},
2608 {
"MPTokenIssuanceSet", featureMPTokensV1},
2609 {
"MPTokenAuthorize", featureMPTokensV1},
2610 {
"CredentialCreate", featureCredentials},
2611 {
"CredentialAccept", featureCredentials},
2612 {
"CredentialDelete", featureCredentials},
2613 {
"NFTokenModify", featureDynamicNFT},
2614 {
"PermissionedDomainSet", featurePermissionedDomains},
2615 {
"PermissionedDomainDelete", featurePermissionedDomains}};
2620 BEAST_EXPECT(txRequiredFeatures.
contains(tx));
2622 Env env(*
this, features - txRequiredFeatures[tx]);
2626 env.
fund(
XRP(100000), alice, bob);
2632 for (
auto const& tx : txRequiredFeatures)
2633 txAmendmentDisabled(features, tx.first);
2639 auto txAmendmentEnabled = [&](
std::string const& tx) {
2640 Env env(*
this, features);
2644 env.
fund(
XRP(100000), alice, bob);
2650 for (
auto const& tx : txRequiredFeatures)
2651 txAmendmentEnabled(tx.first);
2657 for (
auto const permission : {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"})
2659 Env env(*
this, features - featureMPTokensV1);
2663 env.
fund(
XRP(100000), alice, bob);
2674 testcase(
"Make sure GranularSandbox is checked after transaction-level permission");
2676 using namespace jtx;
2682 env.
fund(
XRP(10000), gw, alice, bob);
2684 env(
fset(gw, asfRequireAuth));
2686 env(
trust(alice, gw[
"USD"](50)));
2696 txJson[sfQualityOut.jsonName] = 100;
2700 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustSet"}));
2714 testcase(
"Delegable Transactions Completeness");
2718#pragma push_macro("TRANSACTION")
2721#define TRANSACTION(tag, value, name, txDelegable, ...) \
2722 if (txDelegable == xrpl::Delegable) \
2727#include <xrpl/protocol/detail/transactions.macro>
2730#pragma pop_macro("TRANSACTION")
2755 delegableCount == expectedDelegableCount,
2756 "\n[SECURITY] New delegable transaction detected!"
2760 "\n Action: Verify security requirements to interact with Delegation feature");
2766 testcase(
"non-delegable tx with sfDelegate is rejected at preflight");
2767 using namespace jtx;
2769 Env env(*
this, features);
2772 env.
fund(
XRP(10000), alice, bob);
2789 Vault const vault{env};
2793 env(vault.set({.owner = alice, .id = keylet.key}),
2796 env(vault.del({.owner = alice, .id = keylet.key}),
2799 env(vault.deposit({.depositor = alice, .id = keylet.key, .amount = XRP(1)}),
2802 env(vault.withdraw({.depositor = alice, .id = keylet.key, .amount = XRP(1)}),
2805 env(vault.clawback({.issuer = alice, .id = keylet.key, .holder = bob}),
2812 auto const seq = env.seq(alice);
2814 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
2822 Vault const vault{env};
2854 testcase(
"DelegateUtils nullptr check");
2862 BEAST_EXPECT(granularPermissions.empty());
2868 testcase(
"test Permission to Tx type");
2884 for (
auto const gp : {
2885#pragma push_macro("GRANULAR_PERMISSION")
2886#undef GRANULAR_PERMISSION
2887#define GRANULAR_PERMISSION(type, txType, value, ...) GranularPermissionType::type,
2888#include <xrpl/protocol/detail/permissions.macro>
2889#undef GRANULAR_PERMISSION
2890#pragma pop_macro("GRANULAR_PERMISSION")
TestcaseT testcase
Memberspace for declaring test cases.
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 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.
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{})
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 coverClawback(AccountID const &account, std::uint32_t flags)
json::Value del(AccountID const &account, uint256 const &brokerID, uint32_t flags)
json::Value set(AccountID const &account, uint256 const &loanBrokerID, Number principalRequested, std::uint32_t flags)
json::Value manage(AccountID const &account, uint256 const &loanID, 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)
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.
json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
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.
@ 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::const_ref 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.
NotTEC checkTxPermission(SLE::const_ref delegate, STTx const &tx)
Check if the delegate account has permission to execute the transaction.
std::string to_string(BaseUInt< Bits, Tag > const &a)
@ tecINSUFFICIENT_RESERVE
constexpr FlagValue tfFullyCanonicalSig
std::enable_if_t< std::is_same_v< T, char >||std::is_same_v< T, unsigned char >, Slice > makeSlice(std::array< T, N > const &a)