179 Env env{*
this, features};
181 Account const minter{
"minter"};
185 auto const acctReserve = env.current()->fees().reserve;
186 auto const incReserve = env.current()->fees().increment;
187 auto const baseFee = env.current()->fees().base;
189 env.fund(acctReserve, alice, minter);
192 BEAST_EXPECT(env.balance(alice) == acctReserve);
193 BEAST_EXPECT(env.balance(minter) == acctReserve);
194 BEAST_EXPECT(ownerCount(env, alice) == 0);
195 BEAST_EXPECT(ownerCount(env, minter) == 0);
202 BEAST_EXPECT(ownerCount(env, alice) == 0);
207 env(pay(env.master, alice, incReserve + drops(baseFee - 1)));
212 auto checkAliceOwnerMintedBurned = [&env,
this, &alice](
225 ss <<
"Wrong " << type <<
" count. Found: " << found <<
"; Expected: " << exp;
226 fail(ss.
str(), __FILE__, line);
229 oneCheck(
"owner", ownerCount(env, alice), owners);
230 oneCheck(
"minted",
mintedCount(env, alice), minted);
231 oneCheck(
"burned",
burnedCount(env, alice), burned);
239 checkAliceOwnerMintedBurned(0, 0, 0, __LINE__);
242 env(pay(env.master, alice, drops(baseFee + 1)));
246 env(token::mint(alice));
249 checkAliceOwnerMintedBurned(1, 1, 0, __LINE__);
253 for (
int i = 1; i < 32; ++i)
255 env(token::mint(alice));
256 checkAliceOwnerMintedBurned(1, i + 1, 0, __LINE__);
263 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
266 env(pay(env.master, alice, incReserve + drops(baseFee * 33 - 1)));
273 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
276 env(pay(env.master, alice, drops(baseFee + 1)));
280 env(token::mint(alice));
282 checkAliceOwnerMintedBurned(2, 33, 0, __LINE__);
289 env(token::burn(alice, token::getID(env, alice, 0, seq++)));
291 checkAliceOwnerMintedBurned(((33 - seq) != 0u) ? 1 : 0, 33, seq, __LINE__);
295 env(token::burn(alice, token::getID(env, alice, 197, 5)), Ter(
tecNO_ENTRY));
297 checkAliceOwnerMintedBurned(0, 33, 33, __LINE__);
302 env(token::setMinter(alice, minter));
304 BEAST_EXPECT(env.le(alice)->getAccountID(sfNFTokenMinter) == minter.id());
308 auto checkMintersOwnerMintedBurned = [&env,
this, &alice, &minter](
325 ss <<
"Wrong " << type <<
" count. Found: " << found
326 <<
"; Expected: " << exp;
327 fail(ss.
str(), __FILE__, line);
330 oneCheck(
"alice owner", ownerCount(env, alice), aliceOwners, line);
331 oneCheck(
"alice minted",
mintedCount(env, alice), aliceMinted, line);
332 oneCheck(
"alice burned",
burnedCount(env, alice), aliceBurned, line);
333 oneCheck(
"minter owner", ownerCount(env, minter), minterOwners, line);
334 oneCheck(
"minter minted",
mintedCount(env, minter), minterMinted, line);
335 oneCheck(
"minter burned",
burnedCount(env, minter), minterBurned, line);
341 env(pay(env.master, minter, incReserve - drops(1)));
343 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
348 env(token::mint(minter),
349 token::Issuer(alice),
353 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
356 env(pay(env.master, minter, drops(baseFee + 1)));
360 env(token::mint(minter), token::Issuer(alice), token::Uri(
"uri"));
362 checkMintersOwnerMintedBurned(0, 34, nftSeq, 1, 0, 0, __LINE__);
366 for (
int i = 1; i < 32; ++i)
368 env(token::mint(minter), token::Issuer(alice), token::Uri(
"uri"));
369 checkMintersOwnerMintedBurned(0, i + 34, nftSeq, 1, 0, 0, __LINE__);
374 env(pay(env.master, minter, incReserve + drops(baseFee * 32 - 1)));
379 env(token::mint(minter),
380 token::Issuer(alice),
384 checkMintersOwnerMintedBurned(0, 65, nftSeq, 1, 0, 0, __LINE__);
387 env(pay(env.master, minter, drops(baseFee + 1)));
391 env(token::mint(minter), token::Issuer(alice), token::Uri(
"uri"));
393 checkMintersOwnerMintedBurned(0, 66, nftSeq, 2, 0, 0, __LINE__);
398 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
400 checkMintersOwnerMintedBurned(
401 0, 66, nftSeq, ((65 - seq) != 0u) ? 1 : 0, 0, 0, __LINE__);
406 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
408 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
411 env(token::burn(minter, token::getID(env, alice, 2009, 3)), Ter(
tecNO_ENTRY));
413 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
601 testcase(
"Invalid NFT offer create");
605 Env env{*
this, features};
609 IOU
const gwAUD(gw[
"AUD"]);
614 env.fund(XRP(250), alice, buyer, gw);
616 BEAST_EXPECT(ownerCount(env, alice) == 0);
618 uint256 const nftAlice0ID = token::getNextID(env, alice, 0, tfTransferable, 10);
619 env(token::mint(alice, 0u), Txflags(tfTransferable), token::XferFee(10));
621 BEAST_EXPECT(ownerCount(env, alice) == 1);
623 uint256 const nftXrpOnlyID = token::getNextID(env, alice, 0, tfOnlyXRP | tfTransferable);
624 env(token::mint(alice, 0), Txflags(tfOnlyXRP | tfTransferable));
626 BEAST_EXPECT(ownerCount(env, alice) == 1);
628 uint256 const nftNoXferID = token::getNextID(env, alice, 0);
629 env(token::mint(alice, 0));
631 BEAST_EXPECT(ownerCount(env, alice) == 1);
642 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
646 BEAST_EXPECT(ownerCount(env, buyer) == 0);
649 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
653 BEAST_EXPECT(ownerCount(env, buyer) == 0);
656 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
660 BEAST_EXPECT(ownerCount(env, buyer) == 0);
663 env(token::createOffer(buyer, nftXrpOnlyID, buyer[
"USD"](1)), Ter(
temBAD_AMOUNT));
664 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](0)), Ter(
temBAD_AMOUNT));
665 env(token::createOffer(buyer, nftXrpOnlyID, drops(0)), Ter(
temBAD_AMOUNT));
667 BEAST_EXPECT(ownerCount(env, buyer) == 0);
670 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](1)),
671 token::Expiration(0),
674 BEAST_EXPECT(ownerCount(env, buyer) == 0);
678 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)), Ter(
temMALFORMED));
680 BEAST_EXPECT(ownerCount(env, buyer) == 0);
683 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
685 Txflags(tfSellNFToken),
688 BEAST_EXPECT(ownerCount(env, alice) == 1);
691 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
695 BEAST_EXPECT(ownerCount(env, alice) == 1);
698 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
699 token::Destination(alice),
700 Txflags(tfSellNFToken),
703 BEAST_EXPECT(ownerCount(env, alice) == 1);
706 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
707 token::Destination(
Account(
"demon")),
708 Txflags(tfSellNFToken),
711 BEAST_EXPECT(ownerCount(env, alice) == 1);
717 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
722 BEAST_EXPECT(ownerCount(env, buyer) == 0);
725 env(token::createOffer(buyer, token::getID(env, alice, 0, 1), XRP(1000)),
729 BEAST_EXPECT(ownerCount(env, buyer) == 0);
732 env(token::createOffer(alice, token::getID(env, alice, 0, 1), XRP(1000)),
733 Txflags(tfSellNFToken),
736 BEAST_EXPECT(ownerCount(env, buyer) == 0);
739 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
743 BEAST_EXPECT(ownerCount(env, buyer) == 0);
745 env(trust(buyer, gwAUD(1000)));
747 BEAST_EXPECT(ownerCount(env, buyer) == 1);
751 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
755 BEAST_EXPECT(ownerCount(env, buyer) == 1);
758 env(trust(gw, alice[
"AUD"](999), tfSetFreeze));
763 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
767 BEAST_EXPECT(ownerCount(env, buyer) == 1);
770 env(trust(gw, alice[
"AUD"](999), tfClearFreeze));
774 env(token::createOffer(buyer, nftNoXferID, gwAUD(1000)),
778 BEAST_EXPECT(ownerCount(env, buyer) == 1);
781 env(trust(gw, buyer[
"AUD"](999), tfSetFreeze));
784 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
788 BEAST_EXPECT(ownerCount(env, buyer) == 1);
792 env(trust(gw, buyer[
"AUD"](999), tfClearFreeze));
793 env(trust(buyer, gwAUD(1000)));
796 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
800 BEAST_EXPECT(ownerCount(env, buyer) == 1);
806 env(pay(gw, buyer, gwAUD(999)));
811 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
815 BEAST_EXPECT(ownerCount(env, buyer) == 1);
818 auto const baseFee = env.current()->fees().base;
819 env(pay(env.master, buyer, XRP(50) + drops(baseFee * 12 - 1)));
822 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
826 BEAST_EXPECT(ownerCount(env, buyer) == 1);
829 env(pay(env.master, buyer, drops(baseFee + 1)));
834 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
838 BEAST_EXPECT(ownerCount(env, buyer) == 2);
977 testcase(
"Invalid NFT offer accept");
981 Env env{*
this, features};
985 IOU
const gwAUD(gw[
"AUD"]);
987 env.fund(XRP(1000), alice, buyer, gw);
989 BEAST_EXPECT(ownerCount(env, alice) == 0);
990 BEAST_EXPECT(ownerCount(env, buyer) == 0);
992 uint256 const nftAlice0ID = token::getNextID(env, alice, 0, tfTransferable);
993 env(token::mint(alice, 0u), Txflags(tfTransferable));
995 uint8_t aliceCount = 1;
996 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
998 uint256 const nftXrpOnlyID = token::getNextID(env, alice, 0, tfOnlyXRP | tfTransferable);
999 env(token::mint(alice, 0), Txflags(tfOnlyXRP | tfTransferable));
1001 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1003 uint256 const nftNoXferID = token::getNextID(env, alice, 0);
1004 env(token::mint(alice, 0));
1006 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1010 env(token::createOffer(alice, nftAlice0ID, XRP(10)), Txflags(tfSellNFToken));
1013 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1016 env(token::createOffer(alice, nftAlice0ID, gwAUD(30)), Txflags(tfSellNFToken));
1019 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1022 env(token::createOffer(alice, nftXrpOnlyID, XRP(20)), Txflags(tfSellNFToken));
1025 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1028 env(token::createOffer(alice, nftNoXferID, XRP(30)), Txflags(tfSellNFToken));
1031 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1035 env(token::createOffer(alice, nftNoXferID, XRP(40)),
1036 Txflags(tfSellNFToken),
1040 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1044 env(token::createOffer(buyer, nftAlice0ID, XRP(40)),
1045 token::Owner(alice),
1048 uint8_t buyerCount = 1;
1049 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1055 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1059 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1062 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1063 Txflags(0x00008000),
1066 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1070 json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1074 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1079 json::Value jv = token::acceptBuyOffer(buyer, noXferOfferIndex);
1083 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1088 json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1092 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1096 env(token::brokerOffers(buyer, noXferOfferIndex, xrpOnlyOfferIndex),
1097 token::BrokerFee(gwAUD(0)),
1100 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1108 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1114 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1118 env(token::acceptBuyOffer(alice, buyerExpOfferIndex), Ter(
tecEXPIRED));
1120 if (features[fixCleanup3_1_3])
1125 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1130 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1135 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1139 env(token::acceptSellOffer(buyer, aliceExpOfferIndex), Ter(
tecEXPIRED));
1144 if (features[fixCleanup3_1_3])
1149 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1150 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1157 env(trust(alice, gwAUD(1000)));
1158 env(trust(buyer, gwAUD(1000)));
1160 env(pay(gw, buyer, gwAUD(30)));
1164 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1165 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1167 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1168 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1175 env(token::createOffer(buyer, nftAlice0ID, gwAUD(29)), token::Owner(alice));
1178 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1181 env(token::brokerOffers(gw, buyerOfferIndex, xrpOnlyOfferIndex),
1184 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1187 env(token::brokerOffers(gw, buyerOfferIndex, plainOfferIndex),
1190 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1194 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1197 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1200 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1203 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1208 env(token::createOffer(buyer, nftAlice0ID, gwAUD(31)), token::Owner(alice));
1211 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1215 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1216 token::BrokerFee(XRP(40)),
1219 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1222 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1223 token::BrokerFee(gwAUD(31)),
1226 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1230 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1231 token::BrokerFee(gwAUD(1.5)),
1234 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1237 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1240 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1247 env(token::createOffer(buyer, nftAlice0ID, gwAUD(30)), token::Owner(alice));
1250 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1255 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1258 env(token::acceptBuyOffer(buyer, buyerOfferIndex),
1261 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1264 env(pay(buyer, gw, gwAUD(30)));
1266 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1269 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1274 env(token::createOffer(alice, nftAlice0ID, XRP(0)), Txflags(tfSellNFToken));
1276 env(token::acceptSellOffer(gw, offerIndex));
1278 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1280 env(pay(gw, buyer, gwAUD(30)));
1286 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1289 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1292 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1299 env(token::createOffer(buyer, nftXrpOnlyID, XRP(30)), token::Owner(alice));
1302 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1305 env(token::acceptSellOffer(alice, buyerOfferIndex),
1308 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1311 env(token::acceptSellOffer(alice, plainOfferIndex),
1314 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1318 env(token::acceptSellOffer(buyer, plainOfferIndex), Ter(
tecNO_PERMISSION));
1320 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1327 env(token::createOffer(gw, nftAlice0ID, XRP(0)), Txflags(tfSellNFToken));
1329 env(token::acceptSellOffer(alice, offerIndex));
1331 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1333 env(pay(buyer, gw, gwAUD(30)));
1335 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1338 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1544 testcase(
"Mint flagCreateTrustLines");
1552 IOU
const gwAUD(gw[
"AUD"]);
1553 IOU
const gwCAD(gw[
"CAD"]);
1554 IOU
const gwEUR(gw[
"EUR"]);
1559 for (
auto const& tweakedFeatures :
1560 {features - fixRemoveNFTokenAutoTrustLine, features | fixRemoveNFTokenAutoTrustLine})
1562 Env env{*
this, tweakedFeatures};
1563 env.fund(XRP(1000), alice, becky, cheri, gw);
1567 env(trust(becky, gwAUD(1000)));
1568 env(trust(cheri, gwAUD(1000)));
1569 env(trust(becky, gwCAD(1000)));
1570 env(trust(cheri, gwCAD(1000)));
1571 env(trust(becky, gwEUR(1000)));
1572 env(trust(cheri, gwEUR(1000)));
1574 env(pay(gw, becky, gwAUD(500)));
1575 env(pay(gw, becky, gwCAD(500)));
1576 env(pay(gw, becky, gwEUR(500)));
1577 env(pay(gw, cheri, gwAUD(500)));
1578 env(pay(gw, cheri, gwCAD(500)));
1585 uint256 const nftNoAutoTrustID{
1586 token::getNextID(env, alice, 0u, tfTransferable, xferFee)};
1587 env(token::mint(alice, 0u), token::XferFee(xferFee), Txflags(tfTransferable));
1592 env(token::createOffer(becky, nftNoAutoTrustID, drops(1)), token::Owner(alice));
1594 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1600 env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)),
1601 Txflags(tfSellNFToken),
1602 Ter(createOfferTER));
1607 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
1608 token::Owner(becky),
1609 Ter(createOfferTER));
1613 env(token::cancelOffer(becky, {beckyOfferIndex}));
1614 env(token::cancelOffer(cheri, {cheriOfferIndex}));
1623 token::getNextID(env, alice, 0u, tfTransferable |
tfTrustLine, transferFee)};
1628 TER const mintTER = tweakedFeatures[fixRemoveNFTokenAutoTrustLine]
1632 env(token::mint(alice, 0u),
1633 token::XferFee(transferFee),
1640 if (tweakedFeatures[fixRemoveNFTokenAutoTrustLine])
1645 env(token::createOffer(becky, nftAutoTrustID, drops(1)), token::Owner(alice));
1647 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1652 env(token::createOffer(becky, nftAutoTrustID, gwAUD(100)), Txflags(tfSellNFToken));
1654 env(token::acceptSellOffer(cheri, beckySellOfferIndex));
1658 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1661 uint256 const beckyBuyBackOfferIndex =
1663 env(token::createOffer(becky, nftAutoTrustID, gwCAD(50)), token::Owner(cheri));
1665 env(token::acceptBuyOffer(cheri, beckyBuyBackOfferIndex));
1669 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1670 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(5));
1676 uint256 const nftNoAutoTrustID{
1677 token::getNextID(env, alice, 0u, tfTransferable, transferFee)};
1678 env(token::mint(alice, 0u), token::XferFee(transferFee), Txflags(tfTransferable));
1683 env(token::createOffer(alice, nftNoAutoTrustID, gwAUD(200)),
1684 Txflags(tfSellNFToken));
1686 env(token::acceptSellOffer(cheri, aliceSellOfferIndex));
1692 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(210));
1695 env(token::createOffer(cheri, nftNoAutoTrustID, gwEUR(50)),
1696 Txflags(tfSellNFToken),
1700 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
1701 Txflags(tfSellNFToken));
1703 env(token::acceptSellOffer(becky, cheriSellOfferIndex));
1709 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(10));
1722 Env env{*
this, features};
1726 Account const minter{
"minter"};
1728 env.fund(XRP(1000), alice, becky, minter);
1733 BEAST_EXPECT(ownerCount(env, alice) == 0);
1734 uint256 const nftAliceNoTransferID{token::getNextID(env, alice, 0u)};
1735 env(token::mint(alice, 0u), token::XferFee(0));
1737 BEAST_EXPECT(ownerCount(env, alice) == 1);
1740 BEAST_EXPECT(ownerCount(env, becky) == 0);
1741 env(token::createOffer(becky, nftAliceNoTransferID, XRP(20)),
1742 token::Owner(alice),
1747 env(token::createOffer(alice, nftAliceNoTransferID, XRP(20)), Txflags(tfSellNFToken));
1749 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1751 BEAST_EXPECT(ownerCount(env, alice) == 0);
1752 BEAST_EXPECT(ownerCount(env, becky) == 1);
1755 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1756 Txflags(tfSellNFToken),
1759 BEAST_EXPECT(ownerCount(env, alice) == 0);
1760 BEAST_EXPECT(ownerCount(env, becky) == 1);
1764 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1765 Txflags(tfSellNFToken),
1766 token::Destination(alice),
1769 BEAST_EXPECT(ownerCount(env, alice) == 0);
1770 BEAST_EXPECT(ownerCount(env, becky) == 1);
1775 env(token::createOffer(alice, nftAliceNoTransferID, XRP(22)), token::Owner(becky));
1777 env(token::acceptBuyOffer(becky, aliceBuyOfferIndex));
1779 BEAST_EXPECT(ownerCount(env, alice) == 1);
1780 BEAST_EXPECT(ownerCount(env, becky) == 0);
1783 env(token::burn(alice, nftAliceNoTransferID));
1785 BEAST_EXPECT(ownerCount(env, alice) == 0);
1786 BEAST_EXPECT(ownerCount(env, becky) == 0);
1790 env(token::setMinter(alice, minter));
1793 BEAST_EXPECT(ownerCount(env, minter) == 0);
1794 uint256 const nftMinterNoTransferID{token::getNextID(env, alice, 0u)};
1795 env(token::mint(minter), token::Issuer(alice));
1797 BEAST_EXPECT(ownerCount(env, minter) == 1);
1800 BEAST_EXPECT(ownerCount(env, becky) == 0);
1801 env(token::createOffer(becky, nftMinterNoTransferID, XRP(20)),
1802 token::Owner(minter),
1805 BEAST_EXPECT(ownerCount(env, becky) == 0);
1808 env(token::clearMinter(alice));
1812 BEAST_EXPECT(ownerCount(env, minter) == 1);
1813 env(token::createOffer(minter, nftMinterNoTransferID, XRP(21)),
1814 Txflags(tfSellNFToken),
1817 BEAST_EXPECT(ownerCount(env, minter) == 1);
1821 for (
int i = 0; i < 10; ++i)
1824 env(token::setMinter(alice, minter));
1826 BEAST_EXPECT(ownerCount(env, minter) == 1);
1829 BEAST_EXPECT(ownerCount(env, minter) == 1);
1831 env(token::createOffer(minter, nftMinterNoTransferID, XRP(22)), Txflags(tfSellNFToken));
1833 BEAST_EXPECT(ownerCount(env, minter) == 2);
1837 env(token::clearMinter(alice));
1842 BEAST_EXPECT(ownerCount(env, becky) == 0);
1843 env(token::acceptSellOffer(becky, minterSellOfferIndex));
1845 BEAST_EXPECT(ownerCount(env, becky) == 1);
1846 BEAST_EXPECT(ownerCount(env, minter) == 0);
1849 env(token::createOffer(becky, nftMinterNoTransferID, XRP(23)),
1850 Txflags(tfSellNFToken),
1856 BEAST_EXPECT(ownerCount(env, minter) == 0);
1857 env(token::createOffer(minter, nftMinterNoTransferID, XRP(24)),
1858 token::Owner(becky),
1861 BEAST_EXPECT(ownerCount(env, minter) == 0);
1864 BEAST_EXPECT(ownerCount(env, alice) == 0);
1866 env(token::createOffer(alice, nftMinterNoTransferID, XRP(25)), token::Owner(becky));
1868 BEAST_EXPECT(ownerCount(env, alice) == 1);
1872 for (
int i = 0; i < 10; ++i)
1875 env(token::setMinter(alice, minter));
1879 BEAST_EXPECT(ownerCount(env, minter) == 0);
1881 env(token::createOffer(minter, nftMinterNoTransferID, XRP(26)), token::Owner(becky));
1883 BEAST_EXPECT(ownerCount(env, minter) == 1);
1887 env(token::clearMinter(alice));
1891 BEAST_EXPECT(ownerCount(env, minter) == 1);
1892 BEAST_EXPECT(ownerCount(env, becky) == 1);
1893 env(token::acceptBuyOffer(becky, minterBuyOfferIndex));
1895 BEAST_EXPECT(ownerCount(env, minter) == 1);
1896 BEAST_EXPECT(ownerCount(env, becky) == 0);
1897 BEAST_EXPECT(ownerCount(env, alice) == 1);
1901 env(token::burn(minter, nftMinterNoTransferID), Ter(
tesSUCCESS));
1903 env(token::cancelOffer(alice, {aliceBuyOfferIndex}));
1905 BEAST_EXPECT(ownerCount(env, alice) == 0);
1906 BEAST_EXPECT(ownerCount(env, becky) == 0);
1907 BEAST_EXPECT(ownerCount(env, minter) == 0);
1912 BEAST_EXPECT(ownerCount(env, alice) == 0);
1913 uint256 const nftAliceID{token::getNextID(env, alice, 0u, tfTransferable)};
1914 env(token::mint(alice, 0u), Txflags(tfTransferable));
1916 BEAST_EXPECT(ownerCount(env, alice) == 1);
1920 env(token::createOffer(alice, nftAliceID, XRP(20)), Txflags(tfSellNFToken));
1922 BEAST_EXPECT(ownerCount(env, alice) == 2);
1925 env(token::createOffer(becky, nftAliceID, XRP(21)), token::Owner(alice));
1927 BEAST_EXPECT(ownerCount(env, alice) == 2);
1930 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1932 BEAST_EXPECT(ownerCount(env, alice) == 0);
1933 BEAST_EXPECT(ownerCount(env, becky) == 2);
1937 env(token::createOffer(becky, nftAliceID, XRP(22)), Txflags(tfSellNFToken));
1939 BEAST_EXPECT(ownerCount(env, alice) == 0);
1940 BEAST_EXPECT(ownerCount(env, becky) == 3);
1944 env(token::acceptSellOffer(minter, beckySellOfferIndex));
1946 BEAST_EXPECT(ownerCount(env, alice) == 0);
1947 BEAST_EXPECT(ownerCount(env, becky) == 1);
1948 BEAST_EXPECT(ownerCount(env, minter) == 1);
1952 env(token::createOffer(minter, nftAliceID, XRP(23)), Txflags(tfSellNFToken));
1954 BEAST_EXPECT(ownerCount(env, alice) == 0);
1955 BEAST_EXPECT(ownerCount(env, becky) == 1);
1956 BEAST_EXPECT(ownerCount(env, minter) == 2);
1959 env(token::acceptSellOffer(alice, minterSellOfferIndex));
1961 BEAST_EXPECT(ownerCount(env, alice) == 1);
1962 BEAST_EXPECT(ownerCount(env, becky) == 1);
1963 BEAST_EXPECT(ownerCount(env, minter) == 0);
1967 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1969 BEAST_EXPECT(ownerCount(env, alice) == 0);
1970 BEAST_EXPECT(ownerCount(env, becky) == 1);
1971 BEAST_EXPECT(ownerCount(env, minter) == 0);
1975 env(token::burn(becky, nftAliceID));
1977 BEAST_EXPECT(ownerCount(env, alice) == 0);
1978 BEAST_EXPECT(ownerCount(env, becky) == 0);
1979 BEAST_EXPECT(ownerCount(env, minter) == 0);
1991 Env env{*
this, features};
1992 auto const baseFee = env.current()->fees().base;
1997 Account const minter{
"minter"};
1999 IOU
const gwXAU(gw[
"XAU"]);
2001 env.fund(XRP(1000), alice, becky, carol, minter, gw);
2004 env(trust(alice, gwXAU(2000)));
2005 env(trust(becky, gwXAU(2000)));
2006 env(trust(carol, gwXAU(2000)));
2007 env(trust(minter, gwXAU(2000)));
2009 env(pay(gw, alice, gwXAU(1000)));
2010 env(pay(gw, becky, gwXAU(1000)));
2011 env(pay(gw, carol, gwXAU(1000)));
2012 env(pay(gw, minter, gwXAU(1000)));
2017 env(token::setMinter(alice, minter));
2023 BEAST_EXPECT(ownerCount(env, alice) == 1);
2024 BEAST_EXPECT(ownerCount(env, becky) == 1);
2025 BEAST_EXPECT(ownerCount(env, carol) == 1);
2026 BEAST_EXPECT(ownerCount(env, minter) == 1);
2028 uint256 const nftID = token::getNextID(env, alice, 0u, tfTransferable);
2029 env(token::mint(alice), Txflags(tfTransferable));
2034 env(token::createOffer(becky, nftID, gwXAU(10)), token::Owner(alice));
2036 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2037 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2039 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2041 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2042 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2046 env(token::createOffer(becky, nftID, gwXAU(10)), Txflags(tfSellNFToken));
2048 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2050 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2051 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2052 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2056 env(token::createOffer(minter, nftID, gwXAU(10)), token::Owner(carol));
2058 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2060 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2061 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2062 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2063 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2068 env(token::createOffer(minter, nftID, gwXAU(10)), Txflags(tfSellNFToken));
2070 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2072 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2073 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2074 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2075 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2078 env(token::burn(alice, nftID));
2080 BEAST_EXPECT(ownerCount(env, alice) == 1);
2081 BEAST_EXPECT(ownerCount(env, becky) == 1);
2082 BEAST_EXPECT(ownerCount(env, carol) == 1);
2083 BEAST_EXPECT(ownerCount(env, minter) == 1);
2089 uint256 const nftID = token::getNextID(env, alice, 0u, tfTransferable, 1);
2090 env(token::mint(alice), Txflags(tfTransferable), token::XferFee(1));
2095 env(token::createOffer(becky, nftID, gwXAU(10)), token::Owner(alice));
2097 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2098 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2100 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2102 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2103 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2107 env(token::createOffer(becky, nftID, gwXAU(10)), Txflags(tfSellNFToken));
2109 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2112 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0001));
2113 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2114 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2118 env(token::createOffer(minter, nftID, gwXAU(10)), token::Owner(carol));
2120 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2123 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0002));
2124 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2125 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2126 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2131 env(token::createOffer(minter, nftID, gwXAU(10)), Txflags(tfSellNFToken));
2133 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2135 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000.0002));
2136 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2137 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2138 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2142 env(pay(alice, becky, gwXAU(0.0001)));
2143 env(pay(alice, carol, gwXAU(0.0001)));
2146 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2147 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2148 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2149 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2152 env(token::burn(alice, nftID));
2154 BEAST_EXPECT(ownerCount(env, alice) == 1);
2155 BEAST_EXPECT(ownerCount(env, becky) == 1);
2156 BEAST_EXPECT(ownerCount(env, carol) == 1);
2157 BEAST_EXPECT(ownerCount(env, minter) == 1);
2163 env(token::mint(alice),
2164 Txflags(tfTransferable),
2171 env(token::mint(alice), Txflags(tfTransferable), token::XferFee(
kMaxTransferFee));
2176 env(token::createOffer(becky, nftID, gwXAU(10)), token::Owner(alice));
2178 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2179 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2181 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2183 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2184 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2188 env(token::createOffer(becky, nftID, gwXAU(100)), Txflags(tfSellNFToken));
2190 env(token::acceptSellOffer(minter, beckySellOfferIndex));
2193 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1060));
2194 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2195 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
2199 env(token::createOffer(carol, nftID, gwXAU(10)), token::Owner(minter));
2201 env(token::acceptBuyOffer(minter, carolBuyOfferIndex));
2204 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1065));
2205 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2206 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2207 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2212 env(token::createOffer(carol, nftID, gwXAU(10)), Txflags(tfSellNFToken));
2214 env(token::acceptSellOffer(alice, carolSellOfferIndex));
2217 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1055));
2218 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2219 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2220 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2223 env(pay(alice, minter, gwXAU(55)));
2224 env(pay(becky, minter, gwXAU(40)));
2226 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2227 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2228 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2229 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2232 env(token::burn(alice, nftID));
2234 BEAST_EXPECT(ownerCount(env, alice) == 1);
2235 BEAST_EXPECT(ownerCount(env, becky) == 1);
2236 BEAST_EXPECT(ownerCount(env, carol) == 1);
2237 BEAST_EXPECT(ownerCount(env, minter) == 1);
2244 uint256 const nftID = token::getNextID(env, alice, 0u, tfTransferable, 1);
2245 env(token::mint(alice), Txflags(tfTransferable), token::XferFee(1));
2250 STAmount aliceBalance = env.balance(alice);
2251 STAmount minterBalance = env.balance(minter);
2253 env(token::createOffer(minter, nftID, XRP(1)), token::Owner(alice));
2255 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2257 aliceBalance += XRP(1) - baseFee;
2258 minterBalance -= XRP(1) + baseFee;
2259 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2260 BEAST_EXPECT(env.balance(minter) == minterBalance);
2264 auto pmt = drops(50000);
2265 STAmount carolBalance = env.balance(carol);
2267 env(token::createOffer(minter, nftID, pmt), Txflags(tfSellNFToken));
2269 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2271 minterBalance += pmt - baseFee;
2272 carolBalance -= pmt + baseFee;
2273 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2274 BEAST_EXPECT(env.balance(minter) == minterBalance);
2275 BEAST_EXPECT(env.balance(carol) == carolBalance);
2279 STAmount beckyBalance = env.balance(becky);
2282 env(token::createOffer(becky, nftID, pmt), token::Owner(carol));
2284 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2286 carolBalance += pmt - drops(1) - baseFee;
2287 beckyBalance -= pmt + baseFee;
2288 aliceBalance += drops(1);
2290 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2291 BEAST_EXPECT(env.balance(minter) == minterBalance);
2292 BEAST_EXPECT(env.balance(carol) == carolBalance);
2293 BEAST_EXPECT(env.balance(becky) == beckyBalance);
2300 uint256 const nftID = token::getNextID(env, alice, 0u, tfTransferable, 1);
2301 env(token::mint(alice), Txflags(tfTransferable), token::XferFee(1));
2307 env(pay(alice, gw, env.balance(alice, gwXAU)));
2308 env(pay(minter, gw, env.balance(minter, gwXAU)));
2309 env(pay(becky, gw, env.balance(becky, gwXAU)));
2313 env(pay(gw, alice, startXAUBalance));
2314 env(pay(gw, minter, startXAUBalance));
2315 env(pay(gw, becky, startXAUBalance));
2323 STAmount aliceBalance = env.balance(alice, gwXAU);
2324 STAmount minterBalance = env.balance(minter, gwXAU);
2326 env(token::createOffer(minter, nftID, tinyXAU), token::Owner(alice));
2328 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2330 aliceBalance += tinyXAU;
2331 minterBalance -= tinyXAU;
2332 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2333 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2336 STAmount carolBalance = env.balance(carol, gwXAU);
2338 env(token::createOffer(minter, nftID, tinyXAU), Txflags(tfSellNFToken));
2340 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2343 minterBalance += tinyXAU;
2344 carolBalance -= tinyXAU;
2346 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2347 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2348 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2354 STAmount beckyBalance = env.balance(becky, gwXAU);
2356 env(token::createOffer(becky, nftID, cheapNFT), token::Owner(carol));
2358 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2361 aliceBalance += tinyXAU;
2362 beckyBalance -= cheapNFT;
2363 carolBalance += cheapNFT - tinyXAU;
2364 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2365 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2366 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2367 BEAST_EXPECT(env.balance(becky, gwXAU) == beckyBalance);
2560 testcase(
"Create offer destination");
2564 Env env{*
this, features};
2566 Account const issuer{
"issuer"};
2567 Account const minter{
"minter"};
2569 Account const broker{
"broker"};
2571 env.fund(XRP(1000), issuer, minter, buyer, broker);
2575 env(token::setMinter(issuer, minter));
2578 uint256 const nftokenID = token::getNextID(env, issuer, 0, tfTransferable);
2579 env(token::mint(minter, 0), token::Issuer(issuer), Txflags(tfTransferable));
2586 env(token::createOffer(minter, nftokenID, drops(1)),
2587 token::Destination(issuer),
2588 Txflags(tfSellNFToken));
2591 env(token::createOffer(minter, nftokenID, drops(1)),
2592 token::Destination(buyer),
2593 Txflags(tfSellNFToken));
2596 env(token::createOffer(issuer, nftokenID, drops(1)),
2597 token::Owner(minter),
2598 token::Destination(minter));
2601 env(token::createOffer(issuer, nftokenID, drops(1)),
2602 token::Owner(minter),
2603 token::Destination(buyer));
2606 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2607 BEAST_EXPECT(ownerCount(env, minter) == 3);
2608 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2617 env(token::cancelOffer(issuer, {offerMinterToBuyer}), Ter(
tecNO_PERMISSION));
2618 env(token::cancelOffer(buyer, {offerMinterToIssuer}), Ter(
tecNO_PERMISSION));
2619 env(token::cancelOffer(buyer, {offerIssuerToMinter}), Ter(
tecNO_PERMISSION));
2620 env(token::cancelOffer(minter, {offerIssuerToBuyer}), Ter(
tecNO_PERMISSION));
2622 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2623 BEAST_EXPECT(ownerCount(env, minter) == 3);
2624 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2628 env(token::cancelOffer(buyer, {offerMinterToBuyer}));
2629 env(token::cancelOffer(minter, {offerMinterToIssuer}));
2630 env(token::cancelOffer(buyer, {offerIssuerToBuyer}));
2631 env(token::cancelOffer(issuer, {offerIssuerToMinter}));
2633 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2634 BEAST_EXPECT(ownerCount(env, minter) == 1);
2635 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2641 uint256 const offerMinterSellsToBuyer =
2643 env(token::createOffer(minter, nftokenID, drops(1)),
2644 token::Destination(buyer),
2645 Txflags(tfSellNFToken));
2647 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2648 BEAST_EXPECT(ownerCount(env, minter) == 2);
2649 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2653 env(token::acceptSellOffer(issuer, offerMinterSellsToBuyer), Ter(
tecNO_PERMISSION));
2655 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2656 BEAST_EXPECT(ownerCount(env, minter) == 2);
2657 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2660 env(token::acceptSellOffer(buyer, offerMinterSellsToBuyer));
2662 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2663 BEAST_EXPECT(ownerCount(env, minter) == 0);
2664 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2670 uint256 const offerMinterBuysFromBuyer =
2672 env(token::createOffer(minter, nftokenID, drops(1)),
2673 token::Owner(buyer),
2674 token::Destination(buyer));
2676 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2677 BEAST_EXPECT(ownerCount(env, minter) == 1);
2678 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2682 env(token::acceptBuyOffer(issuer, offerMinterBuysFromBuyer), Ter(
tecNO_PERMISSION));
2684 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2685 BEAST_EXPECT(ownerCount(env, minter) == 1);
2686 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2689 env(token::acceptBuyOffer(buyer, offerMinterBuysFromBuyer));
2691 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2692 BEAST_EXPECT(ownerCount(env, minter) == 1);
2693 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2698 uint256 const offerBuyerBuysFromMinter =
2700 env(token::createOffer(buyer, nftokenID, drops(1)),
2701 token::Owner(minter),
2702 token::Destination(broker));
2704 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2705 BEAST_EXPECT(ownerCount(env, minter) == 1);
2706 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2708 env(token::acceptBuyOffer(minter, offerBuyerBuysFromMinter), Ter(
tecNO_PERMISSION));
2712 env(token::cancelOffer(buyer, {offerBuyerBuysFromMinter}));
2714 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2715 BEAST_EXPECT(ownerCount(env, minter) == 1);
2716 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2723 env(token::createOffer(minter, nftokenID, drops(1)),
2724 token::Destination(broker),
2725 Txflags(tfSellNFToken));
2728 env(token::createOffer(buyer, nftokenID, drops(1)), token::Owner(minter));
2731 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2732 BEAST_EXPECT(ownerCount(env, minter) == 2);
2733 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2738 env(token::brokerOffers(issuer, offerBuyerToMinter, offerMinterToBroker),
2741 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2742 BEAST_EXPECT(ownerCount(env, minter) == 2);
2743 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2748 env(token::brokerOffers(broker, offerBuyerToMinter, offerMinterToBroker));
2750 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2751 BEAST_EXPECT(ownerCount(env, minter) == 0);
2752 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2760 env(token::createOffer(buyer, nftokenID, drops(1)),
2761 token::Destination(minter),
2762 Txflags(tfSellNFToken));
2765 env(token::createOffer(minter, nftokenID, drops(1)), token::Owner(buyer));
2768 env(token::createOffer(issuer, nftokenID, drops(1)), token::Owner(buyer));
2771 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2772 BEAST_EXPECT(ownerCount(env, minter) == 1);
2773 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2778 env(token::brokerOffers(broker, offerIssuerToBuyer, offerBuyerToMinter),
2782 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2783 BEAST_EXPECT(ownerCount(env, minter) == 1);
2784 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2786 env(token::brokerOffers(broker, offerMinterToBuyer, offerBuyerToMinter),
2791 env(token::acceptBuyOffer(buyer, offerMinterToBuyer));
2795 env(token::cancelOffer(buyer, {offerBuyerToMinter}));
2798 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2799 BEAST_EXPECT(ownerCount(env, minter) == 1);
2800 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2803 env(token::cancelOffer(issuer, {offerIssuerToBuyer}));
2805 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2806 BEAST_EXPECT(ownerCount(env, minter) == 1);
2807 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2816 env(token::createOffer(minter, nftokenID, drops(1)),
2817 token::Destination(broker),
2818 Txflags(tfSellNFToken));
2821 env(token::createOffer(buyer, nftokenID, drops(1)),
2822 token::Owner(minter),
2823 token::Destination(broker));
2828 env(token::brokerOffers(issuer, offerBuyerToBroker, offerMinterToBroker),
2831 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2832 BEAST_EXPECT(ownerCount(env, minter) == 2);
2833 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2837 env(token::brokerOffers(broker, offerBuyerToBroker, offerMinterToBroker));
2839 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2840 BEAST_EXPECT(ownerCount(env, minter) == 0);
2841 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2978 testcase(
"Create offer expiration");
2982 Env env{*
this, features};
2984 Account const issuer{
"issuer"};
2985 Account const minter{
"minter"};
2988 env.fund(XRP(1000), issuer, minter, buyer);
2992 env(token::setMinter(issuer, minter));
2995 uint256 const nftokenID0 = token::getNextID(env, issuer, 0, tfTransferable);
2996 env(token::mint(minter, 0), token::Issuer(issuer), Txflags(tfTransferable));
2999 uint256 const nftokenID1 = token::getNextID(env, issuer, 0, tfTransferable);
3000 env(token::mint(minter, 0), token::Issuer(issuer), Txflags(tfTransferable));
3002 uint8_t issuerCount = 0, minterCount = 0, buyerCount = 0;
3010 env(token::createOffer(minter, nftokenID0, drops(1)),
3011 token::Destination(issuer),
3012 token::Expiration(expiration),
3013 Txflags(tfSellNFToken));
3016 env(token::createOffer(minter, nftokenID0, drops(1)),
3017 token::Expiration(expiration),
3018 Txflags(tfSellNFToken));
3021 env(token::createOffer(issuer, nftokenID0, drops(1)),
3022 token::Owner(minter),
3023 token::Expiration(expiration));
3026 env(token::createOffer(buyer, nftokenID0, drops(1)),
3027 token::Owner(minter),
3028 token::Expiration(expiration));
3033 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3034 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3035 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3043 env(token::cancelOffer(issuer, {offerMinterToAnyone}), Ter(
tecNO_PERMISSION));
3044 env(token::cancelOffer(buyer, {offerIssuerToMinter}), Ter(
tecNO_PERMISSION));
3046 BEAST_EXPECT(
lastClose(env) < expiration);
3047 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3048 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3049 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3052 env(token::cancelOffer(minter, {offerMinterToAnyone}));
3057 env(token::cancelOffer(issuer, {offerMinterToIssuer}));
3064 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3065 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3066 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3069 env(token::cancelOffer(issuer, {offerBuyerToMinter}));
3071 env(token::cancelOffer(buyer, {offerIssuerToMinter}));
3074 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3075 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3076 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3086 env(token::createOffer(minter, nftokenID0, drops(1)),
3087 token::Expiration(expiration),
3088 Txflags(tfSellNFToken));
3092 env(token::createOffer(minter, nftokenID1, drops(1)),
3093 token::Expiration(expiration),
3094 Txflags(tfSellNFToken));
3097 BEAST_EXPECT(
lastClose(env) < expiration);
3098 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3099 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3100 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3103 env(token::acceptSellOffer(buyer, offer0));
3111 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3112 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3113 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3116 env(token::acceptSellOffer(buyer, offer1), Ter(
tecEXPIRED));
3121 if (features[fixCleanup3_1_3])
3131 env(token::acceptSellOffer(issuer, offer1), Ter(
tecEXPIRED));
3136 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3137 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3138 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3140 if (!features[fixCleanup3_1_3])
3144 env(token::cancelOffer(issuer, {offer1}));
3150 BEAST_EXPECT(ownerCount(env, issuer) == 0 && issuerCount == 0);
3151 BEAST_EXPECT(ownerCount(env, minter) == 1 && minterCount == 1);
3152 BEAST_EXPECT(ownerCount(env, buyer) == 1 && buyerCount == 1);
3157 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3158 Txflags(tfSellNFToken),
3159 token::Destination(minter));
3161 env(token::acceptSellOffer(minter, offerSellBack));
3164 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3165 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3166 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3176 env(token::createOffer(buyer, nftokenID0, drops(1)),
3177 token::Owner(minter),
3178 token::Expiration(expiration));
3182 env(token::createOffer(buyer, nftokenID1, drops(1)),
3183 token::Owner(minter),
3184 token::Expiration(expiration));
3187 BEAST_EXPECT(
lastClose(env) < expiration);
3188 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3189 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3190 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3193 env(token::acceptBuyOffer(minter, offer0));
3199 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3200 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3201 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3204 env(token::acceptBuyOffer(minter, offer1), Ter(
tecEXPIRED));
3209 if (features[fixCleanup3_1_3])
3219 env(token::acceptBuyOffer(issuer, offer1), Ter(
tecEXPIRED));
3224 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3225 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3226 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3228 if (!features[fixCleanup3_1_3])
3232 env(token::cancelOffer(issuer, {offer1}));
3238 BEAST_EXPECT(ownerCount(env, issuer) == 0 && issuerCount == 0);
3239 BEAST_EXPECT(ownerCount(env, minter) == 1 && minterCount == 1);
3240 BEAST_EXPECT(ownerCount(env, buyer) == 1 && buyerCount == 1);
3245 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3246 Txflags(tfSellNFToken),
3247 token::Destination(minter));
3249 env(token::acceptSellOffer(minter, offerSellBack));
3252 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3253 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3254 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3264 env(token::createOffer(minter, nftokenID0, drops(1)),
3265 token::Expiration(expiration),
3266 Txflags(tfSellNFToken));
3270 env(token::createOffer(minter, nftokenID1, drops(1)),
3271 token::Expiration(expiration),
3272 Txflags(tfSellNFToken));
3276 env(token::createOffer(buyer, nftokenID0, drops(1)), token::Owner(minter));
3280 env(token::createOffer(buyer, nftokenID1, drops(1)), token::Owner(minter));
3284 BEAST_EXPECT(
lastClose(env) < expiration);
3285 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3286 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3287 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3290 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3297 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3298 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3299 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3302 env(token::brokerOffers(issuer, buyOffer1, sellOffer1), Ter(
tecEXPIRED));
3305 if (features[fixCleanup3_1_3])
3311 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3312 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3313 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3315 if (features[fixCleanup3_1_3])
3319 env(token::cancelOffer(buyer, {buyOffer1}));
3325 env(token::cancelOffer(buyer, {buyOffer1, sellOffer1}));
3332 BEAST_EXPECT(ownerCount(env, issuer) == 0 && issuerCount == 0);
3333 BEAST_EXPECT(ownerCount(env, minter) == 1 && minterCount == 1);
3334 BEAST_EXPECT(ownerCount(env, buyer) == 1 && buyerCount == 1);
3339 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3340 Txflags(tfSellNFToken),
3341 token::Destination(minter));
3343 env(token::acceptSellOffer(minter, offerSellBack));
3346 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3347 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3348 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3358 env(token::createOffer(minter, nftokenID0, drops(1)), Txflags(tfSellNFToken));
3361 env(token::createOffer(minter, nftokenID1, drops(1)), Txflags(tfSellNFToken));
3364 env(token::createOffer(buyer, nftokenID0, drops(1)),
3365 token::Expiration(expiration),
3366 token::Owner(minter));
3369 env(token::createOffer(buyer, nftokenID1, drops(1)),
3370 token::Expiration(expiration),
3371 token::Owner(minter));
3374 BEAST_EXPECT(
lastClose(env) < expiration);
3375 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3376 BEAST_EXPECT(ownerCount(env, minter) == 3);
3377 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3380 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3386 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3387 BEAST_EXPECT(ownerCount(env, minter) == 2);
3388 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3390 env(token::brokerOffers(issuer, buyOffer1, sellOffer1), Ter(
tecEXPIRED));
3393 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3394 if (features[fixCleanup3_1_3])
3398 BEAST_EXPECT(ownerCount(env, minter) == 2);
3399 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3402 env(token::cancelOffer(minter, {sellOffer1}));
3407 BEAST_EXPECT(ownerCount(env, minter) == 2);
3408 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3410 env(token::cancelOffer(minter, {buyOffer1, sellOffer1}));
3413 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3414 BEAST_EXPECT(ownerCount(env, minter) == 1);
3415 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3420 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3421 Txflags(tfSellNFToken),
3422 token::Destination(minter));
3424 env(token::acceptSellOffer(minter, offerSellBack));
3426 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3427 BEAST_EXPECT(ownerCount(env, minter) == 1);
3428 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3439 env(token::createOffer(minter, nftokenID0, drops(1)),
3440 token::Expiration(expiration),
3441 Txflags(tfSellNFToken));
3444 env(token::createOffer(minter, nftokenID1, drops(1)),
3445 token::Expiration(expiration),
3446 Txflags(tfSellNFToken));
3449 env(token::createOffer(buyer, nftokenID0, drops(1)),
3450 token::Expiration(expiration),
3451 token::Owner(minter));
3454 env(token::createOffer(buyer, nftokenID1, drops(1)),
3455 token::Expiration(expiration),
3456 token::Owner(minter));
3459 BEAST_EXPECT(
lastClose(env) < expiration);
3460 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3461 BEAST_EXPECT(ownerCount(env, minter) == 3);
3462 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3465 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3471 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3472 BEAST_EXPECT(ownerCount(env, minter) == 2);
3473 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3475 env(token::brokerOffers(issuer, buyOffer1, sellOffer1), Ter(
tecEXPIRED));
3479 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3480 if (!features[fixCleanup3_1_3])
3483 BEAST_EXPECT(ownerCount(env, minter) == 2);
3484 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3486 env(token::cancelOffer(issuer, {buyOffer1, sellOffer1}));
3489 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3490 BEAST_EXPECT(ownerCount(env, minter) == 1);
3491 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3496 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3497 Txflags(tfSellNFToken),
3498 token::Destination(minter));
3500 env(token::acceptSellOffer(minter, offerSellBack));
3502 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3503 BEAST_EXPECT(ownerCount(env, minter) == 1);
3504 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3723 testcase(
"Brokered NFT offer accept");
3728 Env env{*
this, features};
3729 auto const baseFee = env.current()->fees().base;
3737 Account const issuer{
"issuer"};
3738 Account const minter{
"minter"};
3740 Account const broker{
"broker"};
3742 IOU
const gwXAU(gw[
"XAU"]);
3744 env.fund(XRP(1000), issuer, minter, buyer, broker, gw);
3747 env(trust(issuer, gwXAU(2000)));
3748 env(trust(minter, gwXAU(2000)));
3749 env(trust(buyer, gwXAU(2000)));
3750 env(trust(broker, gwXAU(2000)));
3753 env(token::setMinter(issuer, minter));
3757 auto checkOwnerCountIsOne =
3761 for (
Account const& acct : accounts)
3767 ss <<
"Account " << acct.human() <<
" expected ownerCount == 1. Got "
3769 fail(ss.
str(), __FILE__, line);
3775 auto mintNFT = [&env, &issuer, &minter](
std::uint16_t xferFee = 0) {
3776 uint256 const nftID = token::getNextID(env, issuer, 0, tfTransferable, xferFee);
3777 env(token::mint(minter, 0),
3778 token::Issuer(issuer),
3779 token::XferFee(xferFee),
3780 Txflags(tfTransferable));
3791 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3793 uint256 const nftID = mintNFT();
3797 env(token::createOffer(minter, nftID, XRP(0)), Txflags(tfSellNFToken));
3803 env(token::createOffer(buyer, nftID, XRP(1)), token::Owner(minter));
3806 auto const minterBalance = env.balance(minter);
3807 auto const buyerBalance = env.balance(buyer);
3808 auto const brokerBalance = env.balance(broker);
3809 auto const issuerBalance = env.balance(issuer);
3812 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex));
3817 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(1));
3818 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3819 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
3820 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
3823 env(token::burn(buyer, nftID));
3833 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3835 uint256 const nftID = mintNFT();
3839 env(token::createOffer(minter, nftID, XRP(0)), Txflags(tfSellNFToken));
3845 env(token::createOffer(buyer, nftID, XRP(1)), token::Owner(minter));
3849 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
3850 token::BrokerFee(XRP(1.1)),
3854 auto const minterBalance = env.balance(minter);
3855 auto const buyerBalance = env.balance(buyer);
3856 auto const brokerBalance = env.balance(broker);
3857 auto const issuerBalance = env.balance(issuer);
3860 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
3861 token::BrokerFee(XRP(0.5)));
3866 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
3867 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3868 BEAST_EXPECT(env.balance(broker) == brokerBalance + XRP(0.5) - baseFee);
3869 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
3872 env(token::burn(buyer, nftID));
3882 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3888 env(token::createOffer(minter, nftID, XRP(0)), Txflags(tfSellNFToken));
3894 env(token::createOffer(buyer, nftID, XRP(1)), token::Owner(minter));
3897 auto const minterBalance = env.balance(minter);
3898 auto const buyerBalance = env.balance(buyer);
3899 auto const brokerBalance = env.balance(broker);
3900 auto const issuerBalance = env.balance(issuer);
3903 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex));
3908 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
3909 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3910 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
3911 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.5));
3914 env(token::burn(buyer, nftID));
3924 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3930 env(token::createOffer(minter, nftID, XRP(0)), Txflags(tfSellNFToken));
3936 env(token::createOffer(buyer, nftID, XRP(1)), token::Owner(minter));
3939 auto const minterBalance = env.balance(minter);
3940 auto const buyerBalance = env.balance(buyer);
3941 auto const brokerBalance = env.balance(broker);
3942 auto const issuerBalance = env.balance(issuer);
3945 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
3946 token::BrokerFee(XRP(0.75)));
3952 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.125));
3953 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3954 BEAST_EXPECT(env.balance(broker) == brokerBalance + XRP(0.75) - baseFee);
3955 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.125));
3958 env(token::burn(buyer, nftID));
3964 auto setXAUBalance =
3965 [
this, &gw, &gwXAU, &env](
3969 for (
Account const& acct : accounts)
3971 auto const xauAmt = gwXAU(amount);
3972 auto const balance = env.balance(acct, gwXAU);
3973 if (balance < xauAmt)
3975 env(pay(gw, acct, xauAmt - balance));
3978 else if (balance > xauAmt)
3980 env(pay(acct, gw, balance - xauAmt));
3983 if (env.balance(acct, gwXAU) != xauAmt)
3986 ss <<
"Unable to set " << acct.human() <<
" account balance to gwXAU("
3988 this->
fail(ss.
str(), __FILE__, line);
3996 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3997 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
3999 uint256 const nftID = mintNFT();
4003 env(token::createOffer(minter, nftID, gwXAU(1000)), Txflags(tfSellNFToken));
4010 env(token::createOffer(buyer, nftID, gwXAU(1001)), token::Owner(minter));
4014 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4020 env(token::cancelOffer(buyer, {buyOfferIndex}));
4027 env(token::createOffer(buyer, nftID, gwXAU(999)), token::Owner(minter));
4031 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4037 env(token::cancelOffer(buyer, {buyOfferIndex}));
4043 env(token::createOffer(buyer, nftID, gwXAU(1000)), token::Owner(minter));
4047 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4048 token::BrokerFee(gwXAU(0.1)),
4053 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex));
4056 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4057 BEAST_EXPECT(ownerCount(env, minter) == 1);
4058 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4059 BEAST_EXPECT(ownerCount(env, broker) == 1);
4060 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1000));
4061 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(2000));
4062 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4063 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1000));
4066 env(token::burn(buyer, nftID));
4073 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4074 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4080 env(token::createOffer(minter, nftID, gwXAU(900)), Txflags(tfSellNFToken));
4086 env(token::createOffer(buyer, nftID, gwXAU(1001)), token::Owner(minter));
4090 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4096 env(token::cancelOffer(buyer, {buyOfferIndex}));
4103 env(token::createOffer(buyer, nftID, gwXAU(899)), token::Owner(minter));
4107 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4113 env(token::cancelOffer(buyer, {buyOfferIndex}));
4118 env(token::createOffer(buyer, nftID, gwXAU(1000)), token::Owner(minter));
4123 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4124 token::BrokerFee(gwXAU(101)),
4130 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4131 token::BrokerFee(gwXAU(100)));
4134 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4135 BEAST_EXPECT(ownerCount(env, minter) == 1);
4136 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4137 BEAST_EXPECT(ownerCount(env, broker) == 1);
4138 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1450));
4139 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1450));
4140 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4141 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1100));
4144 env(token::burn(buyer, nftID));
4151 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4152 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4158 env(token::createOffer(minter, nftID, gwXAU(900)), Txflags(tfSellNFToken));
4163 env(token::createOffer(buyer, nftID, gwXAU(1000)), token::Owner(minter));
4169 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4170 token::BrokerFee(gwXAU(50)));
4173 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4174 BEAST_EXPECT(ownerCount(env, minter) == 1);
4175 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4176 BEAST_EXPECT(ownerCount(env, broker) == 1);
4177 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4178 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4179 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4180 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1050));
4183 env(token::burn(buyer, nftID));
4188 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4189 setXAUBalance({issuer, minter, buyer}, 1000, __LINE__);
4190 setXAUBalance({broker}, 500, __LINE__);
4195 env(token::createOffer(minter, nftID, gwXAU(900)), Txflags(tfSellNFToken));
4200 env(token::createOffer(buyer, nftID, gwXAU(1000)), token::Owner(minter));
4203 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4204 token::BrokerFee(gwXAU(50)));
4206 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4207 BEAST_EXPECT(ownerCount(env, minter) == 1);
4208 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4209 BEAST_EXPECT(ownerCount(env, broker) == 1);
4210 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4211 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4212 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4213 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(550));
4216 env(token::burn(buyer, nftID));
4788 testcase(
"Payments with IOU transfer fees");
4791 Env env{*
this, features};
4793 Account const minter{
"minter"};
4794 Account const secondarySeller{
"seller"};
4797 Account const broker{
"broker"};
4798 IOU
const gwXAU(gw[
"XAU"]);
4799 IOU
const gwXPB(gw[
"XPB"]);
4801 env.fund(XRP(1000), gw, minter, secondarySeller, buyer, broker);
4804 env(trust(minter, gwXAU(2000)));
4805 env(trust(secondarySeller, gwXAU(2000)));
4806 env(trust(broker, gwXAU(10000)));
4807 env(trust(buyer, gwXAU(2000)));
4808 env(trust(buyer, gwXPB(2000)));
4812 env(rate(gw, 1.02));
4815 auto expectInitialState =
4816 [
this, &env, &buyer, &minter, &secondarySeller, &broker, &gw, &gwXAU, &gwXPB]() {
4821 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(1000));
4822 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(0));
4823 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(0));
4824 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(0));
4825 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(0));
4826 BEAST_EXPECT(env.balance(secondarySeller, gwXPB) == gwXPB(0));
4827 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5000));
4828 BEAST_EXPECT(env.balance(broker, gwXPB) == gwXPB(0));
4829 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-1000));
4830 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(0));
4831 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(0));
4832 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(0));
4833 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(0));
4834 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XPB"]) == gwXPB(0));
4835 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5000));
4836 BEAST_EXPECT(env.balance(gw, broker[
"XPB"]) == gwXPB(0));
4839 auto reinitializeTrustLineBalances = [&expectInitialState,
4848 if (
auto const difference = gwXAU(1000) - env.balance(buyer, gwXAU);
4849 difference > gwXAU(0))
4850 env(pay(gw, buyer, difference));
4851 if (env.balance(buyer, gwXPB) > gwXPB(0))
4852 env(pay(buyer, gw, env.balance(buyer, gwXPB)));
4853 if (env.balance(minter, gwXAU) > gwXAU(0))
4854 env(pay(minter, gw, env.balance(minter, gwXAU)));
4855 if (env.balance(minter, gwXPB) > gwXPB(0))
4856 env(pay(minter, gw, env.balance(minter, gwXPB)));
4857 if (env.balance(secondarySeller, gwXAU) > gwXAU(0))
4858 env(pay(secondarySeller, gw, env.balance(secondarySeller, gwXAU)));
4859 if (env.balance(secondarySeller, gwXPB) > gwXPB(0))
4860 env(pay(secondarySeller, gw, env.balance(secondarySeller, gwXPB)));
4861 auto brokerDiff = gwXAU(5000) - env.balance(broker, gwXAU);
4862 if (brokerDiff > gwXAU(0))
4864 env(pay(gw, broker, brokerDiff));
4866 else if (brokerDiff < gwXAU(0))
4868 brokerDiff.negate();
4869 env(pay(broker, gw, brokerDiff));
4871 if (env.balance(broker, gwXPB) > gwXPB(0))
4872 env(pay(broker, gw, env.balance(broker, gwXPB)));
4874 expectInitialState();
4877 auto mintNFT = [&env](
Account const& minter,
int transferFee = 0) {
4878 uint256 const nftID = token::getNextID(env, minter, 0, tfTransferable, transferFee);
4879 env(token::mint(minter), token::XferFee(transferFee), Txflags(tfTransferable));
4884 auto createBuyOffer = [&env](
4891 env(token::createOffer(offerer, nftID, amount),
4892 token::Owner(owner),
4893 terCode ? Ter(*terCode) : Ter(
static_cast<TER>(
tesSUCCESS)));
4898 auto createSellOffer = [&env](
4904 env(token::createOffer(offerer, nftID, amount),
4905 Txflags(tfSellNFToken),
4906 terCode ? Ter(*terCode) : Ter(
static_cast<TER>(
tesSUCCESS)));
4914 reinitializeTrustLineBalances();
4915 auto const nftID = mintNFT(minter);
4916 auto const offerID = createSellOffer(minter, nftID, gwXAU(1000));
4918 env(token::acceptSellOffer(buyer, offerID), Ter(sellTER));
4921 expectInitialState();
4926 reinitializeTrustLineBalances();
4927 auto const nftID = mintNFT(minter);
4928 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(1000));
4930 env(token::acceptBuyOffer(minter, offerID), Ter(sellTER));
4933 expectInitialState();
4939 reinitializeTrustLineBalances();
4940 auto const nftID = mintNFT(minter);
4941 auto const offerID = createSellOffer(minter, nftID, gwXAU(995));
4943 env(token::acceptSellOffer(buyer, offerID), Ter(sellTER));
4946 expectInitialState();
4952 reinitializeTrustLineBalances();
4953 auto const nftID = mintNFT(minter);
4954 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(995));
4956 env(token::acceptBuyOffer(minter, offerID), Ter(sellTER));
4959 expectInitialState();
4966 reinitializeTrustLineBalances();
4967 auto const nftID = mintNFT(minter);
4968 auto const offerID = createSellOffer(minter, nftID, gwXAU(900));
4969 env(token::acceptSellOffer(buyer, offerID));
4972 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
4973 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
4974 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
4975 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
4982 reinitializeTrustLineBalances();
4983 auto const nftID = mintNFT(minter);
4984 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(900));
4985 env(token::acceptBuyOffer(minter, offerID));
4988 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
4989 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
4990 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
4991 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
4998 reinitializeTrustLineBalances();
5001 env(pay(gw, buyer, gwXAU(20)));
5004 auto const nftID = mintNFT(minter);
5005 auto const offerID = createSellOffer(minter, nftID, gwXAU(1000));
5006 env(token::acceptSellOffer(buyer, offerID));
5009 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5010 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5011 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5012 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5019 reinitializeTrustLineBalances();
5022 env(pay(gw, buyer, gwXAU(20)));
5025 auto const nftID = mintNFT(minter);
5026 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(1000));
5027 env(token::acceptBuyOffer(minter, offerID));
5030 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5031 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5032 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5033 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5038 reinitializeTrustLineBalances();
5040 auto const nftID = mintNFT(minter);
5041 auto const offerID = createSellOffer(minter, nftID, gwXAU(1000));
5043 env(token::acceptSellOffer(gw, offerID), Ter(sellTER));
5046 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5047 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5052 reinitializeTrustLineBalances();
5054 auto const nftID = mintNFT(minter);
5056 auto const offerID = createBuyOffer(gw, minter, nftID, gwXAU(1000), {offerTER});
5058 env(token::acceptBuyOffer(minter, offerID), Ter(sellTER));
5061 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5062 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5067 reinitializeTrustLineBalances();
5068 auto const nftID = mintNFT(minter);
5069 auto const offerID = createSellOffer(minter, nftID, gwXAU(5000));
5071 env(token::acceptSellOffer(gw, offerID), Ter(sellTER));
5074 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5075 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5080 reinitializeTrustLineBalances();
5082 auto const nftID = mintNFT(minter);
5084 auto const offerID = createBuyOffer(gw, minter, nftID, gwXAU(5000), {offerTER});
5086 env(token::acceptBuyOffer(minter, offerID), Ter(sellTER));
5089 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5090 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5096 reinitializeTrustLineBalances();
5097 auto const nftID = mintNFT(gw);
5098 auto const offerID = createSellOffer(gw, nftID, gwXAU(1000));
5099 env(token::acceptSellOffer(buyer, offerID));
5102 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5103 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5109 reinitializeTrustLineBalances();
5111 auto const nftID = mintNFT(gw);
5112 auto const offerID = createBuyOffer(buyer, gw, nftID, gwXAU(1000));
5113 env(token::acceptBuyOffer(gw, offerID));
5116 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5117 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5123 reinitializeTrustLineBalances();
5124 auto const nftID = mintNFT(gw);
5125 auto const offerID = createSellOffer(gw, nftID, gwXAU(2000));
5126 env(token::acceptSellOffer(buyer, offerID),
5129 expectInitialState();
5135 reinitializeTrustLineBalances();
5136 auto const nftID = mintNFT(gw);
5137 auto const offerID = createBuyOffer(buyer, gw, nftID, gwXAU(2000));
5138 env(token::acceptBuyOffer(gw, offerID),
5141 expectInitialState();
5146 reinitializeTrustLineBalances();
5147 auto const nftID = mintNFT(minter);
5148 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5149 env(token::acceptSellOffer(buyer, offerID),
5152 expectInitialState();
5157 reinitializeTrustLineBalances();
5158 auto const nftID = mintNFT(minter);
5159 auto const offerID = createBuyOffer(
5161 env(token::acceptBuyOffer(minter, offerID),
5164 expectInitialState();
5170 reinitializeTrustLineBalances();
5171 env(pay(gw, buyer, gwXPB(100)));
5174 auto const nftID = mintNFT(minter);
5175 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5176 env(token::acceptSellOffer(buyer, offerID));
5179 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5180 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5181 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5182 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5188 reinitializeTrustLineBalances();
5189 env(pay(gw, buyer, gwXPB(100)));
5192 auto const nftID = mintNFT(minter);
5193 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXPB(10));
5194 env(token::acceptBuyOffer(minter, offerID));
5197 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5198 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5199 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5200 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5205 reinitializeTrustLineBalances();
5209 auto const nftID = mintNFT(minter, 3000);
5210 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
5211 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5215 auto const offerID = createSellOffer(secondarySeller, nftID, gwXAU(1000));
5217 env(token::acceptSellOffer(buyer, offerID), Ter(sellTER));
5220 expectInitialState();
5225 reinitializeTrustLineBalances();
5229 auto const nftID = mintNFT(minter, 3000);
5230 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
5231 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5235 auto const offerID = createBuyOffer(buyer, secondarySeller, nftID, gwXAU(1000));
5237 env(token::acceptBuyOffer(secondarySeller, offerID), Ter(sellTER));
5240 expectInitialState();
5245 reinitializeTrustLineBalances();
5249 auto const nftID = mintNFT(minter, 3000);
5250 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
5251 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5255 auto const offerID = createSellOffer(secondarySeller, nftID, gwXAU(900));
5256 env(token::acceptSellOffer(buyer, offerID));
5259 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5260 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5261 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5262 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5263 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5264 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5269 reinitializeTrustLineBalances();
5273 auto const nftID = mintNFT(minter, 3000);
5274 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
5275 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5279 auto const offerID = createBuyOffer(buyer, secondarySeller, nftID, gwXAU(900));
5280 env(token::acceptBuyOffer(secondarySeller, offerID));
5284 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5286 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5288 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5289 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5290 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5291 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5309 reinitializeTrustLineBalances();
5311 auto const nftID = mintNFT(minter);
5312 auto const sellOffer = createSellOffer(minter, nftID, gwXAU(300));
5313 auto const buyOffer = createBuyOffer(buyer, minter, nftID, gwXAU(500));
5314 env(token::brokerOffers(broker, buyOffer, sellOffer), token::BrokerFee(gwXAU(100)));
5317 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(400));
5318 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5319 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5320 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-400));
5321 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5322 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5340 reinitializeTrustLineBalances();
5344 auto const nftID = mintNFT(minter, 3000);
5345 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
5346 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5350 auto const sellOffer = createSellOffer(secondarySeller, nftID, gwXAU(300));
5351 auto const buyOffer = createBuyOffer(buyer, secondarySeller, nftID, gwXAU(500));
5352 env(token::brokerOffers(broker, buyOffer, sellOffer), token::BrokerFee(gwXAU(100)));
5355 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(12));
5356 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5357 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(388));
5358 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5359 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-12));
5360 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5361 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-388));
5362 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5462 auto openLedgerSeq = [](Env& env) {
return env.current()->seq(); };
5466 auto incLgrSeqForAcctDel = [&](Env& env,
Account const& acct) {
5467 int const delta = [&]() ->
int {
5468 if (env.seq(acct) + 255 > openLedgerSeq(env))
5469 return env.seq(acct) - openLedgerSeq(env) + 255;
5472 BEAST_EXPECT(delta >= 0);
5473 for (
int i = 0; i < delta; ++i)
5475 BEAST_EXPECT(openLedgerSeq(env) == env.seq(acct) + 255);
5480 auto incLgrSeqForFixNftRemint = [&](Env& env,
Account const& acct) {
5482 auto const deletableLgrSeq = (*env.le(acct))[~sfFirstNFTokenSequence].value_or(0) +
5483 (*env.le(acct))[sfMintedNFTokens] + 255;
5485 if (deletableLgrSeq > openLedgerSeq(env))
5486 delta = deletableLgrSeq - openLedgerSeq(env);
5488 BEAST_EXPECT(delta >= 0);
5489 for (
int i = 0; i < delta; ++i)
5491 BEAST_EXPECT(openLedgerSeq(env) == deletableLgrSeq);
5497 Env env{*
this, features};
5501 env.fund(XRP(10000), alice, becky);
5505 uint256 const prevNFTokenID = token::getNextID(env, alice, 0u);
5506 env(token::mint(alice));
5508 env(token::burn(alice, prevNFTokenID));
5512 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 1);
5515 incLgrSeqForAcctDel(env, alice);
5519 auto const acctDelFee{drops(env.current()->fees().increment)};
5520 env(acctdelete(alice, becky), Fee(acctDelFee));
5525 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5526 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5529 env.fund(XRP(10000), alice);
5533 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5534 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5535 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5538 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5539 env(token::mint(alice));
5543 env(token::burn(alice, remintNFTokenID));
5547 BEAST_EXPECT(remintNFTokenID != prevNFTokenID);
5553 Env env{*
this, features};
5556 Account const minter{
"minter"};
5558 env.fund(XRP(10000), alice, becky, minter);
5562 env(token::setMinter(alice, minter));
5568 for (
int i = 0; i < 500; i++)
5570 uint256 const nftokenID = token::getNextID(env, alice, 0u);
5572 env(token::mint(minter), token::Issuer(alice));
5577 for (
auto const nftokenID : nftIDs)
5579 env(token::burn(minter, nftokenID));
5583 incLgrSeqForAcctDel(env, alice);
5587 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5588 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5590 auto const acctDelFee{drops(env.current()->fees().increment)};
5599 env(acctdelete(alice, becky), Fee(acctDelFee), Ter(
tecTOO_SOON));
5603 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5608 incLgrSeqForFixNftRemint(env, alice);
5611 env(acctdelete(alice, becky), Fee(acctDelFee));
5616 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5617 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5620 env.fund(XRP(10000), alice);
5624 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5625 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5626 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5630 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5631 env(token::mint(alice));
5635 env(token::burn(alice, remintNFTokenID));
5646 Env env{*
this, features};
5650 env.fund(XRP(10000), alice, becky);
5657 env(ticket::create(alice, 100));
5661 BEAST_EXPECT(ownerCount(env, alice) == 100);
5666 for (
int i = 0; i < 50; i++)
5668 nftIDs.
push_back(token::getNextID(env, alice, 0u));
5669 env(token::mint(alice, 0u), ticket::Use(aliceTicketSeq++));
5674 for (
auto const nftokenID : nftIDs)
5676 env(token::burn(alice, nftokenID), ticket::Use(aliceTicketSeq++));
5682 incLgrSeqForAcctDel(env, alice);
5686 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5687 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5689 auto const acctDelFee{drops(env.current()->fees().increment)};
5698 env(acctdelete(alice, becky), Fee(acctDelFee), Ter(
tecTOO_SOON));
5702 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5707 incLgrSeqForFixNftRemint(env, alice);
5710 env(acctdelete(alice, becky), Fee(acctDelFee));
5715 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5716 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5719 env.fund(XRP(10000), alice);
5723 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5724 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5725 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5729 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5730 env(token::mint(alice));
5734 env(token::burn(alice, remintNFTokenID));
5746 Env env{*
this, features};
5749 Account const minter{
"minter"};
5751 env.fund(XRP(10000), alice, becky, minter);
5755 env(token::setMinter(alice, minter));
5760 env(ticket::create(minter, 100));
5764 BEAST_EXPECT(ownerCount(env, minter) == 100);
5769 for (
int i = 0; i < 50; i++)
5771 uint256 const nftokenID = token::getNextID(env, alice, 0u);
5773 env(token::mint(minter), token::Issuer(alice), ticket::Use(minterTicketSeq++));
5778 for (
auto const nftokenID : nftIDs)
5780 env(token::burn(minter, nftokenID), ticket::Use(minterTicketSeq++));
5786 incLgrSeqForAcctDel(env, alice);
5790 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5791 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5800 auto const acctDelFee{drops(env.current()->fees().increment)};
5801 env(acctdelete(alice, becky), Fee(acctDelFee), Ter(
tecTOO_SOON));
5805 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5810 incLgrSeqForFixNftRemint(env, alice);
5813 env(acctdelete(alice, becky), Fee(acctDelFee));
5818 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5819 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5822 env.fund(XRP(10000), alice);
5826 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5827 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5828 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5832 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5833 env(token::mint(alice));
5837 env(token::burn(alice, remintNFTokenID));
5848 testcase(
"NFTokenMint with Create NFTokenOffer");
5852 if (!features[featureNFTokenMintOffer])
5854 Env env{*
this, features};
5858 env.fund(XRP(10000), alice, buyer);
5861 env(token::mint(alice), token::Amount(XRP(10000)), Ter(
temDISABLED));
5864 env(token::mint(alice), token::Destination(
"buyer"), Ter(
temDISABLED));
5875 Env env{*
this, features};
5876 auto const baseFee = env.current()->fees().base;
5880 Account const issuer(
"issuer");
5881 Account const minter(
"minter");
5883 IOU
const gwAUD(gw[
"AUD"]);
5885 env.fund(XRP(10000), alice, buyer, gw, issuer, minter);
5890 env(token::mint(alice), token::Destination(buyer), Ter(
temMALFORMED));
5892 BEAST_EXPECT(ownerCount(env, alice) == 0);
5897 BEAST_EXPECT(ownerCount(env, buyer) == 0);
5903 env(token::mint(alice),
5904 token::Amount(XRP(1000)),
5905 token::Destination(alice),
5908 BEAST_EXPECT(ownerCount(env, alice) == 0);
5912 env(token::mint(alice),
5913 token::Amount(XRP(1000)),
5914 token::Destination(
Account(
"demon")),
5917 BEAST_EXPECT(ownerCount(env, alice) == 0);
5922 env(token::mint(alice),
5923 token::Amount(XRP(1000)),
5924 token::Expiration(0),
5927 BEAST_EXPECT(ownerCount(env, alice) == 0);
5930 env(token::mint(alice),
5931 token::Amount(XRP(1000)),
5935 BEAST_EXPECT(ownerCount(env, alice) == 0);
5940 env(token::mint(alice),
5941 token::Amount(buyer[
"USD"](1)),
5944 env(token::mint(alice), token::Amount(buyer[
"USD"](0)), Ter(
temBAD_AMOUNT));
5946 BEAST_EXPECT(ownerCount(env, alice) == 0);
5949 env(token::mint(alice),
5950 token::Amount(gwAUD(1000)),
5951 Txflags(tfTransferable),
5955 BEAST_EXPECT(ownerCount(env, alice) == 0);
5960 env(token::mint(gw),
5961 token::Amount(gwAUD(1000)),
5962 Txflags(tfTransferable),
5963 token::XferFee(10));
5967 env(trust(gw, alice[
"AUD"](999), tfSetFreeze));
5972 env(token::mint(alice),
5973 token::Amount(gwAUD(1000)),
5974 Txflags(tfTransferable),
5978 BEAST_EXPECT(ownerCount(env, alice) == 0);
5981 env(token::mint(alice), token::Amount(gwAUD(1000)), Ter(
tecFROZEN));
5983 BEAST_EXPECT(ownerCount(env, alice) == 0);
5986 env(trust(gw, alice[
"AUD"](999), tfClearFreeze));
5992 auto const acctReserve = env.current()->fees().reserve;
5993 auto const incReserve = env.current()->fees().increment;
5995 env.fund(acctReserve + incReserve, bob);
6003 env(pay(env.master, bob, incReserve + drops(baseFee)));
6005 env(token::mint(bob), token::Amount(XRP(0)));
6009 env(pay(env.master, bob, drops(baseFee)));
6015 env(pay(env.master, bob, incReserve + drops(baseFee)));
6017 env(token::mint(bob), token::Amount(XRP(0)));
6022 BEAST_EXPECT(ownerCount(env, alice) == 0);
6023 env(token::mint(alice), token::Amount(XRP(10)));
6024 BEAST_EXPECT(ownerCount(env, alice) == 2);
6028 env(token::mint(alice),
6029 token::Amount(XRP(10)),
6030 token::Destination(buyer),
6031 token::Expiration(
lastClose(env) + 25));
6035 env(trust(alice, gwAUD(1000)));
6037 env(token::mint(alice),
6038 token::Amount(gwAUD(1)),
6039 token::Destination(buyer),
6041 Txflags(tfTransferable),
6042 token::XferFee(10));
6046 env(token::mint(alice),
6047 token::Amount(XRP(10)),
6048 token::Destination(buyer),
6049 token::Expiration(
lastClose(env) + 25));
6051 env(token::cancelOffer(alice, {offerAliceSellsToBuyer}));
6055 env(token::mint(buyer),
6056 token::Amount(XRP(10)),
6057 token::Destination(alice),
6058 token::Expiration(
lastClose(env) + 25));
6060 env(token::cancelOffer(alice, {offerBuyerSellsToAlice}));
6063 env(token::setMinter(issuer, minter));
6067 BEAST_EXPECT(ownerCount(env, minter) == 0);
6068 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6069 env(token::mint(minter), token::Issuer(issuer), token::Amount(drops(1)));
6071 BEAST_EXPECT(ownerCount(env, minter) == 2);
6072 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6075 Env env{*
this, features};
6078 env.fund(XRP(1000000), alice);
6083 env(token::mint(alice), token::Amount(XRP(-2)), Ter(offerCreateTER));
6101 testcase(
"Test synthetic fields from JSON response");
6107 Account const broker{
"broker"};
6109 Env env{*
this, features};
6110 env.fund(XRP(10000), alice, bob, broker);
6116 auto verifyNFTokenID = [&](
uint256 const& actualNftID) {
6122 json::Value const meta = env.rpc(
"tx", txHash)[jss::result][jss::meta];
6125 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_id)))
6132 BEAST_EXPECT(nftID == actualNftID);
6143 json::Value const meta = env.rpc(
"tx", txHash)[jss::result][jss::meta];
6146 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_ids)))
6152 meta[jss::nftoken_ids].begin(),
6153 meta[jss::nftoken_ids].end(),
6157 BEAST_EXPECT(nftID.
parseHex(
id.asString()));
6166 BEAST_EXPECT(metaIDs.
size() == actualNftIDs.size());
6170 for (
size_t i = 0; i < metaIDs.
size(); ++i)
6171 BEAST_EXPECT(metaIDs[i] == actualNftIDs[i]);
6176 auto verifyNFTokenOfferID = [&](
uint256 const& offerID) {
6182 json::Value const meta = env.rpc(
"tx", txHash)[jss::result][jss::meta];
6185 if (!BEAST_EXPECT(meta.
isMember(jss::offer_id)))
6190 BEAST_EXPECT(metaOfferID == offerID);
6197 uint256 const nftId1{token::getNextID(env, alice, 0u, tfTransferable)};
6198 env(token::mint(alice, 0u), Txflags(tfTransferable));
6200 verifyNFTokenID(nftId1);
6202 uint256 const nftId2{token::getNextID(env, alice, 0u, tfTransferable)};
6203 env(token::mint(alice, 0u), Txflags(tfTransferable));
6205 verifyNFTokenID(nftId2);
6211 env(token::createOffer(alice, nftId1, drops(1)), Txflags(tfSellNFToken));
6213 verifyNFTokenOfferID(aliceOfferIndex1);
6216 env(token::createOffer(alice, nftId2, drops(1)), Txflags(tfSellNFToken));
6218 verifyNFTokenOfferID(aliceOfferIndex2);
6223 env(token::cancelOffer(alice, {aliceOfferIndex1, aliceOfferIndex2}));
6225 verifyNFTokenIDsInCancelOffer({nftId1, nftId2});
6230 env(token::createOffer(bob, nftId1, drops(1)), token::Owner(alice));
6232 verifyNFTokenOfferID(bobBuyOfferIndex);
6236 env(token::acceptBuyOffer(alice, bobBuyOfferIndex));
6238 verifyNFTokenID(nftId1);
6244 uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)};
6245 env(token::mint(alice, 0u), Txflags(tfTransferable));
6247 verifyNFTokenID(nftId);
6251 env(token::createOffer(alice, nftId, drops(1)),
6252 token::Destination(broker),
6253 Txflags(tfSellNFToken));
6255 verifyNFTokenOfferID(offerAliceToBroker);
6259 env(token::createOffer(bob, nftId, drops(1)), token::Owner(alice));
6261 verifyNFTokenOfferID(offerBobToBroker);
6264 env(token::brokerOffers(broker, offerBobToBroker, offerAliceToBroker));
6266 verifyNFTokenID(nftId);
6273 uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)};
6274 env(token::mint(alice, 0u), Txflags(tfTransferable));
6276 verifyNFTokenID(nftId);
6280 env(token::createOffer(alice, nftId, drops(1)), Txflags(tfSellNFToken));
6282 verifyNFTokenOfferID(aliceOfferIndex1);
6285 env(token::createOffer(alice, nftId, drops(1)), Txflags(tfSellNFToken));
6287 verifyNFTokenOfferID(aliceOfferIndex2);
6291 env(token::cancelOffer(alice, {aliceOfferIndex1, aliceOfferIndex2}));
6293 verifyNFTokenIDsInCancelOffer({nftId});
6296 if (features[featureNFTokenMintOffer])
6298 uint256 const aliceMintWithOfferIndex1 =
6300 env(token::mint(alice), token::Amount(XRP(0)));
6302 verifyNFTokenOfferID(aliceMintWithOfferIndex1);
6309 testcase(
"Test buyer reserve when accepting an offer");
6314 auto mintAndCreateSellOffer =
6317 uint256 const nftId{token::getNextID(env, acct, 0u, tfTransferable)};
6318 env(token::mint(acct, 0u), Txflags(tfTransferable));
6323 env(token::createOffer(acct, nftId, amt), Txflags(tfSellNFToken));
6326 return sellOfferIndex;
6336 Env env{*
this, features};
6337 auto const acctReserve = env.
current()->fees().reserve;
6338 auto const incReserve = env.current()->fees().increment;
6339 auto const baseFee = env.current()->fees().base;
6341 env.fund(XRP(10000), alice);
6345 env.fund(acctReserve, bob);
6349 auto const sellOfferIndex = mintAndCreateSellOffer(env, alice, XRP(0));
6352 BEAST_EXPECT(ownerCount(env, bob) == 0);
6369 BEAST_EXPECT(ownerCount(env, bob) == 0);
6374 env(pay(env.master, bob, incReserve + drops(baseFee)));
6384 env(pay(env.master, bob, drops(baseFee * 2)));
6388 env(token::acceptSellOffer(bob, sellOfferIndex));
6391 BEAST_EXPECT(ownerCount(env, bob) == 1);
6400 Env env{*
this, features};
6401 auto const acctReserve = env.
current()->fees().reserve;
6402 auto const incReserve = env.current()->fees().increment;
6404 env.fund(XRP(10000), alice);
6407 env.fund(acctReserve + XRP(1), bob);
6411 auto const sellOfferIndex1 = mintAndCreateSellOffer(env, alice, XRP(0));
6419 env(pay(env.master, bob, drops(incReserve)));
6422 BEAST_EXPECT(ownerCount(env, bob) == 0);
6425 env(token::acceptSellOffer(bob, sellOfferIndex1));
6428 BEAST_EXPECT(ownerCount(env, bob) == 1);
6432 for (
size_t i = 0; i < 31; i++)
6435 auto const sellOfferIndex = mintAndCreateSellOffer(env, alice, XRP(0));
6439 env(token::acceptSellOffer(bob, sellOfferIndex));
6443 BEAST_EXPECT(ownerCount(env, bob) == 1);
6447 auto const sellOfferIndex33 = mintAndCreateSellOffer(env, alice, XRP(0));
6455 env(pay(env.master, bob, drops(incReserve)));
6460 env(token::acceptSellOffer(bob, sellOfferIndex33));
6463 BEAST_EXPECT(ownerCount(env, bob) == 2);
6471 Env env{*
this, features};
6472 auto const acctReserve = env.
current()->fees().reserve;
6473 auto const incReserve = env.current()->fees().increment;
6474 auto const baseFee = env.current()->fees().base;
6476 env.fund(XRP(10000), alice);
6482 env.fund(acctReserve + incReserve + XRP(1), bob);
6486 uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)};
6487 env(token::mint(alice, 0u), Txflags(tfTransferable));
6492 env(token::createOffer(bob, nftId, XRP(1)), token::Owner(alice));
6502 env(pay(env.master, bob, drops(baseFee)));
6506 env(token::acceptBuyOffer(alice, buyOfferIndex));
6514 Account const broker{
"broker"};
6516 Env env{*
this, features};
6517 auto const acctReserve = env.
current()->fees().reserve;
6518 auto const incReserve = env.current()->fees().increment;
6519 auto const baseFee = env.current()->fees().base;
6521 env.fund(XRP(10000), alice, broker);
6526 env.fund(acctReserve + incReserve + XRP(1), bob);
6530 uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)};
6531 env(token::mint(alice, 0u), Txflags(tfTransferable));
6536 env(token::createOffer(alice, nftId, XRP(1)),
6537 token::Destination(broker),
6538 Txflags(tfSellNFToken));
6543 env(token::createOffer(bob, nftId, XRP(1)), token::Owner(alice));
6550 env(token::brokerOffers(broker, offerBobToBroker, offerAliceToBroker),
6555 env(pay(env.master, bob, drops(baseFee)));
6559 env(token::brokerOffers(broker, offerBobToBroker, offerAliceToBroker));
6878 Account const issuer{
"issuer"};
6882 bool const modifyEnabled = features[featureDynamicNFT];
6886 Env env{*
this, features};
6887 env.fund(XRP(10000), issuer);
6891 env(token::mint(issuer, 0u), Txflags(tfMutable), Ter(expectedTer));
6895 Env env{*
this, features};
6896 env.fund(XRP(10000), issuer);
6900 uint256 const nftId{token::getNextID(env, issuer, 0u, tfMutable)};
6903 env(token::mint(issuer, 0u), Txflags(tfMutable));
6905 BEAST_EXPECT(ownerCount(env, issuer) == 1);
6906 env(token::modify(issuer, nftId));
6907 BEAST_EXPECT(ownerCount(env, issuer) == 1);
6911 env(token::mint(issuer, 0u));
6913 env(token::modify(issuer, nftId), Ter(
temDISABLED));
6921 Env env{*
this, features};
6922 env.fund(XRP(10000), issuer);
6925 uint256 const nftId{token::getNextID(env, issuer, 0u, tfMutable)};
6926 env(token::mint(issuer, 0u), Txflags(tfMutable));
6934 env(token::modify(issuer, nftId), Txflags(0x00000001), Ter(
temINVALID_FLAG));
6937 env(token::modify(issuer, nftId), token::Owner(issuer), Ter(
temMALFORMED));
6941 env(token::modify(issuer, nftId), token::Uri(
""), Ter(
temMALFORMED));
6945 env(token::modify(issuer, nftId),
6951 Env env{*
this, features};
6952 env.fund(XRP(10000), issuer, alice, bob);
6957 uint256 const nftIDNotExists{token::getNextID(env, issuer, 0u, tfMutable)};
6960 env(token::modify(issuer, nftIDNotExists), Ter(
tecNO_ENTRY));
6965 uint256 const nftIDNotModifiable{token::getNextID(env, issuer, 0u)};
6966 env(token::mint(issuer, 0u));
6974 uint256 const nftId{token::getNextID(env, issuer, 0u, tfMutable)};
6975 env(token::mint(issuer, 0u), Txflags(tfMutable));
6978 env(token::modify(bob, nftId), token::Owner(issuer), Ter(
tecNO_PERMISSION));
6981 env(token::setMinter(issuer, alice));
6984 env(token::modify(bob, nftId), token::Owner(issuer), Ter(
tecNO_PERMISSION));
6989 Env env{*
this, features};
6990 env.fund(XRP(10000), issuer, alice, bob);
6994 uint256 const nftId{token::getNextID(env, issuer, 0u, tfMutable)};
6995 env(token::mint(issuer, 0u), Txflags(tfMutable), token::Uri(
"uri"));
7002 Env env{*
this, features};
7003 env.fund(XRP(10000), issuer, alice, bob);
7007 auto accountNFTs = [&env](
Account const& acct) {
7009 params[jss::account] = acct.human();
7010 params[jss::type] =
"state";
7011 auto response = env.rpc(
"json",
"account_nfts",
to_string(params));
7012 return response[jss::result][jss::account_nfts];
7016 auto checkURI = [&accountNFTs,
this](
Account const& acct,
char const* uri,
int line) {
7017 auto const nfts = accountNFTs(acct);
7018 if (nfts.size() == 1)
7025 text <<
"checkURI: unexpected NFT count on line " << line;
7026 fail(text.
str(), __FILE__, line);
7032 if (!nfts[0u].isMember(sfURI.jsonName))
7039 text <<
"checkURI: unexpected URI present on line " << line;
7040 fail(text.
str(), __FILE__, line);
7052 text <<
"checkURI: unexpected URI contents on line " << line;
7053 fail(text.
str(), __FILE__, line);
7057 uint256 const nftId{token::getNextID(env, issuer, 0u, tfMutable)};
7060 env(token::mint(issuer, 0u), Txflags(tfMutable), token::Uri(
"uri"));
7062 checkURI(issuer,
"uri", __LINE__);
7065 env(token::modify(issuer, nftId), token::Uri(
"new_uri"));
7067 checkURI(issuer,
"new_uri", __LINE__);
7070 env(token::modify(issuer, nftId));
7072 checkURI(issuer,
nullptr, __LINE__);
7075 env(token::modify(issuer, nftId), token::Uri(
"uri"));
7077 checkURI(issuer,
"uri", __LINE__);
7081 env(token::createOffer(issuer, nftId, XRP(0)), Txflags(tfSellNFToken));
7083 env(token::acceptSellOffer(alice, offerID));
7085 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7086 BEAST_EXPECT(ownerCount(env, alice) == 1);
7087 checkURI(alice,
"uri", __LINE__);
7090 env(token::modify(alice, nftId), token::Uri(
"new_uri"), Ter(
tecNO_PERMISSION));
7092 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7093 BEAST_EXPECT(ownerCount(env, alice) == 1);
7094 checkURI(alice,
"uri", __LINE__);
7096 env(token::modify(issuer, nftId), token::Owner(alice), token::Uri(
"new_uri"));
7098 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7099 BEAST_EXPECT(ownerCount(env, alice) == 1);
7100 checkURI(alice,
"new_uri", __LINE__);
7102 env(token::modify(issuer, nftId), token::Owner(alice));
7104 checkURI(alice,
nullptr, __LINE__);
7106 env(token::modify(issuer, nftId), token::Owner(alice), token::Uri(
"uri"));
7108 checkURI(alice,
"uri", __LINE__);
7111 env(token::setMinter(issuer, bob));
7113 env(token::modify(bob, nftId), token::Owner(alice), token::Uri(
"new_uri"));
7115 checkURI(alice,
"new_uri", __LINE__);
7117 env(token::modify(bob, nftId), token::Owner(alice));
7119 checkURI(alice,
nullptr, __LINE__);
7121 env(token::modify(bob, nftId), token::Owner(alice), token::Uri(
"uri"));
7123 checkURI(alice,
"uri", __LINE__);