138 using namespace test::jtx;
140 Env env{*
this, features};
141 Account
const alice{
"alice"};
142 Account
const minter{
"minter"};
146 auto const acctReserve = env.current()->fees().reserve;
147 auto const incReserve = env.current()->fees().increment;
148 auto const baseFee = env.current()->fees().base;
150 env.fund(acctReserve, alice, minter);
153 BEAST_EXPECT(env.balance(alice) == acctReserve);
154 BEAST_EXPECT(env.balance(minter) == acctReserve);
155 BEAST_EXPECT(ownerCount(env, alice) == 0);
156 BEAST_EXPECT(ownerCount(env, minter) == 0);
163 BEAST_EXPECT(ownerCount(env, alice) == 0);
168 env(pay(env.master, alice, incReserve + drops(baseFee - 1)));
173 auto checkAliceOwnerMintedBurned = [&env,
this, &alice](
186 ss <<
"Wrong " << type <<
" count. Found: " << found
187 <<
"; Expected: " << exp;
188 fail(ss.
str(), __FILE__, line);
191 oneCheck(
"owner", ownerCount(env, alice), owners);
192 oneCheck(
"minted",
mintedCount(env, alice), minted);
193 oneCheck(
"burned",
burnedCount(env, alice), burned);
201 checkAliceOwnerMintedBurned(0, 0, 0, __LINE__);
204 env(pay(env.master, alice, drops(baseFee + 1)));
208 env(token::mint(alice));
211 checkAliceOwnerMintedBurned(1, 1, 0, __LINE__);
215 for (
int i = 1; i < 32; ++i)
217 env(token::mint(alice));
218 checkAliceOwnerMintedBurned(1, i + 1, 0, __LINE__);
225 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
228 env(pay(env.master, alice, incReserve + drops(baseFee * 33 - 1)));
235 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
238 env(pay(env.master, alice, drops(baseFee + 1)));
242 env(token::mint(alice));
244 checkAliceOwnerMintedBurned(2, 33, 0, __LINE__);
251 env(token::burn(alice, token::getID(env, alice, 0, seq++)));
253 checkAliceOwnerMintedBurned((33 - seq) ? 1 : 0, 33, seq, __LINE__);
257 env(token::burn(alice, token::getID(env, alice, 197, 5)),
260 checkAliceOwnerMintedBurned(0, 33, 33, __LINE__);
265 env(token::setMinter(alice, minter));
268 env.le(alice)->getAccountID(sfNFTokenMinter) == minter.id());
272 auto checkMintersOwnerMintedBurned = [&env,
this, &alice, &minter](
280 auto oneCheck = [
this](
290 ss <<
"Wrong " << type <<
" count. Found: " << found
291 <<
"; Expected: " << exp;
292 fail(ss.
str(), __FILE__, line);
295 oneCheck(
"alice owner", ownerCount(env, alice), aliceOwners, line);
297 "alice minted",
mintedCount(env, alice), aliceMinted, line);
299 "alice burned",
burnedCount(env, alice), aliceBurned, line);
301 "minter owner", ownerCount(env, minter), minterOwners, line);
303 "minter minted",
mintedCount(env, minter), minterMinted, line);
305 "minter burned",
burnedCount(env, minter), minterBurned, line);
311 env(pay(env.master, minter, incReserve - drops(1)));
313 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
318 env(token::mint(minter),
319 token::issuer(alice),
323 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
326 env(pay(env.master, minter, drops(baseFee + 1)));
330 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
332 checkMintersOwnerMintedBurned(0, 34, nftSeq, 1, 0, 0, __LINE__);
336 for (
int i = 1; i < 32; ++i)
338 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
339 checkMintersOwnerMintedBurned(0, i + 34, nftSeq, 1, 0, 0, __LINE__);
344 env(pay(env.master, minter, incReserve + drops(baseFee * 32 - 1)));
349 env(token::mint(minter),
350 token::issuer(alice),
354 checkMintersOwnerMintedBurned(0, 65, nftSeq, 1, 0, 0, __LINE__);
357 env(pay(env.master, minter, drops(baseFee + 1)));
361 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
363 checkMintersOwnerMintedBurned(0, 66, nftSeq, 2, 0, 0, __LINE__);
368 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
370 checkMintersOwnerMintedBurned(
371 0, 66, nftSeq, (65 - seq) ? 1 : 0, 0, 0, __LINE__);
376 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
378 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
381 env(token::burn(minter, token::getID(env, alice, 2009, 3)),
384 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
587 testcase(
"Invalid NFT offer create");
589 using namespace test::jtx;
591 Env env{*
this, features};
592 Account
const alice{
"alice"};
593 Account
const buyer{
"buyer"};
594 Account
const gw(
"gw");
595 IOU
const gwAUD(gw[
"AUD"]);
600 env.fund(XRP(250), alice, buyer, gw);
602 BEAST_EXPECT(ownerCount(env, alice) == 0);
606 env(token::mint(alice, 0u),
610 BEAST_EXPECT(ownerCount(env, alice) == 1);
616 BEAST_EXPECT(ownerCount(env, alice) == 1);
618 uint256 nftNoXferID = token::getNextID(env, alice, 0);
619 env(token::mint(alice, 0));
621 BEAST_EXPECT(ownerCount(env, alice) == 1);
632 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
636 BEAST_EXPECT(ownerCount(env, buyer) == 0);
639 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
643 BEAST_EXPECT(ownerCount(env, buyer) == 0);
646 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
650 BEAST_EXPECT(ownerCount(env, buyer) == 0);
653 env(token::createOffer(buyer, nftXrpOnlyID, buyer[
"USD"](1)),
655 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](0)),
657 env(token::createOffer(buyer, nftXrpOnlyID, drops(0)),
660 BEAST_EXPECT(ownerCount(env, buyer) == 0);
663 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](1)),
664 token::expiration(0),
667 BEAST_EXPECT(ownerCount(env, buyer) == 0);
671 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
674 BEAST_EXPECT(ownerCount(env, buyer) == 0);
677 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
682 BEAST_EXPECT(ownerCount(env, alice) == 1);
685 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
689 BEAST_EXPECT(ownerCount(env, alice) == 1);
692 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
693 token::destination(alice),
697 BEAST_EXPECT(ownerCount(env, alice) == 1);
700 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
701 token::destination(Account(
"demon")),
705 BEAST_EXPECT(ownerCount(env, alice) == 1);
711 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
716 BEAST_EXPECT(ownerCount(env, buyer) == 0);
719 env(token::createOffer(
720 buyer, token::getID(env, alice, 0, 1), XRP(1000)),
724 BEAST_EXPECT(ownerCount(env, buyer) == 0);
727 env(token::createOffer(
728 alice, token::getID(env, alice, 0, 1), XRP(1000)),
732 BEAST_EXPECT(ownerCount(env, buyer) == 0);
735 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
739 BEAST_EXPECT(ownerCount(env, buyer) == 0);
741 env(trust(buyer, gwAUD(1000)));
743 BEAST_EXPECT(ownerCount(env, buyer) == 1);
747 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
751 BEAST_EXPECT(ownerCount(env, buyer) == 1);
759 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
763 BEAST_EXPECT(ownerCount(env, buyer) == 1);
770 env(token::createOffer(buyer, nftNoXferID, gwAUD(1000)),
774 BEAST_EXPECT(ownerCount(env, buyer) == 1);
780 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
784 BEAST_EXPECT(ownerCount(env, buyer) == 1);
789 env(trust(buyer, gwAUD(1000)));
792 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
796 BEAST_EXPECT(ownerCount(env, buyer) == 1);
802 env(pay(gw, buyer, gwAUD(999)));
807 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
811 BEAST_EXPECT(ownerCount(env, buyer) == 1);
814 auto const baseFee = env.current()->fees().base;
815 env(pay(env.master, buyer, XRP(50) + drops(baseFee * 12 - 1)));
818 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
822 BEAST_EXPECT(ownerCount(env, buyer) == 1);
825 env(pay(env.master, buyer, drops(baseFee + 1)));
830 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
834 BEAST_EXPECT(ownerCount(env, buyer) == 2);
960 testcase(
"Invalid NFT offer accept");
962 using namespace test::jtx;
964 Env env{*
this, features};
965 Account
const alice{
"alice"};
966 Account
const buyer{
"buyer"};
967 Account
const gw(
"gw");
968 IOU
const gwAUD(gw[
"AUD"]);
970 env.fund(XRP(1000), alice, buyer, gw);
972 BEAST_EXPECT(ownerCount(env, alice) == 0);
978 BEAST_EXPECT(ownerCount(env, alice) == 1);
984 BEAST_EXPECT(ownerCount(env, alice) == 1);
986 uint256 nftNoXferID = token::getNextID(env, alice, 0);
987 env(token::mint(alice, 0));
989 BEAST_EXPECT(ownerCount(env, alice) == 1);
992 uint256 const plainOfferIndex =
994 env(token::createOffer(alice, nftAlice0ID, XRP(10)),
997 BEAST_EXPECT(ownerCount(env, alice) == 2);
1001 env(token::createOffer(alice, nftAlice0ID, gwAUD(30)),
1004 BEAST_EXPECT(ownerCount(env, alice) == 3);
1006 uint256 const xrpOnlyOfferIndex =
1008 env(token::createOffer(alice, nftXrpOnlyID, XRP(20)),
1011 BEAST_EXPECT(ownerCount(env, alice) == 4);
1013 uint256 const noXferOfferIndex =
1015 env(token::createOffer(alice, nftNoXferID, XRP(30)),
1018 BEAST_EXPECT(ownerCount(env, alice) == 5);
1021 uint256 const aliceExpOfferIndex =
1023 env(token::createOffer(alice, nftNoXferID, XRP(40)),
1027 BEAST_EXPECT(ownerCount(env, alice) == 6);
1033 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1037 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1040 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1041 txflags(0x00008000),
1044 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1048 Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1052 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1057 Json::Value jv = token::acceptBuyOffer(buyer, noXferOfferIndex);
1058 jv[sfNFTokenBrokerFee.jsonName] =
1062 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1067 Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1068 jv[sfNFTokenBrokerFee.jsonName] =
1072 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1076 env(token::brokerOffers(buyer, noXferOfferIndex, xrpOnlyOfferIndex),
1077 token::brokerFee(gwAUD(0)),
1080 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1086 env(token::acceptBuyOffer(buyer, beast::zero),
1089 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1093 env(token::acceptBuyOffer(buyer, missingOfferIndex),
1096 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1099 env(token::acceptBuyOffer(buyer, aliceExpOfferIndex), ter(
tecEXPIRED));
1101 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1104 env(token::acceptSellOffer(buyer, beast::zero),
1107 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1110 env(token::acceptSellOffer(buyer, missingOfferIndex),
1113 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1116 env(token::acceptSellOffer(buyer, aliceExpOfferIndex), ter(
tecEXPIRED));
1118 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1125 env(trust(alice, gwAUD(1000)));
1126 env(trust(buyer, gwAUD(1000)));
1128 env(pay(gw, buyer, gwAUD(30)));
1130 BEAST_EXPECT(ownerCount(env, alice) == 7);
1131 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1137 uint256 const buyerOfferIndex =
1139 env(token::createOffer(buyer, nftAlice0ID, gwAUD(29)),
1140 token::owner(alice));
1142 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1145 env(token::brokerOffers(gw, buyerOfferIndex, xrpOnlyOfferIndex),
1148 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1151 env(token::brokerOffers(gw, buyerOfferIndex, plainOfferIndex),
1154 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1158 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1161 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1164 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1166 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1170 uint256 const buyerOfferIndex =
1172 env(token::createOffer(buyer, nftAlice0ID, gwAUD(31)),
1173 token::owner(alice));
1175 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1179 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1180 token::brokerFee(XRP(40)),
1183 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1186 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1187 token::brokerFee(gwAUD(31)),
1190 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1194 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1195 token::brokerFee(gwAUD(1.5)),
1198 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1201 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1203 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1209 uint256 const buyerOfferIndex =
1211 env(token::createOffer(buyer, nftAlice0ID, gwAUD(30)),
1212 token::owner(alice));
1214 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1217 env(token::acceptBuyOffer(buyer, plainOfferIndex),
1220 BEAST_EXPECT(ownerCount(env, alice) == 7);
1223 env(token::acceptBuyOffer(buyer, buyerOfferIndex),
1226 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1229 env(pay(buyer, gw, gwAUD(30)));
1231 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1232 env(token::acceptBuyOffer(alice, buyerOfferIndex),
1235 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1241 env(token::createOffer(alice, nftAlice0ID, XRP(0)),
1244 env(token::acceptSellOffer(gw, offerIndex));
1246 BEAST_EXPECT(ownerCount(env, alice) == 7);
1248 env(pay(gw, buyer, gwAUD(30)));
1252 env(token::acceptBuyOffer(alice, buyerOfferIndex),
1255 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1258 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1260 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1266 uint256 const buyerOfferIndex =
1268 env(token::createOffer(buyer, nftXrpOnlyID, XRP(30)),
1269 token::owner(alice));
1271 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1274 env(token::acceptSellOffer(alice, buyerOfferIndex),
1277 BEAST_EXPECT(ownerCount(env, alice) == 7);
1280 env(token::acceptSellOffer(alice, plainOfferIndex),
1283 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1287 env(token::acceptSellOffer(buyer, plainOfferIndex),
1290 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1298 env(token::createOffer(gw, nftAlice0ID, XRP(0)),
1301 env(token::acceptSellOffer(alice, offerIndex));
1303 BEAST_EXPECT(ownerCount(env, alice) == 7);
1305 env(pay(buyer, gw, gwAUD(30)));
1307 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1308 env(token::acceptSellOffer(buyer, audOfferIndex),
1311 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1537 testcase(
"Mint flagCreateTrustLines");
1539 using namespace test::jtx;
1541 Account
const alice{
"alice"};
1542 Account
const becky{
"becky"};
1543 Account
const cheri{
"cheri"};
1544 Account
const gw(
"gw");
1545 IOU
const gwAUD(gw[
"AUD"]);
1546 IOU
const gwCAD(gw[
"CAD"]);
1547 IOU
const gwEUR(gw[
"EUR"]);
1552 for (
auto const& tweakedFeatures :
1553 {features - fixRemoveNFTokenAutoTrustLine,
1554 features | fixRemoveNFTokenAutoTrustLine})
1556 Env env{*
this, tweakedFeatures};
1557 env.fund(XRP(1000), alice, becky, cheri, gw);
1561 env(trust(becky, gwAUD(1000)));
1562 env(trust(cheri, gwAUD(1000)));
1563 env(trust(becky, gwCAD(1000)));
1564 env(trust(cheri, gwCAD(1000)));
1565 env(trust(becky, gwEUR(1000)));
1566 env(trust(cheri, gwEUR(1000)));
1568 env(pay(gw, becky, gwAUD(500)));
1569 env(pay(gw, becky, gwCAD(500)));
1570 env(pay(gw, becky, gwEUR(500)));
1571 env(pay(gw, cheri, gwAUD(500)));
1572 env(pay(gw, cheri, gwCAD(500)));
1579 uint256 const nftNoAutoTrustID{
1581 env(token::mint(alice, 0u),
1582 token::xferFee(xferFee),
1587 uint256 const beckyBuyOfferIndex =
1589 env(token::createOffer(becky, nftNoAutoTrustID, drops(1)),
1590 token::owner(alice));
1592 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1596 TER const createOfferTER =
1598 uint256 const beckyOfferIndex =
1600 env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)),
1602 ter(createOfferTER));
1606 uint256 const cheriOfferIndex =
1608 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
1609 token::owner(becky),
1610 ter(createOfferTER));
1614 env(token::cancelOffer(becky, {beckyOfferIndex}));
1615 env(token::cancelOffer(cheri, {cheriOfferIndex}));
1623 uint256 const nftAutoTrustID{token::getNextID(
1630 tweakedFeatures[fixRemoveNFTokenAutoTrustLine]
1634 env(token::mint(alice, 0u),
1635 token::xferFee(transferFee),
1642 if (tweakedFeatures[fixRemoveNFTokenAutoTrustLine])
1646 uint256 const beckyBuyOfferIndex =
1648 env(token::createOffer(becky, nftAutoTrustID, drops(1)),
1649 token::owner(alice));
1651 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1655 uint256 const beckySellOfferIndex =
1657 env(token::createOffer(becky, nftAutoTrustID, gwAUD(100)),
1660 env(token::acceptSellOffer(cheri, beckySellOfferIndex));
1664 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1667 uint256 const beckyBuyBackOfferIndex =
1669 env(token::createOffer(becky, nftAutoTrustID, gwCAD(50)),
1670 token::owner(cheri));
1672 env(token::acceptBuyOffer(cheri, beckyBuyBackOfferIndex));
1676 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1677 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(5));
1683 uint256 const nftNoAutoTrustID{token::getNextID(
1685 env(token::mint(alice, 0u),
1686 token::xferFee(transferFee),
1691 uint256 const aliceSellOfferIndex =
1693 env(token::createOffer(alice, nftNoAutoTrustID, gwAUD(200)),
1696 env(token::acceptSellOffer(cheri, aliceSellOfferIndex));
1702 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(210));
1705 env(token::createOffer(cheri, nftNoAutoTrustID, gwEUR(50)),
1709 uint256 const cheriSellOfferIndex =
1711 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
1714 env(token::acceptSellOffer(becky, cheriSellOfferIndex));
1720 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(10));
1731 using namespace test::jtx;
1733 Env env{*
this, features};
1735 Account
const alice{
"alice"};
1736 Account
const becky{
"becky"};
1737 Account
const minter{
"minter"};
1739 env.fund(XRP(1000), alice, becky, minter);
1744 BEAST_EXPECT(ownerCount(env, alice) == 0);
1745 uint256 const nftAliceNoTransferID{
1746 token::getNextID(env, alice, 0u)};
1747 env(token::mint(alice, 0u), token::xferFee(0));
1749 BEAST_EXPECT(ownerCount(env, alice) == 1);
1752 BEAST_EXPECT(ownerCount(env, becky) == 0);
1753 env(token::createOffer(becky, nftAliceNoTransferID, XRP(20)),
1754 token::owner(alice),
1758 uint256 const aliceSellOfferIndex =
1760 env(token::createOffer(alice, nftAliceNoTransferID, XRP(20)),
1763 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1765 BEAST_EXPECT(ownerCount(env, alice) == 0);
1766 BEAST_EXPECT(ownerCount(env, becky) == 1);
1769 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1773 BEAST_EXPECT(ownerCount(env, alice) == 0);
1774 BEAST_EXPECT(ownerCount(env, becky) == 1);
1778 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1780 token::destination(alice),
1783 BEAST_EXPECT(ownerCount(env, alice) == 0);
1784 BEAST_EXPECT(ownerCount(env, becky) == 1);
1788 uint256 const aliceBuyOfferIndex =
1790 env(token::createOffer(alice, nftAliceNoTransferID, XRP(22)),
1791 token::owner(becky));
1793 env(token::acceptBuyOffer(becky, aliceBuyOfferIndex));
1795 BEAST_EXPECT(ownerCount(env, alice) == 1);
1796 BEAST_EXPECT(ownerCount(env, becky) == 0);
1799 env(token::burn(alice, nftAliceNoTransferID));
1801 BEAST_EXPECT(ownerCount(env, alice) == 0);
1802 BEAST_EXPECT(ownerCount(env, becky) == 0);
1806 env(token::setMinter(alice, minter));
1809 BEAST_EXPECT(ownerCount(env, minter) == 0);
1810 uint256 const nftMinterNoTransferID{
1811 token::getNextID(env, alice, 0u)};
1812 env(token::mint(minter), token::issuer(alice));
1814 BEAST_EXPECT(ownerCount(env, minter) == 1);
1817 BEAST_EXPECT(ownerCount(env, becky) == 0);
1818 env(token::createOffer(becky, nftMinterNoTransferID, XRP(20)),
1819 token::owner(minter),
1822 BEAST_EXPECT(ownerCount(env, becky) == 0);
1825 env(token::clearMinter(alice));
1829 BEAST_EXPECT(ownerCount(env, minter) == 1);
1830 env(token::createOffer(minter, nftMinterNoTransferID, XRP(21)),
1834 BEAST_EXPECT(ownerCount(env, minter) == 1);
1838 for (
int i = 0; i < 10; ++i)
1841 env(token::setMinter(alice, minter));
1843 BEAST_EXPECT(ownerCount(env, minter) == 1);
1846 BEAST_EXPECT(ownerCount(env, minter) == 1);
1847 uint256 const minterSellOfferIndex =
1849 env(token::createOffer(minter, nftMinterNoTransferID, XRP(22)),
1852 BEAST_EXPECT(ownerCount(env, minter) == 2);
1856 env(token::clearMinter(alice));
1861 BEAST_EXPECT(ownerCount(env, becky) == 0);
1862 env(token::acceptSellOffer(becky, minterSellOfferIndex));
1864 BEAST_EXPECT(ownerCount(env, becky) == 1);
1865 BEAST_EXPECT(ownerCount(env, minter) == 0);
1868 env(token::createOffer(becky, nftMinterNoTransferID, XRP(23)),
1875 BEAST_EXPECT(ownerCount(env, minter) == 0);
1876 env(token::createOffer(minter, nftMinterNoTransferID, XRP(24)),
1877 token::owner(becky),
1880 BEAST_EXPECT(ownerCount(env, minter) == 0);
1883 BEAST_EXPECT(ownerCount(env, alice) == 0);
1884 uint256 const aliceBuyOfferIndex =
1886 env(token::createOffer(alice, nftMinterNoTransferID, XRP(25)),
1887 token::owner(becky));
1889 BEAST_EXPECT(ownerCount(env, alice) == 1);
1893 for (
int i = 0; i < 10; ++i)
1896 env(token::setMinter(alice, minter));
1900 BEAST_EXPECT(ownerCount(env, minter) == 0);
1901 uint256 const minterBuyOfferIndex =
1903 env(token::createOffer(minter, nftMinterNoTransferID, XRP(26)),
1904 token::owner(becky));
1906 BEAST_EXPECT(ownerCount(env, minter) == 1);
1910 env(token::clearMinter(alice));
1914 BEAST_EXPECT(ownerCount(env, minter) == 1);
1915 BEAST_EXPECT(ownerCount(env, becky) == 1);
1916 env(token::acceptBuyOffer(becky, minterBuyOfferIndex));
1918 BEAST_EXPECT(ownerCount(env, minter) == 1);
1919 BEAST_EXPECT(ownerCount(env, becky) == 0);
1920 BEAST_EXPECT(ownerCount(env, alice) == 1);
1924 env(token::burn(minter, nftMinterNoTransferID), ter(
tesSUCCESS));
1926 env(token::cancelOffer(alice, {aliceBuyOfferIndex}));
1928 BEAST_EXPECT(ownerCount(env, alice) == 0);
1929 BEAST_EXPECT(ownerCount(env, becky) == 0);
1930 BEAST_EXPECT(ownerCount(env, minter) == 0);
1935 BEAST_EXPECT(ownerCount(env, alice) == 0);
1940 BEAST_EXPECT(ownerCount(env, alice) == 1);
1943 uint256 const aliceSellOfferIndex =
1945 env(token::createOffer(alice, nftAliceID, XRP(20)),
1948 BEAST_EXPECT(ownerCount(env, alice) == 2);
1950 uint256 const beckyBuyOfferIndex =
1952 env(token::createOffer(becky, nftAliceID, XRP(21)),
1953 token::owner(alice));
1955 BEAST_EXPECT(ownerCount(env, alice) == 2);
1958 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1960 BEAST_EXPECT(ownerCount(env, alice) == 0);
1961 BEAST_EXPECT(ownerCount(env, becky) == 2);
1964 uint256 const beckySellOfferIndex =
1966 env(token::createOffer(becky, nftAliceID, XRP(22)),
1969 BEAST_EXPECT(ownerCount(env, alice) == 0);
1970 BEAST_EXPECT(ownerCount(env, becky) == 3);
1974 env(token::acceptSellOffer(minter, beckySellOfferIndex));
1976 BEAST_EXPECT(ownerCount(env, alice) == 0);
1977 BEAST_EXPECT(ownerCount(env, becky) == 1);
1978 BEAST_EXPECT(ownerCount(env, minter) == 1);
1981 uint256 const minterSellOfferIndex =
1983 env(token::createOffer(minter, nftAliceID, XRP(23)),
1986 BEAST_EXPECT(ownerCount(env, alice) == 0);
1987 BEAST_EXPECT(ownerCount(env, becky) == 1);
1988 BEAST_EXPECT(ownerCount(env, minter) == 2);
1991 env(token::acceptSellOffer(alice, minterSellOfferIndex));
1993 BEAST_EXPECT(ownerCount(env, alice) == 1);
1994 BEAST_EXPECT(ownerCount(env, becky) == 1);
1995 BEAST_EXPECT(ownerCount(env, minter) == 0);
1999 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2001 BEAST_EXPECT(ownerCount(env, alice) == 0);
2002 BEAST_EXPECT(ownerCount(env, becky) == 1);
2003 BEAST_EXPECT(ownerCount(env, minter) == 0);
2007 env(token::burn(becky, nftAliceID));
2009 BEAST_EXPECT(ownerCount(env, alice) == 0);
2010 BEAST_EXPECT(ownerCount(env, becky) == 0);
2011 BEAST_EXPECT(ownerCount(env, minter) == 0);
2021 using namespace test::jtx;
2023 Env env{*
this, features};
2024 auto const baseFee = env.current()->fees().base;
2026 Account
const alice{
"alice"};
2027 Account
const becky{
"becky"};
2028 Account
const carol{
"carol"};
2029 Account
const minter{
"minter"};
2030 Account
const gw{
"gw"};
2031 IOU
const gwXAU(gw[
"XAU"]);
2033 env.fund(XRP(1000), alice, becky, carol, minter, gw);
2036 env(trust(alice, gwXAU(2000)));
2037 env(trust(becky, gwXAU(2000)));
2038 env(trust(carol, gwXAU(2000)));
2039 env(trust(minter, gwXAU(2000)));
2041 env(pay(gw, alice, gwXAU(1000)));
2042 env(pay(gw, becky, gwXAU(1000)));
2043 env(pay(gw, carol, gwXAU(1000)));
2044 env(pay(gw, minter, gwXAU(1000)));
2049 env(token::setMinter(alice, minter));
2055 BEAST_EXPECT(ownerCount(env, alice) == 1);
2056 BEAST_EXPECT(ownerCount(env, becky) == 1);
2057 BEAST_EXPECT(ownerCount(env, carol) == 1);
2058 BEAST_EXPECT(ownerCount(env, minter) == 1);
2066 uint256 const beckyBuyOfferIndex =
2068 env(token::createOffer(becky, nftID, gwXAU(10)),
2069 token::owner(alice));
2071 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2072 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2074 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2076 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2077 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2080 uint256 const beckySellOfferIndex =
2082 env(token::createOffer(becky, nftID, gwXAU(10)),
2085 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2087 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2088 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2089 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2092 uint256 const minterBuyOfferIndex =
2094 env(token::createOffer(minter, nftID, gwXAU(10)),
2095 token::owner(carol));
2097 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2099 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2100 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2101 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2102 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2106 uint256 const minterSellOfferIndex =
2108 env(token::createOffer(minter, nftID, gwXAU(10)),
2111 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2113 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2114 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2115 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2116 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2119 env(token::burn(alice, nftID));
2121 BEAST_EXPECT(ownerCount(env, alice) == 1);
2122 BEAST_EXPECT(ownerCount(env, becky) == 1);
2123 BEAST_EXPECT(ownerCount(env, carol) == 1);
2124 BEAST_EXPECT(ownerCount(env, minter) == 1);
2132 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2136 uint256 const beckyBuyOfferIndex =
2138 env(token::createOffer(becky, nftID, gwXAU(10)),
2139 token::owner(alice));
2141 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2142 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2144 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2146 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2147 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2150 uint256 const beckySellOfferIndex =
2152 env(token::createOffer(becky, nftID, gwXAU(10)),
2155 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2158 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0001));
2159 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2160 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2163 uint256 const minterBuyOfferIndex =
2165 env(token::createOffer(minter, nftID, gwXAU(10)),
2166 token::owner(carol));
2168 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2171 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0002));
2172 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2173 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2174 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2178 uint256 const minterSellOfferIndex =
2180 env(token::createOffer(minter, nftID, gwXAU(10)),
2183 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2185 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000.0002));
2186 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2187 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2188 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2192 env(pay(alice, becky, gwXAU(0.0001)));
2193 env(pay(alice, carol, gwXAU(0.0001)));
2196 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2197 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2198 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2199 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2202 env(token::burn(alice, nftID));
2204 BEAST_EXPECT(ownerCount(env, alice) == 1);
2205 BEAST_EXPECT(ownerCount(env, becky) == 1);
2206 BEAST_EXPECT(ownerCount(env, carol) == 1);
2207 BEAST_EXPECT(ownerCount(env, minter) == 1);
2213 env(token::mint(alice),
2220 uint256 const nftID = token::getNextID(
2222 env(token::mint(alice),
2228 uint256 const beckyBuyOfferIndex =
2230 env(token::createOffer(becky, nftID, gwXAU(10)),
2231 token::owner(alice));
2233 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2234 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2236 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2238 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2239 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2242 uint256 const beckySellOfferIndex =
2244 env(token::createOffer(becky, nftID, gwXAU(100)),
2247 env(token::acceptSellOffer(minter, beckySellOfferIndex));
2250 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1060));
2251 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2252 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
2255 uint256 const carolBuyOfferIndex =
2257 env(token::createOffer(carol, nftID, gwXAU(10)),
2258 token::owner(minter));
2260 env(token::acceptBuyOffer(minter, carolBuyOfferIndex));
2263 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1065));
2264 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2265 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2266 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2270 uint256 const carolSellOfferIndex =
2272 env(token::createOffer(carol, nftID, gwXAU(10)),
2275 env(token::acceptSellOffer(alice, carolSellOfferIndex));
2278 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1055));
2279 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2280 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2281 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2284 env(pay(alice, minter, gwXAU(55)));
2285 env(pay(becky, minter, gwXAU(40)));
2287 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2288 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2289 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2290 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2293 env(token::burn(alice, nftID));
2295 BEAST_EXPECT(ownerCount(env, alice) == 1);
2296 BEAST_EXPECT(ownerCount(env, becky) == 1);
2297 BEAST_EXPECT(ownerCount(env, carol) == 1);
2298 BEAST_EXPECT(ownerCount(env, minter) == 1);
2303 for (
auto NumberSwitchOver : {
true})
2305 if (NumberSwitchOver)
2306 env.enableFeature(fixUniversalNumber);
2308 env.disableFeature(fixUniversalNumber);
2313 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2318 STAmount aliceBalance = env.balance(alice);
2319 STAmount minterBalance = env.balance(minter);
2320 uint256 const minterBuyOfferIndex =
2322 env(token::createOffer(minter, nftID, XRP(1)), token::owner(alice));
2324 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2326 aliceBalance += XRP(1) - baseFee;
2327 minterBalance -= XRP(1) + baseFee;
2328 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2329 BEAST_EXPECT(env.balance(minter) == minterBalance);
2333 auto pmt = NumberSwitchOver ? drops(50000) : drops(99999);
2334 STAmount carolBalance = env.balance(carol);
2335 uint256 const minterSellOfferIndex =
2337 env(token::createOffer(minter, nftID, pmt), txflags(
tfSellNFToken));
2339 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2341 minterBalance += pmt - baseFee;
2342 carolBalance -= pmt + baseFee;
2343 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2344 BEAST_EXPECT(env.balance(minter) == minterBalance);
2345 BEAST_EXPECT(env.balance(carol) == carolBalance);
2349 STAmount beckyBalance = env.balance(becky);
2350 uint256 const beckyBuyOfferIndex =
2352 pmt = NumberSwitchOver ? drops(50001) : drops(100000);
2353 env(token::createOffer(becky, nftID, pmt), token::owner(carol));
2355 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2357 carolBalance += pmt - drops(1) - baseFee;
2358 beckyBalance -= pmt + baseFee;
2359 aliceBalance += drops(1);
2361 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2362 BEAST_EXPECT(env.balance(minter) == minterBalance);
2363 BEAST_EXPECT(env.balance(carol) == carolBalance);
2364 BEAST_EXPECT(env.balance(becky) == beckyBalance);
2373 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2379 env(pay(alice, gw, env.balance(alice, gwXAU)));
2380 env(pay(minter, gw, env.balance(minter, gwXAU)));
2381 env(pay(becky, gw, env.balance(becky, gwXAU)));
2386 env(pay(gw, alice, startXAUBalance));
2387 env(pay(gw, minter, startXAUBalance));
2388 env(pay(gw, becky, startXAUBalance));
2397 STAmount aliceBalance = env.balance(alice, gwXAU);
2398 STAmount minterBalance = env.balance(minter, gwXAU);
2399 uint256 const minterBuyOfferIndex =
2401 env(token::createOffer(minter, nftID, tinyXAU),
2402 token::owner(alice));
2404 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2406 aliceBalance += tinyXAU;
2407 minterBalance -= tinyXAU;
2408 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2409 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2412 STAmount carolBalance = env.balance(carol, gwXAU);
2413 uint256 const minterSellOfferIndex =
2415 env(token::createOffer(minter, nftID, tinyXAU),
2418 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2421 minterBalance += tinyXAU;
2422 carolBalance -= tinyXAU;
2424 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2425 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2426 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2433 STAmount beckyBalance = env.balance(becky, gwXAU);
2434 uint256 const beckyBuyOfferIndex =
2436 env(token::createOffer(becky, nftID, cheapNFT),
2437 token::owner(carol));
2439 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2442 aliceBalance += tinyXAU;
2443 beckyBalance -= cheapNFT;
2444 carolBalance += cheapNFT - tinyXAU;
2445 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2446 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2447 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2448 BEAST_EXPECT(env.balance(becky, gwXAU) == beckyBalance);
2641 testcase(
"Create offer destination");
2643 using namespace test::jtx;
2645 Env env{*
this, features};
2647 Account
const issuer{
"issuer"};
2648 Account
const minter{
"minter"};
2649 Account
const buyer{
"buyer"};
2650 Account
const broker{
"broker"};
2652 env.fund(XRP(1000), issuer, minter, buyer, broker);
2656 env(token::setMinter(issuer, minter));
2661 env(token::mint(minter, 0),
2662 token::issuer(issuer),
2669 uint256 const offerMinterToIssuer =
2671 env(token::createOffer(minter, nftokenID, drops(1)),
2672 token::destination(issuer),
2675 uint256 const offerMinterToBuyer =
2677 env(token::createOffer(minter, nftokenID, drops(1)),
2678 token::destination(buyer),
2681 uint256 const offerIssuerToMinter =
2683 env(token::createOffer(issuer, nftokenID, drops(1)),
2684 token::owner(minter),
2685 token::destination(minter));
2687 uint256 const offerIssuerToBuyer =
2689 env(token::createOffer(issuer, nftokenID, drops(1)),
2690 token::owner(minter),
2691 token::destination(buyer));
2694 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2695 BEAST_EXPECT(ownerCount(env, minter) == 3);
2696 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2705 env(token::cancelOffer(issuer, {offerMinterToBuyer}),
2707 env(token::cancelOffer(buyer, {offerMinterToIssuer}),
2709 env(token::cancelOffer(buyer, {offerIssuerToMinter}),
2711 env(token::cancelOffer(minter, {offerIssuerToBuyer}),
2714 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2715 BEAST_EXPECT(ownerCount(env, minter) == 3);
2716 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2720 env(token::cancelOffer(buyer, {offerMinterToBuyer}));
2721 env(token::cancelOffer(minter, {offerMinterToIssuer}));
2722 env(token::cancelOffer(buyer, {offerIssuerToBuyer}));
2723 env(token::cancelOffer(issuer, {offerIssuerToMinter}));
2725 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2726 BEAST_EXPECT(ownerCount(env, minter) == 1);
2727 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2733 uint256 const offerMinterSellsToBuyer =
2735 env(token::createOffer(minter, nftokenID, drops(1)),
2736 token::destination(buyer),
2739 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2740 BEAST_EXPECT(ownerCount(env, minter) == 2);
2741 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2745 env(token::acceptSellOffer(issuer, offerMinterSellsToBuyer),
2748 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2749 BEAST_EXPECT(ownerCount(env, minter) == 2);
2750 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2753 env(token::acceptSellOffer(buyer, offerMinterSellsToBuyer));
2755 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2756 BEAST_EXPECT(ownerCount(env, minter) == 0);
2757 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2763 uint256 const offerMinterBuysFromBuyer =
2765 env(token::createOffer(minter, nftokenID, drops(1)),
2766 token::owner(buyer),
2767 token::destination(buyer));
2769 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2770 BEAST_EXPECT(ownerCount(env, minter) == 1);
2771 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2775 env(token::acceptBuyOffer(issuer, offerMinterBuysFromBuyer),
2778 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2779 BEAST_EXPECT(ownerCount(env, minter) == 1);
2780 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2783 env(token::acceptBuyOffer(buyer, offerMinterBuysFromBuyer));
2785 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2786 BEAST_EXPECT(ownerCount(env, minter) == 1);
2787 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2792 uint256 const offerBuyerBuysFromMinter =
2794 env(token::createOffer(buyer, nftokenID, drops(1)),
2795 token::owner(minter),
2796 token::destination(broker));
2798 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2799 BEAST_EXPECT(ownerCount(env, minter) == 1);
2800 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2802 env(token::acceptBuyOffer(minter, offerBuyerBuysFromMinter),
2807 env(token::cancelOffer(buyer, {offerBuyerBuysFromMinter}));
2809 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2810 BEAST_EXPECT(ownerCount(env, minter) == 1);
2811 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2817 uint256 const offerMinterToBroker =
2819 env(token::createOffer(minter, nftokenID, drops(1)),
2820 token::destination(broker),
2823 uint256 const offerBuyerToMinter =
2825 env(token::createOffer(buyer, nftokenID, drops(1)),
2826 token::owner(minter));
2829 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2830 BEAST_EXPECT(ownerCount(env, minter) == 2);
2831 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2836 env(token::brokerOffers(
2837 issuer, offerBuyerToMinter, offerMinterToBroker),
2840 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2841 BEAST_EXPECT(ownerCount(env, minter) == 2);
2842 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2847 env(token::brokerOffers(
2848 broker, offerBuyerToMinter, offerMinterToBroker));
2850 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2851 BEAST_EXPECT(ownerCount(env, minter) == 0);
2852 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2859 uint256 const offerBuyerToMinter =
2861 env(token::createOffer(buyer, nftokenID, drops(1)),
2862 token::destination(minter),
2865 uint256 const offerMinterToBuyer =
2867 env(token::createOffer(minter, nftokenID, drops(1)),
2868 token::owner(buyer));
2870 uint256 const offerIssuerToBuyer =
2872 env(token::createOffer(issuer, nftokenID, drops(1)),
2873 token::owner(buyer));
2876 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2877 BEAST_EXPECT(ownerCount(env, minter) == 1);
2878 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2883 env(token::brokerOffers(
2884 broker, offerIssuerToBuyer, offerBuyerToMinter),
2888 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2889 BEAST_EXPECT(ownerCount(env, minter) == 1);
2890 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2892 env(token::brokerOffers(
2893 broker, offerMinterToBuyer, offerBuyerToMinter),
2898 env(token::acceptBuyOffer(buyer, offerMinterToBuyer));
2902 env(token::cancelOffer(buyer, {offerBuyerToMinter}));
2905 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2906 BEAST_EXPECT(ownerCount(env, minter) == 1);
2907 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2910 env(token::cancelOffer(issuer, {offerIssuerToBuyer}));
2912 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2913 BEAST_EXPECT(ownerCount(env, minter) == 1);
2914 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2922 uint256 const offerMinterToBroker =
2924 env(token::createOffer(minter, nftokenID, drops(1)),
2925 token::destination(broker),
2928 uint256 const offerBuyerToBroker =
2930 env(token::createOffer(buyer, nftokenID, drops(1)),
2931 token::owner(minter),
2932 token::destination(broker));
2937 env(token::brokerOffers(
2938 issuer, offerBuyerToBroker, offerMinterToBroker),
2941 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2942 BEAST_EXPECT(ownerCount(env, minter) == 2);
2943 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2947 env(token::brokerOffers(
2948 broker, offerBuyerToBroker, offerMinterToBroker));
2950 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2951 BEAST_EXPECT(ownerCount(env, minter) == 0);
2952 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3109 testcase(
"Create offer expiration");
3111 using namespace test::jtx;
3113 Env env{*
this, features};
3115 Account
const issuer{
"issuer"};
3116 Account
const minter{
"minter"};
3117 Account
const buyer{
"buyer"};
3119 env.fund(XRP(1000), issuer, minter, buyer);
3123 env(token::setMinter(issuer, minter));
3128 env(token::mint(minter, 0),
3129 token::issuer(issuer),
3135 env(token::mint(minter, 0),
3136 token::issuer(issuer),
3145 uint256 const offerMinterToIssuer =
3147 env(token::createOffer(minter, nftokenID0, drops(1)),
3148 token::destination(issuer),
3149 token::expiration(expiration),
3152 uint256 const offerMinterToAnyone =
3154 env(token::createOffer(minter, nftokenID0, drops(1)),
3155 token::expiration(expiration),
3158 uint256 const offerIssuerToMinter =
3160 env(token::createOffer(issuer, nftokenID0, drops(1)),
3161 token::owner(minter),
3162 token::expiration(expiration));
3164 uint256 const offerBuyerToMinter =
3166 env(token::createOffer(buyer, nftokenID0, drops(1)),
3167 token::owner(minter),
3168 token::expiration(expiration));
3170 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3171 BEAST_EXPECT(ownerCount(env, minter) == 3);
3172 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3180 env(token::cancelOffer(issuer, {offerMinterToAnyone}),
3182 env(token::cancelOffer(buyer, {offerIssuerToMinter}),
3185 BEAST_EXPECT(
lastClose(env) < expiration);
3186 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3187 BEAST_EXPECT(ownerCount(env, minter) == 3);
3188 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3191 env(token::cancelOffer(minter, {offerMinterToAnyone}));
3195 env(token::cancelOffer(issuer, {offerMinterToIssuer}));
3201 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3202 BEAST_EXPECT(ownerCount(env, minter) == 1);
3203 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3206 env(token::cancelOffer(issuer, {offerBuyerToMinter}));
3207 env(token::cancelOffer(buyer, {offerIssuerToMinter}));
3209 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3210 BEAST_EXPECT(ownerCount(env, minter) == 1);
3211 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3222 env(token::createOffer(minter, nftokenID0, drops(1)),
3223 token::expiration(expiration),
3228 env(token::createOffer(minter, nftokenID1, drops(1)),
3229 token::expiration(expiration),
3232 BEAST_EXPECT(
lastClose(env) < expiration);
3233 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3234 BEAST_EXPECT(ownerCount(env, minter) == 3);
3235 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3238 env(token::acceptSellOffer(buyer, offer0));
3244 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3245 BEAST_EXPECT(ownerCount(env, minter) == 2);
3246 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3249 env(token::acceptSellOffer(buyer, offer1), ter(
tecEXPIRED));
3250 env(token::acceptSellOffer(issuer, offer1), ter(
tecEXPIRED));
3254 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3255 BEAST_EXPECT(ownerCount(env, minter) == 2);
3256 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3259 env(token::cancelOffer(issuer, {offer1}));
3261 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3262 BEAST_EXPECT(ownerCount(env, minter) == 1);
3263 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3269 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3271 token::destination(minter));
3273 env(token::acceptSellOffer(minter, offerSellBack));
3275 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3276 BEAST_EXPECT(ownerCount(env, minter) == 1);
3277 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3287 env(token::createOffer(buyer, nftokenID0, drops(1)),
3288 token::owner(minter),
3289 token::expiration(expiration));
3292 env(token::createOffer(buyer, nftokenID1, drops(1)),
3293 token::owner(minter),
3294 token::expiration(expiration));
3296 BEAST_EXPECT(
lastClose(env) < expiration);
3297 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3298 BEAST_EXPECT(ownerCount(env, minter) == 1);
3299 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3302 env(token::acceptBuyOffer(minter, offer0));
3308 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3309 BEAST_EXPECT(ownerCount(env, minter) == 1);
3310 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3313 env(token::acceptBuyOffer(minter, offer1), ter(
tecEXPIRED));
3314 env(token::acceptBuyOffer(issuer, offer1), ter(
tecEXPIRED));
3318 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3319 BEAST_EXPECT(ownerCount(env, minter) == 1);
3320 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3323 env(token::cancelOffer(issuer, {offer1}));
3325 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3326 BEAST_EXPECT(ownerCount(env, minter) == 1);
3327 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3333 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3335 token::destination(minter));
3337 env(token::acceptSellOffer(minter, offerSellBack));
3339 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3340 BEAST_EXPECT(ownerCount(env, minter) == 1);
3341 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3352 env(token::createOffer(minter, nftokenID0, drops(1)),
3353 token::expiration(expiration),
3358 env(token::createOffer(minter, nftokenID1, drops(1)),
3359 token::expiration(expiration),
3364 env(token::createOffer(buyer, nftokenID0, drops(1)),
3365 token::owner(minter));
3369 env(token::createOffer(buyer, nftokenID1, drops(1)),
3370 token::owner(minter));
3373 BEAST_EXPECT(
lastClose(env) < expiration);
3374 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3375 BEAST_EXPECT(ownerCount(env, minter) == 3);
3376 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3379 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3385 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3386 BEAST_EXPECT(ownerCount(env, minter) == 2);
3387 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3390 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3395 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3396 BEAST_EXPECT(ownerCount(env, minter) == 2);
3397 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3400 env(token::cancelOffer(buyer, {buyOffer1, sellOffer1}));
3402 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3403 BEAST_EXPECT(ownerCount(env, minter) == 1);
3404 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3410 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3412 token::destination(minter));
3414 env(token::acceptSellOffer(minter, offerSellBack));
3416 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3417 BEAST_EXPECT(ownerCount(env, minter) == 1);
3418 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3429 env(token::createOffer(minter, nftokenID0, drops(1)),
3434 env(token::createOffer(minter, nftokenID1, drops(1)),
3439 env(token::createOffer(buyer, nftokenID0, drops(1)),
3440 token::expiration(expiration),
3441 token::owner(minter));
3445 env(token::createOffer(buyer, nftokenID1, drops(1)),
3446 token::expiration(expiration),
3447 token::owner(minter));
3450 BEAST_EXPECT(
lastClose(env) < expiration);
3451 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3452 BEAST_EXPECT(ownerCount(env, minter) == 3);
3453 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3456 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3462 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3463 BEAST_EXPECT(ownerCount(env, minter) == 2);
3464 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3467 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3472 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3473 BEAST_EXPECT(ownerCount(env, minter) == 2);
3474 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3477 env(token::cancelOffer(minter, {buyOffer1, sellOffer1}));
3479 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3480 BEAST_EXPECT(ownerCount(env, minter) == 1);
3481 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3487 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3489 token::destination(minter));
3491 env(token::acceptSellOffer(minter, offerSellBack));
3493 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3494 BEAST_EXPECT(ownerCount(env, minter) == 1);
3495 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3507 env(token::createOffer(minter, nftokenID0, drops(1)),
3508 token::expiration(expiration),
3513 env(token::createOffer(minter, nftokenID1, drops(1)),
3514 token::expiration(expiration),
3519 env(token::createOffer(buyer, nftokenID0, drops(1)),
3520 token::expiration(expiration),
3521 token::owner(minter));
3525 env(token::createOffer(buyer, nftokenID1, drops(1)),
3526 token::expiration(expiration),
3527 token::owner(minter));
3530 BEAST_EXPECT(
lastClose(env) < expiration);
3531 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3532 BEAST_EXPECT(ownerCount(env, minter) == 3);
3533 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3536 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3542 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3543 BEAST_EXPECT(ownerCount(env, minter) == 2);
3544 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3547 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3552 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3553 BEAST_EXPECT(ownerCount(env, minter) == 2);
3554 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3557 env(token::cancelOffer(issuer, {buyOffer1, sellOffer1}));
3559 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3560 BEAST_EXPECT(ownerCount(env, minter) == 1);
3561 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3567 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3569 token::destination(minter));
3571 env(token::acceptSellOffer(minter, offerSellBack));
3573 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3574 BEAST_EXPECT(ownerCount(env, minter) == 1);
3575 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3816 testcase(
"Brokered NFT offer accept");
3818 using namespace test::jtx;
3821 Env env{*
this, features};
3822 auto const baseFee = env.current()->fees().base;
3830 Account
const issuer{
"issuer"};
3831 Account
const minter{
"minter"};
3832 Account
const buyer{
"buyer"};
3833 Account
const broker{
"broker"};
3834 Account
const gw{
"gw"};
3835 IOU
const gwXAU(gw[
"XAU"]);
3837 env.fund(XRP(1000), issuer, minter, buyer, broker, gw);
3840 env(trust(issuer, gwXAU(2000)));
3841 env(trust(minter, gwXAU(2000)));
3842 env(trust(buyer, gwXAU(2000)));
3843 env(trust(broker, gwXAU(2000)));
3846 env(token::setMinter(issuer, minter));
3850 auto checkOwnerCountIsOne =
3855 for (Account
const& acct : accounts)
3862 ss <<
"Account " << acct.human()
3863 <<
" expected ownerCount == 1. Got "
3865 fail(ss.
str(), __FILE__, line);
3871 auto mintNFT = [&env, &issuer, &minter](
std::uint16_t xferFee = 0) {
3874 env(token::mint(minter, 0),
3875 token::issuer(issuer),
3876 token::xferFee(xferFee),
3888 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3890 uint256 const nftID = mintNFT();
3893 uint256 const minterOfferIndex =
3895 env(token::createOffer(minter, nftID, XRP(0)),
3903 env(token::createOffer(buyer, nftID, XRP(1)),
3904 token::owner(minter));
3907 auto const minterBalance = env.balance(minter);
3908 auto const buyerBalance = env.balance(buyer);
3909 auto const brokerBalance = env.balance(broker);
3910 auto const issuerBalance = env.balance(issuer);
3913 env(token::brokerOffers(
3914 broker, buyOfferIndex, minterOfferIndex));
3919 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(1));
3920 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3921 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
3922 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
3925 env(token::burn(buyer, nftID));
3935 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3937 uint256 const nftID = mintNFT();
3940 uint256 const minterOfferIndex =
3942 env(token::createOffer(minter, nftID, XRP(0)),
3950 env(token::createOffer(buyer, nftID, XRP(1)),
3951 token::owner(minter));
3955 env(token::brokerOffers(
3956 broker, buyOfferIndex, minterOfferIndex),
3957 token::brokerFee(XRP(1.1)),
3961 auto const minterBalance = env.balance(minter);
3962 auto const buyerBalance = env.balance(buyer);
3963 auto const brokerBalance = env.balance(broker);
3964 auto const issuerBalance = env.balance(issuer);
3967 env(token::brokerOffers(
3968 broker, buyOfferIndex, minterOfferIndex),
3969 token::brokerFee(XRP(0.5)));
3974 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
3975 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3977 env.balance(broker) == brokerBalance + XRP(0.5) - baseFee);
3978 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
3981 env(token::burn(buyer, nftID));
3991 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3996 uint256 const minterOfferIndex =
3998 env(token::createOffer(minter, nftID, XRP(0)),
4006 env(token::createOffer(buyer, nftID, XRP(1)),
4007 token::owner(minter));
4010 auto const minterBalance = env.balance(minter);
4011 auto const buyerBalance = env.balance(buyer);
4012 auto const brokerBalance = env.balance(broker);
4013 auto const issuerBalance = env.balance(issuer);
4016 env(token::brokerOffers(
4017 broker, buyOfferIndex, minterOfferIndex));
4022 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
4023 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4024 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
4025 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.5));
4028 env(token::burn(buyer, nftID));
4038 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4043 uint256 const minterOfferIndex =
4045 env(token::createOffer(minter, nftID, XRP(0)),
4053 env(token::createOffer(buyer, nftID, XRP(1)),
4054 token::owner(minter));
4057 auto const minterBalance = env.balance(minter);
4058 auto const buyerBalance = env.balance(buyer);
4059 auto const brokerBalance = env.balance(broker);
4060 auto const issuerBalance = env.balance(issuer);
4063 env(token::brokerOffers(
4064 broker, buyOfferIndex, minterOfferIndex),
4065 token::brokerFee(XRP(0.75)));
4071 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.125));
4072 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4074 env.balance(broker) == brokerBalance + XRP(0.75) - baseFee);
4075 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.125));
4078 env(token::burn(buyer, nftID));
4084 auto setXAUBalance =
4085 [
this, &gw, &gwXAU, &env](
4090 for (Account
const& acct : accounts)
4092 auto const xauAmt = gwXAU(amount);
4093 auto const balance = env.balance(acct, gwXAU);
4094 if (balance < xauAmt)
4096 env(pay(gw, acct, xauAmt - balance));
4099 else if (balance > xauAmt)
4101 env(pay(acct, gw, balance - xauAmt));
4104 if (env.balance(acct, gwXAU) != xauAmt)
4107 ss <<
"Unable to set " << acct.human()
4108 <<
" account balance to gwXAU(" << amount <<
")";
4109 this->
fail(ss.
str(), __FILE__, line);
4117 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4118 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4120 uint256 const nftID = mintNFT();
4123 uint256 const minterOfferIndex =
4125 env(token::createOffer(minter, nftID, gwXAU(1000)),
4134 env(token::createOffer(buyer, nftID, gwXAU(1001)),
4135 token::owner(minter));
4139 env(token::brokerOffers(
4140 broker, buyOfferIndex, minterOfferIndex),
4146 env(token::cancelOffer(buyer, {buyOfferIndex}));
4154 env(token::createOffer(buyer, nftID, gwXAU(999)),
4155 token::owner(minter));
4159 env(token::brokerOffers(
4160 broker, buyOfferIndex, minterOfferIndex),
4166 env(token::cancelOffer(buyer, {buyOfferIndex}));
4173 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4174 token::owner(minter));
4178 env(token::brokerOffers(
4179 broker, buyOfferIndex, minterOfferIndex),
4180 token::brokerFee(gwXAU(0.1)),
4185 env(token::brokerOffers(
4186 broker, buyOfferIndex, minterOfferIndex));
4189 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4190 BEAST_EXPECT(ownerCount(env, minter) == 1);
4191 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4192 BEAST_EXPECT(ownerCount(env, broker) == 1);
4193 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1000));
4194 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(2000));
4195 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4196 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1000));
4199 env(token::burn(buyer, nftID));
4206 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4207 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4212 uint256 const minterOfferIndex =
4214 env(token::createOffer(minter, nftID, gwXAU(900)),
4222 env(token::createOffer(buyer, nftID, gwXAU(1001)),
4223 token::owner(minter));
4227 env(token::brokerOffers(
4228 broker, buyOfferIndex, minterOfferIndex),
4234 env(token::cancelOffer(buyer, {buyOfferIndex}));
4242 env(token::createOffer(buyer, nftID, gwXAU(899)),
4243 token::owner(minter));
4247 env(token::brokerOffers(
4248 broker, buyOfferIndex, minterOfferIndex),
4254 env(token::cancelOffer(buyer, {buyOfferIndex}));
4260 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4261 token::owner(minter));
4266 env(token::brokerOffers(
4267 broker, buyOfferIndex, minterOfferIndex),
4268 token::brokerFee(gwXAU(101)),
4274 env(token::brokerOffers(
4275 broker, buyOfferIndex, minterOfferIndex),
4276 token::brokerFee(gwXAU(100)));
4279 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4280 BEAST_EXPECT(ownerCount(env, minter) == 1);
4281 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4282 BEAST_EXPECT(ownerCount(env, broker) == 1);
4283 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1450));
4284 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1450));
4285 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4286 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1100));
4289 env(token::burn(buyer, nftID));
4296 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4297 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4302 uint256 const minterOfferIndex =
4304 env(token::createOffer(minter, nftID, gwXAU(900)),
4311 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4312 token::owner(minter));
4318 env(token::brokerOffers(
4319 broker, buyOfferIndex, minterOfferIndex),
4320 token::brokerFee(gwXAU(50)));
4323 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4324 BEAST_EXPECT(ownerCount(env, minter) == 1);
4325 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4326 BEAST_EXPECT(ownerCount(env, broker) == 1);
4327 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4328 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4329 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4330 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1050));
4333 env(token::burn(buyer, nftID));
4338 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4339 setXAUBalance({issuer, minter, buyer}, 1000, __LINE__);
4340 setXAUBalance({broker}, 500, __LINE__);
4344 uint256 const minterOfferIndex =
4346 env(token::createOffer(minter, nftID, gwXAU(900)),
4353 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4354 token::owner(minter));
4357 env(token::brokerOffers(
4358 broker, buyOfferIndex, minterOfferIndex),
4359 token::brokerFee(gwXAU(50)));
4361 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4362 BEAST_EXPECT(ownerCount(env, minter) == 1);
4363 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4364 BEAST_EXPECT(ownerCount(env, broker) == 1);
4365 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4366 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4367 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4368 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(550));
4371 env(token::burn(buyer, nftID));
4995 using namespace test::jtx;
4997 testcase(
"Payments with IOU transfer fees");
5000 Env env{*
this, features};
5002 Account
const minter{
"minter"};
5003 Account
const secondarySeller{
"seller"};
5004 Account
const buyer{
"buyer"};
5005 Account
const gw{
"gateway"};
5006 Account
const broker{
"broker"};
5007 IOU
const gwXAU(gw[
"XAU"]);
5008 IOU
const gwXPB(gw[
"XPB"]);
5010 env.fund(XRP(1000), gw, minter, secondarySeller, buyer, broker);
5013 env(trust(minter, gwXAU(2000)));
5014 env(trust(secondarySeller, gwXAU(2000)));
5015 env(trust(broker, gwXAU(10000)));
5016 env(trust(buyer, gwXAU(2000)));
5017 env(trust(buyer, gwXPB(2000)));
5021 env(rate(gw, 1.02));
5024 auto expectInitialState = [
this,
5037 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(1000));
5038 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(0));
5039 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(0));
5040 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(0));
5041 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(0));
5042 BEAST_EXPECT(env.balance(secondarySeller, gwXPB) == gwXPB(0));
5043 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5000));
5044 BEAST_EXPECT(env.balance(broker, gwXPB) == gwXPB(0));
5045 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-1000));
5046 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(0));
5047 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(0));
5048 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(0));
5050 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(0));
5052 env.balance(gw, secondarySeller[
"XPB"]) == gwXPB(0));
5053 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5000));
5054 BEAST_EXPECT(env.balance(gw, broker[
"XPB"]) == gwXPB(0));
5057 auto reinitializeTrustLineBalances = [&expectInitialState,
5066 if (
auto const difference =
5067 gwXAU(1000) - env.balance(buyer, gwXAU);
5068 difference > gwXAU(0))
5069 env(pay(gw, buyer, difference));
5070 if (env.balance(buyer, gwXPB) > gwXPB(0))
5071 env(pay(buyer, gw, env.balance(buyer, gwXPB)));
5072 if (env.balance(minter, gwXAU) > gwXAU(0))
5073 env(pay(minter, gw, env.balance(minter, gwXAU)));
5074 if (env.balance(minter, gwXPB) > gwXPB(0))
5075 env(pay(minter, gw, env.balance(minter, gwXPB)));
5076 if (env.balance(secondarySeller, gwXAU) > gwXAU(0))
5078 pay(secondarySeller,
5080 env.balance(secondarySeller, gwXAU)));
5081 if (env.balance(secondarySeller, gwXPB) > gwXPB(0))
5083 pay(secondarySeller,
5085 env.balance(secondarySeller, gwXPB)));
5086 auto brokerDiff = gwXAU(5000) - env.balance(broker, gwXAU);
5087 if (brokerDiff > gwXAU(0))
5088 env(pay(gw, broker, brokerDiff));
5089 else if (brokerDiff < gwXAU(0))
5091 brokerDiff.negate();
5092 env(pay(broker, gw, brokerDiff));
5094 if (env.balance(broker, gwXPB) > gwXPB(0))
5095 env(pay(broker, gw, env.balance(broker, gwXPB)));
5097 expectInitialState();
5100 auto mintNFT = [&env](Account
const& minter,
int transferFee = 0) {
5101 uint256 const nftID = token::getNextID(
5103 env(token::mint(minter),
5104 token::xferFee(transferFee),
5110 auto createBuyOffer =
5112 Account
const& offerer,
5113 Account
const& owner,
5119 env(token::createOffer(offerer, nftID, amount),
5120 token::owner(owner),
5121 terCode ? ter(*terCode)
5127 auto createSellOffer =
5129 Account
const& offerer,
5135 env(token::createOffer(offerer, nftID, amount),
5137 terCode ? ter(*terCode)
5146 reinitializeTrustLineBalances();
5147 auto const nftID = mintNFT(minter);
5148 auto const offerID =
5149 createSellOffer(minter, nftID, gwXAU(1000));
5151 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5154 expectInitialState();
5159 reinitializeTrustLineBalances();
5160 auto const nftID = mintNFT(minter);
5161 auto const offerID =
5162 createBuyOffer(buyer, minter, nftID, gwXAU(1000));
5164 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5167 expectInitialState();
5173 reinitializeTrustLineBalances();
5174 auto const nftID = mintNFT(minter);
5175 auto const offerID = createSellOffer(minter, nftID, gwXAU(995));
5177 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5180 expectInitialState();
5186 reinitializeTrustLineBalances();
5187 auto const nftID = mintNFT(minter);
5188 auto const offerID =
5189 createBuyOffer(buyer, minter, nftID, gwXAU(995));
5191 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5194 expectInitialState();
5201 reinitializeTrustLineBalances();
5202 auto const nftID = mintNFT(minter);
5203 auto const offerID = createSellOffer(minter, nftID, gwXAU(900));
5204 env(token::acceptSellOffer(buyer, offerID));
5207 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
5208 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5209 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
5210 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5217 reinitializeTrustLineBalances();
5218 auto const nftID = mintNFT(minter);
5219 auto const offerID =
5220 createBuyOffer(buyer, minter, nftID, gwXAU(900));
5221 env(token::acceptBuyOffer(minter, offerID));
5224 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
5225 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5226 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
5227 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5234 reinitializeTrustLineBalances();
5237 env(pay(gw, buyer, gwXAU(20)));
5240 auto const nftID = mintNFT(minter);
5241 auto const offerID =
5242 createSellOffer(minter, nftID, gwXAU(1000));
5243 env(token::acceptSellOffer(buyer, offerID));
5246 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5247 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5248 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5249 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5256 reinitializeTrustLineBalances();
5259 env(pay(gw, buyer, gwXAU(20)));
5262 auto const nftID = mintNFT(minter);
5263 auto const offerID =
5264 createBuyOffer(buyer, minter, nftID, gwXAU(1000));
5265 env(token::acceptBuyOffer(minter, offerID));
5268 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5269 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5270 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5271 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5276 reinitializeTrustLineBalances();
5278 auto const nftID = mintNFT(minter);
5279 auto const offerID =
5280 createSellOffer(minter, nftID, gwXAU(1000));
5282 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
5285 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5286 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5291 reinitializeTrustLineBalances();
5293 auto const nftID = mintNFT(minter);
5295 auto const offerID =
5296 createBuyOffer(gw, minter, nftID, gwXAU(1000), {offerTER});
5298 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5301 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5302 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5307 reinitializeTrustLineBalances();
5308 auto const nftID = mintNFT(minter);
5309 auto const offerID =
5310 createSellOffer(minter, nftID, gwXAU(5000));
5312 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
5315 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5316 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5321 reinitializeTrustLineBalances();
5323 auto const nftID = mintNFT(minter);
5325 auto const offerID =
5326 createBuyOffer(gw, minter, nftID, gwXAU(5000), {offerTER});
5328 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5331 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5332 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5338 reinitializeTrustLineBalances();
5339 auto const nftID = mintNFT(gw);
5340 auto const offerID = createSellOffer(gw, nftID, gwXAU(1000));
5341 env(token::acceptSellOffer(buyer, offerID));
5344 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5345 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5351 reinitializeTrustLineBalances();
5353 auto const nftID = mintNFT(gw);
5354 auto const offerID =
5355 createBuyOffer(buyer, gw, nftID, gwXAU(1000));
5356 env(token::acceptBuyOffer(gw, offerID));
5359 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5360 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5366 reinitializeTrustLineBalances();
5367 auto const nftID = mintNFT(gw);
5368 auto const offerID = createSellOffer(gw, nftID, gwXAU(2000));
5369 env(token::acceptSellOffer(buyer, offerID),
5372 expectInitialState();
5378 reinitializeTrustLineBalances();
5379 auto const nftID = mintNFT(gw);
5380 auto const offerID =
5381 createBuyOffer(buyer, gw, nftID, gwXAU(2000));
5382 env(token::acceptBuyOffer(gw, offerID),
5385 expectInitialState();
5390 reinitializeTrustLineBalances();
5391 auto const nftID = mintNFT(minter);
5392 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5393 env(token::acceptSellOffer(buyer, offerID),
5396 expectInitialState();
5401 reinitializeTrustLineBalances();
5402 auto const nftID = mintNFT(minter);
5403 auto const offerID = createBuyOffer(
5409 env(token::acceptBuyOffer(minter, offerID),
5412 expectInitialState();
5418 reinitializeTrustLineBalances();
5419 env(pay(gw, buyer, gwXPB(100)));
5422 auto const nftID = mintNFT(minter);
5423 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5424 env(token::acceptSellOffer(buyer, offerID));
5427 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5428 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5429 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5430 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5436 reinitializeTrustLineBalances();
5437 env(pay(gw, buyer, gwXPB(100)));
5440 auto const nftID = mintNFT(minter);
5441 auto const offerID =
5442 createBuyOffer(buyer, minter, nftID, gwXPB(10));
5443 env(token::acceptBuyOffer(minter, offerID));
5446 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5447 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5448 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5449 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5454 reinitializeTrustLineBalances();
5458 auto const nftID = mintNFT(minter, 3000);
5459 auto const primaryOfferID =
5460 createSellOffer(minter, nftID, XRP(0));
5461 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5465 auto const offerID =
5466 createSellOffer(secondarySeller, nftID, gwXAU(1000));
5468 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5471 expectInitialState();
5476 reinitializeTrustLineBalances();
5480 auto const nftID = mintNFT(minter, 3000);
5481 auto const primaryOfferID =
5482 createSellOffer(minter, nftID, XRP(0));
5483 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5487 auto const offerID =
5488 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(1000));
5490 env(token::acceptBuyOffer(secondarySeller, offerID),
5494 expectInitialState();
5499 reinitializeTrustLineBalances();
5503 auto const nftID = mintNFT(minter, 3000);
5504 auto const primaryOfferID =
5505 createSellOffer(minter, nftID, XRP(0));
5506 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5510 auto const offerID =
5511 createSellOffer(secondarySeller, nftID, gwXAU(900));
5512 env(token::acceptSellOffer(buyer, offerID));
5515 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5516 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5517 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5518 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5520 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5521 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5526 reinitializeTrustLineBalances();
5530 auto const nftID = mintNFT(minter, 3000);
5531 auto const primaryOfferID =
5532 createSellOffer(minter, nftID, XRP(0));
5533 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5537 auto const offerID =
5538 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(900));
5539 env(token::acceptBuyOffer(secondarySeller, offerID));
5543 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5545 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5547 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5548 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5550 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5551 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5569 reinitializeTrustLineBalances();
5571 auto const nftID = mintNFT(minter);
5572 auto const sellOffer =
5573 createSellOffer(minter, nftID, gwXAU(300));
5574 auto const buyOffer =
5575 createBuyOffer(buyer, minter, nftID, gwXAU(500));
5576 env(token::brokerOffers(broker, buyOffer, sellOffer),
5577 token::brokerFee(gwXAU(100)));
5580 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(400));
5581 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5582 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5583 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-400));
5584 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5585 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5603 reinitializeTrustLineBalances();
5607 auto const nftID = mintNFT(minter, 3000);
5608 auto const primaryOfferID =
5609 createSellOffer(minter, nftID, XRP(0));
5610 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5614 auto const sellOffer =
5615 createSellOffer(secondarySeller, nftID, gwXAU(300));
5616 auto const buyOffer =
5617 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(500));
5618 env(token::brokerOffers(broker, buyOffer, sellOffer),
5619 token::brokerFee(gwXAU(100)));
5622 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(12));
5623 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5624 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(388));
5625 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5626 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-12));
5627 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5629 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-388));
5630 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5728 using namespace test::jtx;
5733 auto openLedgerSeq = [](Env& env) {
return env.current()->seq(); };
5738 auto incLgrSeqForAcctDel = [&](Env& env, Account
const& acct) {
5739 int const delta = [&]() ->
int {
5740 if (env.seq(acct) + 255 > openLedgerSeq(env))
5741 return env.seq(acct) - openLedgerSeq(env) + 255;
5744 BEAST_EXPECT(delta >= 0);
5745 for (
int i = 0; i < delta; ++i)
5747 BEAST_EXPECT(openLedgerSeq(env) == env.seq(acct) + 255);
5752 auto incLgrSeqForFixNftRemint = [&](Env& env, Account
const& acct) {
5754 auto const deletableLgrSeq =
5755 (*env.le(acct))[~sfFirstNFTokenSequence].value_or(0) +
5756 (*env.le(acct))[sfMintedNFTokens] + 255;
5758 if (deletableLgrSeq > openLedgerSeq(env))
5759 delta = deletableLgrSeq - openLedgerSeq(env);
5761 BEAST_EXPECT(delta >= 0);
5762 for (
int i = 0; i < delta; ++i)
5764 BEAST_EXPECT(openLedgerSeq(env) == deletableLgrSeq);
5770 Env env{*
this, features};
5771 Account
const alice(
"alice");
5772 Account
const becky(
"becky");
5774 env.fund(XRP(10000), alice, becky);
5778 uint256 const prevNFTokenID = token::getNextID(env, alice, 0u);
5779 env(token::mint(alice));
5781 env(token::burn(alice, prevNFTokenID));
5785 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 1);
5788 incLgrSeqForAcctDel(env, alice);
5792 auto const acctDelFee{drops(env.current()->fees().increment)};
5793 env(acctdelete(alice, becky), fee(acctDelFee));
5798 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5799 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5802 env.fund(XRP(10000), alice);
5806 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5807 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5808 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5811 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5812 env(token::mint(alice));
5816 env(token::burn(alice, remintNFTokenID));
5820 BEAST_EXPECT(remintNFTokenID != prevNFTokenID);
5826 Env env{*
this, features};
5827 Account
const alice(
"alice");
5828 Account
const becky(
"becky");
5829 Account
const minter{
"minter"};
5831 env.fund(XRP(10000), alice, becky, minter);
5835 env(token::setMinter(alice, minter));
5841 for (
int i = 0; i < 500; i++)
5843 uint256 const nftokenID = token::getNextID(env, alice, 0u);
5845 env(token::mint(minter), token::issuer(alice));
5850 for (
auto const nftokenID : nftIDs)
5852 env(token::burn(minter, nftokenID));
5858 incLgrSeqForAcctDel(env, alice);
5862 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5863 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5865 auto const acctDelFee{drops(env.current()->fees().increment)};
5874 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
5878 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5883 incLgrSeqForFixNftRemint(env, alice);
5886 env(acctdelete(alice, becky), fee(acctDelFee));
5891 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5892 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5895 env.fund(XRP(10000), alice);
5899 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5900 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5901 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5905 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5906 env(token::mint(alice));
5910 env(token::burn(alice, remintNFTokenID));
5923 Env env{*
this, features};
5925 Account
const alice{
"alice"};
5926 Account
const becky{
"becky"};
5927 env.fund(XRP(10000), alice, becky);
5934 env(ticket::create(alice, 100));
5938 BEAST_EXPECT(ownerCount(env, alice) == 100);
5943 for (
int i = 0; i < 50; i++)
5945 nftIDs.
push_back(token::getNextID(env, alice, 0u));
5946 env(token::mint(alice, 0u), ticket::use(aliceTicketSeq++));
5951 for (
auto const nftokenID : nftIDs)
5953 env(token::burn(alice, nftokenID),
5954 ticket::use(aliceTicketSeq++));
5962 incLgrSeqForAcctDel(env, alice);
5966 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5967 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5969 auto const acctDelFee{drops(env.current()->fees().increment)};
5978 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
5982 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5987 incLgrSeqForFixNftRemint(env, alice);
5990 env(acctdelete(alice, becky), fee(acctDelFee));
5995 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5996 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5999 env.fund(XRP(10000), alice);
6003 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6004 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6005 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
6009 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
6010 env(token::mint(alice));
6014 env(token::burn(alice, remintNFTokenID));
6028 Env env{*
this, features};
6029 Account
const alice(
"alice");
6030 Account
const becky(
"becky");
6031 Account
const minter{
"minter"};
6033 env.fund(XRP(10000), alice, becky, minter);
6037 env(token::setMinter(alice, minter));
6042 env(ticket::create(minter, 100));
6046 BEAST_EXPECT(ownerCount(env, minter) == 100);
6051 for (
int i = 0; i < 50; i++)
6053 uint256 const nftokenID = token::getNextID(env, alice, 0u);
6055 env(token::mint(minter),
6056 token::issuer(alice),
6057 ticket::use(minterTicketSeq++));
6062 for (
auto const nftokenID : nftIDs)
6064 env(token::burn(minter, nftokenID), ticket::use(minterTicketSeq++));
6072 incLgrSeqForAcctDel(env, alice);
6076 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6077 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6086 auto const acctDelFee{drops(env.current()->fees().increment)};
6087 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
6091 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6096 incLgrSeqForFixNftRemint(env, alice);
6099 env(acctdelete(alice, becky), fee(acctDelFee));
6104 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
6105 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
6108 env.fund(XRP(10000), alice);
6112 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6113 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6114 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
6118 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
6119 env(token::mint(alice));
6123 env(token::burn(alice, remintNFTokenID));
6136 testcase(
"NFTokenMint with Create NFTokenOffer");
6138 using namespace test::jtx;
6140 if (!features[featureNFTokenMintOffer])
6142 Env env{*
this, features};
6143 Account
const alice(
"alice");
6144 Account
const buyer(
"buyer");
6146 env.fund(XRP(10000), alice, buyer);
6149 env(token::mint(alice),
6150 token::amount(XRP(10000)),
6154 env(token::mint(alice),
6155 token::destination(
"buyer"),
6159 env(token::mint(alice),
6169 Env env{*
this, features};
6170 auto const baseFee = env.current()->fees().base;
6171 Account
const alice(
"alice");
6172 Account
const buyer{
"buyer"};
6173 Account
const gw(
"gw");
6174 Account
const issuer(
"issuer");
6175 Account
const minter(
"minter");
6176 Account
const bob(
"bob");
6177 IOU
const gwAUD(gw[
"AUD"]);
6179 env.fund(XRP(10000), alice, buyer, gw, issuer, minter);
6184 env(token::mint(alice),
6185 token::destination(buyer),
6188 BEAST_EXPECT(ownerCount(env, alice) == 0);
6191 env(token::mint(alice),
6195 BEAST_EXPECT(ownerCount(env, buyer) == 0);
6201 env(token::mint(alice),
6202 token::amount(XRP(1000)),
6203 token::destination(alice),
6206 BEAST_EXPECT(ownerCount(env, alice) == 0);
6210 env(token::mint(alice),
6211 token::amount(XRP(1000)),
6212 token::destination(Account(
"demon")),
6215 BEAST_EXPECT(ownerCount(env, alice) == 0);
6220 env(token::mint(alice),
6221 token::amount(XRP(1000)),
6222 token::expiration(0),
6225 BEAST_EXPECT(ownerCount(env, alice) == 0);
6228 env(token::mint(alice),
6229 token::amount(XRP(1000)),
6233 BEAST_EXPECT(ownerCount(env, alice) == 0);
6238 env(token::mint(alice),
6239 token::amount(buyer[
"USD"](1)),
6242 env(token::mint(alice),
6243 token::amount(buyer[
"USD"](0)),
6246 BEAST_EXPECT(ownerCount(env, alice) == 0);
6249 env(token::mint(alice),
6250 token::amount(gwAUD(1000)),
6255 BEAST_EXPECT(ownerCount(env, alice) == 0);
6260 env(token::mint(gw),
6261 token::amount(gwAUD(1000)),
6263 token::xferFee(10));
6272 env(token::mint(alice),
6273 token::amount(gwAUD(1000)),
6278 BEAST_EXPECT(ownerCount(env, alice) == 0);
6281 env(token::mint(alice),
6282 token::amount(gwAUD(1000)),
6285 BEAST_EXPECT(ownerCount(env, alice) == 0);
6294 auto const acctReserve = env.current()->fees().reserve;
6295 auto const incReserve = env.current()->fees().increment;
6297 env.fund(acctReserve + incReserve, bob);
6301 env(token::mint(bob),
6302 token::amount(XRP(0)),
6307 env(pay(env.master, bob, incReserve + drops(baseFee)));
6309 env(token::mint(bob), token::amount(XRP(0)));
6313 env(pay(env.master, bob, drops(baseFee)));
6315 env(token::mint(bob),
6316 token::amount(XRP(0)),
6321 env(pay(env.master, bob, incReserve + drops(baseFee)));
6323 env(token::mint(bob), token::amount(XRP(0)));
6328 BEAST_EXPECT(ownerCount(env, alice) == 0);
6329 env(token::mint(alice), token::amount(XRP(10)));
6330 BEAST_EXPECT(ownerCount(env, alice) == 2);
6334 env(token::mint(alice),
6335 token::amount(XRP(10)),
6336 token::destination(buyer),
6337 token::expiration(
lastClose(env) + 25));
6341 env(trust(alice, gwAUD(1000)));
6343 env(token::mint(alice),
6344 token::amount(gwAUD(1)),
6345 token::destination(buyer),
6348 token::xferFee(10));
6352 env(token::mint(alice),
6353 token::amount(XRP(10)),
6354 token::destination(buyer),
6355 token::expiration(
lastClose(env) + 25));
6356 uint256 const offerAliceSellsToBuyer =
6358 env(token::cancelOffer(alice, {offerAliceSellsToBuyer}));
6362 env(token::mint(buyer),
6363 token::amount(XRP(10)),
6364 token::destination(alice),
6365 token::expiration(
lastClose(env) + 25));
6366 uint256 const offerBuyerSellsToAlice =
6368 env(token::cancelOffer(alice, {offerBuyerSellsToAlice}));
6371 env(token::setMinter(issuer, minter));
6375 BEAST_EXPECT(ownerCount(env, minter) == 0);
6376 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6377 env(token::mint(minter),
6378 token::issuer(issuer),
6379 token::amount(drops(1)));
6381 BEAST_EXPECT(ownerCount(env, minter) == 2);
6382 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6385 Env env{*
this, features};
6386 Account
const alice(
"alice");
6388 env.fund(XRP(1000000), alice);
6393 env(token::mint(alice), token::amount(XRP(-2)), ter(offerCreateTER));
6411 testcase(
"Test synthetic fields from JSON response");
6413 using namespace test::jtx;
6415 Account
const alice{
"alice"};
6416 Account
const bob{
"bob"};
6417 Account
const broker{
"broker"};
6419 Env env{*
this, features};
6420 env.fund(XRP(10000), alice, bob, broker);
6426 auto verifyNFTokenID = [&](
uint256 const& actualNftID) {
6433 env.rpc(
"tx", txHash)[jss::result][jss::meta];
6436 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_id)))
6443 BEAST_EXPECT(nftID == actualNftID);
6448 auto verifyNFTokenIDsInCancelOffer =
6456 env.rpc(
"tx", txHash)[jss::result][jss::meta];
6459 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_ids)))
6465 meta[jss::nftoken_ids].begin(),
6466 meta[jss::nftoken_ids].end(),
6470 BEAST_EXPECT(nftID.
parseHex(
id.asString()));
6476 std::sort(actualNftIDs.begin(), actualNftIDs.end());
6479 BEAST_EXPECT(metaIDs.
size() == actualNftIDs.size());
6483 for (
size_t i = 0; i < metaIDs.
size(); ++i)
6484 BEAST_EXPECT(metaIDs[i] == actualNftIDs[i]);
6489 auto verifyNFTokenOfferID = [&](
uint256 const& offerID) {
6496 env.rpc(
"tx", txHash)[jss::result][jss::meta];
6499 if (!BEAST_EXPECT(meta.
isMember(jss::offer_id)))
6504 BEAST_EXPECT(metaOfferID == offerID);
6515 verifyNFTokenID(nftId1);
6521 verifyNFTokenID(nftId2);
6526 uint256 const aliceOfferIndex1 =
6528 env(token::createOffer(alice, nftId1, drops(1)),
6531 verifyNFTokenOfferID(aliceOfferIndex1);
6533 uint256 const aliceOfferIndex2 =
6535 env(token::createOffer(alice, nftId2, drops(1)),
6538 verifyNFTokenOfferID(aliceOfferIndex2);
6543 env(token::cancelOffer(
6544 alice, {aliceOfferIndex1, aliceOfferIndex2}));
6546 verifyNFTokenIDsInCancelOffer({nftId1, nftId2});
6550 auto const bobBuyOfferIndex =
6552 env(token::createOffer(bob, nftId1, drops(1)), token::owner(alice));
6554 verifyNFTokenOfferID(bobBuyOfferIndex);
6558 env(token::acceptBuyOffer(alice, bobBuyOfferIndex));
6560 verifyNFTokenID(nftId1);
6570 verifyNFTokenID(nftId);
6573 uint256 const offerAliceToBroker =
6575 env(token::createOffer(alice, nftId, drops(1)),
6576 token::destination(broker),
6579 verifyNFTokenOfferID(offerAliceToBroker);
6582 uint256 const offerBobToBroker =
6584 env(token::createOffer(bob, nftId, drops(1)), token::owner(alice));
6586 verifyNFTokenOfferID(offerBobToBroker);
6589 env(token::brokerOffers(
6590 broker, offerBobToBroker, offerAliceToBroker));
6592 verifyNFTokenID(nftId);
6603 verifyNFTokenID(nftId);
6606 uint256 const aliceOfferIndex1 =
6608 env(token::createOffer(alice, nftId, drops(1)),
6611 verifyNFTokenOfferID(aliceOfferIndex1);
6613 uint256 const aliceOfferIndex2 =
6615 env(token::createOffer(alice, nftId, drops(1)),
6618 verifyNFTokenOfferID(aliceOfferIndex2);
6622 env(token::cancelOffer(
6623 alice, {aliceOfferIndex1, aliceOfferIndex2}));
6625 verifyNFTokenIDsInCancelOffer({nftId});
6628 if (features[featureNFTokenMintOffer])
6630 uint256 const aliceMintWithOfferIndex1 =
6632 env(token::mint(alice), token::amount(XRP(0)));
6634 verifyNFTokenOfferID(aliceMintWithOfferIndex1);
6641 testcase(
"Test buyer reserve when accepting an offer");
6643 using namespace test::jtx;
6656 uint256 const sellOfferIndex =
6658 env(token::createOffer(acct, nftId, amt), txflags(
tfSellNFToken));
6661 return sellOfferIndex;
6668 Account
const alice{
"alice"};
6669 Account
const bob{
"bob"};
6671 Env env{*
this, features};
6672 auto const acctReserve = env.
current()->fees().reserve;
6673 auto const incReserve = env.
current()->fees().increment;
6674 auto const baseFee = env.
current()->fees().base;
6676 env.
fund(XRP(10000), alice);
6680 env.
fund(acctReserve, bob);
6684 auto const sellOfferIndex =
6685 mintAndCreateSellOffer(env, alice, XRP(0));
6688 BEAST_EXPECT(ownerCount(env, bob) == 0);
6692 if (!features[fixNFTokenReserve])
6695 env(token::acceptSellOffer(bob, sellOfferIndex));
6699 BEAST_EXPECT(ownerCount(env, bob) == 1);
6714 env(token::acceptSellOffer(bob, sellOfferIndex),
6721 BEAST_EXPECT(ownerCount(env, bob) == 0);
6726 env(pay(env.
master, bob, incReserve + drops(baseFee)));
6731 env(token::acceptSellOffer(bob, sellOfferIndex),
6737 env(pay(env.
master, bob, drops(baseFee * 2)));
6741 env(token::acceptSellOffer(bob, sellOfferIndex));
6744 BEAST_EXPECT(ownerCount(env, bob) == 1);
6751 Account
const alice{
"alice"};
6752 Account
const bob{
"bob"};
6754 Env env{*
this, features};
6755 auto const acctReserve = env.
current()->fees().reserve;
6756 auto const incReserve = env.
current()->fees().increment;
6758 env.
fund(XRP(10000), alice);
6761 env.
fund(acctReserve + XRP(1), bob);
6764 if (!features[fixNFTokenReserve])
6767 for (
size_t i = 0; i < 200; i++)
6770 auto const sellOfferIndex =
6771 mintAndCreateSellOffer(env, alice, XRP(0));
6774 env(token::acceptSellOffer(bob, sellOfferIndex));
6781 auto const sellOfferIndex1 =
6782 mintAndCreateSellOffer(env, alice, XRP(0));
6786 env(token::acceptSellOffer(bob, sellOfferIndex1),
6791 env(pay(env.
master, bob, drops(incReserve)));
6794 BEAST_EXPECT(ownerCount(env, bob) == 0);
6797 env(token::acceptSellOffer(bob, sellOfferIndex1));
6800 BEAST_EXPECT(ownerCount(env, bob) == 1);
6804 for (
size_t i = 0; i < 31; i++)
6807 auto const sellOfferIndex =
6808 mintAndCreateSellOffer(env, alice, XRP(0));
6812 env(token::acceptSellOffer(bob, sellOfferIndex));
6816 BEAST_EXPECT(ownerCount(env, bob) == 1);
6820 auto const sellOfferIndex33 =
6821 mintAndCreateSellOffer(env, alice, XRP(0));
6825 env(token::acceptSellOffer(bob, sellOfferIndex33),
6830 env(pay(env.
master, bob, drops(incReserve)));
6835 env(token::acceptSellOffer(bob, sellOfferIndex33));
6838 BEAST_EXPECT(ownerCount(env, bob) == 2);
6848 Account
const alice{
"alice"};
6849 Account
const bob{
"bob"};
6851 Env env{*
this, features};
6852 auto const acctReserve = env.
current()->fees().reserve;
6853 auto const incReserve = env.
current()->fees().increment;
6854 auto const baseFee = env.
current()->fees().base;
6856 env.
fund(XRP(10000), alice);
6862 env.
fund(acctReserve + incReserve + XRP(1), bob);
6873 env(token::createOffer(bob, nftId, XRP(1)), token::owner(alice));
6879 env(token::acceptBuyOffer(alice, buyOfferIndex),
6884 env(pay(env.
master, bob, drops(baseFee)));
6888 env(token::acceptBuyOffer(alice, buyOfferIndex));
6898 Account
const alice{
"alice"};
6899 Account
const bob{
"bob"};
6900 Account
const broker{
"broker"};
6902 Env env{*
this, features};
6903 auto const acctReserve = env.
current()->fees().reserve;
6904 auto const incReserve = env.
current()->fees().increment;
6905 auto const baseFee = env.
current()->fees().base;
6907 env.
fund(XRP(10000), alice, broker);
6912 env.
fund(acctReserve + incReserve + XRP(1), bob);
6922 uint256 const offerAliceToBroker =
6924 env(token::createOffer(alice, nftId, XRP(1)),
6925 token::destination(broker),
6930 uint256 const offerBobToBroker =
6932 env(token::createOffer(bob, nftId, XRP(1)), token::owner(alice));
6939 env(token::brokerOffers(
6940 broker, offerBobToBroker, offerAliceToBroker),
6945 env(pay(env.
master, bob, drops(baseFee)));
6949 env(token::brokerOffers(
6950 broker, offerBobToBroker, offerAliceToBroker));
7288 using namespace test::jtx;
7290 Account
const issuer{
"issuer"};
7291 Account
const alice(
"alice");
7292 Account
const bob(
"bob");
7294 bool const modifyEnabled = features[featureDynamicNFT];
7298 Env env{*
this, features};
7299 env.fund(XRP(10000), issuer);
7302 auto const expectedTer =
7304 env(token::mint(issuer, 0u), txflags(
tfMutable), ter(expectedTer));
7308 Env env{*
this, features};
7309 env.fund(XRP(10000), issuer);
7316 env(token::mint(issuer, 0u), txflags(
tfMutable));
7318 BEAST_EXPECT(ownerCount(env, issuer) == 1);
7319 env(token::modify(issuer, nftId));
7320 BEAST_EXPECT(ownerCount(env, issuer) == 1);
7324 env(token::mint(issuer, 0u));
7326 env(token::modify(issuer, nftId), ter(
temDISABLED));
7334 Env env{*
this, features};
7335 env.fund(XRP(10000), issuer);
7339 env(token::mint(issuer, 0u), txflags(
tfMutable));
7343 env(token::modify(issuer, nftId),
7349 env(token::modify(issuer, nftId),
7350 txflags(0x00000001),
7354 env(token::modify(issuer, nftId),
7355 token::owner(issuer),
7360 env(token::modify(issuer, nftId),
7366 env(token::modify(issuer, nftId),
7372 Env env{*
this, features};
7373 env.fund(XRP(10000), issuer, alice, bob);
7379 token::getNextID(env, issuer, 0u,
tfMutable)};
7382 env(token::modify(issuer, nftIDNotExists), ter(
tecNO_ENTRY));
7387 uint256 const nftIDNotModifiable{
7388 token::getNextID(env, issuer, 0u)};
7389 env(token::mint(issuer, 0u));
7392 env(token::modify(issuer, nftIDNotModifiable),
7399 token::getNextID(env, issuer, 0u,
tfMutable)};
7400 env(token::mint(issuer, 0u), txflags(
tfMutable));
7403 env(token::modify(bob, nftId),
7404 token::owner(issuer),
7408 env(token::setMinter(issuer, alice));
7411 env(token::modify(bob, nftId),
7412 token::owner(issuer),
7418 Env env{*
this, features};
7419 env.fund(XRP(10000), issuer, alice, bob);
7424 env(token::mint(issuer, 0u), txflags(
tfMutable), token::uri(
"uri"));
7431 Env env{*
this, features};
7432 env.fund(XRP(10000), issuer, alice, bob);
7436 auto accountNFTs = [&env](Account
const& acct) {
7438 params[jss::account] = acct.human();
7439 params[jss::type] =
"state";
7441 env.rpc(
"json",
"account_nfts",
to_string(params));
7442 return response[jss::result][jss::account_nfts];
7446 auto checkURI = [&accountNFTs,
this](
7447 Account
const& acct,
7450 auto const nfts = accountNFTs(acct);
7451 if (nfts.size() == 1)
7456 text <<
"checkURI: unexpected NFT count on line " << line;
7457 fail(text.
str(), __FILE__, line);
7463 if (!nfts[0u].isMember(sfURI.jsonName))
7468 text <<
"checkURI: unexpected URI present on line "
7470 fail(text.
str(), __FILE__, line);
7480 text <<
"checkURI: unexpected URI contents on line "
7482 fail(text.
str(), __FILE__, line);
7489 env(token::mint(issuer, 0u), txflags(
tfMutable), token::uri(
"uri"));
7491 checkURI(issuer,
"uri", __LINE__);
7494 env(token::modify(issuer, nftId), token::uri(
"new_uri"));
7496 checkURI(issuer,
"new_uri", __LINE__);
7499 env(token::modify(issuer, nftId));
7501 checkURI(issuer,
nullptr, __LINE__);
7504 env(token::modify(issuer, nftId), token::uri(
"uri"));
7506 checkURI(issuer,
"uri", __LINE__);
7511 env(token::createOffer(issuer, nftId, XRP(0)),
7514 env(token::acceptSellOffer(alice, offerID));
7516 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7517 BEAST_EXPECT(ownerCount(env, alice) == 1);
7518 checkURI(alice,
"uri", __LINE__);
7521 env(token::modify(alice, nftId),
7522 token::uri(
"new_uri"),
7525 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7526 BEAST_EXPECT(ownerCount(env, alice) == 1);
7527 checkURI(alice,
"uri", __LINE__);
7529 env(token::modify(issuer, nftId),
7530 token::owner(alice),
7531 token::uri(
"new_uri"));
7533 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7534 BEAST_EXPECT(ownerCount(env, alice) == 1);
7535 checkURI(alice,
"new_uri", __LINE__);
7537 env(token::modify(issuer, nftId), token::owner(alice));
7539 checkURI(alice,
nullptr, __LINE__);
7541 env(token::modify(issuer, nftId),
7542 token::owner(alice),
7545 checkURI(alice,
"uri", __LINE__);
7548 env(token::setMinter(issuer, bob));
7550 env(token::modify(bob, nftId),
7551 token::owner(alice),
7552 token::uri(
"new_uri"));
7554 checkURI(alice,
"new_uri", __LINE__);
7556 env(token::modify(bob, nftId), token::owner(alice));
7558 checkURI(alice,
nullptr, __LINE__);
7560 env(token::modify(bob, nftId),
7561 token::owner(alice),
7564 checkURI(alice,
"uri", __LINE__);