2#include <test/jtx/CaptureLogs.h>
3#include <test/jtx/delegate.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/Permissions.h>
15 testcase(
"test feature not enabled");
18 Env env{*
this, features};
22 env.fund(
XRP(1000000), gw, alice, bob);
38 testcase(
"test valid request creating, updating, deleting permissions");
44 env.
fund(
XRP(100000), gw, alice);
53 "Payment",
"EscrowCreate",
"EscrowFinish",
"TrustlineAuthorize",
"CheckCreate"};
59 auto comparePermissions = [&](
Json::Value const& jle,
64 !jle[jss::result].isMember(jss::error) && jle[jss::result].isMember(jss::node));
65 BEAST_EXPECT(jle[jss::result][jss::node][
"LedgerEntryType"] == jss::Delegate);
66 BEAST_EXPECT(jle[jss::result][jss::node][jss::Account] == account.human());
67 BEAST_EXPECT(jle[jss::result][jss::node][sfAuthorize.jsonName] == authorize.human());
69 auto const& jPermissions = jle[jss::result][jss::node][sfPermissions.jsonName];
71 for (
auto const& permission : permissions)
74 jPermissions[i][sfPermission.jsonName][sfPermissionValue.jsonName] ==
81 comparePermissions(
delegate::entry(env, gw, alice), permissions, gw, alice);
84 auto const newPermissions =
91 comparePermissions(
delegate::entry(env, gw, alice), newPermissions, gw, alice);
97 BEAST_EXPECT(jle[jss::result][jss::error] ==
"entryNotFound");
102 comparePermissions(
delegate::entry(env, alice, gw), permissions, alice, gw);
105 BEAST_EXPECT(response[jss::result][jss::error] ==
"entryNotFound");
111 testcase(
"test invalid DelegateSet");
114 Env env(*
this, features);
118 env.
fund(
XRP(100000), gw, alice, bob);
149 jv[jss::TransactionType] = jss::DelegateSet;
150 jv[jss::Account] = gw.human();
151 jv[sfAuthorize.jsonName] = alice.human();
154 permissionValue[sfPermissionValue.jsonName] =
"Payment";
156 permissionObj[sfPermission.jsonName] = permissionValue;
157 permissionsJson.
append(permissionObj);
158 jv[sfPermissions.jsonName] = permissionsJson;
159 jv[sfFee.jsonName] = -1;
172 "TrustlineAuthorize",
174 "TrustlineAuthorize"}),
209 auto const txFee = env.
current()->fees().base;
210 env.
fund(env.
current()->fees().accountReserve(0) + txFee, alice);
225 auto const txFee = env.
current()->fees().base;
227 env.
fund(env.
current()->fees().accountReserve(1) + (txFee * 4), alice);
228 env.
fund(
XRP(100000), bob, carol);
278 auto setup = [&](
Env& env) {
282 env.fund(
XRP(1000), alice, bob, carol);
290 auto [alice, bob, carol] = setup(env);
292 auto const aliceBalance = env.
balance(alice);
293 auto const bobBalance = env.
balance(bob);
294 auto const carolBalance = env.
balance(carol);
298 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
299 BEAST_EXPECT(env.
balance(bob) == bobBalance);
300 BEAST_EXPECT(env.
balance(carol) == carolBalance);
306 auto [alice, bob, carol] = setup(env);
310 auto const aliceBalance = env.
balance(alice);
311 auto const bobBalance = env.
balance(bob);
312 auto const carolBalance = env.
balance(carol);
314 auto const sendAmt =
XRP(100);
315 auto const feeAmt =
XRP(10);
318 BEAST_EXPECT(env.
balance(alice) == aliceBalance - sendAmt);
319 BEAST_EXPECT(env.
balance(bob) == bobBalance - feeAmt);
320 BEAST_EXPECT(env.
balance(carol) == carolBalance + sendAmt);
326 auto [alice, bob, carol] = setup(env);
330 auto const aliceBalance = env.
balance(alice);
331 auto const bobBalance = env.
balance(bob);
332 auto const carolBalance = env.
balance(carol);
334 env(
pay(alice, carol,
XRP(100)),
339 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
340 BEAST_EXPECT(env.
balance(bob) == bobBalance);
341 BEAST_EXPECT(env.
balance(carol) == carolBalance);
351 auto setup = [&](
Env& env) {
356 auto const baseFee = env.current()->fees().base;
357 auto const reserve = env.current()->fees().accountReserve(1);
358 auto const paymentAmount =
XRP(1);
359 auto const highFee =
reserve + baseFee;
360 BEAST_EXPECT(highFee >
reserve);
362 env.fund(paymentAmount +
reserve + baseFee, alice);
363 env.fund(
XRP(1000), bob);
364 env.fund(
XRP(1000), carol);
383 auto [alice, bob, carol, paymentAmount, highFee,
reserve] = setup(env);
384 auto const aliceBalance = env.
balance(alice);
385 auto const bobBalance = env.
balance(bob);
386 auto const carolBalance = env.
balance(carol);
391 BEAST_EXPECT(env.
balance(alice) == aliceBalance - highFee);
392 BEAST_EXPECT(env.
balance(bob) == bobBalance);
393 BEAST_EXPECT(env.
balance(carol) == carolBalance);
400 auto [alice, bob, carol, paymentAmount, highFee,
reserve] = setup(env);
402 auto const alicePrePay = env.
balance(alice,
XRP);
404 auto const carolPrePay = env.
balance(carol,
XRP);
422 auto const baseFee = env.
current()->fees().base;
423 auto const baseReserve = env.
current()->fees().accountReserve(0);
425 env.
fund(env.
current()->fees().accountReserve(1) + baseFee +
XRP(1), alice);
426 env.
fund(baseReserve, bob);
433 auto const alicePreTx = env.
balance(alice,
XRP);
442 BEAST_EXPECT(env.
balance(bob,
XRP) < baseReserve);
457 auto const baseFee = env.
current()->fees().base;
471 auto const alicePrePay = env.
balance(alice,
XRP);
473 auto const carolPrePay = env.
balance(carol,
XRP);
494 env.
fund(
XRP(10000), alice, bob, carol);
497 auto aliceSeq = env.
seq(alice);
498 auto bobSeq = env.
seq(bob);
502 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
503 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
504 aliceSeq = env.
seq(alice);
505 bobSeq = env.
seq(bob);
507 for (
auto i = 0; i < 20; ++i)
512 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
513 BEAST_EXPECT(env.
seq(bob) == bobSeq);
514 aliceSeq = env.
seq(alice);
518 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
519 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
520 bobSeq = env.
seq(bob);
525 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
526 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
527 bobSeq = env.
seq(bob);
531 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
532 BEAST_EXPECT(env.
seq(bob) == bobSeq);
533 aliceSeq = env.
seq(alice);
546 env.
fund(
XRP(100000), alice, bob);
556 auto const aliceBalance = env.
balance(alice);
557 auto const bobBalance = env.
balance(bob);
560 auto const deleteFee =
drops(env.
current()->fees().increment);
566 BEAST_EXPECT(env.
balance(bob) == bobBalance + aliceBalance - deleteFee);
574 testcase(
"test delegate transaction");
648 auto const USD = gw[
"USD"];
649 auto const EUR = gw2[
"EUR"];
654 env.
trust(USD(200), alice);
655 env.
trust(EUR(400), gw);
700 BEAST_EXPECT(env.
balance(bob, USD) == USD(0));
710 BEAST_EXPECT(env.
balance(bob, USD) == USD(0));
728 env(
pay(gw2, gw, EUR(200)));
752 auto const USD = gw[
"USD"];
757 env.
trust(USD(200), alice);
792 BEAST_EXPECT(env.
balance(bob, USD) == USD(0));
798 Env env(*
this, features);
803 auto const USD = gw[
"USD"];
805 env.
fund(
XRP(10000), alice, bob, carol, gw);
807 env.
trust(USD(50000), alice);
808 env.
trust(USD(50000), bob);
809 env.
trust(USD(50000), carol);
810 env(
pay(gw, alice, USD(10000)));
811 env(
pay(gw, bob, USD(10000)));
812 env(
pay(gw, carol, USD(10000)));
817 env(
offer(carol,
XRP(100), USD(501)));
824 env(
pay(gw, alice, USD(5000)),
831 env(
pay(gw, alice, USD(5000)),
845 env(
offer(bob,
XRP(100), USD(501)));
852 env(
pay(alice, gw, USD(5000)),
859 env(
pay(alice, gw, USD(5000)),
880 MPTTester mpt(env, gw, {.holders = {alice, bob}});
881 mpt.
create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer});
883 mpt.authorize({.account = alice});
884 mpt.authorize({.account = bob});
886 auto const MPT = mpt[
"MPT"];
887 env(
pay(gw, alice,
MPT(500)));
888 env(
pay(gw, bob,
MPT(500)));
900 BEAST_EXPECT(env.
balance(bob,
MPT) == bobMPT);
911 BEAST_EXPECT(env.
balance(bob,
MPT) == bobMPT);
917 env(
delegate::set(alice, bob, {
"PaymentBurn",
"PaymentMint",
"Payment"}));
921 BEAST_EXPECT(env.
balance(bob,
MPT) == bobMPT);
924 BEAST_EXPECT(env.
balance(alice,
MPT) == aliceMPT -
MPT(100));
933 testcase(
"test TrustSet granular permissions");
942 env.
fund(
XRP(10000), gw, alice, bob);
943 env(
fset(gw, asfRequireAuth));
954 env(
trust(alice, gw[
"USD"](50)));
962 env(
trust(alice, gw[
"USD"](50), tfSetNoRipple),
965 env(
trust(alice, gw[
"USD"](50), tfClearNoRipple),
968 env(
trust(gw, gw[
"USD"](0), alice, tfSetDeepFreeze),
971 env(
trust(gw, gw[
"USD"](0), alice, tfClearDeepFreeze),
977 env(
trust(gw, gw[
"USD"](0), alice, tfSetfAuth),
980 env(
trust(gw, gw[
"USD"](0), alice, tfSetFreeze),
987 env(
trust(gw, gw[
"USD"](0), alice, tfClearFreeze),
993 env(
trust(gw, gw[
"USD"](50), alice, tfSetfAuth),
1001 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
1005 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustlineUnfreeze"}));
1011 env(
trust(gw, gw[
"USD"](0), alice, tfSetFreeze),
1021 auto tx =
trust(alice, gw[
"USD"](50));
1022 tx[
"QualityIn"] =
"1000";
1024 auto tx2 =
trust(alice, gw[
"USD"](50));
1025 tx2[
"QualityOut"] =
"1000";
1027 auto tx3 =
trust(gw, alice[
"USD"](50));
1028 tx3[
"QualityIn"] =
"1000";
1030 auto tx4 =
trust(gw, alice[
"USD"](50));
1031 tx4[
"QualityOut"] =
"1000";
1037 auto tx5 =
trust(gw, alice[
"USD"](50));
1038 tx5[
"QualityOut"] =
"1000";
1040 auto tx6 =
trust(alice, gw[
"USD"](50));
1041 tx6[
"QualityOut"] =
"1000";
1054 env.
fund(
XRP(10000), gw, alice, bob);
1055 env(
fset(gw, asfRequireAuth));
1060 env(
delegate::set(alice, bob, {
"TrustlineUnfreeze",
"NFTokenCreateOffer"}));
1069 {
"TrustlineUnfreeze",
"NFTokenCreateOffer",
"TrustSet",
"AccountTransferRateSet"}));
1077 {
"TrustlineUnfreeze",
"NFTokenCreateOffer",
"TrustSet",
"AccountTransferRateSet"}));
1099 env.
fund(
XRP(10000), gw, alice, bob);
1100 env(
fset(gw, asfRequireAuth));
1102 env(
trust(alice, gw[
"USD"](50)));
1115 testcase(
"test AccountSet granular permissions");
1116 using namespace jtx;
1123 auto const alice =
Account{
"alice"};
1124 auto const bob =
Account{
"bob"};
1125 env.
fund(
XRP(10000), alice, bob);
1136 auto jt =
noop(alice);
1138 jt[sfDelegate] = bob.human();
1142 env(
delegate::set(alice, bob, {
"TrustlineUnfreeze",
"AccountEmailHashSet"}));
1157 BEAST_EXPECT(!env.
le(alice)->isFieldPresent(sfDomain));
1160 std::string const failDomain =
"fail_domain_update";
1161 jt[sfFlags] = tfRequireAuth;
1162 jt[sfDomain] =
strHex(failDomain);
1170 std::string const mh(
"5F31A79367DC3137FADA860C05742EE6");
1171 jt[sfEmailHash] = mh;
1175 env(
delegate::set(alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet"}));
1178 BEAST_EXPECT(
to_string((*env.
le(alice))[sfEmailHash]) == mh);
1183 jt[sfMessageKey] =
strHex(rkp.first.slice());
1188 alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet",
"AccountMessageKeySet"}));
1193 BEAST_EXPECT(
strHex((*env.
le(alice))[sfMessageKey]) ==
strHex(rkp.first.slice()));
1194 jt[sfMessageKey] =
"";
1196 BEAST_EXPECT(!env.
le(alice)->isFieldPresent(sfMessageKey));
1205 {
"AccountDomainSet",
1206 "AccountEmailHashSet",
1207 "AccountMessageKeySet",
1208 "AccountTransferRateSet"}));
1210 auto jtRate =
rate(alice, 2.0);
1211 jtRate[sfDelegate] = bob.human();
1213 BEAST_EXPECT((*env.
le(alice))[sfTransferRate] == 2000000000);
1223 {
"AccountDomainSet",
1224 "AccountEmailHashSet",
1225 "AccountMessageKeySet",
1226 "AccountTransferRateSet",
1227 "AccountTickSizeSet"}));
1230 BEAST_EXPECT((*env.
le(alice))[sfTickSize] == 8);
1242 env(
fset(alice, asfRequireAuth));
1251 alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet",
"AccountMessageKeySet"}));
1256 "9633EC8AF54F16B5286DB1D7B519EF49EEFC050C0C8AC4384F1D88ACD1BFDF"
1258 auto jv2 =
noop(alice);
1260 jv2[sfDelegate] = bob.human();
1261 jv2[sfWalletLocator] = locator;
1268 auto const alice =
Account{
"alice"};
1269 auto const bob =
Account{
"bob"};
1270 env.
fund(
XRP(10000), alice, bob);
1277 env(
fset(alice, flag));
1285 testSetClearFlag(asfRequireAuth);
1286 testSetClearFlag(asfAllowTrustLineClawback);
1290 alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet",
"AccountMessageKeySet"}));
1293 testSetClearFlag(asfDefaultRipple);
1294 testSetClearFlag(asfDepositAuth);
1295 testSetClearFlag(asfDisallowIncomingCheck);
1296 testSetClearFlag(asfDisallowIncomingNFTokenOffer);
1297 testSetClearFlag(asfDisallowIncomingPayChan);
1298 testSetClearFlag(asfDisallowIncomingTrustline);
1299 testSetClearFlag(asfDisallowXRP);
1300 testSetClearFlag(asfRequireDest);
1301 testSetClearFlag(asfGlobalFreeze);
1305 env(
fset(alice, asfAccountTxnID));
1307 BEAST_EXPECT(env.
le(alice)->isFieldPresent(sfAccountTxnID));
1312 jt[sfDelegate] = bob.human();
1313 jt[sfNFTokenMinter] = bob.human();
1318 bob, alice, {
"AccountDomainSet",
"AccountEmailHashSet",
"AccountMessageKeySet"}));
1325 env(
fset(bob, asfNoFreeze));
1333 env(
regkey(bob, bobKey));
1335 env(
fset(alice, asfDisableMaster),
1346 env.
fund(
XRP(10000), alice, bob);
1349 env(
delegate::set(alice, bob, {
"AccountDomainSet",
"AccountEmailHashSet"}));
1353 auto jt =
noop(alice);
1355 jt[sfDelegate] = bob.human();
1366 testcase(
"test MPTokenIssuanceSet granular");
1367 using namespace jtx;
1374 env.
fund(
XRP(100000), alice, bob);
1379 mpt.create({.flags = tfMPTCanLock});
1401 mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob});
1404 .flags = tfMPTUnlock,
1409 env(
delegate::set(alice, bob, {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"}));
1411 mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob});
1412 mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob});
1421 env.
fund(
XRP(100000), alice, bob);
1426 mpt.create({.flags = tfMPTCanLock});
1432 mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob});
1436 .flags = tfMPTUnlock,
1442 env(
delegate::set(alice, bob, {
"NFTokenMint",
"MPTokenIssuanceLock",
"NFTokenBurn"}));
1447 .flags = tfMPTUnlock,
1455 {
"NFTokenMint",
"MPTokenIssuanceLock",
"NFTokenBurn",
"MPTokenIssuanceSet"}));
1456 mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob});
1458 mpt.set({.account = alice, .flags = tfMPTLock});
1459 mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob});
1460 mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob});
1468 env.
fund(
XRP(100000), alice, bob);
1473 mpt.create({.flags = tfMPTCanLock});
1487 using namespace jtx;
1493 env.
fund(
XRP(100000), alice, bob, carol);
1499 auto aliceBalance = env.
balance(alice);
1500 auto bobBalance = env.
balance(bob);
1501 auto carolBalance = env.
balance(carol);
1505 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(100));
1506 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
1507 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(100));
1513 testcase(
"test single sign with bad secret");
1514 using namespace jtx;
1521 env.
fund(
XRP(100000), alice, bob, carol);
1527 auto aliceBalance = env.
balance(alice);
1528 auto bobBalance = env.
balance(bob);
1529 auto carolBalance = env.
balance(carol);
1531 env(
pay(alice, carol,
XRP(100)),
1537 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
1538 BEAST_EXPECT(env.
balance(bob) == bobBalance);
1539 BEAST_EXPECT(env.
balance(carol) == carolBalance);
1547 env.
fund(
XRP(100000), alice, bob, carol);
1553 auto aliceBalance = env.
balance(alice);
1554 auto bobBalance = env.
balance(bob);
1555 auto carolBalance = env.
balance(carol);
1557 env(
pay(alice, carol,
XRP(100)),
1563 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
1564 BEAST_EXPECT(env.
balance(bob) == bobBalance);
1565 BEAST_EXPECT(env.
balance(carol) == carolBalance);
1567 env(
pay(alice, carol,
XRP(100)),
1573 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
1574 BEAST_EXPECT(env.
balance(bob) == bobBalance);
1575 BEAST_EXPECT(env.
balance(carol) == carolBalance);
1583 env.
fund(
XRP(100000), alice, bob, carol);
1586 auto aliceBalance = env.
balance(alice);
1587 auto bobBalance = env.
balance(bob);
1588 auto carolBalance = env.
balance(carol);
1590 env(
pay(alice, carol,
XRP(100)),
1596 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
1597 BEAST_EXPECT(env.
balance(bob) == bobBalance);
1598 BEAST_EXPECT(env.
balance(carol) == carolBalance);
1600 env(
pay(alice, carol,
XRP(100)),
1606 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
1607 BEAST_EXPECT(env.
balance(bob) == bobBalance);
1608 BEAST_EXPECT(env.
balance(carol) == carolBalance);
1616 using namespace jtx;
1624 env.
fund(
XRP(100000), alice, bob, carol, daria, edward);
1627 env(
signers(bob, 2, {{daria, 1}, {edward, 1}}));
1633 auto aliceBalance = env.
balance(alice);
1634 auto bobBalance = env.
balance(bob);
1635 auto carolBalance = env.
balance(carol);
1636 auto dariaBalance = env.
balance(daria);
1637 auto edwardBalance = env.
balance(edward);
1641 BEAST_EXPECT(env.
balance(alice) == aliceBalance -
XRP(100));
1642 BEAST_EXPECT(env.
balance(bob) == bobBalance -
XRP(10));
1643 BEAST_EXPECT(env.
balance(carol) == carolBalance +
XRP(100));
1644 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
1645 BEAST_EXPECT(env.
balance(edward) == edwardBalance);
1651 testcase(
"test multi sign which does not meet quorum");
1652 using namespace jtx;
1661 env.
fund(
XRP(100000), alice, bob, carol, daria, edward, fred);
1664 env(
signers(bob, 3, {{daria, 1}, {edward, 1}, {fred, 1}}));
1670 auto aliceBalance = env.
balance(alice);
1671 auto bobBalance = env.
balance(bob);
1672 auto carolBalance = env.
balance(carol);
1673 auto dariaBalance = env.
balance(daria);
1674 auto edwardBalance = env.
balance(edward);
1676 env(
pay(alice, carol,
XRP(100)),
1679 msig(daria, edward),
1682 BEAST_EXPECT(env.
balance(alice) == aliceBalance);
1683 BEAST_EXPECT(env.
balance(bob) == bobBalance);
1684 BEAST_EXPECT(env.
balance(carol) == carolBalance);
1685 BEAST_EXPECT(env.
balance(daria) == dariaBalance);
1686 BEAST_EXPECT(env.
balance(edward) == edwardBalance);
1693 using namespace jtx;
1695 Env env(*
this, features);
1699 env.
fund(
XRP(100000), alice, bob);
1702 auto buildRequest = [&](
auto value) ->
Json::Value {
1704 jv[jss::TransactionType] = jss::DelegateSet;
1705 jv[jss::Account] = alice.human();
1706 jv[sfAuthorize.jsonName] = bob.human();
1710 permissionValue[sfPermissionValue.jsonName] = value;
1712 permissionObj[sfPermission.jsonName] = permissionValue;
1713 permissionsJson.
append(permissionObj);
1714 jv[sfPermissions.jsonName] = permissionsJson;
1721 for (
auto value : {0, 100000, 54321})
1723 auto jv = buildRequest(value);
1731 testcase(
"test delegate disabled tx");
1732 using namespace jtx;
1739 {
"Clawback", featureClawback},
1740 {
"AMMClawback", featureAMMClawback},
1741 {
"AMMCreate", featureAMM},
1742 {
"AMMDeposit", featureAMM},
1743 {
"AMMWithdraw", featureAMM},
1744 {
"AMMVote", featureAMM},
1745 {
"AMMBid", featureAMM},
1746 {
"AMMDelete", featureAMM},
1747 {
"XChainCreateClaimID", featureXChainBridge},
1748 {
"XChainCommit", featureXChainBridge},
1749 {
"XChainClaim", featureXChainBridge},
1750 {
"XChainAccountCreateCommit", featureXChainBridge},
1751 {
"XChainAddClaimAttestation", featureXChainBridge},
1752 {
"XChainAddAccountCreateAttestation", featureXChainBridge},
1753 {
"XChainModifyBridge", featureXChainBridge},
1754 {
"XChainCreateBridge", featureXChainBridge},
1755 {
"DIDSet", featureDID},
1756 {
"DIDDelete", featureDID},
1757 {
"OracleSet", featurePriceOracle},
1758 {
"OracleDelete", featurePriceOracle},
1759 {
"LedgerStateFix", fixNFTokenPageLinks},
1760 {
"MPTokenIssuanceCreate", featureMPTokensV1},
1761 {
"MPTokenIssuanceDestroy", featureMPTokensV1},
1762 {
"MPTokenIssuanceSet", featureMPTokensV1},
1763 {
"MPTokenAuthorize", featureMPTokensV1},
1764 {
"CredentialCreate", featureCredentials},
1765 {
"CredentialAccept", featureCredentials},
1766 {
"CredentialDelete", featureCredentials},
1767 {
"NFTokenModify", featureDynamicNFT},
1768 {
"PermissionedDomainSet", featurePermissionedDomains},
1769 {
"PermissionedDomainDelete", featurePermissionedDomains}};
1774 BEAST_EXPECT(txRequiredFeatures.contains(tx));
1776 Env env(*
this, features - txRequiredFeatures[tx]);
1780 env.
fund(
XRP(100000), alice, bob);
1786 for (
auto const& tx : txRequiredFeatures)
1787 txAmendmentDisabled(features, tx.first);
1793 auto txAmendmentEnabled = [&](
std::string const& tx) {
1794 Env env(*
this, features);
1798 env.
fund(
XRP(100000), alice, bob);
1804 for (
auto const& tx : txRequiredFeatures)
1805 txAmendmentEnabled(tx.first);
1812 testcase(
"Delegable Transactions Completeness");
1816#pragma push_macro("TRANSACTION")
1819#define TRANSACTION(tag, value, name, delegable, ...) \
1820 if (delegable == xrpl::delegable) \
1825#include <xrpl/protocol/detail/transactions.macro>
1828#pragma pop_macro("TRANSACTION")
1851 delegableCount == expectedDelegableCount,
1852 "\n[SECURITY] New delegable transaction detected!"
1856 "\n Action: Verify security requirements to interact with Delegation feature");
1886BEAST_DEFINE_TESTSUITE(Delegate, app,
xrpl);
Value & append(Value const &value)
Append value to array at the end.
testcase_t testcase
Memberspace for declaring test cases.
void testMultiSignQuorumNotMet()
void testTrustSetGranular()
void testFeatureDisabled(FeatureBitset features)
void testInvalidRequest(FeatureBitset features)
void run() override
Runs the suite.
void testMPTokenIssuanceSetGranular()
void testDelegateTransaction()
void testSingleSignBadSecret()
void testTxDelegableCount()
void testPaymentGranular(FeatureBitset features)
void testPermissionValue(FeatureBitset features)
void testAccountSetGranular()
void testTxRequireFeatures(FeatureBitset features)
Immutable cryptographic account descriptor.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
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.
void create(MPTCreate const &arg=MPTCreate{})
Converts to MPT Issue or STAmount.
Sets the optional URI on a DIDSet.
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.
@ arrayValue
array value (ordered list)
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 create(A const &account, A const &dest, STAmount const &sendMax)
Create a check.
Json::Value set(jtx::Account const &account, jtx::Account const &authorize, std::vector< std::string > const &permissions)
Json::Value entry(jtx::Env &env, jtx::Account const &account, jtx::Account const &authorize)
Json::Value set(jtx::Account const &account)
bool expectOffers(Env &env, AccountID const &account, std::uint16_t size, std::vector< Amounts > const &toMatch)
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Json::Value signers(Account const &account, std::uint32_t quorum, std::vector< signer > const &v)
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
XRP_t const XRP
Converts to XRP Issue or STAmount.
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
FeatureBitset testable_amendments()
Json::Value regkey(Account const &account, disabled_t)
Disable the regular key.
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Json::Value acctdelete(Account const &account, Account const &dest)
Delete account.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
static XRPAmount reserve(jtx::Env &env, std::uint32_t count)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
@ terNO_DELEGATE_PERMISSION
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
std::string to_string(base_uint< Bits, Tag > const &a)
std::string strHex(FwdIt begin, FwdIt end)
@ tecINSUFFICIENT_RESERVE
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
constexpr FlagValue tfFullyCanonicalSig