198 using namespace test::jtx;
200 Account
const gw{
"gateway"};
201 Account
const alice{
"alice"};
202 Account
const bob{
"bob"};
203 IOU
const USD{gw[
"USD"]};
205 Env env{*
this, features};
207 STAmount const startBalance{XRP(1000).value()};
208 env.fund(startBalance, gw, alice, bob);
214 auto writeTwoChecks = [&env, &USD,
this](
215 Account
const& from, Account
const& to) {
222 env(check::create(from, to, XRP(2000)));
225 env(check::create(from, to, USD(50)));
231 env.require(owners(from, fromOwnerCount + 2));
233 owners(to, to == from ? fromOwnerCount + 2 : toOwnerCount));
236 writeTwoChecks(alice, bob);
237 writeTwoChecks(gw, alice);
238 writeTwoChecks(alice, gw);
244 using namespace std::chrono_literals;
247 env(check::create(alice, bob, USD(50)), expiration(env.now() + 1s));
250 env(check::create(alice, bob, USD(50)), source_tag(2));
252 env(check::create(alice, bob, USD(50)), dest_tag(3));
254 env(check::create(alice, bob, USD(50)), invoice_id(
uint256{4}));
256 env(check::create(alice, bob, USD(50)),
257 expiration(env.now() + 1s),
268 env(regkey(alice, alie));
273 env(signers(alice, 2, {{bogie, 1}, {demon, 1}}), sig(alie));
277 env(check::create(alice, bob, USD(50)), sig(alie));
283 XRPAmount const baseFeeDrops{env.current()->fees().base};
284 env(check::create(alice, bob, USD(50)),
286 fee(3 * baseFeeDrops));
393 using namespace test::jtx;
395 Account
const gw1{
"gateway1"};
396 Account
const gwF{
"gatewayFrozen"};
397 Account
const alice{
"alice"};
398 Account
const bob{
"bob"};
399 IOU
const USD{gw1[
"USD"]};
401 Env env{*
this, features};
403 STAmount const startBalance{XRP(1000).value()};
404 env.fund(startBalance, gw1, gwF, alice, bob);
408 env(check::create(alice, bob, USD(50)),
414 env(check::create(alice, bob, USD(50)),
420 env(check::create(alice, alice, XRP(10)), ter(
temREDUNDANT));
424 env(check::create(alice, bob, drops(-1)), ter(
temBAD_AMOUNT));
427 env(check::create(alice, bob, drops(0)), ter(
temBAD_AMOUNT));
430 env(check::create(alice, bob, drops(1)));
439 env(check::create(alice, bob, USD(1)));
448 env(check::create(alice, bob, USD(50)),
454 Account
const bogie{
"bogie"};
455 env(check::create(alice, bogie, USD(50)), ter(
tecNO_DST));
465 env(check::create(alice, bob, USD(50)), dest_tag(11));
472 IOU
const USF{gwF[
"USF"]};
476 env(check::create(alice, bob, USF(50)), ter(
tecFROZEN));
482 env(check::create(alice, bob, USF(50)));
488 env.trust(USD(1000), alice);
489 env.trust(USD(1000), bob);
491 env(pay(gw1, alice, USD(25)));
492 env(pay(gw1, bob, USD(25)));
500 env(check::create(alice, bob, USD(50)), ter(
tecFROZEN));
504 env(check::create(bob, alice, USD(50)));
506 env(pay(bob, alice, USD(1)));
508 env(check::create(gw1, alice, USD(50)));
510 env(pay(gw1, alice, USD(1)));
516 env(check::create(alice, bob, USD(50)));
518 env(check::create(bob, alice, USD(50)));
520 env(check::create(gw1, alice, USD(50)));
528 env(check::create(alice, bob, USD(50)));
530 env(pay(alice, bob, USD(1)));
532 env(check::create(bob, alice, USD(50)), ter(
tecFROZEN));
536 env(check::create(gw1, alice, USD(50)), ter(
tecFROZEN));
547 env(check::create(alice, bob, USD(50)),
548 expiration(env.now()),
552 using namespace std::chrono_literals;
553 env(check::create(alice, bob, USD(50)), expiration(env.now() + 1s));
557 Account
const cheri{
"cheri"};
558 env.fund(env.current()->fees().accountReserve(1) - drops(1), cheri);
561 env(check::create(cheri, bob, USD(50)),
562 fee(drops(env.current()->fees().base)),
566 env(pay(bob, cheri, drops(env.current()->fees().base + 1)));
569 env(check::create(cheri, bob, USD(50)));
579 using namespace test::jtx;
581 Account
const alice{
"alice"};
582 Account
const bob{
"bob"};
584 Env env{*
this, features};
586 XRPAmount const baseFeeDrops{env.current()->fees().base};
587 STAmount const startBalance{XRP(300).value()};
588 env.fund(startBalance, alice, bob);
593 env(check::create(alice, bob, XRP(10)));
595 env.require(balance(alice, startBalance - drops(baseFeeDrops)));
596 env.require(balance(bob, startBalance));
599 BEAST_EXPECT(ownerCount(env, alice) == 1);
600 BEAST_EXPECT(ownerCount(env, bob) == 0);
602 env(check::cash(bob, chkId, XRP(10)));
605 balance(alice, startBalance - XRP(10) - drops(baseFeeDrops)));
607 balance(bob, startBalance + XRP(10) - drops(baseFeeDrops)));
610 BEAST_EXPECT(ownerCount(env, alice) == 0);
611 BEAST_EXPECT(ownerCount(env, bob) == 0);
614 env(pay(env.master, alice, XRP(10) + drops(baseFeeDrops)));
615 env(pay(bob, env.master, XRP(10) - drops(baseFeeDrops * 2)));
617 env.require(balance(alice, startBalance));
618 env.require(balance(bob, startBalance));
622 STAmount const reserve{env.current()->fees().accountReserve(0)};
624 startBalance - reserve - drops(baseFeeDrops)};
626 env(check::create(alice, bob, checkAmount));
630 env(check::cash(bob, chkId, checkAmount + drops(1)),
634 bob, chkId, check::DeliverMin(checkAmount + drops(1))),
641 env(check::cash(bob, chkId, check::DeliverMin(checkAmount)));
643 env.require(balance(alice, reserve));
645 bob, startBalance + checkAmount - drops(baseFeeDrops * 3)));
648 BEAST_EXPECT(ownerCount(env, alice) == 0);
649 BEAST_EXPECT(ownerCount(env, bob) == 0);
652 env(pay(env.master, alice, checkAmount + drops(baseFeeDrops)));
653 env(pay(bob, env.master, checkAmount - drops(baseFeeDrops * 4)));
655 env.require(balance(alice, startBalance));
656 env.require(balance(bob, startBalance));
660 STAmount const reserve{env.current()->fees().accountReserve(0)};
662 startBalance - reserve - drops(baseFeeDrops - 1)};
664 env(check::create(alice, bob, checkAmount));
673 env(check::cash(bob, chkId, check::DeliverMin(drops(1))));
675 env.require(balance(alice, reserve));
677 bob, startBalance + checkAmount - drops(baseFeeDrops * 2 + 1)));
680 BEAST_EXPECT(ownerCount(env, alice) == 0);
681 BEAST_EXPECT(ownerCount(env, bob) == 0);
684 env(pay(env.master, alice, checkAmount + drops(baseFeeDrops - 1)));
686 bob, env.master, checkAmount - drops(baseFeeDrops * 3 + 1)));
688 env.require(balance(alice, startBalance));
689 env.require(balance(bob, startBalance));
699 using namespace test::jtx;
701 bool const cashCheckMakesTrustLine =
702 features[featureCheckCashMakesTrustLine];
704 Account
const gw{
"gateway"};
705 Account
const alice{
"alice"};
706 Account
const bob{
"bob"};
707 IOU
const USD{gw[
"USD"]};
710 Env env{*
this, features};
712 env.fund(XRP(1000), gw, alice, bob);
717 env(check::create(alice, bob, USD(10)));
725 env(trust(alice, USD(20)));
727 env(pay(gw, alice, USD(9.5)));
734 env(pay(gw, alice, USD(0.5)));
736 if (!cashCheckMakesTrustLine)
741 env(check::cash(bob, chkId1, USD(10)), ter(
tecNO_LINE));
746 env(trust(bob, USD(9.5)));
748 if (!cashCheckMakesTrustLine)
759 env(trust(bob, USD(10.5)));
765 env(check::cash(bob, chkId1, USD(10)));
767 env.require(balance(alice, USD(0)));
768 env.require(balance(bob, USD(10)));
771 BEAST_EXPECT(ownerCount(env, alice) == 1);
772 BEAST_EXPECT(ownerCount(env, bob) == 1);
775 env(check::cash(bob, chkId1, USD(10)), ter(
tecNO_ENTRY));
779 env(pay(bob, alice, USD(7)));
783 env(check::create(alice, bob, USD(7)));
790 env(check::cash(bob, chkId2, USD(5)));
792 env.require(balance(alice, USD(2)));
793 env.require(balance(bob, USD(8)));
796 BEAST_EXPECT(ownerCount(env, alice) == 1);
797 BEAST_EXPECT(ownerCount(env, bob) == 1);
801 env(check::create(alice, bob, USD(2)));
804 env(check::create(alice, bob, USD(2)));
810 env(check::cash(bob, chkId4, USD(2)));
812 env.require(balance(alice, USD(0)));
813 env.require(balance(bob, USD(10)));
816 BEAST_EXPECT(ownerCount(env, alice) == 2);
817 BEAST_EXPECT(ownerCount(env, bob) == 1);
823 env.require(balance(alice, USD(0)));
824 env.require(balance(bob, USD(10)));
827 BEAST_EXPECT(ownerCount(env, alice) == 2);
828 BEAST_EXPECT(ownerCount(env, bob) == 1);
830 if (cashCheckMakesTrustLine)
846 env(check::create(gw, bob, USD(20)));
850 env(check::cash(bob, chkId20, USD(20)));
852 env.require(balance(bob, USD(30)));
856 env(pay(bob, gw, USD(20)));
860 env(check::cancel(bob, chkId3));
862 env.require(balance(alice, USD(0)));
863 env.require(balance(bob, USD(10)));
866 BEAST_EXPECT(ownerCount(env, alice) == 1);
867 BEAST_EXPECT(ownerCount(env, bob) == 1);
871 Env env{*
this, features};
873 env.fund(XRP(1000), gw, alice, bob);
876 env(trust(alice, USD(20)));
877 env(trust(bob, USD(20)));
879 env(pay(gw, alice, USD(8)));
884 env(check::create(alice, bob, USD(9)));
887 env(check::create(alice, bob, USD(8)));
890 env(check::create(alice, bob, USD(7)));
893 env(check::create(alice, bob, USD(6)));
898 env(check::cash(bob, chkId9, check::DeliverMin(USD(9))),
903 env(check::cash(bob, chkId9, check::DeliverMin(USD(7))));
905 env.require(balance(alice, USD(0)));
906 env.require(balance(bob, USD(8)));
909 BEAST_EXPECT(ownerCount(env, alice) == 4);
910 BEAST_EXPECT(ownerCount(env, bob) == 1);
913 env(pay(bob, alice, USD(7)));
918 env(check::cash(bob, chkId7, check::DeliverMin(USD(7))));
920 env.require(balance(alice, USD(0)));
921 env.require(balance(bob, USD(8)));
924 BEAST_EXPECT(ownerCount(env, alice) == 3);
925 BEAST_EXPECT(ownerCount(env, bob) == 1);
928 env(pay(bob, alice, USD(8)));
933 env(check::cash(bob, chkId6, check::DeliverMin(USD(4))));
935 env.require(balance(alice, USD(2)));
936 env.require(balance(bob, USD(6)));
939 BEAST_EXPECT(ownerCount(env, alice) == 2);
940 BEAST_EXPECT(ownerCount(env, bob) == 1);
944 env(check::cash(bob, chkId8, check::DeliverMin(USD(2))));
946 env.require(balance(alice, USD(0)));
947 env.require(balance(bob, USD(8)));
950 BEAST_EXPECT(ownerCount(env, alice) == 1);
951 BEAST_EXPECT(ownerCount(env, bob) == 1);
955 Env env(*
this, features);
957 env.fund(XRP(1000), gw, alice, bob);
960 env(trust(gw, alice[
"USD"](100)), txflags(
tfSetfAuth));
961 env(trust(alice, USD(20)));
963 env(pay(gw, alice, USD(8)));
969 env(check::create(alice, bob, USD(7)));
972 env(check::cash(bob, chkId, USD(7)),
978 env(trust(bob, USD(5)));
981 env(check::cash(bob, chkId, USD(7)), ter(
tecNO_AUTH));
985 env(trust(gw, bob[
"USD"](1)), txflags(
tfSetfAuth));
990 if (!cashCheckMakesTrustLine)
1006 env(check::cash(bob, chkId, check::DeliverMin(USD(4))));
1007 STAmount const bobGot = cashCheckMakesTrustLine ? USD(7) : USD(5);
1009 env.require(balance(alice, USD(8) - bobGot));
1010 env.require(balance(bob, bobGot));
1014 BEAST_EXPECT(ownerCount(env, alice) == 1);
1015 BEAST_EXPECT(ownerCount(env, bob) == 1);
1021 for (
auto const& testFeatures :
1022 {features - featureMultiSignReserve,
1023 features | featureMultiSignReserve})
1025 Env env{*
this, testFeatures};
1027 env.fund(XRP(1000), gw, alice, bob);
1032 env(check::create(alice, bob, USD(1)));
1036 env(check::create(alice, bob, USD(2)));
1039 env(trust(alice, USD(20)));
1040 env(trust(bob, USD(20)));
1042 env(pay(gw, alice, USD(8)));
1047 env(regkey(bob, bobby));
1052 env(signers(bob, 2, {{bogie, 1}, {demon, 1}}), sig(bobby));
1057 int const signersCount = {
1058 testFeatures[featureMultiSignReserve] ? 1 : 4};
1059 BEAST_EXPECT(ownerCount(env, bob) == signersCount + 1);
1062 env(check::cash(bob, chkId1, (USD(1))), sig(bobby));
1064 env.require(balance(alice, USD(7)));
1065 env.require(balance(bob, USD(1)));
1068 BEAST_EXPECT(ownerCount(env, alice) == 2);
1069 BEAST_EXPECT(ownerCount(env, bob) == signersCount + 1);
1072 XRPAmount const baseFeeDrops{env.current()->fees().base};
1073 env(check::cash(bob, chkId2, (USD(2))),
1075 fee(3 * baseFeeDrops));
1077 env.require(balance(alice, USD(5)));
1078 env.require(balance(bob, USD(3)));
1081 BEAST_EXPECT(ownerCount(env, alice) == 1);
1082 BEAST_EXPECT(ownerCount(env, bob) == signersCount + 1);
1163 using namespace test::jtx;
1165 Account
const gw{
"gateway"};
1166 Account
const alice{
"alice"};
1167 Account
const bob{
"bob"};
1168 IOU
const USD{gw[
"USD"]};
1170 Env env{*
this, features};
1172 env.fund(XRP(1000), gw, alice, bob);
1175 env(trust(alice, USD(1000)));
1176 env(trust(bob, USD(1000)));
1178 env(pay(gw, alice, USD(1000)));
1186 auto qIn = [](
double percent) {
return qualityInPercent(percent); };
1187 auto qOut = [](
double percent) {
return qualityOutPercent(percent); };
1191 auto testNonIssuerQPay = [&env, &alice, &bob, &USD](
1192 Account
const& truster,
1194 auto const& inOrOut,
1198 STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1199 STAmount const bobStart{env.balance(bob, USD.issue()).value()};
1202 env(trust(truster, iou(1000)), inOrOut(pct));
1205 env(pay(alice, bob, USD(amount)), sendmax(USD(10)));
1207 env.require(balance(alice, aliceStart - USD(10)));
1208 env.require(balance(bob, bobStart + USD(10)));
1212 env(trust(truster, iou(1000)), inOrOut(0));
1216 auto testNonIssuerQCheck = [&env, &alice, &bob, &USD](
1217 Account
const& truster,
1219 auto const& inOrOut,
1223 STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1224 STAmount const bobStart{env.balance(bob, USD.issue()).value()};
1227 env(trust(truster, iou(1000)), inOrOut(pct));
1231 env(check::create(alice, bob, USD(10)));
1234 env(check::cash(bob, chkId, USD(amount)));
1236 env.require(balance(alice, aliceStart - USD(10)));
1237 env.require(balance(bob, bobStart + USD(10)));
1241 env(trust(truster, iou(1000)), inOrOut(0));
1246 testNonIssuerQPay(alice, gw[
"USD"], qIn, 50, 10);
1247 testNonIssuerQCheck(alice, gw[
"USD"], qIn, 50, 10);
1250 testNonIssuerQPay(bob, gw[
"USD"], qIn, 50, 5);
1251 testNonIssuerQCheck(bob, gw[
"USD"], qIn, 50, 5);
1253 testNonIssuerQPay(gw, alice[
"USD"], qIn, 50, 10);
1254 testNonIssuerQCheck(gw, alice[
"USD"], qIn, 50, 10);
1256 testNonIssuerQPay(gw, bob[
"USD"], qIn, 50, 10);
1257 testNonIssuerQCheck(gw, bob[
"USD"], qIn, 50, 10);
1259 testNonIssuerQPay(alice, gw[
"USD"], qOut, 200, 10);
1260 testNonIssuerQCheck(alice, gw[
"USD"], qOut, 200, 10);
1262 testNonIssuerQPay(bob, gw[
"USD"], qOut, 200, 10);
1263 testNonIssuerQCheck(bob, gw[
"USD"], qOut, 200, 10);
1265 testNonIssuerQPay(gw, alice[
"USD"], qOut, 200, 10);
1266 testNonIssuerQCheck(gw, alice[
"USD"], qOut, 200, 10);
1268 testNonIssuerQPay(gw, bob[
"USD"], qOut, 200, 10);
1269 testNonIssuerQCheck(gw, bob[
"USD"], qOut, 200, 10);
1276 auto testIssuerQPay = [&env, &gw, &alice, &USD](
1277 Account
const& truster,
1279 auto const& inOrOut,
1287 STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1290 env(trust(truster, iou(1000)), inOrOut(pct));
1294 env(pay(alice, gw, USD(amt1)), sendmax(USD(max1)));
1296 env.require(balance(alice, aliceStart - USD(10)));
1299 env(pay(gw, alice, USD(amt2)), sendmax(USD(max2)));
1301 env.require(balance(alice, aliceStart));
1305 env(trust(truster, iou(1000)), inOrOut(0));
1309 auto testIssuerQCheck = [&env, &gw, &alice, &USD](
1310 Account
const& truster,
1312 auto const& inOrOut,
1320 STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1323 env(trust(truster, iou(1000)), inOrOut(pct));
1328 env(check::create(alice, gw, USD(max1)));
1331 env(check::cash(gw, chkAliceId, USD(amt1)));
1333 env.require(balance(alice, aliceStart - USD(10)));
1337 env(check::create(gw, alice, USD(max2)));
1340 env(check::cash(alice, chkGwId, USD(amt2)));
1342 env.require(balance(alice, aliceStart));
1346 env(trust(truster, iou(1000)), inOrOut(0));
1352 testIssuerQPay(alice, gw[
"USD"], qIn, 50, 10, 10, 5, 10);
1353 testIssuerQCheck(alice, gw[
"USD"], qIn, 50, 10, 10, 5, 10);
1355 testIssuerQPay(gw, alice[
"USD"], qIn, 50, 10, 10, 10, 10);
1356 testIssuerQCheck(gw, alice[
"USD"], qIn, 50, 10, 10, 10, 10);
1358 testIssuerQPay(alice, gw[
"USD"], qOut, 200, 10, 10, 10, 10);
1359 testIssuerQCheck(alice, gw[
"USD"], qOut, 200, 10, 10, 10, 10);
1361 testIssuerQPay(gw, alice[
"USD"], qOut, 200, 10, 10, 10, 10);
1362 testIssuerQCheck(gw, alice[
"USD"], qOut, 200, 10, 10, 10, 10);
1371 using namespace test::jtx;
1373 Account
const gw{
"gateway"};
1374 Account
const alice{
"alice"};
1375 Account
const bob{
"bob"};
1376 Account
const zoe{
"zoe"};
1377 IOU
const USD{gw[
"USD"]};
1379 Env env(*
this, features);
1381 env.fund(XRP(1000), gw, alice, bob, zoe);
1385 env(trust(alice, USD(20)));
1387 env(pay(gw, alice, USD(20)));
1394 env(check::create(alice, bob, USD(20)));
1397 if (!features[featureCheckCashMakesTrustLine])
1402 env(check::cash(bob, chkId, USD(20)), ter(
tecNO_LINE));
1408 env(trust(bob, USD(20)));
1414 env(check::cash(bob, chkId, USD(20)), ter(
tecNO_ENTRY));
1420 env(check::create(alice, bob, USD(20)));
1424 env(check::create(alice, bob, XRP(10)));
1427 using namespace std::chrono_literals;
1429 env(check::create(alice, bob, XRP(10)), expiration(env.now() + 1s));
1433 env(check::create(alice, bob, USD(1)));
1437 env(check::create(alice, bob, USD(2)));
1441 env(check::create(alice, bob, USD(3)));
1445 env(check::create(alice, bob, USD(4)));
1449 env(check::create(alice, bob, USD(1)));
1453 env(check::create(alice, bob, USD(2)), dest_tag(7));
1457 auto failingCases = [&env, &gw, &alice, &bob](
1460 env(check::cash(bob, chkId, amount),
1466 env(check::cash(bob, chkId, amount),
1492 env(check::cash(bob, chkId, amount.zeroed()),
1498 if (!amount.native())
1515 IOU
const wrongCurrency{gw[
"EUR"]};
1517 badAmount.
setIssue(wrongCurrency.issue());
1518 env(check::cash(bob, chkId, badAmount), ter(
temMALFORMED));
1524 IOU
const wrongIssuer{alice[
"USD"]};
1526 badAmount.
setIssue(wrongIssuer.issue());
1527 env(check::cash(bob, chkId, badAmount), ter(
temMALFORMED));
1536 env(check::cash(bob, chkId, check::DeliverMin(amount + amount)),
1541 failingCases(chkIdX, XRP(10));
1542 failingCases(chkIdU, USD(20));
1545 env(check::cash(bob, chkIdU, USD(20)));
1547 env(check::cash(bob, chkIdX, check::DeliverMin(XRP(10))));
1551 env(check::cash(bob, chkIdExp, XRP(10)), ter(
tecEXPIRED));
1555 env(check::cancel(zoe, chkIdExp));
1560 env(pay(bob, alice, USD(20)));
1562 env.require(balance(alice, USD(20)));
1563 env.require(balance(bob, USD(0)));
1571 env(check::cash(bob, chkIdFroz1, check::DeliverMin(USD(0.5))),
1579 env(check::cash(bob, chkIdFroz1, USD(1)));
1581 env.require(balance(alice, USD(19)));
1582 env.require(balance(bob, USD(1)));
1589 env(check::cash(bob, chkIdFroz2, check::DeliverMin(USD(1))),
1596 env(check::cash(bob, chkIdFroz2, USD(2)));
1598 env.require(balance(alice, USD(17)));
1599 env.require(balance(bob, USD(3)));
1604 env(check::cash(bob, chkIdFroz3, USD(3)), ter(
tecFROZEN));
1606 env(check::cash(bob, chkIdFroz3, check::DeliverMin(USD(1))),
1613 env(check::cash(bob, chkIdFroz3, check::DeliverMin(USD(1))));
1615 env.require(balance(alice, USD(14)));
1616 env.require(balance(bob, USD(6)));
1622 env(check::cash(bob, chkIdFroz4, USD(4)), ter(
terNO_LINE));
1624 env(check::cash(bob, chkIdFroz4, check::DeliverMin(USD(1))),
1631 env(check::cash(bob, chkIdFroz4, USD(4)));
1633 env.require(balance(alice, USD(10)));
1634 env.require(balance(bob, USD(10)));
1643 env(check::cash(bob, chkIdNoDest1, check::DeliverMin(USD(0.5))),
1648 env(check::cash(bob, chkIdHasDest2, USD(2)));
1650 env.require(balance(alice, USD(8)));
1651 env.require(balance(bob, USD(12)));
1657 env(check::cash(bob, chkIdNoDest1, USD(1)));
1659 env.require(balance(alice, USD(7)));
1660 env.require(balance(bob, USD(13)));
1670 using namespace test::jtx;
1672 Account
const gw{
"gateway"};
1673 Account
const alice{
"alice"};
1674 Account
const bob{
"bob"};
1675 Account
const zoe{
"zoe"};
1676 IOU
const USD{gw[
"USD"]};
1680 for (
auto const& testFeatures :
1681 {features - featureMultiSignReserve,
1682 features | featureMultiSignReserve})
1684 Env env{*
this, testFeatures};
1686 env.fund(XRP(1000), gw, alice, bob, zoe);
1692 env(check::create(alice, bob, USD(10)));
1696 env(check::create(alice, bob, XRP(10)));
1700 env(check::create(alice, bob, USD(10)));
1704 using namespace std::chrono_literals;
1706 env(check::create(alice, bob, XRP(10)),
1707 expiration(env.now() + 600s));
1711 env(check::create(alice, bob, USD(10)),
1712 expiration(env.now() + 600s));
1716 env(check::create(alice, bob, XRP(10)),
1717 expiration(env.now() + 600s));
1722 env(check::create(alice, bob, USD(10)), expiration(env.now() + 1s));
1726 env(check::create(alice, bob, XRP(10)), expiration(env.now() + 1s));
1730 env(check::create(alice, bob, USD(10)), expiration(env.now() + 1s));
1735 env(check::create(alice, bob, USD(10)));
1739 env(check::create(alice, bob, XRP(10)));
1742 BEAST_EXPECT(ownerCount(env, alice) == 11);
1745 env(check::cancel(alice, chkId1));
1748 BEAST_EXPECT(ownerCount(env, alice) == 10);
1750 env(check::cancel(bob, chkId2));
1753 BEAST_EXPECT(ownerCount(env, alice) == 9);
1758 BEAST_EXPECT(ownerCount(env, alice) == 9);
1761 env(check::cancel(alice, chkIdNotExp1));
1764 BEAST_EXPECT(ownerCount(env, alice) == 8);
1766 env(check::cancel(bob, chkIdNotExp2));
1769 BEAST_EXPECT(ownerCount(env, alice) == 7);
1774 BEAST_EXPECT(ownerCount(env, alice) == 7);
1777 env(check::cancel(alice, chkIdExp1));
1780 BEAST_EXPECT(ownerCount(env, alice) == 6);
1782 env(check::cancel(bob, chkIdExp2));
1785 BEAST_EXPECT(ownerCount(env, alice) == 5);
1787 env(check::cancel(zoe, chkIdExp3));
1790 BEAST_EXPECT(ownerCount(env, alice) == 4);
1794 env(regkey(alice, alie));
1799 env(signers(alice, 2, {{bogie, 1}, {demon, 1}}), sig(alie));
1804 int const signersCount{
1805 testFeatures[featureMultiSignReserve] ? 1 : 4};
1808 env(check::cancel(alice, chkIdReg), sig(alie));
1811 BEAST_EXPECT(ownerCount(env, alice) == signersCount + 3);
1814 XRPAmount const baseFeeDrops{env.current()->fees().base};
1815 env(check::cancel(alice, chkIdMSig),
1817 fee(3 * baseFeeDrops));
1820 BEAST_EXPECT(ownerCount(env, alice) == signersCount + 2);
1823 env(check::cancel(alice, chkId3), sig(alice));
1826 BEAST_EXPECT(ownerCount(env, alice) == signersCount + 1);
1828 env(check::cancel(bob, chkIdNotExp3));
1831 BEAST_EXPECT(ownerCount(env, alice) == signersCount + 0);
1920 using namespace test::jtx;
1922 Account
const gw{
"gw"};
1923 Account
const alice{
"alice"};
1924 Account
const bob{
"bob"};
1925 IOU
const USD{gw[
"USD"]};
1927 Env env{*
this, features};
1928 env.fund(XRP(1000), gw, alice, bob);
1935 env(ticket::create(alice, 10));
1939 env(ticket::create(bob, 10));
1943 env.require(owners(alice, 10));
1944 env.require(owners(bob, 10));
1947 env(trust(alice, USD(1000)), ticket::use(aliceTicketSeq++));
1948 env(trust(bob, USD(1000)), ticket::use(bobTicketSeq++));
1950 env.require(owners(alice, 10));
1951 env.require(owners(bob, 10));
1953 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1954 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1956 env.require(tickets(bob, env.seq(bob) - bobTicketSeq));
1957 BEAST_EXPECT(env.seq(bob) == bobSeq);
1959 env(pay(gw, alice, USD(900)));
1965 env(check::create(alice, bob, XRP(200)), ticket::use(aliceTicketSeq++));
1968 env(check::create(alice, bob, XRP(300)), ticket::use(aliceTicketSeq++));
1971 env(check::create(alice, bob, USD(200)), ticket::use(aliceTicketSeq++));
1974 env(check::create(alice, bob, USD(300)), ticket::use(aliceTicketSeq++));
1978 env.require(owners(alice, 10));
1979 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1981 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1983 env.require(owners(bob, 10));
1984 BEAST_EXPECT(env.seq(bob) == bobSeq);
1987 env(check::cancel(bob, chkIdXrp1), ticket::use(bobTicketSeq++));
1988 env(check::cancel(bob, chkIdUsd2), ticket::use(bobTicketSeq++));
1991 env.require(owners(alice, 8));
1992 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1994 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1996 env.require(owners(bob, 8));
1997 BEAST_EXPECT(env.seq(bob) == bobSeq);
2000 env(check::cash(bob, chkIdXrp2, XRP(300)), ticket::use(bobTicketSeq++));
2001 env(check::cash(bob, chkIdUsd1, USD(200)), ticket::use(bobTicketSeq++));
2004 env.require(owners(alice, 6));
2005 env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
2007 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2008 env.require(balance(alice, USD(700)));
2010 env.require(owners(bob, 6));
2011 BEAST_EXPECT(env.seq(bob) == bobSeq);
2012 env.require(balance(bob, USD(200)));
2023 assert(features[featureCheckCashMakesTrustLine]);
2027 using namespace test::jtx;
2029 Env env{*
this, features};
2043 ownerCount(env, acct) == owners,
2044 "Owner count mismatch",
2050 operator Account
const()
const
2067 AccountOwns alice{*
this, env,
"alice", 0};
2068 AccountOwns bob{*
this, env,
"bob", 0};
2071 env.fund(XRP(5000), noripple(alice, bob));
2077 AccountOwns gw1{*
this, env,
"gw1", 0};
2082 env.fund(XRP(5000), noripple(gw1));
2085 IOU
const CK8 = gw1[
"CK8"];
2086 gw1.verifyOwners(__LINE__);
2088 Account
const yui{
"yui"};
2093 env.fund(XRP(200), yui);
2097 env(check::create(gw1, yui, CK8(99)));
2100 env(check::cash(yui, chkId, CK8(99)),
2103 alice.verifyOwners(__LINE__);
2107 env(pay(env.master, yui, XRP(51)));
2109 env(check::cash(yui, chkId, CK8(99)));
2112 BEAST_EXPECT(ownerCount(env, yui) == 1);
2116 gw1.verifyOwners(__LINE__);
2131 auto cmpTrustLines = [
this, &env](
2132 Account
const& acct1,
2133 Account
const& acct2,
2134 IOU
const& offerIou,
2135 IOU
const& checkIou) {
2136 auto const offerLine =
2138 auto const checkLine =
2140 if (offerLine ==
nullptr || checkLine ==
nullptr)
2142 BEAST_EXPECT(offerLine ==
nullptr && checkLine ==
nullptr);
2148 BEAST_EXPECT(offerLine->at(sfFlags) == checkLine->at(sfFlags));
2153 [
this, offerLine, checkLine](
SF_AMOUNT const& sfield) {
2154 STAmount const offerAmount = offerLine->at(sfield);
2155 STAmount const checkAmount = checkLine->at(sfield);
2172 cmpReqAmount(sfBalance);
2173 cmpReqAmount(sfLowLimit);
2174 cmpReqAmount(sfHighLimit);
2179 [
this, offerLine, checkLine](
auto const& sfield) {
2182 offerLine->isFieldPresent(sfield) ==
2183 checkLine->isFieldPresent(sfield)))
2188 if (!offerLine->isFieldPresent(sfield))
2194 offerLine->at(sfield) == checkLine->at(sfield));
2196 cmpOptField(sfLowNode);
2197 cmpOptField(sfLowQualityIn);
2198 cmpOptField(sfLowQualityOut);
2200 cmpOptField(sfHighNode);
2201 cmpOptField(sfHighQualityIn);
2202 cmpOptField(sfHighQualityOut);
2210 AccountOwns gw1{*
this, env,
"gw1", 0};
2212 BEAST_EXPECT((*env.le(gw1))[sfFlags] == 0);
2213 BEAST_EXPECT((*env.le(alice))[sfFlags] == 0);
2214 BEAST_EXPECT((*env.le(bob))[sfFlags] == 0);
2217 IOU
const OF1 = gw1[
"OF1"];
2218 env(offer(gw1, XRP(98), OF1(98)));
2221 env.le(
keylet::line(gw1, alice, OF1.currency)) ==
nullptr);
2222 env(offer(alice, OF1(98), XRP(98)));
2229 gw1.verifyOwners(__LINE__);
2232 alice.verifyOwners(__LINE__);
2235 IOU
const CK1 = gw1[
"CK1"];
2237 env(check::create(gw1, alice, CK1(98)));
2240 env.le(
keylet::line(gw1, alice, CK1.currency)) ==
nullptr);
2241 env(check::cash(alice, chkId, CK1(98)));
2249 gw1.verifyOwners(__LINE__);
2252 alice.verifyOwners(__LINE__);
2254 cmpTrustLines(gw1, alice, OF1, CK1);
2265 AccountOwns gw1{*
this, env,
"gw1", 0};
2266 IOU
const OF1 = gw1[
"OF1"];
2267 env(offer(alice, XRP(97), OF1(97)));
2270 env.le(
keylet::line(alice, bob, OF1.currency)) ==
nullptr);
2271 env(offer(bob, OF1(97), XRP(97)));
2276 env.require(balance(alice, OF1(1)));
2277 env.require(balance(bob, OF1(97)));
2280 gw1.verifyOwners(__LINE__);
2281 alice.verifyOwners(__LINE__);
2282 bob.verifyOwners(__LINE__);
2290 IOU
const CK1 = gw1[
"CK1"];
2292 env(check::create(alice, bob, CK1(97)));
2295 env.le(
keylet::line(alice, bob, CK1.currency)) ==
nullptr);
2296 env(check::cash(bob, chkId, CK1(97)), ter(
terNO_RIPPLE));
2300 env.le(
keylet::line(gw1, bob, OF1.currency)) !=
nullptr);
2302 env.le(
keylet::line(gw1, bob, CK1.currency)) ==
nullptr);
2305 env(check::cancel(alice, chkId));
2309 gw1.verifyOwners(__LINE__);
2310 alice.verifyOwners(__LINE__);
2311 bob.verifyOwners(__LINE__);
2318 AccountOwns gw1{*
this, env,
"gw1", 0};
2323 IOU
const OF2 = gw1[
"OF2"];
2324 env(offer(gw1, XRP(96), OF2(96)));
2327 env.le(
keylet::line(gw1, alice, OF2.currency)) ==
nullptr);
2328 env(offer(alice, OF2(96), XRP(96)));
2335 gw1.verifyOwners(__LINE__);
2338 alice.verifyOwners(__LINE__);
2341 IOU
const CK2 = gw1[
"CK2"];
2343 env(check::create(gw1, alice, CK2(96)));
2346 env.le(
keylet::line(gw1, alice, CK2.currency)) ==
nullptr);
2347 env(check::cash(alice, chkId, CK2(96)));
2355 gw1.verifyOwners(__LINE__);
2358 alice.verifyOwners(__LINE__);
2360 cmpTrustLines(gw1, alice, OF2, CK2);
2368 AccountOwns gw1{*
this, env,
"gw1", 0};
2369 IOU
const OF2 = gw1[
"OF2"];
2370 env(offer(alice, XRP(95), OF2(95)));
2373 env.le(
keylet::line(alice, bob, OF2.currency)) ==
nullptr);
2374 env(offer(bob, OF2(95), XRP(95)));
2379 gw1.verifyOwners(__LINE__);
2380 alice.verifyOwners(__LINE__);
2381 bob.verifyOwners(__LINE__);
2384 IOU
const CK2 = gw1[
"CK2"];
2386 env(check::create(alice, bob, CK2(95)));
2389 env.le(
keylet::line(alice, bob, CK2.currency)) ==
nullptr);
2390 env(check::cash(bob, chkId, CK2(95)));
2396 gw1.verifyOwners(__LINE__);
2397 alice.verifyOwners(__LINE__);
2398 bob.verifyOwners(__LINE__);
2400 cmpTrustLines(alice, bob, OF2, CK2);
2411 AccountOwns gw1{*
this, env,
"gw1", 0};
2418 IOU
const OF3 = gw1[
"OF3"];
2419 env(offer(gw1, XRP(94), OF3(94)));
2422 env.le(
keylet::line(gw1, alice, OF3.currency)) ==
nullptr);
2423 env(offer(alice, OF3(94), XRP(94)));
2430 gw1.verifyOwners(__LINE__);
2433 alice.verifyOwners(__LINE__);
2436 IOU
const CK3 = gw1[
"CK3"];
2438 env(check::create(gw1, alice, CK3(94)));
2441 env.le(
keylet::line(gw1, alice, CK3.currency)) ==
nullptr);
2442 env(check::cash(alice, chkId, CK3(94)));
2450 gw1.verifyOwners(__LINE__);
2453 alice.verifyOwners(__LINE__);
2455 cmpTrustLines(gw1, alice, OF3, CK3);
2463 AccountOwns gw1{*
this, env,
"gw1", 0};
2464 IOU
const OF3 = gw1[
"OF3"];
2465 env(offer(alice, XRP(93), OF3(93)));
2468 env.le(
keylet::line(alice, bob, OF3.currency)) ==
nullptr);
2469 env(offer(bob, OF3(93), XRP(93)));
2474 gw1.verifyOwners(__LINE__);
2475 alice.verifyOwners(__LINE__);
2476 bob.verifyOwners(__LINE__);
2479 IOU
const CK3 = gw1[
"CK3"];
2481 env(check::create(alice, bob, CK3(93)));
2484 env.le(
keylet::line(alice, bob, CK3.currency)) ==
nullptr);
2485 env(check::cash(bob, chkId, CK3(93)));
2491 gw1.verifyOwners(__LINE__);
2492 alice.verifyOwners(__LINE__);
2493 bob.verifyOwners(__LINE__);
2495 cmpTrustLines(alice, bob, OF3, CK3);
2502 AccountOwns gw1{*
this, env,
"gw1", 0};
2507 IOU
const OF4 = gw1[
"OF4"];
2508 env(offer(gw1, XRP(92), OF4(92)), ter(
tecFROZEN));
2511 env.le(
keylet::line(gw1, alice, OF4.currency)) ==
nullptr);
2512 env(offer(alice, OF4(92), XRP(92)), ter(
tecFROZEN));
2516 gw1.verifyOwners(__LINE__);
2517 alice.verifyOwners(__LINE__);
2518 bob.verifyOwners(__LINE__);
2521 IOU
const CK4 = gw1[
"CK4"];
2523 env(check::create(gw1, alice, CK4(92)), ter(
tecFROZEN));
2526 env.le(
keylet::line(gw1, alice, CK4.currency)) ==
nullptr);
2527 env(check::cash(alice, chkId, CK4(92)), ter(
tecNO_ENTRY));
2531 gw1.verifyOwners(__LINE__);
2532 alice.verifyOwners(__LINE__);
2533 bob.verifyOwners(__LINE__);
2538 env.le(
keylet::line(gw1, alice, OF4.currency)) ==
nullptr);
2540 env.le(
keylet::line(gw1, alice, CK4.currency)) ==
nullptr);
2548 AccountOwns gw1{*
this, env,
"gw1", 0};
2549 IOU
const OF4 = gw1[
"OF4"];
2550 env(offer(alice, XRP(91), OF4(91)), ter(
tecFROZEN));
2553 env.le(
keylet::line(alice, bob, OF4.currency)) ==
nullptr);
2554 env(offer(bob, OF4(91), XRP(91)), ter(
tecFROZEN));
2558 gw1.verifyOwners(__LINE__);
2559 alice.verifyOwners(__LINE__);
2560 bob.verifyOwners(__LINE__);
2563 IOU
const CK4 = gw1[
"CK4"];
2565 env(check::create(alice, bob, CK4(91)), ter(
tecFROZEN));
2568 env.le(
keylet::line(alice, bob, CK4.currency)) ==
nullptr);
2569 env(check::cash(bob, chkId, CK4(91)), ter(
tecNO_ENTRY));
2573 gw1.verifyOwners(__LINE__);
2574 alice.verifyOwners(__LINE__);
2575 bob.verifyOwners(__LINE__);
2580 env.le(
keylet::line(gw1, bob, OF4.currency)) ==
nullptr);
2582 env.le(
keylet::line(gw1, bob, CK4.currency)) ==
nullptr);
2591 AccountOwns gw2{*
this, env,
"gw2", 0};
2592 env.fund(XRP(5000), gw2);
2601 IOU
const OF5 = gw2[
"OF5"];
2603 env(offer(gw2, XRP(92), OF5(92)));
2607 env.le(
keylet::line(gw2, alice, OF5.currency)) ==
nullptr);
2608 env(offer(alice, OF5(92), XRP(92)), ter(
tecNO_LINE));
2613 gw2.verifyOwners(__LINE__);
2614 alice.verifyOwners(__LINE__);
2615 bob.verifyOwners(__LINE__);
2618 env(offer_cancel(gw2, gw2OfferSeq));
2621 gw2.verifyOwners(__LINE__);
2624 IOU
const CK5 = gw2[
"CK5"];
2626 env(check::create(gw2, alice, CK5(92)));
2630 env.le(
keylet::line(gw2, alice, CK5.currency)) ==
nullptr);
2631 env(check::cash(alice, chkId, CK5(92)), ter(
tecNO_AUTH));
2636 gw2.verifyOwners(__LINE__);
2637 alice.verifyOwners(__LINE__);
2638 bob.verifyOwners(__LINE__);
2643 env.le(
keylet::line(gw2, alice, OF5.currency)) ==
nullptr);
2645 env.le(
keylet::line(gw2, alice, CK5.currency)) ==
nullptr);
2648 env(check::cancel(gw2, chkId));
2651 gw2.verifyOwners(__LINE__);
2659 AccountOwns gw2{*
this, env,
"gw2", 0};
2660 IOU
const OF5 = gw2[
"OF5"];
2663 env(offer(bob, OF5(91), XRP(91)), ter(
tecNO_LINE));
2665 env.le(
keylet::line(gw2, bob, OF5.currency)) ==
nullptr);
2668 gw2.verifyOwners(__LINE__);
2669 alice.verifyOwners(__LINE__);
2670 bob.verifyOwners(__LINE__);
2673 IOU
const CK5 = gw2[
"CK5"];
2675 env(check::create(alice, bob, CK5(91)));
2678 env.le(
keylet::line(alice, bob, CK5.currency)) ==
nullptr);
2683 env(check::cancel(alice, chkId));
2687 gw2.verifyOwners(__LINE__);
2688 alice.verifyOwners(__LINE__);
2689 bob.verifyOwners(__LINE__);
2694 env.le(
keylet::line(gw2, bob, OF5.currency)) ==
nullptr);
2696 env.le(
keylet::line(gw2, bob, CK5.currency)) ==
nullptr);