20 #include <ripple/app/tx/impl/details/NFTokenUtils.h> 
   21 #include <ripple/basics/random.h> 
   22 #include <ripple/protocol/Feature.h> 
   23 #include <ripple/protocol/jss.h> 
   39         if (
auto const sleAcct = env.
le(acct))
 
   49         if (
auto const sleIssuer = env.
le(issuer))
 
   59         if (
auto const sleIssuer = env.
le(issuer))
 
   69         params[jss::account] = acct.
human();
 
   70         params[jss::type] = 
"state";
 
   72         return nfts[jss::result][jss::account_nfts].
size();
 
   80         if (
auto const sleAcct = env.
le(acct))
 
   89         return env.
current()->info().parentCloseTime.time_since_epoch().count();
 
   97         using namespace test::jtx;
 
  105             Account 
const& master = env.master;
 
  111             uint256 const nftId{token::getNextID(env, master, 0u)};
 
  126             env(token::createOffer(master, nftId, XRP(10)), ter(
temDISABLED));
 
  132             env(token::cancelOffer(master, {offerIndex}), ter(
temDISABLED));
 
  138             env(token::acceptBuyOffer(master, offerIndex), ter(
temDISABLED));
 
  147             Env env{*
this, features};
 
  148             Account 
const& master = env.master;
 
  154             uint256 const nftId0{token::getNextID(env, env.master, 0u)};
 
  155             env(token::mint(env.master, 0u));
 
  161             env(token::burn(env.master, nftId0));
 
  175             Account 
const alice{
"alice"};
 
  176             env.fund(XRP(10000), alice);
 
  178             uint256 const aliceOfferIndex =
 
  180             env(token::createOffer(alice, nftId1, XRP(1000)),
 
  181                 token::owner(master));
 
  192             env(token::acceptBuyOffer(master, aliceOfferIndex));
 
  209         testcase(
"Mint reserve");
 
  211         using namespace test::jtx;
 
  213         Env env{*
this, features};
 
  214         Account 
const alice{
"alice"};
 
  215         Account 
const minter{
"minter"};
 
  219         auto const acctReserve = env.current()->fees().accountReserve(0);
 
  220         auto const incReserve = env.current()->fees().increment;
 
  221         env.fund(acctReserve, alice, minter);
 
  223         BEAST_EXPECT(env.balance(alice) == acctReserve);
 
  224         BEAST_EXPECT(env.balance(minter) == acctReserve);
 
  237         env(pay(env.master, alice, incReserve + drops(9)));
 
  242         auto checkAliceOwnerMintedBurned = [&env, 
this, &alice](
 
  255                         ss << 
"Wrong " << type << 
" count.  Found: " << found
 
  256                            << 
"; Expected: " << exp;
 
  257                         fail(ss.
str(), __FILE__, line);
 
  260             oneCheck(
"owner", 
ownerCount(env, alice), owners);
 
  261             oneCheck(
"minted", 
mintedCount(env, alice), minted);
 
  262             oneCheck(
"burned", 
burnedCount(env, alice), burned);
 
  269         checkAliceOwnerMintedBurned(0, 0, 0, __LINE__);
 
  272         env(pay(env.master, alice, drops(11)));
 
  276         env(token::mint(alice));
 
  278         checkAliceOwnerMintedBurned(1, 1, 0, __LINE__);
 
  282         for (
int i = 1; i < 32; ++i)
 
  284             env(token::mint(alice));
 
  285             checkAliceOwnerMintedBurned(1, i + 1, 0, __LINE__);
 
  292         checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
 
  295         env(pay(env.master, alice, XRP(50) + drops(329)));
 
  302         checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
 
  305         env(pay(env.master, alice, drops(11)));
 
  309         env(token::mint(alice));
 
  311         checkAliceOwnerMintedBurned(2, 33, 0, __LINE__);
 
  318             env(token::burn(alice, token::getID(env, alice, 0, seq++)));
 
  320             checkAliceOwnerMintedBurned((33 - seq) ? 1 : 0, 33, seq, __LINE__);
 
  324         env(token::burn(alice, token::getID(env, alice, 197, 5)),
 
  327         checkAliceOwnerMintedBurned(0, 33, 33, __LINE__);
 
  332         env(token::setMinter(alice, minter));
 
  339         auto checkMintersOwnerMintedBurned = [&env, 
this, &alice, &minter](
 
  347             auto oneCheck = [
this](
 
  357                     ss << 
"Wrong " << type << 
" count.  Found: " << found
 
  358                        << 
"; Expected: " << exp;
 
  359                     fail(ss.
str(), __FILE__, line);
 
  362             oneCheck(
"alice owner", 
ownerCount(env, alice), aliceOwners, line);
 
  364                 "alice minted", 
mintedCount(env, alice), aliceMinted, line);
 
  366                 "alice burned", 
burnedCount(env, alice), aliceBurned, line);
 
  368                 "minter owner", 
ownerCount(env, minter), minterOwners, line);
 
  370                 "minter minted", 
mintedCount(env, minter), minterMinted, line);
 
  372                 "minter burned", 
burnedCount(env, minter), minterBurned, line);
 
  378         env(pay(env.master, minter, XRP(50) - drops(1)));
 
  380         checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
 
  385         env(token::mint(minter),
 
  386             token::issuer(alice),
 
  390         checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
 
  393         env(pay(env.master, minter, drops(11)));
 
  397         env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
 
  399         checkMintersOwnerMintedBurned(0, 34, nftSeq, 1, 0, 0, __LINE__);
 
  403         for (
int i = 1; i < 32; ++i)
 
  405             env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
 
  406             checkMintersOwnerMintedBurned(0, i + 34, nftSeq, 1, 0, 0, __LINE__);
 
  411         env(pay(env.master, minter, XRP(50) + drops(319)));
 
  416         env(token::mint(minter),
 
  417             token::issuer(alice),
 
  421         checkMintersOwnerMintedBurned(0, 65, nftSeq, 1, 0, 0, __LINE__);
 
  424         env(pay(env.master, minter, drops(11)));
 
  428         env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
 
  430         checkMintersOwnerMintedBurned(0, 66, nftSeq, 2, 0, 0, __LINE__);
 
  435             env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
 
  437             checkMintersOwnerMintedBurned(
 
  438                 0, 66, nftSeq, (65 - seq) ? 1 : 0, 0, 0, __LINE__);
 
  443         env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
 
  445         checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
 
  448         env(token::burn(minter, token::getID(env, alice, 2009, 3)),
 
  451         checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
 
  459         testcase(
"Mint max tokens");
 
  461         using namespace test::jtx;
 
  463         Account 
const alice{
"alice"};
 
  464         Env env{*
this, features};
 
  465         env.fund(XRP(1000), alice);
 
  474             uint256 const nftId0{token::getNextID(env, alice, 0u)};
 
  475             env(token::mint(alice, 0u));
 
  478             env(token::burn(alice, nftId0));
 
  485         env.app().openLedger().modify(
 
  494                 auto replacement = std::make_shared<SLE>(*sle, sle->key());
 
  507                     (*replacement)[sfMintedNFTokens] = 0x0000'0000;
 
  515                 view.rawReplace(replacement); 
  519         // See whether alice is at the boundary that causes an error. 
  520         env(token::mint(alice, 0u), ter(tesSUCCESS)); 
  521         env(token::mint(alice, 0u), ter(tecMAX_SEQUENCE_REACHED)); 
  525     testMintInvalid(FeatureBitset features) 
  527         // Explore many of the invalid ways to mint an NFT. 
  528         testcase("Mint invalid"); 
  530         using namespace test::jtx; 
  532         Env env{*this, features}; 
  533         Account const alice{"alice"}; 
  534         Account const minter{"minter"}; 
  536         // Fund alice and minter enough to exist, but not enough to meet 
  537         // the reserve for creating their first NFT.  Account reserve for unit 
  538         // tests is 200 XRP, not 20. 
  539         env.fund(XRP(200), alice, minter); 
  542         env(token::mint(alice, 0u), ter(tecINSUFFICIENT_RESERVE)); 
  545         // Fund alice enough to start minting NFTs. 
  546         env(pay(env.master, alice, XRP(1000))); 
  549         //---------------------------------------------------------------------- 
  552         // Set a negative fee. 
  553         env(token::mint(alice, 0u), 
  554             fee(STAmount(10ull, true)), 
  557         // Set an invalid flag. 
  558         env(token::mint(alice, 0u), txflags(0x00008000), ter(temINVALID_FLAG)); 
  560         // Can't 
set a transfer fee 
if the NFT does not have the tfTRANSFERABLE
 
  562         env(token::mint(alice, 0u),
 
  567         env(token::mint(alice, 0u),
 
  573         env(token::mint(alice, 0u), token::issuer(alice), ter(
temMALFORMED));
 
  576         env(token::mint(alice, 0u), token::uri(
""), ter(
temMALFORMED));
 
  579         env(token::mint(alice, 0u),
 
  587         env(token::mint(alice, 0u),
 
  588             token::issuer(Account(
"demon")),
 
  595         env(token::mint(minter, 0u),
 
  596             token::issuer(alice),
 
  604         testcase(
"Burn invalid");
 
  606         using namespace test::jtx;
 
  608         Env env{*
this, features};
 
  609         Account 
const alice{
"alice"};
 
  610         Account 
const buyer{
"buyer"};
 
  611         Account 
const minter{
"minter"};
 
  612         Account 
const gw(
"gw");
 
  613         IOU 
const gwAUD(gw[
"AUD"]);
 
  618         env.fund(XRP(250), alice, buyer, minter, gw);
 
  632         env(token::burn(alice, nftAlice0ID),
 
  639         env(token::burn(alice, nftAlice0ID),
 
  649         env(token::burn(alice, token::getID(env, alice, 0, 1)),
 
  664         testcase(
"Invalid NFT offer create");
 
  666         using namespace test::jtx;
 
  668         Env env{*
this, features};
 
  669         Account 
const alice{
"alice"};
 
  670         Account 
const buyer{
"buyer"};
 
  671         Account 
const gw(
"gw");
 
  672         IOU 
const gwAUD(gw[
"AUD"]);
 
  677         env.fund(XRP(250), alice, buyer, gw);
 
  683         env(token::mint(alice, 0u),
 
  695         uint256 nftNoXferID = token::getNextID(env, alice, 0);
 
  696         env(token::mint(alice, 0));
 
  709         env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
 
  716         env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
 
  723         env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
 
  730         env(token::createOffer(buyer, nftXrpOnlyID, buyer[
"USD"](1)),
 
  732         env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](0)),
 
  734         env(token::createOffer(buyer, nftXrpOnlyID, drops(0)),
 
  740         env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](1)),
 
  741             token::expiration(0),
 
  748         env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
 
  754         env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
 
  762         env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
 
  769         env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
 
  770             token::destination(alice),
 
  777         env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
 
  778             token::destination(Account(
"demon")),
 
  788         env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
 
  796         env(token::createOffer(
 
  797                 buyer, token::getID(env, alice, 0, 1), XRP(1000)),
 
  804         env(token::createOffer(
 
  805                 alice, token::getID(env, alice, 0, 1), XRP(1000)),
 
  812         env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
 
  818         env(trust(buyer, gwAUD(1000)));
 
  824         env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
 
  836         env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
 
  847         env(token::createOffer(buyer, nftNoXferID, gwAUD(1000)),
 
  857         env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
 
  866         env(trust(buyer, gwAUD(1000)));
 
  869         env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
 
  879         env(pay(gw, buyer, gwAUD(999)));
 
  884         env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
 
  891         env(pay(env.master, buyer, XRP(50) + drops(119)));
 
  894         env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
 
  901         env(pay(env.master, buyer, drops(11)));
 
  906         env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
 
  916         testcase(
"Invalid NFT offer cancel");
 
  918         using namespace test::jtx;
 
  920         Env env{*
this, features};
 
  921         Account 
const alice{
"alice"};
 
  922         Account 
const buyer{
"buyer"};
 
  923         Account 
const gw(
"gw");
 
  924         IOU 
const gwAUD(gw[
"AUD"]);
 
  926         env.fund(XRP(1000), alice, buyer, gw);
 
  937         uint256 const buyerOfferIndex =
 
  939         env(token::createOffer(buyer, nftAlice0ID, XRP(1)),
 
  949         env(token::cancelOffer(buyer, {buyerOfferIndex}),
 
  956         env(token::cancelOffer(buyer, {buyerOfferIndex}),
 
  976             env(token::cancelOffer(buyer, offers), ter(
temMALFORMED));
 
  982         env(token::cancelOffer(buyer, {buyerOfferIndex, buyerOfferIndex}),
 
  996         env(pay(env.master, gw, XRP(5000)));
 
 1000             env(offer(gw, XRP(i), gwAUD(1)));
 
 1007             env(check::create(gw, env.master, XRP(300)));
 
 1014             env(check::cancel(gw, gwCheckId));
 
 1028         env(token::cancelOffer(buyer, {buyerOfferIndex}));
 
 1036         testcase(
"Invalid NFT offer accept");
 
 1038         using namespace test::jtx;
 
 1040         Env env{*
this, features};
 
 1041         Account 
const alice{
"alice"};
 
 1042         Account 
const buyer{
"buyer"};
 
 1043         Account 
const gw(
"gw");
 
 1044         IOU 
const gwAUD(gw[
"AUD"]);
 
 1046         env.fund(XRP(1000), alice, buyer, gw);
 
 1062         uint256 nftNoXferID = token::getNextID(env, alice, 0);
 
 1063         env(token::mint(alice, 0));
 
 1068         uint256 const plainOfferIndex =
 
 1070         env(token::createOffer(alice, nftAlice0ID, XRP(10)),
 
 1077         env(token::createOffer(alice, nftAlice0ID, gwAUD(30)),
 
 1082         uint256 const xrpOnlyOfferIndex =
 
 1084         env(token::createOffer(alice, nftXrpOnlyID, XRP(20)),
 
 1089         uint256 const noXferOfferIndex =
 
 1091         env(token::createOffer(alice, nftNoXferID, XRP(30)),
 
 1097         uint256 const aliceExpOfferIndex =
 
 1099         env(token::createOffer(alice, nftNoXferID, XRP(40)),
 
 1109         env(token::acceptSellOffer(buyer, noXferOfferIndex),
 
 1116         env(token::acceptSellOffer(buyer, noXferOfferIndex),
 
 1117             txflags(0x00008000),
 
 1124             Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
 
 1133             Json::Value jv = token::acceptBuyOffer(buyer, noXferOfferIndex);
 
 1143             Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
 
 1152         env(token::brokerOffers(buyer, noXferOfferIndex, xrpOnlyOfferIndex),
 
 1153             token::brokerFee(gwAUD(0)),
 
 1162         env(token::acceptBuyOffer(buyer, beast::zero),
 
 1169         env(token::acceptBuyOffer(buyer, missingOfferIndex),
 
 1175         env(token::acceptBuyOffer(buyer, aliceExpOfferIndex), ter(
tecEXPIRED));
 
 1180         env(token::acceptSellOffer(buyer, beast::zero),
 
 1186         env(token::acceptSellOffer(buyer, missingOfferIndex),
 
 1192         env(token::acceptSellOffer(buyer, aliceExpOfferIndex), ter(
tecEXPIRED));
 
 1201         env(trust(alice, gwAUD(1000)));
 
 1202         env(trust(buyer, gwAUD(1000)));
 
 1204         env(pay(gw, buyer, gwAUD(30)));
 
 1213             uint256 const buyerOfferIndex =
 
 1215             env(token::createOffer(buyer, nftAlice0ID, gwAUD(29)),
 
 1216                 token::owner(alice));
 
 1221             env(token::brokerOffers(gw, buyerOfferIndex, xrpOnlyOfferIndex),
 
 1227             env(token::brokerOffers(gw, buyerOfferIndex, plainOfferIndex),
 
 1234             env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
 
 1240             env(token::cancelOffer(buyer, {buyerOfferIndex}));
 
 1246             uint256 const buyerOfferIndex =
 
 1248             env(token::createOffer(buyer, nftAlice0ID, gwAUD(31)),
 
 1249                 token::owner(alice));
 
 1255             env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
 
 1256                 token::brokerFee(XRP(40)),
 
 1262             env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
 
 1263                 token::brokerFee(gwAUD(31)),
 
 1270             env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
 
 1271                 token::brokerFee(gwAUD(1.5)),
 
 1277             env(token::cancelOffer(buyer, {buyerOfferIndex}));
 
 1285             uint256 const buyerOfferIndex =
 
 1287             env(token::createOffer(buyer, nftAlice0ID, gwAUD(30)),
 
 1288                 token::owner(alice));
 
 1293             env(token::acceptBuyOffer(buyer, plainOfferIndex),
 
 1299             env(token::acceptBuyOffer(buyer, buyerOfferIndex),
 
 1305             env(pay(buyer, gw, gwAUD(30)));
 
 1307             BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
 
 1308             env(token::acceptBuyOffer(alice, buyerOfferIndex),
 
 1317                 env(token::createOffer(alice, nftAlice0ID, XRP(0)),
 
 1320                 env(token::acceptSellOffer(gw, offerIndex));
 
 1324             env(pay(gw, buyer, gwAUD(30)));
 
 1328             env(token::acceptBuyOffer(alice, buyerOfferIndex),
 
 1334             env(token::cancelOffer(buyer, {buyerOfferIndex}));
 
 1342             uint256 const buyerOfferIndex =
 
 1344             env(token::createOffer(buyer, nftXrpOnlyID, XRP(30)),
 
 1345                 token::owner(alice));
 
 1350             env(token::acceptSellOffer(alice, buyerOfferIndex),
 
 1356             env(token::acceptSellOffer(alice, plainOfferIndex),
 
 1363             env(token::acceptSellOffer(buyer, plainOfferIndex),
 
 1374                 env(token::createOffer(gw, nftAlice0ID, XRP(0)),
 
 1377                 env(token::acceptSellOffer(alice, offerIndex));
 
 1381             env(pay(buyer, gw, gwAUD(30)));
 
 1383             BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
 
 1384             env(token::acceptSellOffer(buyer, audOfferIndex),
 
 1401         testcase(
"Mint flagBurnable");
 
 1403         using namespace test::jtx;
 
 1405         Env env{*
this, features};
 
 1406         Account 
const alice{
"alice"};
 
 1407         Account 
const buyer{
"buyer"};
 
 1408         Account 
const minter1{
"minter1"};
 
 1409         Account 
const minter2{
"minter2"};
 
 1411         env.fund(XRP(1000), alice, buyer, minter1, minter2);
 
 1416         env(token::setMinter(alice, minter1));
 
 1423         auto nftToBuyer = [&env, &alice, &minter1, &buyer](
 
 1425             uint256 const nftID{token::getNextID(env, alice, 0u, flags)};
 
 1426             env(token::mint(minter1, 0u), token::issuer(alice), txflags(flags));
 
 1431             env(token::createOffer(minter1, nftID, XRP(0)),
 
 1435             env(token::acceptSellOffer(buyer, offerIndex));
 
 1443             uint256 const noBurnID = nftToBuyer(0);
 
 1444             env(token::burn(alice, noBurnID),
 
 1445                 token::owner(buyer),
 
 1448             env(token::burn(minter1, noBurnID),
 
 1449                 token::owner(buyer),
 
 1452             env(token::burn(minter2, noBurnID),
 
 1453                 token::owner(buyer),
 
 1458             env(token::burn(buyer, noBurnID), token::owner(buyer));
 
 1465             env(token::burn(minter2, burnableID),
 
 1466                 token::owner(buyer),
 
 1471             env(token::burn(alice, burnableID), token::owner(buyer));
 
 1479             env(token::burn(buyer, burnableID));
 
 1487             env(token::burn(buyer, burnableID), token::owner(buyer));
 
 1497             env(token::setMinter(alice, minter2));
 
 1502             env(token::burn(minter1, burnableID),
 
 1503                 token::owner(buyer),
 
 1509             env(token::burn(minter2, burnableID), token::owner(buyer));
 
 1519         testcase(
"Mint flagOnlyXRP");
 
 1521         using namespace test::jtx;
 
 1523         Env env{*
this, features};
 
 1524         Account 
const alice{
"alice"};
 
 1525         Account 
const buyer{
"buyer"};
 
 1526         Account 
const gw(
"gw");
 
 1527         IOU 
const gwAUD(gw[
"AUD"]);
 
 1530         env.fund(XRP(1000), alice, buyer, gw);
 
 1532         env(trust(alice, gwAUD(1000)));
 
 1533         env(trust(buyer, gwAUD(1000)));
 
 1535         env(pay(gw, buyer, gwAUD(100)));
 
 1545             uint256 const aliceOfferIndex =
 
 1547             env(token::createOffer(alice, nftIOUsOkayID, gwAUD(50)),
 
 1553             uint256 const buyerOfferIndex =
 
 1555             env(token::createOffer(buyer, nftIOUsOkayID, gwAUD(50)),
 
 1556                 token::owner(alice));
 
 1561             env(token::cancelOffer(alice, {aliceOfferIndex}));
 
 1562             env(token::cancelOffer(buyer, {buyerOfferIndex}));
 
 1568             env(token::burn(alice, nftIOUsOkayID));
 
 1581             env(token::createOffer(alice, nftOnlyXRPID, gwAUD(50)),
 
 1588             env(token::createOffer(buyer, nftOnlyXRPID, gwAUD(50)),
 
 1589                 token::owner(alice),
 
 1596             env(token::createOffer(alice, nftOnlyXRPID, XRP(60)),
 
 1602             env(token::createOffer(buyer, nftOnlyXRPID, XRP(60)),
 
 1603                 token::owner(alice));
 
 1613         testcase(
"Mint flagCreateTrustLines");
 
 1615         using namespace test::jtx;
 
 1617         Account 
const alice{
"alice"};
 
 1618         Account 
const becky{
"becky"};
 
 1619         Account 
const cheri{
"cheri"};
 
 1620         Account 
const gw(
"gw");
 
 1621         IOU 
const gwAUD(gw[
"AUD"]);
 
 1622         IOU 
const gwCAD(gw[
"CAD"]);
 
 1623         IOU 
const gwEUR(gw[
"EUR"]);
 
 1628         for (
auto const& tweakedFeatures :
 
 1632             Env env{*
this, tweakedFeatures};
 
 1633             env.fund(XRP(1000), alice, becky, cheri, gw);
 
 1637             env(trust(becky, gwAUD(1000)));
 
 1638             env(trust(cheri, gwAUD(1000)));
 
 1639             env(trust(becky, gwCAD(1000)));
 
 1640             env(trust(cheri, gwCAD(1000)));
 
 1641             env(trust(becky, gwEUR(1000)));
 
 1642             env(trust(cheri, gwEUR(1000)));
 
 1644             env(pay(gw, becky, gwAUD(500)));
 
 1645             env(pay(gw, becky, gwCAD(500)));
 
 1646             env(pay(gw, becky, gwEUR(500)));
 
 1647             env(pay(gw, cheri, gwAUD(500)));
 
 1648             env(pay(gw, cheri, gwCAD(500)));
 
 1655                 uint256 const nftNoAutoTrustID{
 
 1657                 env(token::mint(alice, 0u),
 
 1658                     token::xferFee(xferFee),
 
 1663                 uint256 const beckyBuyOfferIndex =
 
 1665                 env(token::createOffer(becky, nftNoAutoTrustID, drops(1)),
 
 1666                     token::owner(alice));
 
 1668                 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
 
 1672                 TER const createOfferTER =
 
 1674                 uint256 const beckyOfferIndex =
 
 1676                 env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)),
 
 1678                     ter(createOfferTER));
 
 1682                 uint256 const cheriOfferIndex =
 
 1684                 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
 
 1685                     token::owner(becky),
 
 1686                     ter(createOfferTER));
 
 1690                 env(token::cancelOffer(becky, {beckyOfferIndex}));
 
 1691                 env(token::cancelOffer(cheri, {cheriOfferIndex}));
 
 1699                 uint256 const nftAutoTrustID{token::getNextID(
 
 1710                     env(token::mint(alice, 0u),
 
 1711                         token::xferFee(transferFee),
 
 1722                 uint256 const beckyBuyOfferIndex =
 
 1724                 env(token::createOffer(becky, nftAutoTrustID, drops(1)),
 
 1725                     token::owner(alice));
 
 1727                 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
 
 1731                 uint256 const beckySellOfferIndex =
 
 1733                 env(token::createOffer(becky, nftAutoTrustID, gwAUD(100)),
 
 1736                 env(token::acceptSellOffer(cheri, beckySellOfferIndex));
 
 1740                 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
 
 1743                 uint256 const beckyBuyBackOfferIndex =
 
 1745                 env(token::createOffer(becky, nftAutoTrustID, gwCAD(50)),
 
 1746                     token::owner(cheri));
 
 1748                 env(token::acceptBuyOffer(cheri, beckyBuyBackOfferIndex));
 
 1752                 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
 
 1753                 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(5));
 
 1759                 uint256 const nftNoAutoTrustID{token::getNextID(
 
 1761                 env(token::mint(alice, 0u),
 
 1762                     token::xferFee(transferFee),
 
 1767                 uint256 const aliceSellOfferIndex =
 
 1769                 env(token::createOffer(alice, nftNoAutoTrustID, gwAUD(200)),
 
 1772                 env(token::acceptSellOffer(cheri, aliceSellOfferIndex));
 
 1778                 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(210));
 
 1781                 env(token::createOffer(cheri, nftNoAutoTrustID, gwEUR(50)),
 
 1785                 uint256 const cheriSellOfferIndex =
 
 1787                 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
 
 1790                 env(token::acceptSellOffer(becky, cheriSellOfferIndex));
 
 1796                 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(10));
 
 1805         testcase(
"Mint flagTransferable");
 
 1807         using namespace test::jtx;
 
 1809         Env env{*
this, features};
 
 1811         Account 
const alice{
"alice"};
 
 1812         Account 
const becky{
"becky"};
 
 1813         Account 
const minter{
"minter"};
 
 1815         env.fund(XRP(1000), alice, becky, minter);
 
 1821             uint256 const nftAliceNoTransferID{
 
 1822                 token::getNextID(env, alice, 0u)};
 
 1823             env(token::mint(alice, 0u), token::xferFee(0));
 
 1829             env(token::createOffer(becky, nftAliceNoTransferID, XRP(20)),
 
 1830                 token::owner(alice),
 
 1834             uint256 const aliceSellOfferIndex =
 
 1836             env(token::createOffer(alice, nftAliceNoTransferID, XRP(20)),
 
 1839             env(token::acceptSellOffer(becky, aliceSellOfferIndex));
 
 1845             env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
 
 1854             env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
 
 1856                 token::destination(alice),
 
 1864             uint256 const aliceBuyOfferIndex =
 
 1866             env(token::createOffer(alice, nftAliceNoTransferID, XRP(22)),
 
 1867                 token::owner(becky));
 
 1869             env(token::acceptBuyOffer(becky, aliceBuyOfferIndex));
 
 1875             env(token::burn(alice, nftAliceNoTransferID));
 
 1882             env(token::setMinter(alice, minter));
 
 1886             uint256 const nftMinterNoTransferID{
 
 1887                 token::getNextID(env, alice, 0u)};
 
 1888             env(token::mint(minter), token::issuer(alice));
 
 1894             env(token::createOffer(becky, nftMinterNoTransferID, XRP(20)),
 
 1895                 token::owner(minter),
 
 1901             env(token::clearMinter(alice));
 
 1906             env(token::createOffer(minter, nftMinterNoTransferID, XRP(21)),
 
 1914             for (
int i = 0; i < 10; ++i)
 
 1917             env(token::setMinter(alice, minter));
 
 1923             uint256 const minterSellOfferIndex =
 
 1925             env(token::createOffer(minter, nftMinterNoTransferID, XRP(22)),
 
 1932             env(token::clearMinter(alice));
 
 1938             env(token::acceptSellOffer(becky, minterSellOfferIndex));
 
 1944             env(token::createOffer(becky, nftMinterNoTransferID, XRP(23)),
 
 1952             env(token::createOffer(minter, nftMinterNoTransferID, XRP(24)),
 
 1953                 token::owner(becky),
 
 1960             uint256 const aliceBuyOfferIndex =
 
 1962             env(token::createOffer(alice, nftMinterNoTransferID, XRP(25)),
 
 1963                 token::owner(becky));
 
 1969             for (
int i = 0; i < 10; ++i)
 
 1972             env(token::setMinter(alice, minter));
 
 1977             uint256 const minterBuyOfferIndex =
 
 1979             env(token::createOffer(minter, nftMinterNoTransferID, XRP(26)),
 
 1980                 token::owner(becky));
 
 1986             env(token::clearMinter(alice));
 
 1992             env(token::acceptBuyOffer(becky, minterBuyOfferIndex));
 
 2000             env(token::burn(minter, nftMinterNoTransferID), ter(
tesSUCCESS));
 
 2002             env(token::cancelOffer(alice, {aliceBuyOfferIndex}));
 
 2019             uint256 const aliceSellOfferIndex =
 
 2021             env(token::createOffer(alice, nftAliceID, XRP(20)),
 
 2026             uint256 const beckyBuyOfferIndex =
 
 2028             env(token::createOffer(becky, nftAliceID, XRP(21)),
 
 2029                 token::owner(alice));
 
 2034             env(token::acceptSellOffer(becky, aliceSellOfferIndex));
 
 2040             uint256 const beckySellOfferIndex =
 
 2042             env(token::createOffer(becky, nftAliceID, XRP(22)),
 
 2050             env(token::acceptSellOffer(minter, beckySellOfferIndex));
 
 2057             uint256 const minterSellOfferIndex =
 
 2059             env(token::createOffer(minter, nftAliceID, XRP(23)),
 
 2067             env(token::acceptSellOffer(alice, minterSellOfferIndex));
 
 2075             env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
 
 2083             env(token::burn(becky, nftAliceID));
 
 2095         testcase(
"Mint transferFee");
 
 2097         using namespace test::jtx;
 
 2099         Env env{*
this, features};
 
 2101         Account 
const alice{
"alice"};
 
 2102         Account 
const becky{
"becky"};
 
 2103         Account 
const carol{
"carol"};
 
 2104         Account 
const minter{
"minter"};
 
 2105         Account 
const gw{
"gw"};
 
 2106         IOU 
const gwXAU(gw[
"XAU"]);
 
 2108         env.fund(XRP(1000), alice, becky, carol, minter, gw);
 
 2111         env(trust(alice, gwXAU(2000)));
 
 2112         env(trust(becky, gwXAU(2000)));
 
 2113         env(trust(carol, gwXAU(2000)));
 
 2114         env(trust(minter, gwXAU(2000)));
 
 2116         env(pay(gw, alice, gwXAU(1000)));
 
 2117         env(pay(gw, becky, gwXAU(1000)));
 
 2118         env(pay(gw, carol, gwXAU(1000)));
 
 2119         env(pay(gw, minter, gwXAU(1000)));
 
 2124         env(token::setMinter(alice, minter));
 
 2141             uint256 const beckyBuyOfferIndex =
 
 2143             env(token::createOffer(becky, nftID, gwXAU(10)),
 
 2144                 token::owner(alice));
 
 2146             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
 
 2147             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
 
 2149             env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
 
 2151             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
 
 2152             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
 
 2155             uint256 const beckySellOfferIndex =
 
 2157             env(token::createOffer(becky, nftID, gwXAU(10)),
 
 2160             env(token::acceptSellOffer(carol, beckySellOfferIndex));
 
 2162             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
 
 2163             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
 
 2164             BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
 
 2167             uint256 const minterBuyOfferIndex =
 
 2169             env(token::createOffer(minter, nftID, gwXAU(10)),
 
 2170                 token::owner(carol));
 
 2172             env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
 
 2174             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
 
 2175             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
 
 2176             BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
 
 2177             BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
 
 2181             uint256 const minterSellOfferIndex =
 
 2183             env(token::createOffer(minter, nftID, gwXAU(10)),
 
 2186             env(token::acceptSellOffer(alice, minterSellOfferIndex));
 
 2188             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
 
 2189             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
 
 2190             BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
 
 2191             BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
 
 2194             env(token::burn(alice, nftID));
 
 2207             env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
 
 2211             uint256 const beckyBuyOfferIndex =
 
 2213             env(token::createOffer(becky, nftID, gwXAU(10)),
 
 2214                 token::owner(alice));
 
 2216             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
 
 2217             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
 
 2219             env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
 
 2221             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
 
 2222             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
 
 2225             uint256 const beckySellOfferIndex =
 
 2227             env(token::createOffer(becky, nftID, gwXAU(10)),
 
 2230             env(token::acceptSellOffer(carol, beckySellOfferIndex));
 
 2233             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0001));
 
 2234             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
 
 2235             BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
 
 2238             uint256 const minterBuyOfferIndex =
 
 2240             env(token::createOffer(minter, nftID, gwXAU(10)),
 
 2241                 token::owner(carol));
 
 2243             env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
 
 2246             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0002));
 
 2247             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
 
 2248             BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
 
 2249             BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
 
 2253             uint256 const minterSellOfferIndex =
 
 2255             env(token::createOffer(minter, nftID, gwXAU(10)),
 
 2258             env(token::acceptSellOffer(alice, minterSellOfferIndex));
 
 2260             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000.0002));
 
 2261             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
 
 2262             BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
 
 2263             BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
 
 2267             env(pay(alice, becky, gwXAU(0.0001)));
 
 2268             env(pay(alice, carol, gwXAU(0.0001)));
 
 2271             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
 
 2272             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
 
 2273             BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
 
 2274             BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
 
 2277             env(token::burn(alice, nftID));
 
 2288             env(token::mint(alice),
 
 2295             uint256 const nftID = token::getNextID(
 
 2297             env(token::mint(alice),
 
 2303             uint256 const beckyBuyOfferIndex =
 
 2305             env(token::createOffer(becky, nftID, gwXAU(10)),
 
 2306                 token::owner(alice));
 
 2308             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
 
 2309             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
 
 2311             env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
 
 2313             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
 
 2314             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
 
 2317             uint256 const beckySellOfferIndex =
 
 2319             env(token::createOffer(becky, nftID, gwXAU(100)),
 
 2322             env(token::acceptSellOffer(minter, beckySellOfferIndex));
 
 2325             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1060));
 
 2326             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
 
 2327             BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
 
 2330             uint256 const carolBuyOfferIndex =
 
 2332             env(token::createOffer(carol, nftID, gwXAU(10)),
 
 2333                 token::owner(minter));
 
 2335             env(token::acceptBuyOffer(minter, carolBuyOfferIndex));
 
 2338             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1065));
 
 2339             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
 
 2340             BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
 
 2341             BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
 
 2345             uint256 const carolSellOfferIndex =
 
 2347             env(token::createOffer(carol, nftID, gwXAU(10)),
 
 2350             env(token::acceptSellOffer(alice, carolSellOfferIndex));
 
 2353             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1055));
 
 2354             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
 
 2355             BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
 
 2356             BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
 
 2359             env(pay(alice, minter, gwXAU(55)));
 
 2360             env(pay(becky, minter, gwXAU(40)));
 
 2362             BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
 
 2363             BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
 
 2364             BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
 
 2365             BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
 
 2368             env(token::burn(alice, nftID));
 
 2378         for (
auto NumberSwitchOver : {
true})
 
 2380             if (NumberSwitchOver)
 
 2388             env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
 
 2394             STAmount aliceBalance = env.balance(alice);
 
 2395             STAmount minterBalance = env.balance(minter);
 
 2396             uint256 const minterBuyOfferIndex =
 
 2398             env(token::createOffer(minter, nftID, XRP(1)), token::owner(alice));
 
 2400             env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
 
 2402             aliceBalance += XRP(1) - fee;
 
 2403             minterBalance -= XRP(1) + fee;
 
 2404             BEAST_EXPECT(env.balance(alice) == aliceBalance);
 
 2405             BEAST_EXPECT(env.balance(minter) == minterBalance);
 
 2409             auto pmt = NumberSwitchOver ? drops(50000) : drops(99999);
 
 2410             STAmount carolBalance = env.balance(carol);
 
 2411             uint256 const minterSellOfferIndex =
 
 2413             env(token::createOffer(minter, nftID, pmt), txflags(
tfSellNFToken));
 
 2415             env(token::acceptSellOffer(carol, minterSellOfferIndex));
 
 2417             minterBalance += pmt - fee;
 
 2418             carolBalance -= pmt + fee;
 
 2419             BEAST_EXPECT(env.balance(alice) == aliceBalance);
 
 2420             BEAST_EXPECT(env.balance(minter) == minterBalance);
 
 2421             BEAST_EXPECT(env.balance(carol) == carolBalance);
 
 2425             STAmount beckyBalance = env.balance(becky);
 
 2426             uint256 const beckyBuyOfferIndex =
 
 2428             pmt = NumberSwitchOver ? drops(50001) : drops(100000);
 
 2429             env(token::createOffer(becky, nftID, pmt), token::owner(carol));
 
 2431             env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
 
 2433             carolBalance += pmt - drops(1) - fee;
 
 2434             beckyBalance -= pmt + fee;
 
 2435             aliceBalance += drops(1);
 
 2437             BEAST_EXPECT(env.balance(alice) == aliceBalance);
 
 2438             BEAST_EXPECT(env.balance(minter) == minterBalance);
 
 2439             BEAST_EXPECT(env.balance(carol) == carolBalance);
 
 2440             BEAST_EXPECT(env.balance(becky) == beckyBalance);
 
 2449             env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
 
 2455             env(pay(alice, gw, env.balance(alice, gwXAU)));
 
 2456             env(pay(minter, gw, env.balance(minter, gwXAU)));
 
 2457             env(pay(becky, gw, env.balance(becky, gwXAU)));
 
 2462             env(pay(gw, alice, startXAUBalance));
 
 2463             env(pay(gw, minter, startXAUBalance));
 
 2464             env(pay(gw, becky, startXAUBalance));
 
 2473             STAmount aliceBalance = env.balance(alice, gwXAU);
 
 2474             STAmount minterBalance = env.balance(minter, gwXAU);
 
 2475             uint256 const minterBuyOfferIndex =
 
 2477             env(token::createOffer(minter, nftID, tinyXAU),
 
 2478                 token::owner(alice));
 
 2480             env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
 
 2482             aliceBalance += tinyXAU;
 
 2483             minterBalance -= tinyXAU;
 
 2484             BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
 
 2485             BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
 
 2488             STAmount carolBalance = env.balance(carol, gwXAU);
 
 2489             uint256 const minterSellOfferIndex =
 
 2491             env(token::createOffer(minter, nftID, tinyXAU),
 
 2494             env(token::acceptSellOffer(carol, minterSellOfferIndex));
 
 2497             minterBalance += tinyXAU;
 
 2498             carolBalance -= tinyXAU;
 
 2500             BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
 
 2501             BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
 
 2502             BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
 
 2509             STAmount beckyBalance = env.balance(becky, gwXAU);
 
 2510             uint256 const beckyBuyOfferIndex =
 
 2512             env(token::createOffer(becky, nftID, cheapNFT),
 
 2513                 token::owner(carol));
 
 2515             env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
 
 2518             aliceBalance += tinyXAU;
 
 2519             beckyBalance -= cheapNFT;
 
 2520             carolBalance += cheapNFT - tinyXAU;
 
 2521             BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
 
 2522             BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
 
 2523             BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
 
 2524             BEAST_EXPECT(env.balance(becky, gwXAU) == beckyBalance);
 
 2532         testcase(
"Mint taxon");
 
 2534         using namespace test::jtx;
 
 2536         Env env{*
this, features};
 
 2538         Account 
const alice{
"alice"};
 
 2539         Account 
const becky{
"becky"};
 
 2541         env.fund(XRP(1000), alice, becky);
 
 2550             uint256 const nftID = token::getNextID(env, alice, 0u);
 
 2557             uint256 const nftID = token::getNextID(env, alice, 0xFFFFFFFFu);
 
 2565             for (
int i = 0; i < 10; ++i)
 
 2575                         ss << 
"Taxon recovery failed from nftID " 
 2576                            << 
to_string(nftID) << 
".  Expected: " << taxon
 
 2577                            << 
"; got: " << gotTaxon;
 
 2582                 uint256 const nftAliceID = token::getID(
 
 2586                     rand_int<std::uint32_t>(),
 
 2587                     rand_int<std::uint16_t>(),
 
 2588                     rand_int<std::uint16_t>());
 
 2589                 check(taxon, nftAliceID);
 
 2591                 uint256 const nftBeckyID = token::getID(
 
 2595                     rand_int<std::uint32_t>(),
 
 2596                     rand_int<std::uint16_t>(),
 
 2597                     rand_int<std::uint16_t>());
 
 2598                 check(taxon, nftBeckyID);
 
 2610         testcase(
"Mint URI");
 
 2612         using namespace test::jtx;
 
 2614         Env env{*
this, features};
 
 2616         Account 
const alice{
"alice"};
 
 2617         Account 
const becky{
"becky"};
 
 2619         env.fund(XRP(10000), alice, becky);
 
 2625         auto randURI = []() {
 
 2647                 : uri(std::move(uri_)), taxon(taxon_)
 
 2655             entries.
emplace_back(randURI(), rand_int<std::uint32_t>());
 
 2658         for (Entry 
const& entry : entries)
 
 2660             if (entry.uri.empty())
 
 2662                 env(token::mint(alice, entry.taxon));
 
 2666                 env(token::mint(alice, entry.taxon), token::uri(entry.uri));
 
 2674             params[jss::account] = alice.human();
 
 2675             params[jss::type] = 
"state";
 
 2676             return env.rpc(
"json", 
"account_nfts", 
to_string(params));
 
 2680         Json::Value& nfts = aliceNFTs[jss::result][jss::account_nfts];
 
 2681         if (!BEAST_EXPECT(nfts.
size() == entries.size()))
 
 2694                 return lhs[jss::nft_serial] < rhs[jss::nft_serial];
 
 2699             Entry 
const& entry = entries[i];
 
 2702             if (entry.uri.empty())
 
 2717         testcase(
"Create offer destination");
 
 2719         using namespace test::jtx;
 
 2721         Env env{*
this, features};
 
 2723         Account 
const issuer{
"issuer"};
 
 2724         Account 
const minter{
"minter"};
 
 2725         Account 
const buyer{
"buyer"};
 
 2726         Account 
const broker{
"broker"};
 
 2728         env.fund(XRP(1000), issuer, minter, buyer, broker);
 
 2732         env(token::setMinter(issuer, minter));
 
 2737         env(token::mint(minter, 0),
 
 2738             token::issuer(issuer),
 
 2745             uint256 const offerMinterToIssuer =
 
 2747             env(token::createOffer(minter, nftokenID, drops(1)),
 
 2748                 token::destination(issuer),
 
 2751             uint256 const offerMinterToBuyer =
 
 2753             env(token::createOffer(minter, nftokenID, drops(1)),
 
 2754                 token::destination(buyer),
 
 2757             uint256 const offerIssuerToMinter =
 
 2759             env(token::createOffer(issuer, nftokenID, drops(1)),
 
 2760                 token::owner(minter),
 
 2761                 token::destination(minter));
 
 2763             uint256 const offerIssuerToBuyer =
 
 2765             env(token::createOffer(issuer, nftokenID, drops(1)),
 
 2766                 token::owner(minter),
 
 2767                 token::destination(buyer));
 
 2781             env(token::cancelOffer(issuer, {offerMinterToBuyer}),
 
 2783             env(token::cancelOffer(buyer, {offerMinterToIssuer}),
 
 2785             env(token::cancelOffer(buyer, {offerIssuerToMinter}),
 
 2787             env(token::cancelOffer(minter, {offerIssuerToBuyer}),
 
 2796             env(token::cancelOffer(buyer, {offerMinterToBuyer}));
 
 2797             env(token::cancelOffer(minter, {offerMinterToIssuer}));
 
 2798             env(token::cancelOffer(buyer, {offerIssuerToBuyer}));
 
 2799             env(token::cancelOffer(issuer, {offerIssuerToMinter}));
 
 2809             uint256 const offerMinterSellsToBuyer =
 
 2811             env(token::createOffer(minter, nftokenID, drops(1)),
 
 2812                 token::destination(buyer),
 
 2821             env(token::acceptSellOffer(issuer, offerMinterSellsToBuyer),
 
 2829             env(token::acceptSellOffer(buyer, offerMinterSellsToBuyer));
 
 2839             uint256 const offerMinterBuysFromBuyer =
 
 2841             env(token::createOffer(minter, nftokenID, drops(1)),
 
 2842                 token::owner(buyer),
 
 2843                 token::destination(buyer));
 
 2851             env(token::acceptBuyOffer(issuer, offerMinterBuysFromBuyer),
 
 2859             env(token::acceptBuyOffer(buyer, offerMinterBuysFromBuyer));
 
 2868             uint256 const offerBuyerBuysFromMinter =
 
 2870             env(token::createOffer(buyer, nftokenID, drops(1)),
 
 2871                 token::owner(minter),
 
 2872                 token::destination(broker));
 
 2878             env(token::acceptBuyOffer(minter, offerBuyerBuysFromMinter),
 
 2883             env(token::cancelOffer(buyer, {offerBuyerBuysFromMinter}));
 
 2893             uint256 const offerMinterToBroker =
 
 2895             env(token::createOffer(minter, nftokenID, drops(1)),
 
 2896                 token::destination(broker),
 
 2899             uint256 const offerBuyerToMinter =
 
 2901             env(token::createOffer(buyer, nftokenID, drops(1)),
 
 2902                 token::owner(minter));
 
 2915                 env(token::brokerOffers(
 
 2916                         issuer, offerBuyerToMinter, offerMinterToBroker),
 
 2926             env(token::brokerOffers(
 
 2927                 broker, offerBuyerToMinter, offerMinterToBroker));
 
 2938             uint256 const offerBuyerToMinter =
 
 2940             env(token::createOffer(buyer, nftokenID, drops(1)),
 
 2941                 token::destination(minter),
 
 2944             uint256 const offerMinterToBuyer =
 
 2946             env(token::createOffer(minter, nftokenID, drops(1)),
 
 2947                 token::owner(buyer));
 
 2949             uint256 const offerIssuerToBuyer =
 
 2951             env(token::createOffer(issuer, nftokenID, drops(1)),
 
 2952                 token::owner(buyer));
 
 2965                 env(token::brokerOffers(
 
 2966                         broker, offerIssuerToBuyer, offerBuyerToMinter),
 
 2979                 env(token::brokerOffers(
 
 2980                         broker, offerMinterToBuyer, offerBuyerToMinter),
 
 2986                     env(token::acceptBuyOffer(buyer, offerMinterToBuyer));
 
 2990                 env(token::cancelOffer(buyer, {offerBuyerToMinter}));
 
 2998                 env(token::cancelOffer(issuer, {offerIssuerToBuyer}));
 
 3010             uint256 const offerMinterToBroker =
 
 3012             env(token::createOffer(minter, nftokenID, drops(1)),
 
 3013                 token::destination(broker),
 
 3016             uint256 const offerBuyerToBroker =
 
 3018             env(token::createOffer(buyer, nftokenID, drops(1)),
 
 3019                 token::owner(minter),
 
 3020                 token::destination(broker));
 
 3028                 env(token::brokerOffers(
 
 3029                         issuer, offerBuyerToBroker, offerMinterToBroker),
 
 3038             env(token::brokerOffers(
 
 3039                 broker, offerBuyerToBroker, offerMinterToBroker));
 
 3050         testcase(
"Create offer destination disallow incoming");
 
 3052         using namespace test::jtx;
 
 3057             Account 
const alice{
"alice"};
 
 3058             env.fund(XRP(10000), alice);
 
 3061             auto const sle = env.le(alice);
 
 3062             uint32_t flags = sle->getFlags();
 
 3068         Account 
const issuer{
"issuer"};
 
 3069         Account 
const minter{
"minter"};
 
 3070         Account 
const buyer{
"buyer"};
 
 3071         Account 
const alice{
"alice"};
 
 3073         env.fund(XRP(1000), issuer, minter, buyer, alice);
 
 3075         env(token::setMinter(issuer, minter));
 
 3080         env(token::mint(minter, 0),
 
 3081             token::issuer(issuer),
 
 3091             env(token::createOffer(minter, nftokenID, drops(1)),
 
 3092                 token::destination(buyer),
 
 3110             env(token::createOffer(minter, nftokenID, drops(1)),
 
 3111                 token::destination(buyer),
 
 3115             env(token::cancelOffer(minter, {offerIndex}));
 
 3124             env(token::createOffer(minter, nftokenID, drops(1)),
 
 3125                 token::destination(buyer),
 
 3132             env(token::cancelOffer(minter, {offerIndex}));
 
 3144             env(token::createOffer(minter, nftokenID, drops(1)),
 
 3145                 token::destination(buyer),
 
 3149             env(token::acceptSellOffer(buyer, offerIndex));
 
 3161             env(token::createOffer(alice, nftokenID, drops(1)),
 
 3162                 token::owner(buyer),
 
 3169             env(token::createOffer(minter, nftokenID, drops(1)),
 
 3170                 token::owner(buyer),
 
 3180         testcase(
"Create offer expiration");
 
 3182         using namespace test::jtx;
 
 3184         Env env{*
this, features};
 
 3186         Account 
const issuer{
"issuer"};
 
 3187         Account 
const minter{
"minter"};
 
 3188         Account 
const buyer{
"buyer"};
 
 3190         env.fund(XRP(1000), issuer, minter, buyer);
 
 3194         env(token::setMinter(issuer, minter));
 
 3199         env(token::mint(minter, 0),
 
 3200             token::issuer(issuer),
 
 3206         env(token::mint(minter, 0),
 
 3207             token::issuer(issuer),
 
 3216             uint256 const offerMinterToIssuer =
 
 3218             env(token::createOffer(minter, nftokenID0, drops(1)),
 
 3219                 token::destination(issuer),
 
 3220                 token::expiration(expiration),
 
 3223             uint256 const offerMinterToAnyone =
 
 3225             env(token::createOffer(minter, nftokenID0, drops(1)),
 
 3226                 token::expiration(expiration),
 
 3229             uint256 const offerIssuerToMinter =
 
 3231             env(token::createOffer(issuer, nftokenID0, drops(1)),
 
 3232                 token::owner(minter),
 
 3233                 token::expiration(expiration));
 
 3235             uint256 const offerBuyerToMinter =
 
 3237             env(token::createOffer(buyer, nftokenID0, drops(1)),
 
 3238                 token::owner(minter),
 
 3239                 token::expiration(expiration));
 
 3251             env(token::cancelOffer(issuer, {offerMinterToAnyone}),
 
 3253             env(token::cancelOffer(buyer, {offerIssuerToMinter}),
 
 3256             BEAST_EXPECT(
lastClose(env) < expiration);
 
 3262             env(token::cancelOffer(minter, {offerMinterToAnyone}));
 
 3266             env(token::cancelOffer(issuer, {offerMinterToIssuer}));
 
 3277             env(token::cancelOffer(issuer, {offerBuyerToMinter}));
 
 3278             env(token::cancelOffer(buyer, {offerIssuerToMinter}));
 
 3293             env(token::createOffer(minter, nftokenID0, drops(1)),
 
 3294                 token::expiration(expiration),
 
 3299             env(token::createOffer(minter, nftokenID1, drops(1)),
 
 3300                 token::expiration(expiration),
 
 3303             BEAST_EXPECT(
lastClose(env) < expiration);
 
 3309             env(token::acceptSellOffer(buyer, offer0));
 
 3320             env(token::acceptSellOffer(buyer, offer1), ter(
tecEXPIRED));
 
 3321             env(token::acceptSellOffer(issuer, offer1), ter(
tecEXPIRED));
 
 3330             env(token::cancelOffer(issuer, {offer1}));
 
 3340             env(token::createOffer(buyer, nftokenID0, XRP(0)),
 
 3342                 token::destination(minter));
 
 3344             env(token::acceptSellOffer(minter, offerSellBack));
 
 3358             env(token::createOffer(buyer, nftokenID0, drops(1)),
 
 3359                 token::owner(minter),
 
 3360                 token::expiration(expiration));
 
 3363             env(token::createOffer(buyer, nftokenID1, drops(1)),
 
 3364                 token::owner(minter),
 
 3365                 token::expiration(expiration));
 
 3367             BEAST_EXPECT(
lastClose(env) < expiration);
 
 3373             env(token::acceptBuyOffer(minter, offer0));
 
 3384             env(token::acceptBuyOffer(minter, offer1), ter(
tecEXPIRED));
 
 3385             env(token::acceptBuyOffer(issuer, offer1), ter(
tecEXPIRED));
 
 3394             env(token::cancelOffer(issuer, {offer1}));
 
 3404             env(token::createOffer(buyer, nftokenID0, XRP(0)),
 
 3406                 token::destination(minter));
 
 3408             env(token::acceptSellOffer(minter, offerSellBack));
 
 3423             env(token::createOffer(minter, nftokenID0, drops(1)),
 
 3424                 token::expiration(expiration),
 
 3429             env(token::createOffer(minter, nftokenID1, drops(1)),
 
 3430                 token::expiration(expiration),
 
 3435             env(token::createOffer(buyer, nftokenID0, drops(1)),
 
 3436                 token::owner(minter));
 
 3440             env(token::createOffer(buyer, nftokenID1, drops(1)),
 
 3441                 token::owner(minter));
 
 3444             BEAST_EXPECT(
lastClose(env) < expiration);
 
 3450             env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
 
 3461             env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
 
 3471             env(token::cancelOffer(buyer, {buyOffer1, sellOffer1}));
 
 3481             env(token::createOffer(buyer, nftokenID0, XRP(0)),
 
 3483                 token::destination(minter));
 
 3485             env(token::acceptSellOffer(minter, offerSellBack));
 
 3500             env(token::createOffer(minter, nftokenID0, drops(1)),
 
 3505             env(token::createOffer(minter, nftokenID1, drops(1)),
 
 3510             env(token::createOffer(buyer, nftokenID0, drops(1)),
 
 3511                 token::expiration(expiration),
 
 3512                 token::owner(minter));
 
 3516             env(token::createOffer(buyer, nftokenID1, drops(1)),
 
 3517                 token::expiration(expiration),
 
 3518                 token::owner(minter));
 
 3521             BEAST_EXPECT(
lastClose(env) < expiration);
 
 3527             env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
 
 3538             env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
 
 3548             env(token::cancelOffer(minter, {buyOffer1, sellOffer1}));
 
 3558             env(token::createOffer(buyer, nftokenID0, XRP(0)),
 
 3560                 token::destination(minter));
 
 3562             env(token::acceptSellOffer(minter, offerSellBack));
 
 3578             env(token::createOffer(minter, nftokenID0, drops(1)),
 
 3579                 token::expiration(expiration),
 
 3584             env(token::createOffer(minter, nftokenID1, drops(1)),
 
 3585                 token::expiration(expiration),
 
 3590             env(token::createOffer(buyer, nftokenID0, drops(1)),
 
 3591                 token::expiration(expiration),
 
 3592                 token::owner(minter));
 
 3596             env(token::createOffer(buyer, nftokenID1, drops(1)),
 
 3597                 token::expiration(expiration),
 
 3598                 token::owner(minter));
 
 3601             BEAST_EXPECT(
lastClose(env) < expiration);
 
 3607             env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
 
 3618             env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
 
 3628             env(token::cancelOffer(issuer, {buyOffer1, sellOffer1}));
 
 3638             env(token::createOffer(buyer, nftokenID0, XRP(0)),
 
 3640                 token::destination(minter));
 
 3642             env(token::acceptSellOffer(minter, offerSellBack));
 
 3654         testcase(
"Cancel offers");
 
 3656         using namespace test::jtx;
 
 3658         Env env{*
this, features};
 
 3660         Account 
const alice(
"alice");
 
 3661         Account 
const becky(
"becky");
 
 3662         Account 
const minter(
"minter");
 
 3663         env.fund(XRP(50000), alice, becky, minter);
 
 3667         env(token::setMinter(alice, minter));
 
 3676         uint256 const expiredOfferIndex =
 
 3679         env(token::createOffer(alice, nftokenID, XRP(1000)),
 
 3681             token::expiration(
lastClose(env) + 13));
 
 3686         env(token::cancelOffer(becky, {expiredOfferIndex}),
 
 3694         env(token::cancelOffer(becky, {expiredOfferIndex}));
 
 3700         uint256 const dest1OfferIndex =
 
 3703         env(token::createOffer(alice, nftokenID, XRP(1000)),
 
 3704             token::destination(becky),
 
 3710         env(token::cancelOffer(minter, {dest1OfferIndex}),
 
 3715         env(token::cancelOffer(becky, {dest1OfferIndex}));
 
 3720         uint256 const dest2OfferIndex =
 
 3723         env(token::createOffer(alice, nftokenID, XRP(1000)),
 
 3724             token::destination(becky),
 
 3729         env(token::cancelOffer(alice, {dest2OfferIndex}));
 
 3736         uint256 const mintersNFTokenID =
 
 3738         env(token::mint(minter, 0),
 
 3739             token::issuer(alice),
 
 3743         uint256 const minterOfferIndex =
 
 3746         env(token::createOffer(minter, mintersNFTokenID, XRP(1000)),
 
 3752         env(token::cancelOffer(alice, {minterOfferIndex}),
 
 3754         env(token::cancelOffer(becky, {minterOfferIndex}),
 
 3759         env(token::cancelOffer(minter, {minterOfferIndex}));
 
 3768         testcase(
"Cancel too many offers");
 
 3770         using namespace test::jtx;
 
 3772         Env env{*
this, features};
 
 3787         Account 
const alice(
"alice");
 
 3788         env.fund(XRP(1000), alice);
 
 3797             Account 
const offerAcct(
 
 3799             env.fund(XRP(1000), nftAcct, offerAcct);
 
 3804             env(token::mint(nftAcct, 0),
 
 3811             env(token::createOffer(offerAcct, nftokenID, drops(1)),
 
 3812                 token::owner(nftAcct),
 
 3821         for (
uint256 const& offerIndex : offerIndexes)
 
 3828         env(token::cancelOffer(alice, offerIndexes), ter(
temMALFORMED));
 
 3832         env(token::cancelOffer(alice, {offerIndexes.back()}));
 
 3837         offerIndexes.pop_back();
 
 3843             env(token::mint(alice, 0),
 
 3849             env(token::createOffer(alice, nftokenID, drops(1)),
 
 3858             env(token::cancelOffer(alice, offerIndexes), ter(
temMALFORMED));
 
 3862             env(token::burn(alice, nftokenID));
 
 3868             offerIndexes.pop_back();
 
 3873         env(token::cancelOffer(alice, offerIndexes));
 
 3877         for (
uint256 const& offerIndex : offerIndexes)
 
 3887         testcase(
"Brokered NFT offer accept");
 
 3889         using namespace test::jtx;
 
 3891         for (
auto const& tweakedFeatures :
 
 3895             Env env{*
this, tweakedFeatures};
 
 3903             Account 
const issuer{
"issuer"};
 
 3904             Account 
const minter{
"minter"};
 
 3905             Account 
const buyer{
"buyer"};
 
 3906             Account 
const broker{
"broker"};
 
 3907             Account 
const gw{
"gw"};
 
 3908             IOU 
const gwXAU(gw[
"XAU"]);
 
 3910             env.fund(XRP(1000), issuer, minter, buyer, broker, gw);
 
 3913             env(trust(issuer, gwXAU(2000)));
 
 3914             env(trust(minter, gwXAU(2000)));
 
 3915             env(trust(buyer, gwXAU(2000)));
 
 3916             env(trust(broker, gwXAU(2000)));
 
 3919             env(token::setMinter(issuer, minter));
 
 3923             auto checkOwnerCountIsOne =
 
 3928                     for (Account 
const& acct : accounts)
 
 3935                             ss << 
"Account " << acct.human()
 
 3936                                << 
" expected ownerCount == 1.  Got " 
 3938                             fail(ss.
str(), __FILE__, line);
 
 3944             auto mintNFT = [&env, &issuer, &minter](
std::uint16_t xferFee = 0) {
 
 3947                 env(token::mint(minter, 0),
 
 3948                     token::issuer(issuer),
 
 3949                     token::xferFee(xferFee),
 
 3961                 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
 
 3963                 uint256 const nftID = mintNFT();
 
 3966                 uint256 const minterOfferIndex =
 
 3968                 env(token::createOffer(minter, nftID, XRP(0)),
 
 3976                 env(token::createOffer(buyer, nftID, XRP(1)),
 
 3977                     token::owner(minter));
 
 3980                 auto const minterBalance = env.balance(minter);
 
 3981                 auto const buyerBalance = env.balance(buyer);
 
 3982                 auto const brokerBalance = env.balance(broker);
 
 3983                 auto const issuerBalance = env.balance(issuer);
 
 3986                 env(token::brokerOffers(
 
 3987                     broker, buyOfferIndex, minterOfferIndex));
 
 3992                 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(1));
 
 3993                 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
 
 3994                 BEAST_EXPECT(env.balance(broker) == brokerBalance - drops(10));
 
 3995                 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
 
 3998                 env(token::burn(buyer, nftID));
 
 4008                 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
 
 4010                 uint256 const nftID = mintNFT();
 
 4013                 uint256 const minterOfferIndex =
 
 4015                 env(token::createOffer(minter, nftID, XRP(0)),
 
 4023                 env(token::createOffer(buyer, nftID, XRP(1)),
 
 4024                     token::owner(minter));
 
 4028                 env(token::brokerOffers(
 
 4029                         broker, buyOfferIndex, minterOfferIndex),
 
 4030                     token::brokerFee(XRP(1.1)),
 
 4034                 auto const minterBalance = env.balance(minter);
 
 4035                 auto const buyerBalance = env.balance(buyer);
 
 4036                 auto const brokerBalance = env.balance(broker);
 
 4037                 auto const issuerBalance = env.balance(issuer);
 
 4040                 env(token::brokerOffers(
 
 4041                         broker, buyOfferIndex, minterOfferIndex),
 
 4042                     token::brokerFee(XRP(0.5)));
 
 4047                 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
 
 4048                 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
 
 4050                     env.balance(broker) ==
 
 4051                     brokerBalance + XRP(0.5) - drops(10));
 
 4052                 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
 
 4055                 env(token::burn(buyer, nftID));
 
 4065                 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
 
 4070                 uint256 const minterOfferIndex =
 
 4072                 env(token::createOffer(minter, nftID, XRP(0)),
 
 4080                 env(token::createOffer(buyer, nftID, XRP(1)),
 
 4081                     token::owner(minter));
 
 4084                 auto const minterBalance = env.balance(minter);
 
 4085                 auto const buyerBalance = env.balance(buyer);
 
 4086                 auto const brokerBalance = env.balance(broker);
 
 4087                 auto const issuerBalance = env.balance(issuer);
 
 4090                 env(token::brokerOffers(
 
 4091                     broker, buyOfferIndex, minterOfferIndex));
 
 4096                 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
 
 4097                 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
 
 4098                 BEAST_EXPECT(env.balance(broker) == brokerBalance - drops(10));
 
 4099                 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.5));
 
 4102                 env(token::burn(buyer, nftID));
 
 4112                 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
 
 4117                 uint256 const minterOfferIndex =
 
 4119                 env(token::createOffer(minter, nftID, XRP(0)),
 
 4127                 env(token::createOffer(buyer, nftID, XRP(1)),
 
 4128                     token::owner(minter));
 
 4131                 auto const minterBalance = env.balance(minter);
 
 4132                 auto const buyerBalance = env.balance(buyer);
 
 4133                 auto const brokerBalance = env.balance(broker);
 
 4134                 auto const issuerBalance = env.balance(issuer);
 
 4137                 env(token::brokerOffers(
 
 4138                         broker, buyOfferIndex, minterOfferIndex),
 
 4139                     token::brokerFee(XRP(0.75)));
 
 4145                 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.125));
 
 4146                 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
 
 4148                     env.balance(broker) ==
 
 4149                     brokerBalance + XRP(0.75) - drops(10));
 
 4150                 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.125));
 
 4153                 env(token::burn(buyer, nftID));
 
 4159             auto setXAUBalance =
 
 4160                 [
this, &gw, &gwXAU, &env](
 
 4165                     for (Account 
const& acct : accounts)
 
 4167                         auto const xauAmt = gwXAU(amount);
 
 4168                         auto const balance = env.balance(acct, gwXAU);
 
 4169                         if (balance < xauAmt)
 
 4171                             env(pay(gw, acct, xauAmt - balance));
 
 4174                         else if (balance > xauAmt)
 
 4176                             env(pay(acct, gw, balance - xauAmt));
 
 4179                         if (env.balance(acct, gwXAU) != xauAmt)
 
 4182                             ss << 
"Unable to set " << acct.human()
 
 4183                                << 
" account balance to gwXAU(" << amount << 
")";
 
 4184                             this->fail(ss.
str(), __FILE__, line);
 
 4192                 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
 
 4193                 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
 
 4195                 uint256 const nftID = mintNFT();
 
 4198                 uint256 const minterOfferIndex =
 
 4200                 env(token::createOffer(minter, nftID, gwXAU(1000)),
 
 4209                     env(token::createOffer(buyer, nftID, gwXAU(1001)),
 
 4210                         token::owner(minter));
 
 4214                     env(token::brokerOffers(
 
 4215                             broker, buyOfferIndex, minterOfferIndex),
 
 4221                     env(token::cancelOffer(buyer, {buyOfferIndex}));
 
 4229                     env(token::createOffer(buyer, nftID, gwXAU(999)),
 
 4230                         token::owner(minter));
 
 4234                     env(token::brokerOffers(
 
 4235                             broker, buyOfferIndex, minterOfferIndex),
 
 4241                     env(token::cancelOffer(buyer, {buyOfferIndex}));
 
 4248                 env(token::createOffer(buyer, nftID, gwXAU(1000)),
 
 4249                     token::owner(minter));
 
 4253                 env(token::brokerOffers(
 
 4254                         broker, buyOfferIndex, minterOfferIndex),
 
 4255                     token::brokerFee(gwXAU(0.1)),
 
 4260                 env(token::brokerOffers(
 
 4261                     broker, buyOfferIndex, minterOfferIndex));
 
 4268                 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1000));
 
 4269                 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(2000));
 
 4270                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
 
 4271                 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1000));
 
 4274                 env(token::burn(buyer, nftID));
 
 4281                 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
 
 4282                 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
 
 4287                 uint256 const minterOfferIndex =
 
 4289                 env(token::createOffer(minter, nftID, gwXAU(900)),
 
 4297                     env(token::createOffer(buyer, nftID, gwXAU(1001)),
 
 4298                         token::owner(minter));
 
 4302                     env(token::brokerOffers(
 
 4303                             broker, buyOfferIndex, minterOfferIndex),
 
 4309                     env(token::cancelOffer(buyer, {buyOfferIndex}));
 
 4317                     env(token::createOffer(buyer, nftID, gwXAU(899)),
 
 4318                         token::owner(minter));
 
 4322                     env(token::brokerOffers(
 
 4323                             broker, buyOfferIndex, minterOfferIndex),
 
 4329                     env(token::cancelOffer(buyer, {buyOfferIndex}));
 
 4335                 env(token::createOffer(buyer, nftID, gwXAU(1000)),
 
 4336                     token::owner(minter));
 
 4341                 env(token::brokerOffers(
 
 4342                         broker, buyOfferIndex, minterOfferIndex),
 
 4343                     token::brokerFee(gwXAU(101)),
 
 4349                 env(token::brokerOffers(
 
 4350                         broker, buyOfferIndex, minterOfferIndex),
 
 4351                     token::brokerFee(gwXAU(100)));
 
 4358                 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1450));
 
 4359                 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1450));
 
 4360                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
 
 4361                 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1100));
 
 4364                 env(token::burn(buyer, nftID));
 
 4371                 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
 
 4372                 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
 
 4377                 uint256 const minterOfferIndex =
 
 4379                 env(token::createOffer(minter, nftID, gwXAU(900)),
 
 4386                 env(token::createOffer(buyer, nftID, gwXAU(1000)),
 
 4387                     token::owner(minter));
 
 4393                 env(token::brokerOffers(
 
 4394                         broker, buyOfferIndex, minterOfferIndex),
 
 4395                     token::brokerFee(gwXAU(50)));
 
 4402                 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
 
 4403                 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
 
 4404                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
 
 4405                 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1050));
 
 4408                 env(token::burn(buyer, nftID));
 
 4413                 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
 
 4414                 setXAUBalance({issuer, minter, buyer}, 1000, __LINE__);
 
 4415                 setXAUBalance({broker}, 500, __LINE__);
 
 4419                 uint256 const minterOfferIndex =
 
 4421                 env(token::createOffer(minter, nftID, gwXAU(900)),
 
 4428                 env(token::createOffer(buyer, nftID, gwXAU(1000)),
 
 4429                     token::owner(minter));
 
 4434                     env(token::brokerOffers(
 
 4435                             broker, buyOfferIndex, minterOfferIndex),
 
 4436                         token::brokerFee(gwXAU(50)));
 
 4442                     BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
 
 4443                     BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
 
 4444                     BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
 
 4445                     BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(550));
 
 4448                     env(token::burn(buyer, nftID));
 
 4453                     env(token::brokerOffers(
 
 4454                             broker, buyOfferIndex, minterOfferIndex),
 
 4455                         token::brokerFee(gwXAU(50)),
 
 4462                     BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1000));
 
 4463                     BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
 
 4464                     BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(1000));
 
 4465                     BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(500));
 
 4468                     env(token::burn(minter, nftID));
 
 4479         testcase(
"NFToken offer owner");
 
 4481         using namespace test::jtx;
 
 4483         Env env{*
this, features};
 
 4485         Account 
const issuer{
"issuer"};
 
 4486         Account 
const buyer1{
"buyer1"};
 
 4487         Account 
const buyer2{
"buyer2"};
 
 4488         env.fund(XRP(10000), issuer, buyer1, buyer2);
 
 4497         BEAST_EXPECT(
nftCount(env, issuer) == 1);
 
 4498         BEAST_EXPECT(
nftCount(env, buyer1) == 0);
 
 4499         BEAST_EXPECT(
nftCount(env, buyer2) == 0);
 
 4502         uint256 const buyer1OfferIndex =
 
 4504         env(token::createOffer(buyer1, nftId, XRP(100)), token::owner(issuer));
 
 4505         uint256 const buyer2OfferIndex =
 
 4507         env(token::createOffer(buyer2, nftId, XRP(100)), token::owner(issuer));
 
 4517                 env.rpc(
"json", 
"nft_buy_offers", 
to_string(params));
 
 4519             if (buyOffers.
isMember(jss::result) &&
 
 4520                 buyOffers[jss::result].
isMember(jss::offers))
 
 4521                 return buyOffers[jss::result][jss::offers].
size();
 
 4527         BEAST_EXPECT(nftBuyOfferCount(nftId) == 2);
 
 4530         env(token::acceptBuyOffer(issuer, buyer1OfferIndex));
 
 4534         BEAST_EXPECT(
nftCount(env, issuer) == 0);
 
 4535         BEAST_EXPECT(
nftCount(env, buyer1) == 1);
 
 4536         BEAST_EXPECT(
nftCount(env, buyer2) == 0);
 
 4540         BEAST_EXPECT(nftBuyOfferCount(nftId) == 1);
 
 4544         env(token::acceptBuyOffer(buyer1, buyer2OfferIndex));
 
 4548         BEAST_EXPECT(
nftCount(env, issuer) == 0);
 
 4549         BEAST_EXPECT(
nftCount(env, buyer1) == 0);
 
 4550         BEAST_EXPECT(
nftCount(env, buyer2) == 1);
 
 4553         BEAST_EXPECT(nftBuyOfferCount(nftId) == 0);
 
 4560         testcase(
"NFToken transactions with tickets");
 
 4562         using namespace test::jtx;
 
 4564         Env env{*
this, features};
 
 4566         Account 
const issuer{
"issuer"};
 
 4567         Account 
const buyer{
"buyer"};
 
 4568         env.fund(XRP(10000), issuer, buyer);
 
 4575         env(ticket::create(issuer, 10));
 
 4581         env(ticket::create(buyer, 10));
 
 4589         env(token::mint(issuer, 0u),
 
 4591             ticket::use(issuerTicketSeq++));
 
 4599         env(token::createOffer(buyer, nftId, XRP(1)),
 
 4600             token::owner(issuer),
 
 4601             ticket::use(buyerTicketSeq++));
 
 4607         env(token::cancelOffer(buyer, {offerIndex0}),
 
 4608             ticket::use(buyerTicketSeq++));
 
 4615         env(token::createOffer(buyer, nftId, XRP(2)),
 
 4616             token::owner(issuer),
 
 4617             ticket::use(buyerTicketSeq++));
 
 4623         env(token::acceptBuyOffer(issuer, offerIndex1),
 
 4624             ticket::use(issuerTicketSeq++));
 
 4631         env(token::burn(buyer, nftId), ticket::use(buyerTicketSeq++));
 
 4638         BEAST_EXPECT(env.seq(issuer) == issuerSeq);
 
 4639         BEAST_EXPECT(env.seq(buyer) == buyerSeq);
 
 4650         testcase(
"NFToken delete account");
 
 4652         using namespace test::jtx;
 
 4654         Env env{*
this, features};
 
 4656         Account 
const issuer{
"issuer"};
 
 4657         Account 
const minter{
"minter"};
 
 4658         Account 
const becky{
"becky"};
 
 4659         Account 
const carla{
"carla"};
 
 4660         Account 
const daria{
"daria"};
 
 4662         env.fund(XRP(10000), issuer, minter, becky, carla, daria);
 
 4666         for (
int i = 0; i < 300; ++i)
 
 4669         env(token::setMinter(issuer, minter));
 
 4673         env(token::mint(minter, 0u),
 
 4674             token::issuer(issuer),
 
 4687         for (
int i = 0; i < 15; ++i)
 
 4691         env(token::createOffer(becky, nftId, XRP(2)), token::owner(minter));
 
 4694         uint256 const carlaOfferIndex =
 
 4696         env(token::createOffer(carla, nftId, XRP(3)), token::owner(minter));
 
 4701         env(acctdelete(becky, daria), fee(XRP(50)));
 
 4705         env(token::acceptBuyOffer(minter, carlaOfferIndex));
 
 4710         env(acctdelete(minter, daria), fee(XRP(50)));
 
 4722         for (
int i = 0; i < 15; ++i)
 
 4727         env(token::burn(carla, nftId));
 
 4730         env(acctdelete(issuer, daria), fee(XRP(50)));
 
 4731         env(acctdelete(carla, daria), fee(XRP(50)));
 
 4738         testcase(
"nft_buy_offers and nft_sell_offers");
 
 4747         using namespace test::jtx;
 
 4749         Env env{*
this, features};
 
 4751         Account 
const issuer{
"issuer"};
 
 4752         Account 
const buyer{
"buyer"};
 
 4755         env.fund(XRP(1000000), issuer, buyer);
 
 4764         auto checkOffers = [
this, &env, &nftID](
 
 4765                                char const* request,
 
 4767                                int expectMarkerCount,
 
 4769             int markerCount = 0;
 
 4776                 Json::Value nftOffers = [&env, &nftID, &request, &marker]() {
 
 4780                     if (!marker.
empty())
 
 4781                         params[jss::marker] = marker;
 
 4782                     return env.rpc(
"json", request, 
to_string(params));
 
 4786                 if (expectCount == 0)
 
 4790                             "expected \"result\"",
 
 4795                                 nftOffers[jss::result].isMember(jss::error),
 
 4796                                 "expected \"error\"",
 
 4801                                 nftOffers[jss::result][jss::error].asString() ==
 
 4803                                 "expected \"objectNotFound\"",
 
 4814                         "expected \"result\"",
 
 4823                         marker = result[jss::marker].
asString();
 
 4828                             "expected \"offers\"",
 
 4834                             allOffers.
append(someOffers[i]);
 
 4837             } 
while (!marker.
empty());
 
 4841                 allOffers.
size() == expectCount,
 
 4842                 "Unexpected returned offer count",
 
 4846                 markerCount == expectMarkerCount,
 
 4847                 "Unexpected marker count",
 
 4857                     globalFlags = offer[jss::flags].asInt();
 
 4860                     *globalFlags == offer[jss::flags].asInt(),
 
 4861                     "Inconsistent flags returned",
 
 4867                 offerIndexes.
insert(offer[jss::nft_offer_index].asString());
 
 4868                 amounts.
insert(offer[jss::amount].asString());
 
 4872                 offerIndexes.
size() == expectCount,
 
 4873                 "Duplicate indexes returned?",
 
 4877                 amounts.
size() == expectCount,
 
 4878                 "Duplicate amounts returned?",
 
 4884         checkOffers(
"nft_sell_offers", 0, 
false, __LINE__);
 
 4888         auto makeSellOffers =
 
 4889             [&env, &issuer, &nftID, &sellPrice](
STAmount const& limit) {
 
 4892                 while (sellPrice < limit)
 
 4894                     sellPrice += XRP(1);
 
 4895                     env(token::createOffer(issuer, nftID, sellPrice),
 
 4897                     if (++offerCount % 10 == 0)
 
 4904         makeSellOffers(XRP(1));
 
 4905         checkOffers(
"nft_sell_offers", 1, 0, __LINE__);
 
 4908         makeSellOffers(XRP(250));
 
 4909         checkOffers(
"nft_sell_offers", 250, 0, __LINE__);
 
 4912         makeSellOffers(XRP(251));
 
 4913         checkOffers(
"nft_sell_offers", 251, 1, __LINE__);
 
 4916         makeSellOffers(XRP(500));
 
 4917         checkOffers(
"nft_sell_offers", 500, 1, __LINE__);
 
 4920         makeSellOffers(XRP(501));
 
 4921         checkOffers(
"nft_sell_offers", 501, 2, __LINE__);
 
 4924         checkOffers(
"nft_buy_offers", 0, 0, __LINE__);
 
 4928         auto makeBuyOffers =
 
 4929             [&env, &buyer, &issuer, &nftID, &buyPrice](
STAmount const& limit) {
 
 4932                 while (buyPrice < limit)
 
 4935                     env(token::createOffer(buyer, nftID, buyPrice),
 
 4936                         token::owner(issuer));
 
 4937                     if (++offerCount % 10 == 0)
 
 4944         makeBuyOffers(XRP(1));
 
 4945         checkOffers(
"nft_buy_offers", 1, 0, __LINE__);
 
 4948         makeBuyOffers(XRP(250));
 
 4949         checkOffers(
"nft_buy_offers", 250, 0, __LINE__);
 
 4952         makeBuyOffers(XRP(251));
 
 4953         checkOffers(
"nft_buy_offers", 251, 1, __LINE__);
 
 4956         makeBuyOffers(XRP(500));
 
 4957         checkOffers(
"nft_buy_offers", 500, 1, __LINE__);
 
 4960         makeBuyOffers(XRP(501));
 
 4961         checkOffers(
"nft_buy_offers", 501, 2, __LINE__);
 
 4968         using namespace test::jtx;
 
 4970         testcase(
"fixNFTokenNegOffer");
 
 4972         Account 
const issuer{
"issuer"};
 
 4973         Account 
const buyer{
"buyer"};
 
 4974         Account 
const gw{
"gw"};
 
 4975         IOU 
const gwXAU(gw[
"XAU"]);
 
 4981         for (
auto const& tweakedFeatures :
 
 4990             Env env{*
this, tweakedFeatures};
 
 4992             env.fund(XRP(1000000), issuer, buyer, gw);
 
 4995             env(trust(issuer, gwXAU(2000)));
 
 4996             env(trust(buyer, gwXAU(2000)));
 
 4999             env(pay(gw, issuer, gwXAU(1000)));
 
 5000             env(pay(gw, buyer, gwXAU(1000)));
 
 5020             uint256 const sellNegXrpOfferIndex =
 
 5022             env(token::createOffer(issuer, nftID0, XRP(-2)),
 
 5024                 ter(offerCreateTER));
 
 5027             uint256 const sellNegIouOfferIndex =
 
 5029             env(token::createOffer(issuer, nftID1, gwXAU(-2)),
 
 5031                 ter(offerCreateTER));
 
 5034             uint256 const buyNegXrpOfferIndex =
 
 5036             env(token::createOffer(buyer, nftID0, XRP(-1)),
 
 5037                 token::owner(issuer),
 
 5038                 ter(offerCreateTER));
 
 5041             uint256 const buyNegIouOfferIndex =
 
 5043             env(token::createOffer(buyer, nftID1, gwXAU(-1)),
 
 5044                 token::owner(issuer),
 
 5045                 ter(offerCreateTER));
 
 5057                 env(token::acceptSellOffer(buyer, sellNegXrpOfferIndex),
 
 5058                     ter(offerAcceptTER));
 
 5060                 env(token::acceptSellOffer(buyer, sellNegIouOfferIndex),
 
 5061                     ter(offerAcceptTER));
 
 5065                 env(token::acceptBuyOffer(issuer, buyNegXrpOfferIndex),
 
 5066                     ter(offerAcceptTER));
 
 5068                 env(token::acceptBuyOffer(issuer, buyNegIouOfferIndex),
 
 5069                     ter(offerAcceptTER));
 
 5082                 env(token::brokerOffers(
 
 5083                         gw, buyNegXrpOfferIndex, sellNegXrpOfferIndex),
 
 5084                     ter(offerAcceptTER));
 
 5086                 env(token::brokerOffers(
 
 5087                         gw, buyNegIouOfferIndex, sellNegIouOfferIndex),
 
 5088                     ter(offerAcceptTER));
 
 5100             env.fund(XRP(1000000), issuer, buyer, gw);
 
 5103             env(trust(issuer, gwXAU(2000)));
 
 5104             env(trust(buyer, gwXAU(2000)));
 
 5107             env(pay(gw, issuer, gwXAU(1000)));
 
 5108             env(pay(gw, buyer, gwXAU(1000)));
 
 5124             uint256 const sellNegXrpOfferIndex =
 
 5126             env(token::createOffer(issuer, nftID0, XRP(-2)),
 
 5130             uint256 const sellNegIouOfferIndex =
 
 5132             env(token::createOffer(issuer, nftID1, gwXAU(-2)),
 
 5136             uint256 const buyNegXrpOfferIndex =
 
 5138             env(token::createOffer(buyer, nftID0, XRP(-1)),
 
 5139                 token::owner(issuer));
 
 5142             uint256 const buyNegIouOfferIndex =
 
 5144             env(token::createOffer(buyer, nftID1, gwXAU(-1)),
 
 5145                 token::owner(issuer));
 
 5154             env(token::acceptSellOffer(buyer, sellNegXrpOfferIndex),
 
 5157             env(token::acceptSellOffer(buyer, sellNegIouOfferIndex),
 
 5162             env(token::acceptBuyOffer(issuer, buyNegXrpOfferIndex),
 
 5165             env(token::acceptBuyOffer(issuer, buyNegIouOfferIndex),
 
 5170             env(token::brokerOffers(
 
 5171                     gw, buyNegXrpOfferIndex, sellNegXrpOfferIndex),
 
 5174             env(token::brokerOffers(
 
 5175                     gw, buyNegIouOfferIndex, sellNegIouOfferIndex),
 
 5182         for (
auto const& tweakedFeatures :
 
 5186             Env env{*
this, tweakedFeatures};
 
 5188             env.fund(XRP(1000000), issuer, buyer);
 
 5200             env(token::createOffer(buyer, nftID, drops(1)),
 
 5201                 token::owner(issuer),
 
 5202                 token::destination(issuer),
 
 5203                 ter(offerCreateTER));
 
 5211         using namespace test::jtx;
 
 5213         testcase(
"Payments with IOU transfer fees");
 
 5215         for (
auto const& tweakedFeatures :
 
 5219             Env env{*
this, tweakedFeatures};
 
 5221             Account 
const minter{
"minter"};
 
 5222             Account 
const secondarySeller{
"seller"};
 
 5223             Account 
const buyer{
"buyer"};
 
 5224             Account 
const gw{
"gateway"};
 
 5225             Account 
const broker{
"broker"};
 
 5226             IOU 
const gwXAU(gw[
"XAU"]);
 
 5227             IOU 
const gwXPB(gw[
"XPB"]);
 
 5229             env.fund(XRP(1000), gw, minter, secondarySeller, buyer, broker);
 
 5232             env(trust(minter, gwXAU(2000)));
 
 5233             env(trust(secondarySeller, gwXAU(2000)));
 
 5234             env(trust(broker, gwXAU(10000)));
 
 5235             env(trust(buyer, gwXAU(2000)));
 
 5236             env(trust(buyer, gwXPB(2000)));
 
 5240             env(rate(gw, 1.02));
 
 5243             auto expectInitialState = [
this,
 
 5256                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(1000));
 
 5257                 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(0));
 
 5258                 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(0));
 
 5259                 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(0));
 
 5260                 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(0));
 
 5261                 BEAST_EXPECT(env.balance(secondarySeller, gwXPB) == gwXPB(0));
 
 5262                 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5000));
 
 5263                 BEAST_EXPECT(env.balance(broker, gwXPB) == gwXPB(0));
 
 5264                 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-1000));
 
 5265                 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(0));
 
 5266                 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(0));
 
 5267                 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(0));
 
 5269                     env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(0));
 
 5271                     env.balance(gw, secondarySeller[
"XPB"]) == gwXPB(0));
 
 5272                 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5000));
 
 5273                 BEAST_EXPECT(env.balance(gw, broker[
"XPB"]) == gwXPB(0));
 
 5276             auto reinitializeTrustLineBalances = [&expectInitialState,
 
 5285                 if (
auto const difference =
 
 5286                         gwXAU(1000) - env.balance(buyer, gwXAU);
 
 5287                     difference > gwXAU(0))
 
 5288                     env(pay(gw, buyer, difference));
 
 5289                 if (env.balance(buyer, gwXPB) > gwXPB(0))
 
 5290                     env(pay(buyer, gw, env.balance(buyer, gwXPB)));
 
 5291                 if (env.balance(minter, gwXAU) > gwXAU(0))
 
 5292                     env(pay(minter, gw, env.balance(minter, gwXAU)));
 
 5293                 if (env.balance(minter, gwXPB) > gwXPB(0))
 
 5294                     env(pay(minter, gw, env.balance(minter, gwXPB)));
 
 5295                 if (env.balance(secondarySeller, gwXAU) > gwXAU(0))
 
 5297                         pay(secondarySeller,
 
 5299                             env.balance(secondarySeller, gwXAU)));
 
 5300                 if (env.balance(secondarySeller, gwXPB) > gwXPB(0))
 
 5302                         pay(secondarySeller,
 
 5304                             env.balance(secondarySeller, gwXPB)));
 
 5305                 auto brokerDiff = gwXAU(5000) - env.balance(broker, gwXAU);
 
 5306                 if (brokerDiff > gwXAU(0))
 
 5307                     env(pay(gw, broker, brokerDiff));
 
 5308                 else if (brokerDiff < gwXAU(0))
 
 5310                     brokerDiff.negate();
 
 5311                     env(pay(broker, gw, brokerDiff));
 
 5313                 if (env.balance(broker, gwXPB) > gwXPB(0))
 
 5314                     env(pay(broker, gw, env.balance(broker, gwXPB)));
 
 5316                 expectInitialState();
 
 5319             auto mintNFT = [&env](Account 
const& minter, 
int transferFee = 0) {
 
 5320                 uint256 const nftID = token::getNextID(
 
 5322                 env(token::mint(minter),
 
 5323                     token::xferFee(transferFee),
 
 5329             auto createBuyOffer =
 
 5331                     Account 
const& offerer,
 
 5332                     Account 
const& owner,
 
 5338                     env(token::createOffer(offerer, nftID, amount),
 
 5339                         token::owner(owner),
 
 5340                         terCode ? ter(*terCode)
 
 5346             auto createSellOffer =
 
 5348                     Account 
const& offerer,
 
 5354                     env(token::createOffer(offerer, nftID, amount),
 
 5356                         terCode ? ter(*terCode)
 
 5365                 reinitializeTrustLineBalances();
 
 5366                 auto const nftID = mintNFT(minter);
 
 5367                 auto const offerID =
 
 5368                     createSellOffer(minter, nftID, gwXAU(1000));
 
 5372                 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
 
 5376                     expectInitialState();
 
 5379                     BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
 
 5380                     BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(-20));
 
 5382                         env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
 
 5383                     BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(20));
 
 5389                 reinitializeTrustLineBalances();
 
 5390                 auto const nftID = mintNFT(minter);
 
 5391                 auto const offerID =
 
 5392                     createBuyOffer(buyer, minter, nftID, gwXAU(1000));
 
 5396                 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
 
 5400                     expectInitialState();
 
 5403                     BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
 
 5404                     BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(-20));
 
 5406                         env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
 
 5407                     BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(20));
 
 5414                 reinitializeTrustLineBalances();
 
 5415                 auto const nftID = mintNFT(minter);
 
 5416                 auto const offerID = createSellOffer(minter, nftID, gwXAU(995));
 
 5420                 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
 
 5424                     expectInitialState();
 
 5427                     BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(995));
 
 5428                     BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(-14.9));
 
 5429                     BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-995));
 
 5430                     BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(14.9));
 
 5437                 reinitializeTrustLineBalances();
 
 5438                 auto const nftID = mintNFT(minter);
 
 5439                 auto const offerID =
 
 5440                     createBuyOffer(buyer, minter, nftID, gwXAU(995));
 
 5444                 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
 
 5448                     expectInitialState();
 
 5451                     BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(995));
 
 5452                     BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(-14.9));
 
 5453                     BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-995));
 
 5454                     BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(14.9));
 
 5462                 reinitializeTrustLineBalances();
 
 5463                 auto const nftID = mintNFT(minter);
 
 5464                 auto const offerID = createSellOffer(minter, nftID, gwXAU(900));
 
 5465                 env(token::acceptSellOffer(buyer, offerID));
 
 5468                 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
 
 5469                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
 
 5470                 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
 
 5471                 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
 
 5478                 reinitializeTrustLineBalances();
 
 5479                 auto const nftID = mintNFT(minter);
 
 5480                 auto const offerID =
 
 5481                     createBuyOffer(buyer, minter, nftID, gwXAU(900));
 
 5482                 env(token::acceptBuyOffer(minter, offerID));
 
 5485                 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
 
 5486                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
 
 5487                 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
 
 5488                 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
 
 5495                 reinitializeTrustLineBalances();
 
 5498                 env(pay(gw, buyer, gwXAU(20)));
 
 5501                 auto const nftID = mintNFT(minter);
 
 5502                 auto const offerID =
 
 5503                     createSellOffer(minter, nftID, gwXAU(1000));
 
 5504                 env(token::acceptSellOffer(buyer, offerID));
 
 5507                 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
 
 5508                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
 
 5509                 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
 
 5510                 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
 
 5517                 reinitializeTrustLineBalances();
 
 5520                 env(pay(gw, buyer, gwXAU(20)));
 
 5523                 auto const nftID = mintNFT(minter);
 
 5524                 auto const offerID =
 
 5525                     createBuyOffer(buyer, minter, nftID, gwXAU(1000));
 
 5526                 env(token::acceptBuyOffer(minter, offerID));
 
 5529                 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
 
 5530                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
 
 5531                 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
 
 5532                 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
 
 5537                 reinitializeTrustLineBalances();
 
 5539                 auto const nftID = mintNFT(minter);
 
 5540                 auto const offerID =
 
 5541                     createSellOffer(minter, nftID, gwXAU(1000));
 
 5545                 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
 
 5550                     BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
 
 5552                         env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
 
 5555                     expectInitialState();
 
 5560                 reinitializeTrustLineBalances();
 
 5562                 auto const nftID = mintNFT(minter);
 
 5566                 auto const offerID =
 
 5567                     createBuyOffer(gw, minter, nftID, gwXAU(1000), {offerTER});
 
 5571                 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
 
 5576                     BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
 
 5578                         env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
 
 5581                     expectInitialState();
 
 5586                 reinitializeTrustLineBalances();
 
 5587                 auto const nftID = mintNFT(minter);
 
 5588                 auto const offerID =
 
 5589                     createSellOffer(minter, nftID, gwXAU(5000));
 
 5593                 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
 
 5598                     BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
 
 5600                         env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
 
 5603                     expectInitialState();
 
 5608                 reinitializeTrustLineBalances();
 
 5610                 auto const nftID = mintNFT(minter);
 
 5614                 auto const offerID =
 
 5615                     createBuyOffer(gw, minter, nftID, gwXAU(5000), {offerTER});
 
 5619                 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
 
 5624                     BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
 
 5626                         env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
 
 5629                     expectInitialState();
 
 5635                 reinitializeTrustLineBalances();
 
 5636                 auto const nftID = mintNFT(gw);
 
 5637                 auto const offerID = createSellOffer(gw, nftID, gwXAU(1000));
 
 5638                 env(token::acceptSellOffer(buyer, offerID));
 
 5641                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
 
 5642                 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
 
 5648                 reinitializeTrustLineBalances();
 
 5650                 auto const nftID = mintNFT(gw);
 
 5651                 auto const offerID =
 
 5652                     createBuyOffer(buyer, gw, nftID, gwXAU(1000));
 
 5653                 env(token::acceptBuyOffer(gw, offerID));
 
 5656                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
 
 5657                 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
 
 5663                 reinitializeTrustLineBalances();
 
 5664                 auto const nftID = mintNFT(gw);
 
 5665                 auto const offerID = createSellOffer(gw, nftID, gwXAU(2000));
 
 5666                 env(token::acceptSellOffer(buyer, offerID),
 
 5669                 expectInitialState();
 
 5675                 reinitializeTrustLineBalances();
 
 5676                 auto const nftID = mintNFT(gw);
 
 5677                 auto const offerID =
 
 5678                     createBuyOffer(buyer, gw, nftID, gwXAU(2000));
 
 5679                 env(token::acceptBuyOffer(gw, offerID),
 
 5682                 expectInitialState();
 
 5687                 reinitializeTrustLineBalances();
 
 5688                 auto const nftID = mintNFT(minter);
 
 5689                 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
 
 5690                 env(token::acceptSellOffer(buyer, offerID),
 
 5693                 expectInitialState();
 
 5698                 reinitializeTrustLineBalances();
 
 5699                 auto const nftID = mintNFT(minter);
 
 5700                 auto const offerID = createBuyOffer(
 
 5706                 env(token::acceptBuyOffer(minter, offerID),
 
 5709                 expectInitialState();
 
 5715                 reinitializeTrustLineBalances();
 
 5716                 env(pay(gw, buyer, gwXPB(100)));
 
 5719                 auto const nftID = mintNFT(minter);
 
 5720                 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
 
 5721                 env(token::acceptSellOffer(buyer, offerID));
 
 5724                 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
 
 5725                 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
 
 5726                 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
 
 5727                 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
 
 5733                 reinitializeTrustLineBalances();
 
 5734                 env(pay(gw, buyer, gwXPB(100)));
 
 5737                 auto const nftID = mintNFT(minter);
 
 5738                 auto const offerID =
 
 5739                     createBuyOffer(buyer, minter, nftID, gwXPB(10));
 
 5740                 env(token::acceptBuyOffer(minter, offerID));
 
 5743                 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
 
 5744                 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
 
 5745                 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
 
 5746                 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
 
 5751                 reinitializeTrustLineBalances();
 
 5755                 auto const nftID = mintNFT(minter, 3000);  
 
 5756                 auto const primaryOfferID =
 
 5757                     createSellOffer(minter, nftID, XRP(0));
 
 5758                 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
 
 5762                 auto const offerID =
 
 5763                     createSellOffer(secondarySeller, nftID, gwXAU(1000));
 
 5767                 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
 
 5771                     expectInitialState();
 
 5774                     BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(30));
 
 5776                         env.balance(secondarySeller, gwXAU) == gwXAU(970));
 
 5777                     BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(-20));
 
 5778                     BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-30));
 
 5780                         env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-970));
 
 5781                     BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(20));
 
 5787                 reinitializeTrustLineBalances();
 
 5791                 auto const nftID = mintNFT(minter, 3000);  
 
 5792                 auto const primaryOfferID =
 
 5793                     createSellOffer(minter, nftID, XRP(0));
 
 5794                 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
 
 5798                 auto const offerID =
 
 5799                     createBuyOffer(buyer, secondarySeller, nftID, gwXAU(1000));
 
 5803                 env(token::acceptBuyOffer(secondarySeller, offerID),
 
 5808                     expectInitialState();
 
 5811                     BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(30));
 
 5813                         env.balance(secondarySeller, gwXAU) == gwXAU(970));
 
 5814                     BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(-20));
 
 5815                     BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-30));
 
 5817                         env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-970));
 
 5818                     BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(20));
 
 5824                 reinitializeTrustLineBalances();
 
 5828                 auto const nftID = mintNFT(minter, 3000);  
 
 5829                 auto const primaryOfferID =
 
 5830                     createSellOffer(minter, nftID, XRP(0));
 
 5831                 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
 
 5835                 auto const offerID =
 
 5836                     createSellOffer(secondarySeller, nftID, gwXAU(900));
 
 5837                 env(token::acceptSellOffer(buyer, offerID));
 
 5840                 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
 
 5841                 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
 
 5842                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
 
 5843                 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
 
 5845                     env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
 
 5846                 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
 
 5851                 reinitializeTrustLineBalances();
 
 5855                 auto const nftID = mintNFT(minter, 3000);  
 
 5856                 auto const primaryOfferID =
 
 5857                     createSellOffer(minter, nftID, XRP(0));
 
 5858                 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
 
 5862                 auto const offerID =
 
 5863                     createBuyOffer(buyer, secondarySeller, nftID, gwXAU(900));
 
 5864                 env(token::acceptBuyOffer(secondarySeller, offerID));
 
 5868                 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
 
 5870                 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
 
 5872                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
 
 5873                 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
 
 5875                     env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
 
 5876                 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
 
 5894                 reinitializeTrustLineBalances();
 
 5896                 auto const nftID = mintNFT(minter);
 
 5897                 auto const sellOffer =
 
 5898                     createSellOffer(minter, nftID, gwXAU(300));
 
 5899                 auto const buyOffer =
 
 5900                     createBuyOffer(buyer, minter, nftID, gwXAU(500));
 
 5901                 env(token::brokerOffers(broker, buyOffer, sellOffer),
 
 5902                     token::brokerFee(gwXAU(100)));
 
 5905                 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(400));
 
 5906                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
 
 5907                 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
 
 5908                 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-400));
 
 5909                 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
 
 5910                 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
 
 5928                 reinitializeTrustLineBalances();
 
 5932                 auto const nftID = mintNFT(minter, 3000);  
 
 5933                 auto const primaryOfferID =
 
 5934                     createSellOffer(minter, nftID, XRP(0));
 
 5935                 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
 
 5939                 auto const sellOffer =
 
 5940                     createSellOffer(secondarySeller, nftID, gwXAU(300));
 
 5941                 auto const buyOffer =
 
 5942                     createBuyOffer(buyer, secondarySeller, nftID, gwXAU(500));
 
 5943                 env(token::brokerOffers(broker, buyOffer, sellOffer),
 
 5944                     token::brokerFee(gwXAU(100)));
 
 5947                 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(12));
 
 5948                 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
 
 5949                 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(388));
 
 5950                 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
 
 5951                 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-12));
 
 5952                 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
 
 5954                     env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-388));
 
 5955                 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
 
 5975         testcase(
"Brokered sale to self");
 
 5977         using namespace test::jtx;
 
 5979         Account 
const alice{
"alice"};
 
 5980         Account 
const bob{
"bob"};
 
 5981         Account 
const broker{
"broker"};
 
 5983         Env env{*
this, features};
 
 5984         env.fund(XRP(10000), alice, bob, broker);
 
 6010         uint256 const bobBuyOfferIndex =
 
 6012         env(token::createOffer(bob, nftId, XRP(5)), token::owner(alice));
 
 6014         uint256 const aliceSellOfferIndex =
 
 6016         env(token::createOffer(alice, nftId, XRP(0)),
 
 6017             token::destination(bob),
 
 6022         env(token::acceptSellOffer(bob, aliceSellOfferIndex));
 
 6029         uint256 const bobSellOfferIndex =
 
 6031         env(token::createOffer(bob, nftId, XRP(4)), txflags(
tfSellNFToken));
 
 6036         BEAST_EXPECT(
nftCount(env, bob) == 1);
 
 6037         auto const bobsPriorBalance = env.balance(bob);
 
 6038         auto const brokersPriorBalance = env.balance(broker);
 
 6042         env(token::brokerOffers(broker, bobBuyOfferIndex, bobSellOfferIndex),
 
 6043             token::brokerFee(XRP(1)),
 
 6052             BEAST_EXPECT(
nftCount(env, bob) == 1);
 
 6053             BEAST_EXPECT(env.balance(bob) == bobsPriorBalance - XRP(1));
 
 6055                 env.balance(broker) ==
 
 6056                 brokersPriorBalance + XRP(1) - drops(10));
 
 6062             BEAST_EXPECT(
nftCount(env, bob) == 1);
 
 6063             BEAST_EXPECT(env.balance(bob) == bobsPriorBalance);
 
 6065                 env.balance(broker) == brokersPriorBalance - drops(10));
 
 6072         using namespace test::jtx;
 
 6074         testcase(
"fixNFTokenRemint");
 
 6077         auto openLedgerSeq = [](Env& env) { 
return env.current()->seq(); };
 
 6082         auto incLgrSeqForAcctDel = [&](Env& env, Account 
const& acct) {
 
 6083             int const delta = [&]() -> 
int {
 
 6084                 if (env.seq(acct) + 255 > openLedgerSeq(env))
 
 6085                     return env.seq(acct) - openLedgerSeq(env) + 255;
 
 6088             BEAST_EXPECT(delta >= 0);
 
 6089             for (
int i = 0; i < delta; ++i)
 
 6091             BEAST_EXPECT(openLedgerSeq(env) == env.seq(acct) + 255);
 
 6097         auto incLgrSeqForFixNftRemint = [&](Env& env, Account 
const& acct) {
 
 6099             auto const deletableLgrSeq =
 
 6103             if (deletableLgrSeq > openLedgerSeq(env))
 
 6104                 delta = deletableLgrSeq - openLedgerSeq(env);
 
 6106             BEAST_EXPECT(delta >= 0);
 
 6107             for (
int i = 0; i < delta; ++i)
 
 6109             BEAST_EXPECT(openLedgerSeq(env) == deletableLgrSeq);
 
 6115             Env env{*
this, features};
 
 6116             Account 
const alice(
"alice");
 
 6117             Account 
const becky(
"becky");
 
 6119             env.fund(XRP(10000), alice, becky);
 
 6123             uint256 const prevNFTokenID = token::getNextID(env, alice, 0u);
 
 6124             env(token::mint(alice));
 
 6126             env(token::burn(alice, prevNFTokenID));
 
 6133             incLgrSeqForAcctDel(env, alice);
 
 6137             auto const acctDelFee{drops(env.current()->fees().increment)};
 
 6138             env(acctdelete(alice, becky), fee(acctDelFee));
 
 6143             BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
 
 6144             BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
 
 6147             env.fund(XRP(10000), alice);
 
 6151             BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
 
 6152             BEAST_EXPECT(env.current()->exists(aliceAcctKey));
 
 6156             uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
 
 6157             env(token::mint(alice));
 
 6161             env(token::burn(alice, remintNFTokenID));
 
 6166                 BEAST_EXPECT(remintNFTokenID != prevNFTokenID);
 
 6169                 BEAST_EXPECT(remintNFTokenID == prevNFTokenID);
 
 6175             Env env{*
this, features};
 
 6176             Account 
const alice(
"alice");
 
 6177             Account 
const becky(
"becky");
 
 6178             Account 
const minter{
"minter"};
 
 6180             env.fund(XRP(10000), alice, becky, minter);
 
 6184             env(token::setMinter(alice, minter));
 
 6190             for (
int i = 0; i < 500; i++)
 
 6192                 uint256 const nftokenID = token::getNextID(env, alice, 0u);
 
 6194                 env(token::mint(minter), token::issuer(alice));
 
 6199             for (
auto const nftokenID : nftIDs)
 
 6201                 env(token::burn(minter, nftokenID));
 
 6207             incLgrSeqForAcctDel(env, alice);
 
 6211             BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
 
 6212             BEAST_EXPECT(env.current()->exists(aliceAcctKey));
 
 6214             auto const acctDelFee{drops(env.current()->fees().increment)};
 
 6219                 env(acctdelete(alice, becky), fee(acctDelFee));
 
 6221                 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
 
 6224                 env.fund(XRP(10000), alice);
 
 6228                 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
 
 6229                 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
 
 6234                 uint256 const remintNFTokenID =
 
 6235                     token::getNextID(env, alice, 0u);
 
 6236                 env(token::mint(alice));
 
 6240                 env(token::burn(alice, remintNFTokenID));
 
 6246                     std::find(nftIDs.begin(), nftIDs.end(), remintNFTokenID) !=
 
 6258                 env(acctdelete(alice, becky),
 
 6264                 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
 
 6269                 incLgrSeqForFixNftRemint(env, alice);
 
 6272                 env(acctdelete(alice, becky), fee(acctDelFee));
 
 6277                 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
 
 6278                 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
 
 6281                 env.fund(XRP(10000), alice);
 
 6285                 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
 
 6286                 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
 
 6291                 uint256 const remintNFTokenID =
 
 6292                     token::getNextID(env, alice, 0u);
 
 6293                 env(token::mint(alice));
 
 6297                 env(token::burn(alice, remintNFTokenID));
 
 6303                     std::find(nftIDs.begin(), nftIDs.end(), remintNFTokenID) ==
 
 6311             Env env{*
this, features};
 
 6313             Account 
const alice{
"alice"};
 
 6314             Account 
const becky{
"becky"};
 
 6315             env.fund(XRP(10000), alice, becky);
 
 6322             env(ticket::create(alice, 100));
 
 6331             for (
int i = 0; i < 50; i++)
 
 6333                 nftIDs.
push_back(token::getNextID(env, alice, 0u));
 
 6334                 env(token::mint(alice, 0u), ticket::use(aliceTicketSeq++));
 
 6339             for (
auto const nftokenID : nftIDs)
 
 6341                 env(token::burn(alice, nftokenID),
 
 6342                     ticket::use(aliceTicketSeq++));
 
 6350             incLgrSeqForAcctDel(env, alice);
 
 6354             BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
 
 6355             BEAST_EXPECT(env.current()->exists(aliceAcctKey));
 
 6357             auto const acctDelFee{drops(env.current()->fees().increment)};
 
 6362                 env(acctdelete(alice, becky), fee(acctDelFee));
 
 6367                 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
 
 6368                 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
 
 6371                 env.fund(XRP(10000), alice);
 
 6375                 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
 
 6376                 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
 
 6381                 uint256 const remintNFTokenID =
 
 6382                     token::getNextID(env, alice, 0u);
 
 6383                 env(token::mint(alice));
 
 6387                 env(token::burn(alice, remintNFTokenID));
 
 6393                     std::find(nftIDs.begin(), nftIDs.end(), remintNFTokenID) !=
 
 6405                 env(acctdelete(alice, becky),
 
 6411                 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
 
 6416                 incLgrSeqForFixNftRemint(env, alice);
 
 6419                 env(acctdelete(alice, becky), fee(acctDelFee));
 
 6424                 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
 
 6425                 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
 
 6428                 env.fund(XRP(10000), alice);
 
 6432                 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
 
 6433                 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
 
 6438                 uint256 const remintNFTokenID =
 
 6439                     token::getNextID(env, alice, 0u);
 
 6440                 env(token::mint(alice));
 
 6444                 env(token::burn(alice, remintNFTokenID));
 
 6450                     std::find(nftIDs.begin(), nftIDs.end(), remintNFTokenID) ==
 
 6462             Env env{*
this, features};
 
 6463             Account 
const alice(
"alice");
 
 6464             Account 
const becky(
"becky");
 
 6465             Account 
const minter{
"minter"};
 
 6467             env.fund(XRP(10000), alice, becky, minter);
 
 6471             env(token::setMinter(alice, minter));
 
 6476             env(ticket::create(minter, 100));
 
 6480             BEAST_EXPECT(
ownerCount(env, minter) == 100);
 
 6485             for (
int i = 0; i < 50; i++)
 
 6487                 uint256 const nftokenID = token::getNextID(env, alice, 0u);
 
 6489                 env(token::mint(minter),
 
 6490                     token::issuer(alice),
 
 6491                     ticket::use(minterTicketSeq++));
 
 6496             for (
auto const nftokenID : nftIDs)
 
 6498                 env(token::burn(minter, nftokenID),
 
 6499                     ticket::use(minterTicketSeq++));
 
 6507             incLgrSeqForAcctDel(env, alice);
 
 6511             BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
 
 6512             BEAST_EXPECT(env.current()->exists(aliceAcctKey));
 
 6521             auto const acctDelFee{drops(env.current()->fees().increment)};
 
 6522             env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
 
 6526             BEAST_EXPECT(env.current()->exists(aliceAcctKey));
 
 6531             incLgrSeqForFixNftRemint(env, alice);
 
 6534             env(acctdelete(alice, becky), fee(acctDelFee));
 
 6539             BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
 
 6540             BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
 
 6543             env.fund(XRP(10000), alice);
 
 6547             BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
 
 6548             BEAST_EXPECT(env.current()->exists(aliceAcctKey));
 
 6553             uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
 
 6554             env(token::mint(alice));
 
 6558             env(token::burn(alice, remintNFTokenID));
 
 6564                 std::find(nftIDs.begin(), nftIDs.end(), remintNFTokenID) ==
 
 6583         testcase(
"Test synthetic fields from JSON response");
 
 6585         using namespace test::jtx;
 
 6587         Account 
const alice{
"alice"};
 
 6588         Account 
const bob{
"bob"};
 
 6589         Account 
const broker{
"broker"};
 
 6591         Env env{*
this, features};
 
 6592         env.fund(XRP(10000), alice, bob, broker);
 
 6598         auto verifyNFTokenID = [&](
uint256 const& actualNftID) {
 
 6605                 env.rpc(
"tx", txHash)[jss::result][jss::meta];
 
 6608             if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_id)))
 
 6615             BEAST_EXPECT(nftID == actualNftID);
 
 6620         auto verifyNFTokenIDsInCancelOffer =
 
 6628                     env.rpc(
"tx", txHash)[jss::result][jss::meta];
 
 6631                 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_ids)))
 
 6637                     meta[jss::nftoken_ids].begin(),
 
 6638                     meta[jss::nftoken_ids].end(),
 
 6642                         BEAST_EXPECT(nftID.
parseHex(
id.asString()));
 
 6648                 std::sort(actualNftIDs.begin(), actualNftIDs.end());
 
 6651                 BEAST_EXPECT(metaIDs.
size() == actualNftIDs.size());
 
 6655                 for (
size_t i = 0; i < metaIDs.
size(); ++i)
 
 6656                     BEAST_EXPECT(metaIDs[i] == actualNftIDs[i]);
 
 6661         auto verifyNFTokenOfferID = [&](
uint256 const& offerID) {
 
 6668                 env.rpc(
"tx", txHash)[jss::result][jss::meta];
 
 6671             if (!BEAST_EXPECT(meta.
isMember(jss::offer_id)))
 
 6676             BEAST_EXPECT(metaOfferID == offerID);
 
 6687             verifyNFTokenID(nftId1);
 
 6693             verifyNFTokenID(nftId2);
 
 6698             uint256 const aliceOfferIndex1 =
 
 6700             env(token::createOffer(alice, nftId1, drops(1)),
 
 6703             verifyNFTokenOfferID(aliceOfferIndex1);
 
 6705             uint256 const aliceOfferIndex2 =
 
 6707             env(token::createOffer(alice, nftId2, drops(1)),
 
 6710             verifyNFTokenOfferID(aliceOfferIndex2);
 
 6715             env(token::cancelOffer(
 
 6716                 alice, {aliceOfferIndex1, aliceOfferIndex2}));
 
 6718             verifyNFTokenIDsInCancelOffer({nftId1, nftId2});
 
 6722             auto const bobBuyOfferIndex =
 
 6724             env(token::createOffer(bob, nftId1, drops(1)), token::owner(alice));
 
 6726             verifyNFTokenOfferID(bobBuyOfferIndex);
 
 6730             env(token::acceptBuyOffer(alice, bobBuyOfferIndex));
 
 6732             verifyNFTokenID(nftId1);
 
 6742             verifyNFTokenID(nftId);
 
 6745             uint256 const offerAliceToBroker =
 
 6747             env(token::createOffer(alice, nftId, drops(1)),
 
 6748                 token::destination(broker),
 
 6751             verifyNFTokenOfferID(offerAliceToBroker);
 
 6754             uint256 const offerBobToBroker =
 
 6756             env(token::createOffer(bob, nftId, drops(1)), token::owner(alice));
 
 6758             verifyNFTokenOfferID(offerBobToBroker);
 
 6761             env(token::brokerOffers(
 
 6762                 broker, offerBobToBroker, offerAliceToBroker));
 
 6764             verifyNFTokenID(nftId);
 
 6775             verifyNFTokenID(nftId);
 
 6778             uint256 const aliceOfferIndex1 =
 
 6780             env(token::createOffer(alice, nftId, drops(1)),
 
 6783             verifyNFTokenOfferID(aliceOfferIndex1);
 
 6785             uint256 const aliceOfferIndex2 =
 
 6787             env(token::createOffer(alice, nftId, drops(1)),
 
 6790             verifyNFTokenOfferID(aliceOfferIndex2);
 
 6794             env(token::cancelOffer(
 
 6795                 alice, {aliceOfferIndex1, aliceOfferIndex2}));
 
 6797             verifyNFTokenIDsInCancelOffer({nftId});
 
 6840         using namespace test::jtx;