139 using namespace test::jtx;
141 Env env{*
this, features};
142 Account
const alice{
"alice"};
143 Account
const minter{
"minter"};
147 auto const acctReserve = env.current()->fees().reserve;
148 auto const incReserve = env.current()->fees().increment;
149 auto const baseFee = env.current()->fees().base;
151 env.fund(acctReserve, alice, minter);
154 BEAST_EXPECT(env.balance(alice) == acctReserve);
155 BEAST_EXPECT(env.balance(minter) == acctReserve);
156 BEAST_EXPECT(ownerCount(env, alice) == 0);
157 BEAST_EXPECT(ownerCount(env, minter) == 0);
164 BEAST_EXPECT(ownerCount(env, alice) == 0);
169 env(pay(env.master, alice, incReserve + drops(baseFee - 1)));
174 auto checkAliceOwnerMintedBurned = [&env,
this, &alice](
187 ss <<
"Wrong " << type <<
" count. Found: " << found
188 <<
"; Expected: " << exp;
189 fail(ss.
str(), __FILE__, line);
192 oneCheck(
"owner", ownerCount(env, alice), owners);
193 oneCheck(
"minted",
mintedCount(env, alice), minted);
194 oneCheck(
"burned",
burnedCount(env, alice), burned);
202 checkAliceOwnerMintedBurned(0, 0, 0, __LINE__);
205 env(pay(env.master, alice, drops(baseFee + 1)));
209 env(token::mint(alice));
212 checkAliceOwnerMintedBurned(1, 1, 0, __LINE__);
216 for (
int i = 1; i < 32; ++i)
218 env(token::mint(alice));
219 checkAliceOwnerMintedBurned(1, i + 1, 0, __LINE__);
226 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
229 env(pay(env.master, alice, incReserve + drops(baseFee * 33 - 1)));
236 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
239 env(pay(env.master, alice, drops(baseFee + 1)));
243 env(token::mint(alice));
245 checkAliceOwnerMintedBurned(2, 33, 0, __LINE__);
252 env(token::burn(alice, token::getID(env, alice, 0, seq++)));
254 checkAliceOwnerMintedBurned((33 - seq) ? 1 : 0, 33, seq, __LINE__);
258 env(token::burn(alice, token::getID(env, alice, 197, 5)),
261 checkAliceOwnerMintedBurned(0, 33, 33, __LINE__);
266 env(token::setMinter(alice, minter));
269 env.le(alice)->getAccountID(sfNFTokenMinter) == minter.id());
273 auto checkMintersOwnerMintedBurned = [&env,
this, &alice, &minter](
281 auto oneCheck = [
this](
291 ss <<
"Wrong " << type <<
" count. Found: " << found
292 <<
"; Expected: " << exp;
293 fail(ss.
str(), __FILE__, line);
296 oneCheck(
"alice owner", ownerCount(env, alice), aliceOwners, line);
298 "alice minted",
mintedCount(env, alice), aliceMinted, line);
300 "alice burned",
burnedCount(env, alice), aliceBurned, line);
302 "minter owner", ownerCount(env, minter), minterOwners, line);
304 "minter minted",
mintedCount(env, minter), minterMinted, line);
306 "minter burned",
burnedCount(env, minter), minterBurned, line);
312 env(pay(env.master, minter, incReserve - drops(1)));
314 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
319 env(token::mint(minter),
320 token::issuer(alice),
324 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
327 env(pay(env.master, minter, drops(baseFee + 1)));
331 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
333 checkMintersOwnerMintedBurned(0, 34, nftSeq, 1, 0, 0, __LINE__);
337 for (
int i = 1; i < 32; ++i)
339 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
340 checkMintersOwnerMintedBurned(0, i + 34, nftSeq, 1, 0, 0, __LINE__);
345 env(pay(env.master, minter, incReserve + drops(baseFee * 32 - 1)));
350 env(token::mint(minter),
351 token::issuer(alice),
355 checkMintersOwnerMintedBurned(0, 65, nftSeq, 1, 0, 0, __LINE__);
358 env(pay(env.master, minter, drops(baseFee + 1)));
362 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
364 checkMintersOwnerMintedBurned(0, 66, nftSeq, 2, 0, 0, __LINE__);
369 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
371 checkMintersOwnerMintedBurned(
372 0, 66, nftSeq, (65 - seq) ? 1 : 0, 0, 0, __LINE__);
377 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
379 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
382 env(token::burn(minter, token::getID(env, alice, 2009, 3)),
385 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
588 testcase(
"Invalid NFT offer create");
590 using namespace test::jtx;
592 Env env{*
this, features};
593 Account
const alice{
"alice"};
594 Account
const buyer{
"buyer"};
595 Account
const gw(
"gw");
596 IOU
const gwAUD(gw[
"AUD"]);
601 env.fund(XRP(250), alice, buyer, gw);
603 BEAST_EXPECT(ownerCount(env, alice) == 0);
607 env(token::mint(alice, 0u),
611 BEAST_EXPECT(ownerCount(env, alice) == 1);
617 BEAST_EXPECT(ownerCount(env, alice) == 1);
619 uint256 nftNoXferID = token::getNextID(env, alice, 0);
620 env(token::mint(alice, 0));
622 BEAST_EXPECT(ownerCount(env, alice) == 1);
633 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
637 BEAST_EXPECT(ownerCount(env, buyer) == 0);
640 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
644 BEAST_EXPECT(ownerCount(env, buyer) == 0);
647 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
651 BEAST_EXPECT(ownerCount(env, buyer) == 0);
654 env(token::createOffer(buyer, nftXrpOnlyID, buyer[
"USD"](1)),
656 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](0)),
658 env(token::createOffer(buyer, nftXrpOnlyID, drops(0)),
661 BEAST_EXPECT(ownerCount(env, buyer) == 0);
664 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](1)),
665 token::expiration(0),
668 BEAST_EXPECT(ownerCount(env, buyer) == 0);
672 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
675 BEAST_EXPECT(ownerCount(env, buyer) == 0);
678 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
683 BEAST_EXPECT(ownerCount(env, alice) == 1);
686 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
690 BEAST_EXPECT(ownerCount(env, alice) == 1);
693 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
694 token::destination(alice),
698 BEAST_EXPECT(ownerCount(env, alice) == 1);
701 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
702 token::destination(Account(
"demon")),
706 BEAST_EXPECT(ownerCount(env, alice) == 1);
712 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
717 BEAST_EXPECT(ownerCount(env, buyer) == 0);
720 env(token::createOffer(
721 buyer, token::getID(env, alice, 0, 1), XRP(1000)),
725 BEAST_EXPECT(ownerCount(env, buyer) == 0);
728 env(token::createOffer(
729 alice, token::getID(env, alice, 0, 1), XRP(1000)),
733 BEAST_EXPECT(ownerCount(env, buyer) == 0);
736 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
740 BEAST_EXPECT(ownerCount(env, buyer) == 0);
742 env(trust(buyer, gwAUD(1000)));
744 BEAST_EXPECT(ownerCount(env, buyer) == 1);
748 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
752 BEAST_EXPECT(ownerCount(env, buyer) == 1);
760 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
764 BEAST_EXPECT(ownerCount(env, buyer) == 1);
771 env(token::createOffer(buyer, nftNoXferID, gwAUD(1000)),
775 BEAST_EXPECT(ownerCount(env, buyer) == 1);
781 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
785 BEAST_EXPECT(ownerCount(env, buyer) == 1);
790 env(trust(buyer, gwAUD(1000)));
793 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
797 BEAST_EXPECT(ownerCount(env, buyer) == 1);
803 env(pay(gw, buyer, gwAUD(999)));
808 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
812 BEAST_EXPECT(ownerCount(env, buyer) == 1);
815 auto const baseFee = env.current()->fees().base;
816 env(pay(env.master, buyer, XRP(50) + drops(baseFee * 12 - 1)));
819 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
823 BEAST_EXPECT(ownerCount(env, buyer) == 1);
826 env(pay(env.master, buyer, drops(baseFee + 1)));
831 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
835 BEAST_EXPECT(ownerCount(env, buyer) == 2);
961 testcase(
"Invalid NFT offer accept");
963 using namespace test::jtx;
965 Env env{*
this, features};
966 Account
const alice{
"alice"};
967 Account
const buyer{
"buyer"};
968 Account
const gw(
"gw");
969 IOU
const gwAUD(gw[
"AUD"]);
971 env.fund(XRP(1000), alice, buyer, gw);
973 BEAST_EXPECT(ownerCount(env, alice) == 0);
979 BEAST_EXPECT(ownerCount(env, alice) == 1);
985 BEAST_EXPECT(ownerCount(env, alice) == 1);
987 uint256 nftNoXferID = token::getNextID(env, alice, 0);
988 env(token::mint(alice, 0));
990 BEAST_EXPECT(ownerCount(env, alice) == 1);
993 uint256 const plainOfferIndex =
995 env(token::createOffer(alice, nftAlice0ID, XRP(10)),
998 BEAST_EXPECT(ownerCount(env, alice) == 2);
1002 env(token::createOffer(alice, nftAlice0ID, gwAUD(30)),
1005 BEAST_EXPECT(ownerCount(env, alice) == 3);
1007 uint256 const xrpOnlyOfferIndex =
1009 env(token::createOffer(alice, nftXrpOnlyID, XRP(20)),
1012 BEAST_EXPECT(ownerCount(env, alice) == 4);
1014 uint256 const noXferOfferIndex =
1016 env(token::createOffer(alice, nftNoXferID, XRP(30)),
1019 BEAST_EXPECT(ownerCount(env, alice) == 5);
1022 uint256 const aliceExpOfferIndex =
1024 env(token::createOffer(alice, nftNoXferID, XRP(40)),
1028 BEAST_EXPECT(ownerCount(env, alice) == 6);
1034 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1038 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1041 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1042 txflags(0x00008000),
1045 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1049 Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1053 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1058 Json::Value jv = token::acceptBuyOffer(buyer, noXferOfferIndex);
1059 jv[sfNFTokenBrokerFee.jsonName] =
1063 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1068 Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1069 jv[sfNFTokenBrokerFee.jsonName] =
1073 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1077 env(token::brokerOffers(buyer, noXferOfferIndex, xrpOnlyOfferIndex),
1078 token::brokerFee(gwAUD(0)),
1081 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1087 env(token::acceptBuyOffer(buyer, beast::zero),
1090 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1094 env(token::acceptBuyOffer(buyer, missingOfferIndex),
1097 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1100 env(token::acceptBuyOffer(buyer, aliceExpOfferIndex), ter(
tecEXPIRED));
1102 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1105 env(token::acceptSellOffer(buyer, beast::zero),
1108 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1111 env(token::acceptSellOffer(buyer, missingOfferIndex),
1114 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1117 env(token::acceptSellOffer(buyer, aliceExpOfferIndex), ter(
tecEXPIRED));
1119 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1126 env(trust(alice, gwAUD(1000)));
1127 env(trust(buyer, gwAUD(1000)));
1129 env(pay(gw, buyer, gwAUD(30)));
1131 BEAST_EXPECT(ownerCount(env, alice) == 7);
1132 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1138 uint256 const buyerOfferIndex =
1140 env(token::createOffer(buyer, nftAlice0ID, gwAUD(29)),
1141 token::owner(alice));
1143 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1146 env(token::brokerOffers(gw, buyerOfferIndex, xrpOnlyOfferIndex),
1149 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1152 env(token::brokerOffers(gw, buyerOfferIndex, plainOfferIndex),
1155 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1159 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1162 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1165 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1167 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1171 uint256 const buyerOfferIndex =
1173 env(token::createOffer(buyer, nftAlice0ID, gwAUD(31)),
1174 token::owner(alice));
1176 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1180 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1181 token::brokerFee(XRP(40)),
1184 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1187 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1188 token::brokerFee(gwAUD(31)),
1191 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1195 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1196 token::brokerFee(gwAUD(1.5)),
1199 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1202 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1204 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1210 uint256 const buyerOfferIndex =
1212 env(token::createOffer(buyer, nftAlice0ID, gwAUD(30)),
1213 token::owner(alice));
1215 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1218 env(token::acceptBuyOffer(buyer, plainOfferIndex),
1221 BEAST_EXPECT(ownerCount(env, alice) == 7);
1224 env(token::acceptBuyOffer(buyer, buyerOfferIndex),
1227 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1230 env(pay(buyer, gw, gwAUD(30)));
1232 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1233 env(token::acceptBuyOffer(alice, buyerOfferIndex),
1236 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1242 env(token::createOffer(alice, nftAlice0ID, XRP(0)),
1245 env(token::acceptSellOffer(gw, offerIndex));
1247 BEAST_EXPECT(ownerCount(env, alice) == 7);
1249 env(pay(gw, buyer, gwAUD(30)));
1253 env(token::acceptBuyOffer(alice, buyerOfferIndex),
1256 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1259 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1261 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1267 uint256 const buyerOfferIndex =
1269 env(token::createOffer(buyer, nftXrpOnlyID, XRP(30)),
1270 token::owner(alice));
1272 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1275 env(token::acceptSellOffer(alice, buyerOfferIndex),
1278 BEAST_EXPECT(ownerCount(env, alice) == 7);
1281 env(token::acceptSellOffer(alice, plainOfferIndex),
1284 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1288 env(token::acceptSellOffer(buyer, plainOfferIndex),
1291 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1299 env(token::createOffer(gw, nftAlice0ID, XRP(0)),
1302 env(token::acceptSellOffer(alice, offerIndex));
1304 BEAST_EXPECT(ownerCount(env, alice) == 7);
1306 env(pay(buyer, gw, gwAUD(30)));
1308 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1309 env(token::acceptSellOffer(buyer, audOfferIndex),
1312 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1538 testcase(
"Mint flagCreateTrustLines");
1540 using namespace test::jtx;
1542 Account
const alice{
"alice"};
1543 Account
const becky{
"becky"};
1544 Account
const cheri{
"cheri"};
1545 Account
const gw(
"gw");
1546 IOU
const gwAUD(gw[
"AUD"]);
1547 IOU
const gwCAD(gw[
"CAD"]);
1548 IOU
const gwEUR(gw[
"EUR"]);
1553 for (
auto const& tweakedFeatures :
1554 {features - fixRemoveNFTokenAutoTrustLine,
1555 features | fixRemoveNFTokenAutoTrustLine})
1557 Env env{*
this, tweakedFeatures};
1558 env.fund(XRP(1000), alice, becky, cheri, gw);
1562 env(trust(becky, gwAUD(1000)));
1563 env(trust(cheri, gwAUD(1000)));
1564 env(trust(becky, gwCAD(1000)));
1565 env(trust(cheri, gwCAD(1000)));
1566 env(trust(becky, gwEUR(1000)));
1567 env(trust(cheri, gwEUR(1000)));
1569 env(pay(gw, becky, gwAUD(500)));
1570 env(pay(gw, becky, gwCAD(500)));
1571 env(pay(gw, becky, gwEUR(500)));
1572 env(pay(gw, cheri, gwAUD(500)));
1573 env(pay(gw, cheri, gwCAD(500)));
1580 uint256 const nftNoAutoTrustID{
1582 env(token::mint(alice, 0u),
1583 token::xferFee(xferFee),
1588 uint256 const beckyBuyOfferIndex =
1590 env(token::createOffer(becky, nftNoAutoTrustID, drops(1)),
1591 token::owner(alice));
1593 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1597 TER const createOfferTER =
1599 uint256 const beckyOfferIndex =
1601 env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)),
1603 ter(createOfferTER));
1607 uint256 const cheriOfferIndex =
1609 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
1610 token::owner(becky),
1611 ter(createOfferTER));
1615 env(token::cancelOffer(becky, {beckyOfferIndex}));
1616 env(token::cancelOffer(cheri, {cheriOfferIndex}));
1624 uint256 const nftAutoTrustID{token::getNextID(
1631 tweakedFeatures[fixRemoveNFTokenAutoTrustLine]
1635 env(token::mint(alice, 0u),
1636 token::xferFee(transferFee),
1643 if (tweakedFeatures[fixRemoveNFTokenAutoTrustLine])
1647 uint256 const beckyBuyOfferIndex =
1649 env(token::createOffer(becky, nftAutoTrustID, drops(1)),
1650 token::owner(alice));
1652 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1656 uint256 const beckySellOfferIndex =
1658 env(token::createOffer(becky, nftAutoTrustID, gwAUD(100)),
1661 env(token::acceptSellOffer(cheri, beckySellOfferIndex));
1665 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1668 uint256 const beckyBuyBackOfferIndex =
1670 env(token::createOffer(becky, nftAutoTrustID, gwCAD(50)),
1671 token::owner(cheri));
1673 env(token::acceptBuyOffer(cheri, beckyBuyBackOfferIndex));
1677 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1678 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(5));
1684 uint256 const nftNoAutoTrustID{token::getNextID(
1686 env(token::mint(alice, 0u),
1687 token::xferFee(transferFee),
1692 uint256 const aliceSellOfferIndex =
1694 env(token::createOffer(alice, nftNoAutoTrustID, gwAUD(200)),
1697 env(token::acceptSellOffer(cheri, aliceSellOfferIndex));
1703 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(210));
1706 env(token::createOffer(cheri, nftNoAutoTrustID, gwEUR(50)),
1710 uint256 const cheriSellOfferIndex =
1712 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
1715 env(token::acceptSellOffer(becky, cheriSellOfferIndex));
1721 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(10));
1732 using namespace test::jtx;
1734 Env env{*
this, features};
1736 Account
const alice{
"alice"};
1737 Account
const becky{
"becky"};
1738 Account
const minter{
"minter"};
1740 env.fund(XRP(1000), alice, becky, minter);
1745 BEAST_EXPECT(ownerCount(env, alice) == 0);
1746 uint256 const nftAliceNoTransferID{
1747 token::getNextID(env, alice, 0u)};
1748 env(token::mint(alice, 0u), token::xferFee(0));
1750 BEAST_EXPECT(ownerCount(env, alice) == 1);
1753 BEAST_EXPECT(ownerCount(env, becky) == 0);
1754 env(token::createOffer(becky, nftAliceNoTransferID, XRP(20)),
1755 token::owner(alice),
1759 uint256 const aliceSellOfferIndex =
1761 env(token::createOffer(alice, nftAliceNoTransferID, XRP(20)),
1764 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1766 BEAST_EXPECT(ownerCount(env, alice) == 0);
1767 BEAST_EXPECT(ownerCount(env, becky) == 1);
1770 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1774 BEAST_EXPECT(ownerCount(env, alice) == 0);
1775 BEAST_EXPECT(ownerCount(env, becky) == 1);
1779 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1781 token::destination(alice),
1784 BEAST_EXPECT(ownerCount(env, alice) == 0);
1785 BEAST_EXPECT(ownerCount(env, becky) == 1);
1789 uint256 const aliceBuyOfferIndex =
1791 env(token::createOffer(alice, nftAliceNoTransferID, XRP(22)),
1792 token::owner(becky));
1794 env(token::acceptBuyOffer(becky, aliceBuyOfferIndex));
1796 BEAST_EXPECT(ownerCount(env, alice) == 1);
1797 BEAST_EXPECT(ownerCount(env, becky) == 0);
1800 env(token::burn(alice, nftAliceNoTransferID));
1802 BEAST_EXPECT(ownerCount(env, alice) == 0);
1803 BEAST_EXPECT(ownerCount(env, becky) == 0);
1807 env(token::setMinter(alice, minter));
1810 BEAST_EXPECT(ownerCount(env, minter) == 0);
1811 uint256 const nftMinterNoTransferID{
1812 token::getNextID(env, alice, 0u)};
1813 env(token::mint(minter), token::issuer(alice));
1815 BEAST_EXPECT(ownerCount(env, minter) == 1);
1818 BEAST_EXPECT(ownerCount(env, becky) == 0);
1819 env(token::createOffer(becky, nftMinterNoTransferID, XRP(20)),
1820 token::owner(minter),
1823 BEAST_EXPECT(ownerCount(env, becky) == 0);
1826 env(token::clearMinter(alice));
1830 BEAST_EXPECT(ownerCount(env, minter) == 1);
1831 env(token::createOffer(minter, nftMinterNoTransferID, XRP(21)),
1835 BEAST_EXPECT(ownerCount(env, minter) == 1);
1839 for (
int i = 0; i < 10; ++i)
1842 env(token::setMinter(alice, minter));
1844 BEAST_EXPECT(ownerCount(env, minter) == 1);
1847 BEAST_EXPECT(ownerCount(env, minter) == 1);
1848 uint256 const minterSellOfferIndex =
1850 env(token::createOffer(minter, nftMinterNoTransferID, XRP(22)),
1853 BEAST_EXPECT(ownerCount(env, minter) == 2);
1857 env(token::clearMinter(alice));
1862 BEAST_EXPECT(ownerCount(env, becky) == 0);
1863 env(token::acceptSellOffer(becky, minterSellOfferIndex));
1865 BEAST_EXPECT(ownerCount(env, becky) == 1);
1866 BEAST_EXPECT(ownerCount(env, minter) == 0);
1869 env(token::createOffer(becky, nftMinterNoTransferID, XRP(23)),
1876 BEAST_EXPECT(ownerCount(env, minter) == 0);
1877 env(token::createOffer(minter, nftMinterNoTransferID, XRP(24)),
1878 token::owner(becky),
1881 BEAST_EXPECT(ownerCount(env, minter) == 0);
1884 BEAST_EXPECT(ownerCount(env, alice) == 0);
1885 uint256 const aliceBuyOfferIndex =
1887 env(token::createOffer(alice, nftMinterNoTransferID, XRP(25)),
1888 token::owner(becky));
1890 BEAST_EXPECT(ownerCount(env, alice) == 1);
1894 for (
int i = 0; i < 10; ++i)
1897 env(token::setMinter(alice, minter));
1901 BEAST_EXPECT(ownerCount(env, minter) == 0);
1902 uint256 const minterBuyOfferIndex =
1904 env(token::createOffer(minter, nftMinterNoTransferID, XRP(26)),
1905 token::owner(becky));
1907 BEAST_EXPECT(ownerCount(env, minter) == 1);
1911 env(token::clearMinter(alice));
1915 BEAST_EXPECT(ownerCount(env, minter) == 1);
1916 BEAST_EXPECT(ownerCount(env, becky) == 1);
1917 env(token::acceptBuyOffer(becky, minterBuyOfferIndex));
1919 BEAST_EXPECT(ownerCount(env, minter) == 1);
1920 BEAST_EXPECT(ownerCount(env, becky) == 0);
1921 BEAST_EXPECT(ownerCount(env, alice) == 1);
1925 env(token::burn(minter, nftMinterNoTransferID), ter(
tesSUCCESS));
1927 env(token::cancelOffer(alice, {aliceBuyOfferIndex}));
1929 BEAST_EXPECT(ownerCount(env, alice) == 0);
1930 BEAST_EXPECT(ownerCount(env, becky) == 0);
1931 BEAST_EXPECT(ownerCount(env, minter) == 0);
1936 BEAST_EXPECT(ownerCount(env, alice) == 0);
1941 BEAST_EXPECT(ownerCount(env, alice) == 1);
1944 uint256 const aliceSellOfferIndex =
1946 env(token::createOffer(alice, nftAliceID, XRP(20)),
1949 BEAST_EXPECT(ownerCount(env, alice) == 2);
1951 uint256 const beckyBuyOfferIndex =
1953 env(token::createOffer(becky, nftAliceID, XRP(21)),
1954 token::owner(alice));
1956 BEAST_EXPECT(ownerCount(env, alice) == 2);
1959 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1961 BEAST_EXPECT(ownerCount(env, alice) == 0);
1962 BEAST_EXPECT(ownerCount(env, becky) == 2);
1965 uint256 const beckySellOfferIndex =
1967 env(token::createOffer(becky, nftAliceID, XRP(22)),
1970 BEAST_EXPECT(ownerCount(env, alice) == 0);
1971 BEAST_EXPECT(ownerCount(env, becky) == 3);
1975 env(token::acceptSellOffer(minter, beckySellOfferIndex));
1977 BEAST_EXPECT(ownerCount(env, alice) == 0);
1978 BEAST_EXPECT(ownerCount(env, becky) == 1);
1979 BEAST_EXPECT(ownerCount(env, minter) == 1);
1982 uint256 const minterSellOfferIndex =
1984 env(token::createOffer(minter, nftAliceID, XRP(23)),
1987 BEAST_EXPECT(ownerCount(env, alice) == 0);
1988 BEAST_EXPECT(ownerCount(env, becky) == 1);
1989 BEAST_EXPECT(ownerCount(env, minter) == 2);
1992 env(token::acceptSellOffer(alice, minterSellOfferIndex));
1994 BEAST_EXPECT(ownerCount(env, alice) == 1);
1995 BEAST_EXPECT(ownerCount(env, becky) == 1);
1996 BEAST_EXPECT(ownerCount(env, minter) == 0);
2000 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2002 BEAST_EXPECT(ownerCount(env, alice) == 0);
2003 BEAST_EXPECT(ownerCount(env, becky) == 1);
2004 BEAST_EXPECT(ownerCount(env, minter) == 0);
2008 env(token::burn(becky, nftAliceID));
2010 BEAST_EXPECT(ownerCount(env, alice) == 0);
2011 BEAST_EXPECT(ownerCount(env, becky) == 0);
2012 BEAST_EXPECT(ownerCount(env, minter) == 0);
2022 using namespace test::jtx;
2024 Env env{*
this, features};
2025 auto const baseFee = env.current()->fees().base;
2027 Account
const alice{
"alice"};
2028 Account
const becky{
"becky"};
2029 Account
const carol{
"carol"};
2030 Account
const minter{
"minter"};
2031 Account
const gw{
"gw"};
2032 IOU
const gwXAU(gw[
"XAU"]);
2034 env.fund(XRP(1000), alice, becky, carol, minter, gw);
2037 env(trust(alice, gwXAU(2000)));
2038 env(trust(becky, gwXAU(2000)));
2039 env(trust(carol, gwXAU(2000)));
2040 env(trust(minter, gwXAU(2000)));
2042 env(pay(gw, alice, gwXAU(1000)));
2043 env(pay(gw, becky, gwXAU(1000)));
2044 env(pay(gw, carol, gwXAU(1000)));
2045 env(pay(gw, minter, gwXAU(1000)));
2050 env(token::setMinter(alice, minter));
2056 BEAST_EXPECT(ownerCount(env, alice) == 1);
2057 BEAST_EXPECT(ownerCount(env, becky) == 1);
2058 BEAST_EXPECT(ownerCount(env, carol) == 1);
2059 BEAST_EXPECT(ownerCount(env, minter) == 1);
2067 uint256 const beckyBuyOfferIndex =
2069 env(token::createOffer(becky, nftID, gwXAU(10)),
2070 token::owner(alice));
2072 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2073 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2075 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2077 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2078 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2081 uint256 const beckySellOfferIndex =
2083 env(token::createOffer(becky, nftID, gwXAU(10)),
2086 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2088 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2089 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2090 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2093 uint256 const minterBuyOfferIndex =
2095 env(token::createOffer(minter, nftID, gwXAU(10)),
2096 token::owner(carol));
2098 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2100 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2101 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2102 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2103 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2107 uint256 const minterSellOfferIndex =
2109 env(token::createOffer(minter, nftID, gwXAU(10)),
2112 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2114 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2115 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2116 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2117 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2120 env(token::burn(alice, nftID));
2122 BEAST_EXPECT(ownerCount(env, alice) == 1);
2123 BEAST_EXPECT(ownerCount(env, becky) == 1);
2124 BEAST_EXPECT(ownerCount(env, carol) == 1);
2125 BEAST_EXPECT(ownerCount(env, minter) == 1);
2133 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2137 uint256 const beckyBuyOfferIndex =
2139 env(token::createOffer(becky, nftID, gwXAU(10)),
2140 token::owner(alice));
2142 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2143 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2145 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2147 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2148 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2151 uint256 const beckySellOfferIndex =
2153 env(token::createOffer(becky, nftID, gwXAU(10)),
2156 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2159 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0001));
2160 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2161 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2164 uint256 const minterBuyOfferIndex =
2166 env(token::createOffer(minter, nftID, gwXAU(10)),
2167 token::owner(carol));
2169 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2172 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0002));
2173 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2174 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2175 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2179 uint256 const minterSellOfferIndex =
2181 env(token::createOffer(minter, nftID, gwXAU(10)),
2184 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2186 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000.0002));
2187 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2188 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2189 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2193 env(pay(alice, becky, gwXAU(0.0001)));
2194 env(pay(alice, carol, gwXAU(0.0001)));
2197 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2198 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2199 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2200 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2203 env(token::burn(alice, nftID));
2205 BEAST_EXPECT(ownerCount(env, alice) == 1);
2206 BEAST_EXPECT(ownerCount(env, becky) == 1);
2207 BEAST_EXPECT(ownerCount(env, carol) == 1);
2208 BEAST_EXPECT(ownerCount(env, minter) == 1);
2214 env(token::mint(alice),
2221 uint256 const nftID = token::getNextID(
2223 env(token::mint(alice),
2229 uint256 const beckyBuyOfferIndex =
2231 env(token::createOffer(becky, nftID, gwXAU(10)),
2232 token::owner(alice));
2234 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2235 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2237 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2239 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2240 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2243 uint256 const beckySellOfferIndex =
2245 env(token::createOffer(becky, nftID, gwXAU(100)),
2248 env(token::acceptSellOffer(minter, beckySellOfferIndex));
2251 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1060));
2252 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2253 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
2256 uint256 const carolBuyOfferIndex =
2258 env(token::createOffer(carol, nftID, gwXAU(10)),
2259 token::owner(minter));
2261 env(token::acceptBuyOffer(minter, carolBuyOfferIndex));
2264 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1065));
2265 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2266 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2267 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2271 uint256 const carolSellOfferIndex =
2273 env(token::createOffer(carol, nftID, gwXAU(10)),
2276 env(token::acceptSellOffer(alice, carolSellOfferIndex));
2279 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1055));
2280 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2281 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2282 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2285 env(pay(alice, minter, gwXAU(55)));
2286 env(pay(becky, minter, gwXAU(40)));
2288 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2289 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2290 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2291 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2294 env(token::burn(alice, nftID));
2296 BEAST_EXPECT(ownerCount(env, alice) == 1);
2297 BEAST_EXPECT(ownerCount(env, becky) == 1);
2298 BEAST_EXPECT(ownerCount(env, carol) == 1);
2299 BEAST_EXPECT(ownerCount(env, minter) == 1);
2304 for (
auto NumberSwitchOver : {
true})
2306 if (NumberSwitchOver)
2307 env.enableFeature(fixUniversalNumber);
2309 env.disableFeature(fixUniversalNumber);
2314 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2319 STAmount aliceBalance = env.balance(alice);
2320 STAmount minterBalance = env.balance(minter);
2321 uint256 const minterBuyOfferIndex =
2323 env(token::createOffer(minter, nftID, XRP(1)), token::owner(alice));
2325 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2327 aliceBalance += XRP(1) - baseFee;
2328 minterBalance -= XRP(1) + baseFee;
2329 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2330 BEAST_EXPECT(env.balance(minter) == minterBalance);
2334 auto pmt = NumberSwitchOver ? drops(50000) : drops(99999);
2335 STAmount carolBalance = env.balance(carol);
2336 uint256 const minterSellOfferIndex =
2338 env(token::createOffer(minter, nftID, pmt), txflags(
tfSellNFToken));
2340 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2342 minterBalance += pmt - baseFee;
2343 carolBalance -= pmt + baseFee;
2344 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2345 BEAST_EXPECT(env.balance(minter) == minterBalance);
2346 BEAST_EXPECT(env.balance(carol) == carolBalance);
2350 STAmount beckyBalance = env.balance(becky);
2351 uint256 const beckyBuyOfferIndex =
2353 pmt = NumberSwitchOver ? drops(50001) : drops(100000);
2354 env(token::createOffer(becky, nftID, pmt), token::owner(carol));
2356 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2358 carolBalance += pmt - drops(1) - baseFee;
2359 beckyBalance -= pmt + baseFee;
2360 aliceBalance += drops(1);
2362 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2363 BEAST_EXPECT(env.balance(minter) == minterBalance);
2364 BEAST_EXPECT(env.balance(carol) == carolBalance);
2365 BEAST_EXPECT(env.balance(becky) == beckyBalance);
2374 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2380 env(pay(alice, gw, env.balance(alice, gwXAU)));
2381 env(pay(minter, gw, env.balance(minter, gwXAU)));
2382 env(pay(becky, gw, env.balance(becky, gwXAU)));
2387 env(pay(gw, alice, startXAUBalance));
2388 env(pay(gw, minter, startXAUBalance));
2389 env(pay(gw, becky, startXAUBalance));
2398 STAmount aliceBalance = env.balance(alice, gwXAU);
2399 STAmount minterBalance = env.balance(minter, gwXAU);
2400 uint256 const minterBuyOfferIndex =
2402 env(token::createOffer(minter, nftID, tinyXAU),
2403 token::owner(alice));
2405 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2407 aliceBalance += tinyXAU;
2408 minterBalance -= tinyXAU;
2409 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2410 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2413 STAmount carolBalance = env.balance(carol, gwXAU);
2414 uint256 const minterSellOfferIndex =
2416 env(token::createOffer(minter, nftID, tinyXAU),
2419 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2422 minterBalance += tinyXAU;
2423 carolBalance -= tinyXAU;
2425 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2426 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2427 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2434 STAmount beckyBalance = env.balance(becky, gwXAU);
2435 uint256 const beckyBuyOfferIndex =
2437 env(token::createOffer(becky, nftID, cheapNFT),
2438 token::owner(carol));
2440 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2443 aliceBalance += tinyXAU;
2444 beckyBalance -= cheapNFT;
2445 carolBalance += cheapNFT - tinyXAU;
2446 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2447 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2448 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2449 BEAST_EXPECT(env.balance(becky, gwXAU) == beckyBalance);
2642 testcase(
"Create offer destination");
2644 using namespace test::jtx;
2646 Env env{*
this, features};
2648 Account
const issuer{
"issuer"};
2649 Account
const minter{
"minter"};
2650 Account
const buyer{
"buyer"};
2651 Account
const broker{
"broker"};
2653 env.fund(XRP(1000), issuer, minter, buyer, broker);
2657 env(token::setMinter(issuer, minter));
2662 env(token::mint(minter, 0),
2663 token::issuer(issuer),
2670 uint256 const offerMinterToIssuer =
2672 env(token::createOffer(minter, nftokenID, drops(1)),
2673 token::destination(issuer),
2676 uint256 const offerMinterToBuyer =
2678 env(token::createOffer(minter, nftokenID, drops(1)),
2679 token::destination(buyer),
2682 uint256 const offerIssuerToMinter =
2684 env(token::createOffer(issuer, nftokenID, drops(1)),
2685 token::owner(minter),
2686 token::destination(minter));
2688 uint256 const offerIssuerToBuyer =
2690 env(token::createOffer(issuer, nftokenID, drops(1)),
2691 token::owner(minter),
2692 token::destination(buyer));
2695 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2696 BEAST_EXPECT(ownerCount(env, minter) == 3);
2697 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2706 env(token::cancelOffer(issuer, {offerMinterToBuyer}),
2708 env(token::cancelOffer(buyer, {offerMinterToIssuer}),
2710 env(token::cancelOffer(buyer, {offerIssuerToMinter}),
2712 env(token::cancelOffer(minter, {offerIssuerToBuyer}),
2715 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2716 BEAST_EXPECT(ownerCount(env, minter) == 3);
2717 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2721 env(token::cancelOffer(buyer, {offerMinterToBuyer}));
2722 env(token::cancelOffer(minter, {offerMinterToIssuer}));
2723 env(token::cancelOffer(buyer, {offerIssuerToBuyer}));
2724 env(token::cancelOffer(issuer, {offerIssuerToMinter}));
2726 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2727 BEAST_EXPECT(ownerCount(env, minter) == 1);
2728 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2734 uint256 const offerMinterSellsToBuyer =
2736 env(token::createOffer(minter, nftokenID, drops(1)),
2737 token::destination(buyer),
2740 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2741 BEAST_EXPECT(ownerCount(env, minter) == 2);
2742 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2746 env(token::acceptSellOffer(issuer, offerMinterSellsToBuyer),
2749 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2750 BEAST_EXPECT(ownerCount(env, minter) == 2);
2751 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2754 env(token::acceptSellOffer(buyer, offerMinterSellsToBuyer));
2756 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2757 BEAST_EXPECT(ownerCount(env, minter) == 0);
2758 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2764 uint256 const offerMinterBuysFromBuyer =
2766 env(token::createOffer(minter, nftokenID, drops(1)),
2767 token::owner(buyer),
2768 token::destination(buyer));
2770 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2771 BEAST_EXPECT(ownerCount(env, minter) == 1);
2772 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2776 env(token::acceptBuyOffer(issuer, offerMinterBuysFromBuyer),
2779 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2780 BEAST_EXPECT(ownerCount(env, minter) == 1);
2781 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2784 env(token::acceptBuyOffer(buyer, offerMinterBuysFromBuyer));
2786 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2787 BEAST_EXPECT(ownerCount(env, minter) == 1);
2788 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2793 uint256 const offerBuyerBuysFromMinter =
2795 env(token::createOffer(buyer, nftokenID, drops(1)),
2796 token::owner(minter),
2797 token::destination(broker));
2799 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2800 BEAST_EXPECT(ownerCount(env, minter) == 1);
2801 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2803 env(token::acceptBuyOffer(minter, offerBuyerBuysFromMinter),
2808 env(token::cancelOffer(buyer, {offerBuyerBuysFromMinter}));
2810 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2811 BEAST_EXPECT(ownerCount(env, minter) == 1);
2812 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2818 uint256 const offerMinterToBroker =
2820 env(token::createOffer(minter, nftokenID, drops(1)),
2821 token::destination(broker),
2824 uint256 const offerBuyerToMinter =
2826 env(token::createOffer(buyer, nftokenID, drops(1)),
2827 token::owner(minter));
2830 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2831 BEAST_EXPECT(ownerCount(env, minter) == 2);
2832 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2837 env(token::brokerOffers(
2838 issuer, offerBuyerToMinter, offerMinterToBroker),
2841 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2842 BEAST_EXPECT(ownerCount(env, minter) == 2);
2843 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2848 env(token::brokerOffers(
2849 broker, offerBuyerToMinter, offerMinterToBroker));
2851 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2852 BEAST_EXPECT(ownerCount(env, minter) == 0);
2853 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2860 uint256 const offerBuyerToMinter =
2862 env(token::createOffer(buyer, nftokenID, drops(1)),
2863 token::destination(minter),
2866 uint256 const offerMinterToBuyer =
2868 env(token::createOffer(minter, nftokenID, drops(1)),
2869 token::owner(buyer));
2871 uint256 const offerIssuerToBuyer =
2873 env(token::createOffer(issuer, nftokenID, drops(1)),
2874 token::owner(buyer));
2877 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2878 BEAST_EXPECT(ownerCount(env, minter) == 1);
2879 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2884 env(token::brokerOffers(
2885 broker, offerIssuerToBuyer, offerBuyerToMinter),
2889 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2890 BEAST_EXPECT(ownerCount(env, minter) == 1);
2891 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2893 env(token::brokerOffers(
2894 broker, offerMinterToBuyer, offerBuyerToMinter),
2899 env(token::acceptBuyOffer(buyer, offerMinterToBuyer));
2903 env(token::cancelOffer(buyer, {offerBuyerToMinter}));
2906 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2907 BEAST_EXPECT(ownerCount(env, minter) == 1);
2908 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2911 env(token::cancelOffer(issuer, {offerIssuerToBuyer}));
2913 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2914 BEAST_EXPECT(ownerCount(env, minter) == 1);
2915 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2923 uint256 const offerMinterToBroker =
2925 env(token::createOffer(minter, nftokenID, drops(1)),
2926 token::destination(broker),
2929 uint256 const offerBuyerToBroker =
2931 env(token::createOffer(buyer, nftokenID, drops(1)),
2932 token::owner(minter),
2933 token::destination(broker));
2938 env(token::brokerOffers(
2939 issuer, offerBuyerToBroker, offerMinterToBroker),
2942 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2943 BEAST_EXPECT(ownerCount(env, minter) == 2);
2944 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2948 env(token::brokerOffers(
2949 broker, offerBuyerToBroker, offerMinterToBroker));
2951 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2952 BEAST_EXPECT(ownerCount(env, minter) == 0);
2953 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3098 testcase(
"Create offer expiration");
3100 using namespace test::jtx;
3102 Env env{*
this, features};
3104 Account
const issuer{
"issuer"};
3105 Account
const minter{
"minter"};
3106 Account
const buyer{
"buyer"};
3108 env.fund(XRP(1000), issuer, minter, buyer);
3112 env(token::setMinter(issuer, minter));
3117 env(token::mint(minter, 0),
3118 token::issuer(issuer),
3124 env(token::mint(minter, 0),
3125 token::issuer(issuer),
3134 uint256 const offerMinterToIssuer =
3136 env(token::createOffer(minter, nftokenID0, drops(1)),
3137 token::destination(issuer),
3138 token::expiration(expiration),
3141 uint256 const offerMinterToAnyone =
3143 env(token::createOffer(minter, nftokenID0, drops(1)),
3144 token::expiration(expiration),
3147 uint256 const offerIssuerToMinter =
3149 env(token::createOffer(issuer, nftokenID0, drops(1)),
3150 token::owner(minter),
3151 token::expiration(expiration));
3153 uint256 const offerBuyerToMinter =
3155 env(token::createOffer(buyer, nftokenID0, drops(1)),
3156 token::owner(minter),
3157 token::expiration(expiration));
3159 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3160 BEAST_EXPECT(ownerCount(env, minter) == 3);
3161 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3169 env(token::cancelOffer(issuer, {offerMinterToAnyone}),
3171 env(token::cancelOffer(buyer, {offerIssuerToMinter}),
3174 BEAST_EXPECT(
lastClose(env) < expiration);
3175 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3176 BEAST_EXPECT(ownerCount(env, minter) == 3);
3177 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3180 env(token::cancelOffer(minter, {offerMinterToAnyone}));
3184 env(token::cancelOffer(issuer, {offerMinterToIssuer}));
3190 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3191 BEAST_EXPECT(ownerCount(env, minter) == 1);
3192 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3195 env(token::cancelOffer(issuer, {offerBuyerToMinter}));
3196 env(token::cancelOffer(buyer, {offerIssuerToMinter}));
3198 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3199 BEAST_EXPECT(ownerCount(env, minter) == 1);
3200 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3211 env(token::createOffer(minter, nftokenID0, drops(1)),
3212 token::expiration(expiration),
3217 env(token::createOffer(minter, nftokenID1, drops(1)),
3218 token::expiration(expiration),
3221 BEAST_EXPECT(
lastClose(env) < expiration);
3222 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3223 BEAST_EXPECT(ownerCount(env, minter) == 3);
3224 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3227 env(token::acceptSellOffer(buyer, offer0));
3233 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3234 BEAST_EXPECT(ownerCount(env, minter) == 2);
3235 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3238 env(token::acceptSellOffer(buyer, offer1), ter(
tecEXPIRED));
3239 env(token::acceptSellOffer(issuer, offer1), ter(
tecEXPIRED));
3243 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3244 BEAST_EXPECT(ownerCount(env, minter) == 2);
3245 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3248 env(token::cancelOffer(issuer, {offer1}));
3250 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3251 BEAST_EXPECT(ownerCount(env, minter) == 1);
3252 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3258 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3260 token::destination(minter));
3262 env(token::acceptSellOffer(minter, offerSellBack));
3264 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3265 BEAST_EXPECT(ownerCount(env, minter) == 1);
3266 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3276 env(token::createOffer(buyer, nftokenID0, drops(1)),
3277 token::owner(minter),
3278 token::expiration(expiration));
3281 env(token::createOffer(buyer, nftokenID1, drops(1)),
3282 token::owner(minter),
3283 token::expiration(expiration));
3285 BEAST_EXPECT(
lastClose(env) < expiration);
3286 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3287 BEAST_EXPECT(ownerCount(env, minter) == 1);
3288 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3291 env(token::acceptBuyOffer(minter, offer0));
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, offer1), ter(
tecEXPIRED));
3303 env(token::acceptBuyOffer(issuer, offer1), ter(
tecEXPIRED));
3307 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3308 BEAST_EXPECT(ownerCount(env, minter) == 1);
3309 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3312 env(token::cancelOffer(issuer, {offer1}));
3314 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3315 BEAST_EXPECT(ownerCount(env, minter) == 1);
3316 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3322 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3324 token::destination(minter));
3326 env(token::acceptSellOffer(minter, offerSellBack));
3328 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3329 BEAST_EXPECT(ownerCount(env, minter) == 1);
3330 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3341 env(token::createOffer(minter, nftokenID0, drops(1)),
3342 token::expiration(expiration),
3347 env(token::createOffer(minter, nftokenID1, drops(1)),
3348 token::expiration(expiration),
3353 env(token::createOffer(buyer, nftokenID0, drops(1)),
3354 token::owner(minter));
3358 env(token::createOffer(buyer, nftokenID1, drops(1)),
3359 token::owner(minter));
3362 BEAST_EXPECT(
lastClose(env) < expiration);
3363 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3364 BEAST_EXPECT(ownerCount(env, minter) == 3);
3365 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3368 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3374 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3375 BEAST_EXPECT(ownerCount(env, minter) == 2);
3376 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3379 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3384 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3385 BEAST_EXPECT(ownerCount(env, minter) == 2);
3386 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3389 env(token::cancelOffer(buyer, {buyOffer1, sellOffer1}));
3391 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3392 BEAST_EXPECT(ownerCount(env, minter) == 1);
3393 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3399 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3401 token::destination(minter));
3403 env(token::acceptSellOffer(minter, offerSellBack));
3405 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3406 BEAST_EXPECT(ownerCount(env, minter) == 1);
3407 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3418 env(token::createOffer(minter, nftokenID0, drops(1)),
3423 env(token::createOffer(minter, nftokenID1, drops(1)),
3428 env(token::createOffer(buyer, nftokenID0, drops(1)),
3429 token::expiration(expiration),
3430 token::owner(minter));
3434 env(token::createOffer(buyer, nftokenID1, drops(1)),
3435 token::expiration(expiration),
3436 token::owner(minter));
3439 BEAST_EXPECT(
lastClose(env) < expiration);
3440 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3441 BEAST_EXPECT(ownerCount(env, minter) == 3);
3442 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3445 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3451 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3452 BEAST_EXPECT(ownerCount(env, minter) == 2);
3453 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3456 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3461 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3462 BEAST_EXPECT(ownerCount(env, minter) == 2);
3463 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3466 env(token::cancelOffer(minter, {buyOffer1, sellOffer1}));
3468 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3469 BEAST_EXPECT(ownerCount(env, minter) == 1);
3470 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3476 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3478 token::destination(minter));
3480 env(token::acceptSellOffer(minter, offerSellBack));
3482 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3483 BEAST_EXPECT(ownerCount(env, minter) == 1);
3484 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3496 env(token::createOffer(minter, nftokenID0, drops(1)),
3497 token::expiration(expiration),
3502 env(token::createOffer(minter, nftokenID1, drops(1)),
3503 token::expiration(expiration),
3508 env(token::createOffer(buyer, nftokenID0, drops(1)),
3509 token::expiration(expiration),
3510 token::owner(minter));
3514 env(token::createOffer(buyer, nftokenID1, drops(1)),
3515 token::expiration(expiration),
3516 token::owner(minter));
3519 BEAST_EXPECT(
lastClose(env) < expiration);
3520 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3521 BEAST_EXPECT(ownerCount(env, minter) == 3);
3522 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3525 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3531 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3532 BEAST_EXPECT(ownerCount(env, minter) == 2);
3533 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3536 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3541 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3542 BEAST_EXPECT(ownerCount(env, minter) == 2);
3543 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3546 env(token::cancelOffer(issuer, {buyOffer1, sellOffer1}));
3548 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3549 BEAST_EXPECT(ownerCount(env, minter) == 1);
3550 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3556 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3558 token::destination(minter));
3560 env(token::acceptSellOffer(minter, offerSellBack));
3562 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3563 BEAST_EXPECT(ownerCount(env, minter) == 1);
3564 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3805 testcase(
"Brokered NFT offer accept");
3807 using namespace test::jtx;
3810 Env env{*
this, features};
3811 auto const baseFee = env.current()->fees().base;
3819 Account
const issuer{
"issuer"};
3820 Account
const minter{
"minter"};
3821 Account
const buyer{
"buyer"};
3822 Account
const broker{
"broker"};
3823 Account
const gw{
"gw"};
3824 IOU
const gwXAU(gw[
"XAU"]);
3826 env.fund(XRP(1000), issuer, minter, buyer, broker, gw);
3829 env(trust(issuer, gwXAU(2000)));
3830 env(trust(minter, gwXAU(2000)));
3831 env(trust(buyer, gwXAU(2000)));
3832 env(trust(broker, gwXAU(2000)));
3835 env(token::setMinter(issuer, minter));
3839 auto checkOwnerCountIsOne =
3844 for (Account
const& acct : accounts)
3851 ss <<
"Account " << acct.human()
3852 <<
" expected ownerCount == 1. Got "
3854 fail(ss.
str(), __FILE__, line);
3860 auto mintNFT = [&env, &issuer, &minter](
std::uint16_t xferFee = 0) {
3863 env(token::mint(minter, 0),
3864 token::issuer(issuer),
3865 token::xferFee(xferFee),
3877 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3879 uint256 const nftID = mintNFT();
3882 uint256 const minterOfferIndex =
3884 env(token::createOffer(minter, nftID, XRP(0)),
3892 env(token::createOffer(buyer, nftID, XRP(1)),
3893 token::owner(minter));
3896 auto const minterBalance = env.balance(minter);
3897 auto const buyerBalance = env.balance(buyer);
3898 auto const brokerBalance = env.balance(broker);
3899 auto const issuerBalance = env.balance(issuer);
3902 env(token::brokerOffers(
3903 broker, buyOfferIndex, minterOfferIndex));
3908 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(1));
3909 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3910 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
3911 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
3914 env(token::burn(buyer, nftID));
3924 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3926 uint256 const nftID = mintNFT();
3929 uint256 const minterOfferIndex =
3931 env(token::createOffer(minter, nftID, XRP(0)),
3939 env(token::createOffer(buyer, nftID, XRP(1)),
3940 token::owner(minter));
3944 env(token::brokerOffers(
3945 broker, buyOfferIndex, minterOfferIndex),
3946 token::brokerFee(XRP(1.1)),
3950 auto const minterBalance = env.balance(minter);
3951 auto const buyerBalance = env.balance(buyer);
3952 auto const brokerBalance = env.balance(broker);
3953 auto const issuerBalance = env.balance(issuer);
3956 env(token::brokerOffers(
3957 broker, buyOfferIndex, minterOfferIndex),
3958 token::brokerFee(XRP(0.5)));
3963 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
3964 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3966 env.balance(broker) == brokerBalance + XRP(0.5) - baseFee);
3967 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
3970 env(token::burn(buyer, nftID));
3980 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3985 uint256 const minterOfferIndex =
3987 env(token::createOffer(minter, nftID, XRP(0)),
3995 env(token::createOffer(buyer, nftID, XRP(1)),
3996 token::owner(minter));
3999 auto const minterBalance = env.balance(minter);
4000 auto const buyerBalance = env.balance(buyer);
4001 auto const brokerBalance = env.balance(broker);
4002 auto const issuerBalance = env.balance(issuer);
4005 env(token::brokerOffers(
4006 broker, buyOfferIndex, minterOfferIndex));
4011 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
4012 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4013 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
4014 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.5));
4017 env(token::burn(buyer, nftID));
4027 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4032 uint256 const minterOfferIndex =
4034 env(token::createOffer(minter, nftID, XRP(0)),
4042 env(token::createOffer(buyer, nftID, XRP(1)),
4043 token::owner(minter));
4046 auto const minterBalance = env.balance(minter);
4047 auto const buyerBalance = env.balance(buyer);
4048 auto const brokerBalance = env.balance(broker);
4049 auto const issuerBalance = env.balance(issuer);
4052 env(token::brokerOffers(
4053 broker, buyOfferIndex, minterOfferIndex),
4054 token::brokerFee(XRP(0.75)));
4060 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.125));
4061 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4063 env.balance(broker) == brokerBalance + XRP(0.75) - baseFee);
4064 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.125));
4067 env(token::burn(buyer, nftID));
4073 auto setXAUBalance =
4074 [
this, &gw, &gwXAU, &env](
4079 for (Account
const& acct : accounts)
4081 auto const xauAmt = gwXAU(amount);
4082 auto const balance = env.balance(acct, gwXAU);
4083 if (balance < xauAmt)
4085 env(pay(gw, acct, xauAmt - balance));
4088 else if (balance > xauAmt)
4090 env(pay(acct, gw, balance - xauAmt));
4093 if (env.balance(acct, gwXAU) != xauAmt)
4096 ss <<
"Unable to set " << acct.human()
4097 <<
" account balance to gwXAU(" << amount <<
")";
4098 this->
fail(ss.
str(), __FILE__, line);
4106 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4107 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4109 uint256 const nftID = mintNFT();
4112 uint256 const minterOfferIndex =
4114 env(token::createOffer(minter, nftID, gwXAU(1000)),
4123 env(token::createOffer(buyer, nftID, gwXAU(1001)),
4124 token::owner(minter));
4128 env(token::brokerOffers(
4129 broker, buyOfferIndex, minterOfferIndex),
4135 env(token::cancelOffer(buyer, {buyOfferIndex}));
4143 env(token::createOffer(buyer, nftID, gwXAU(999)),
4144 token::owner(minter));
4148 env(token::brokerOffers(
4149 broker, buyOfferIndex, minterOfferIndex),
4155 env(token::cancelOffer(buyer, {buyOfferIndex}));
4162 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4163 token::owner(minter));
4167 env(token::brokerOffers(
4168 broker, buyOfferIndex, minterOfferIndex),
4169 token::brokerFee(gwXAU(0.1)),
4174 env(token::brokerOffers(
4175 broker, buyOfferIndex, minterOfferIndex));
4178 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4179 BEAST_EXPECT(ownerCount(env, minter) == 1);
4180 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4181 BEAST_EXPECT(ownerCount(env, broker) == 1);
4182 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1000));
4183 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(2000));
4184 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4185 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1000));
4188 env(token::burn(buyer, nftID));
4195 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4196 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4201 uint256 const minterOfferIndex =
4203 env(token::createOffer(minter, nftID, gwXAU(900)),
4211 env(token::createOffer(buyer, nftID, gwXAU(1001)),
4212 token::owner(minter));
4216 env(token::brokerOffers(
4217 broker, buyOfferIndex, minterOfferIndex),
4223 env(token::cancelOffer(buyer, {buyOfferIndex}));
4231 env(token::createOffer(buyer, nftID, gwXAU(899)),
4232 token::owner(minter));
4236 env(token::brokerOffers(
4237 broker, buyOfferIndex, minterOfferIndex),
4243 env(token::cancelOffer(buyer, {buyOfferIndex}));
4249 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4250 token::owner(minter));
4255 env(token::brokerOffers(
4256 broker, buyOfferIndex, minterOfferIndex),
4257 token::brokerFee(gwXAU(101)),
4263 env(token::brokerOffers(
4264 broker, buyOfferIndex, minterOfferIndex),
4265 token::brokerFee(gwXAU(100)));
4268 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4269 BEAST_EXPECT(ownerCount(env, minter) == 1);
4270 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4271 BEAST_EXPECT(ownerCount(env, broker) == 1);
4272 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1450));
4273 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1450));
4274 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4275 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1100));
4278 env(token::burn(buyer, nftID));
4285 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4286 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4291 uint256 const minterOfferIndex =
4293 env(token::createOffer(minter, nftID, gwXAU(900)),
4300 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4301 token::owner(minter));
4307 env(token::brokerOffers(
4308 broker, buyOfferIndex, minterOfferIndex),
4309 token::brokerFee(gwXAU(50)));
4312 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4313 BEAST_EXPECT(ownerCount(env, minter) == 1);
4314 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4315 BEAST_EXPECT(ownerCount(env, broker) == 1);
4316 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4317 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4318 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4319 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1050));
4322 env(token::burn(buyer, nftID));
4327 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4328 setXAUBalance({issuer, minter, buyer}, 1000, __LINE__);
4329 setXAUBalance({broker}, 500, __LINE__);
4333 uint256 const minterOfferIndex =
4335 env(token::createOffer(minter, nftID, gwXAU(900)),
4342 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4343 token::owner(minter));
4346 env(token::brokerOffers(
4347 broker, buyOfferIndex, minterOfferIndex),
4348 token::brokerFee(gwXAU(50)));
4350 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4351 BEAST_EXPECT(ownerCount(env, minter) == 1);
4352 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4353 BEAST_EXPECT(ownerCount(env, broker) == 1);
4354 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4355 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4356 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4357 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(550));
4360 env(token::burn(buyer, nftID));
4984 using namespace test::jtx;
4986 testcase(
"Payments with IOU transfer fees");
4989 Env env{*
this, features};
4991 Account
const minter{
"minter"};
4992 Account
const secondarySeller{
"seller"};
4993 Account
const buyer{
"buyer"};
4994 Account
const gw{
"gateway"};
4995 Account
const broker{
"broker"};
4996 IOU
const gwXAU(gw[
"XAU"]);
4997 IOU
const gwXPB(gw[
"XPB"]);
4999 env.fund(XRP(1000), gw, minter, secondarySeller, buyer, broker);
5002 env(trust(minter, gwXAU(2000)));
5003 env(trust(secondarySeller, gwXAU(2000)));
5004 env(trust(broker, gwXAU(10000)));
5005 env(trust(buyer, gwXAU(2000)));
5006 env(trust(buyer, gwXPB(2000)));
5010 env(rate(gw, 1.02));
5013 auto expectInitialState = [
this,
5026 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(1000));
5027 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(0));
5028 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(0));
5029 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(0));
5030 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(0));
5031 BEAST_EXPECT(env.balance(secondarySeller, gwXPB) == gwXPB(0));
5032 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5000));
5033 BEAST_EXPECT(env.balance(broker, gwXPB) == gwXPB(0));
5034 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-1000));
5035 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(0));
5036 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(0));
5037 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(0));
5039 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(0));
5041 env.balance(gw, secondarySeller[
"XPB"]) == gwXPB(0));
5042 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5000));
5043 BEAST_EXPECT(env.balance(gw, broker[
"XPB"]) == gwXPB(0));
5046 auto reinitializeTrustLineBalances = [&expectInitialState,
5055 if (
auto const difference =
5056 gwXAU(1000) - env.balance(buyer, gwXAU);
5057 difference > gwXAU(0))
5058 env(pay(gw, buyer, difference));
5059 if (env.balance(buyer, gwXPB) > gwXPB(0))
5060 env(pay(buyer, gw, env.balance(buyer, gwXPB)));
5061 if (env.balance(minter, gwXAU) > gwXAU(0))
5062 env(pay(minter, gw, env.balance(minter, gwXAU)));
5063 if (env.balance(minter, gwXPB) > gwXPB(0))
5064 env(pay(minter, gw, env.balance(minter, gwXPB)));
5065 if (env.balance(secondarySeller, gwXAU) > gwXAU(0))
5067 pay(secondarySeller,
5069 env.balance(secondarySeller, gwXAU)));
5070 if (env.balance(secondarySeller, gwXPB) > gwXPB(0))
5072 pay(secondarySeller,
5074 env.balance(secondarySeller, gwXPB)));
5075 auto brokerDiff = gwXAU(5000) - env.balance(broker, gwXAU);
5076 if (brokerDiff > gwXAU(0))
5077 env(pay(gw, broker, brokerDiff));
5078 else if (brokerDiff < gwXAU(0))
5080 brokerDiff.negate();
5081 env(pay(broker, gw, brokerDiff));
5083 if (env.balance(broker, gwXPB) > gwXPB(0))
5084 env(pay(broker, gw, env.balance(broker, gwXPB)));
5086 expectInitialState();
5089 auto mintNFT = [&env](Account
const& minter,
int transferFee = 0) {
5090 uint256 const nftID = token::getNextID(
5092 env(token::mint(minter),
5093 token::xferFee(transferFee),
5099 auto createBuyOffer =
5101 Account
const& offerer,
5102 Account
const& owner,
5108 env(token::createOffer(offerer, nftID, amount),
5109 token::owner(owner),
5110 terCode ? ter(*terCode)
5116 auto createSellOffer =
5118 Account
const& offerer,
5124 env(token::createOffer(offerer, nftID, amount),
5126 terCode ? ter(*terCode)
5135 reinitializeTrustLineBalances();
5136 auto const nftID = mintNFT(minter);
5137 auto const offerID =
5138 createSellOffer(minter, nftID, gwXAU(1000));
5140 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5143 expectInitialState();
5148 reinitializeTrustLineBalances();
5149 auto const nftID = mintNFT(minter);
5150 auto const offerID =
5151 createBuyOffer(buyer, minter, nftID, gwXAU(1000));
5153 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5156 expectInitialState();
5162 reinitializeTrustLineBalances();
5163 auto const nftID = mintNFT(minter);
5164 auto const offerID = createSellOffer(minter, nftID, gwXAU(995));
5166 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5169 expectInitialState();
5175 reinitializeTrustLineBalances();
5176 auto const nftID = mintNFT(minter);
5177 auto const offerID =
5178 createBuyOffer(buyer, minter, nftID, gwXAU(995));
5180 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5183 expectInitialState();
5190 reinitializeTrustLineBalances();
5191 auto const nftID = mintNFT(minter);
5192 auto const offerID = createSellOffer(minter, nftID, gwXAU(900));
5193 env(token::acceptSellOffer(buyer, offerID));
5196 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
5197 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5198 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
5199 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5206 reinitializeTrustLineBalances();
5207 auto const nftID = mintNFT(minter);
5208 auto const offerID =
5209 createBuyOffer(buyer, minter, nftID, gwXAU(900));
5210 env(token::acceptBuyOffer(minter, offerID));
5213 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
5214 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5215 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
5216 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5223 reinitializeTrustLineBalances();
5226 env(pay(gw, buyer, gwXAU(20)));
5229 auto const nftID = mintNFT(minter);
5230 auto const offerID =
5231 createSellOffer(minter, nftID, gwXAU(1000));
5232 env(token::acceptSellOffer(buyer, offerID));
5235 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5236 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5237 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5238 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5245 reinitializeTrustLineBalances();
5248 env(pay(gw, buyer, gwXAU(20)));
5251 auto const nftID = mintNFT(minter);
5252 auto const offerID =
5253 createBuyOffer(buyer, minter, nftID, gwXAU(1000));
5254 env(token::acceptBuyOffer(minter, offerID));
5257 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5258 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5259 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5260 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5265 reinitializeTrustLineBalances();
5267 auto const nftID = mintNFT(minter);
5268 auto const offerID =
5269 createSellOffer(minter, nftID, gwXAU(1000));
5271 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
5274 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5275 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5280 reinitializeTrustLineBalances();
5282 auto const nftID = mintNFT(minter);
5284 auto const offerID =
5285 createBuyOffer(gw, minter, nftID, gwXAU(1000), {offerTER});
5287 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5290 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5291 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5296 reinitializeTrustLineBalances();
5297 auto const nftID = mintNFT(minter);
5298 auto const offerID =
5299 createSellOffer(minter, nftID, gwXAU(5000));
5301 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
5304 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5305 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5310 reinitializeTrustLineBalances();
5312 auto const nftID = mintNFT(minter);
5314 auto const offerID =
5315 createBuyOffer(gw, minter, nftID, gwXAU(5000), {offerTER});
5317 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5320 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5321 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5327 reinitializeTrustLineBalances();
5328 auto const nftID = mintNFT(gw);
5329 auto const offerID = createSellOffer(gw, nftID, gwXAU(1000));
5330 env(token::acceptSellOffer(buyer, offerID));
5333 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5334 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5340 reinitializeTrustLineBalances();
5342 auto const nftID = mintNFT(gw);
5343 auto const offerID =
5344 createBuyOffer(buyer, gw, nftID, gwXAU(1000));
5345 env(token::acceptBuyOffer(gw, offerID));
5348 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5349 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5355 reinitializeTrustLineBalances();
5356 auto const nftID = mintNFT(gw);
5357 auto const offerID = createSellOffer(gw, nftID, gwXAU(2000));
5358 env(token::acceptSellOffer(buyer, offerID),
5361 expectInitialState();
5367 reinitializeTrustLineBalances();
5368 auto const nftID = mintNFT(gw);
5369 auto const offerID =
5370 createBuyOffer(buyer, gw, nftID, gwXAU(2000));
5371 env(token::acceptBuyOffer(gw, offerID),
5374 expectInitialState();
5379 reinitializeTrustLineBalances();
5380 auto const nftID = mintNFT(minter);
5381 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5382 env(token::acceptSellOffer(buyer, offerID),
5385 expectInitialState();
5390 reinitializeTrustLineBalances();
5391 auto const nftID = mintNFT(minter);
5392 auto const offerID = createBuyOffer(
5398 env(token::acceptBuyOffer(minter, offerID),
5401 expectInitialState();
5407 reinitializeTrustLineBalances();
5408 env(pay(gw, buyer, gwXPB(100)));
5411 auto const nftID = mintNFT(minter);
5412 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5413 env(token::acceptSellOffer(buyer, offerID));
5416 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5417 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5418 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5419 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5425 reinitializeTrustLineBalances();
5426 env(pay(gw, buyer, gwXPB(100)));
5429 auto const nftID = mintNFT(minter);
5430 auto const offerID =
5431 createBuyOffer(buyer, minter, nftID, gwXPB(10));
5432 env(token::acceptBuyOffer(minter, offerID));
5435 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5436 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5437 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5438 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5443 reinitializeTrustLineBalances();
5447 auto const nftID = mintNFT(minter, 3000);
5448 auto const primaryOfferID =
5449 createSellOffer(minter, nftID, XRP(0));
5450 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5454 auto const offerID =
5455 createSellOffer(secondarySeller, nftID, gwXAU(1000));
5457 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5460 expectInitialState();
5465 reinitializeTrustLineBalances();
5469 auto const nftID = mintNFT(minter, 3000);
5470 auto const primaryOfferID =
5471 createSellOffer(minter, nftID, XRP(0));
5472 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5476 auto const offerID =
5477 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(1000));
5479 env(token::acceptBuyOffer(secondarySeller, offerID),
5483 expectInitialState();
5488 reinitializeTrustLineBalances();
5492 auto const nftID = mintNFT(minter, 3000);
5493 auto const primaryOfferID =
5494 createSellOffer(minter, nftID, XRP(0));
5495 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5499 auto const offerID =
5500 createSellOffer(secondarySeller, nftID, gwXAU(900));
5501 env(token::acceptSellOffer(buyer, offerID));
5504 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5505 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5506 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5507 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5509 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5510 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5515 reinitializeTrustLineBalances();
5519 auto const nftID = mintNFT(minter, 3000);
5520 auto const primaryOfferID =
5521 createSellOffer(minter, nftID, XRP(0));
5522 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5526 auto const offerID =
5527 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(900));
5528 env(token::acceptBuyOffer(secondarySeller, offerID));
5532 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5534 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5536 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5537 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5539 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5540 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5558 reinitializeTrustLineBalances();
5560 auto const nftID = mintNFT(minter);
5561 auto const sellOffer =
5562 createSellOffer(minter, nftID, gwXAU(300));
5563 auto const buyOffer =
5564 createBuyOffer(buyer, minter, nftID, gwXAU(500));
5565 env(token::brokerOffers(broker, buyOffer, sellOffer),
5566 token::brokerFee(gwXAU(100)));
5569 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(400));
5570 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5571 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5572 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-400));
5573 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5574 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5592 reinitializeTrustLineBalances();
5596 auto const nftID = mintNFT(minter, 3000);
5597 auto const primaryOfferID =
5598 createSellOffer(minter, nftID, XRP(0));
5599 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5603 auto const sellOffer =
5604 createSellOffer(secondarySeller, nftID, gwXAU(300));
5605 auto const buyOffer =
5606 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(500));
5607 env(token::brokerOffers(broker, buyOffer, sellOffer),
5608 token::brokerFee(gwXAU(100)));
5611 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(12));
5612 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5613 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(388));
5614 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5615 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-12));
5616 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5618 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-388));
5619 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5717 using namespace test::jtx;
5722 auto openLedgerSeq = [](Env& env) {
return env.current()->seq(); };
5726 auto incLgrSeqForAcctDel = [&](Env& env, Account
const& acct) {
5727 int const delta = [&]() ->
int {
5728 if (env.seq(acct) + 255 > openLedgerSeq(env))
5729 return env.seq(acct) - openLedgerSeq(env) + 255;
5732 BEAST_EXPECT(delta >= 0);
5733 for (
int i = 0; i < delta; ++i)
5735 BEAST_EXPECT(openLedgerSeq(env) == env.seq(acct) + 255);
5740 auto incLgrSeqForFixNftRemint = [&](Env& env, Account
const& acct) {
5742 auto const deletableLgrSeq =
5743 (*env.le(acct))[~sfFirstNFTokenSequence].value_or(0) +
5744 (*env.le(acct))[sfMintedNFTokens] + 255;
5746 if (deletableLgrSeq > openLedgerSeq(env))
5747 delta = deletableLgrSeq - openLedgerSeq(env);
5749 BEAST_EXPECT(delta >= 0);
5750 for (
int i = 0; i < delta; ++i)
5752 BEAST_EXPECT(openLedgerSeq(env) == deletableLgrSeq);
5758 Env env{*
this, features};
5759 Account
const alice(
"alice");
5760 Account
const becky(
"becky");
5762 env.fund(XRP(10000), alice, becky);
5766 uint256 const prevNFTokenID = token::getNextID(env, alice, 0u);
5767 env(token::mint(alice));
5769 env(token::burn(alice, prevNFTokenID));
5773 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 1);
5776 incLgrSeqForAcctDel(env, alice);
5780 auto const acctDelFee{drops(env.current()->fees().increment)};
5781 env(acctdelete(alice, becky), fee(acctDelFee));
5786 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5787 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5790 env.fund(XRP(10000), alice);
5794 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5795 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5796 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5799 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5800 env(token::mint(alice));
5804 env(token::burn(alice, remintNFTokenID));
5808 BEAST_EXPECT(remintNFTokenID != prevNFTokenID);
5814 Env env{*
this, features};
5815 Account
const alice(
"alice");
5816 Account
const becky(
"becky");
5817 Account
const minter{
"minter"};
5819 env.fund(XRP(10000), alice, becky, minter);
5823 env(token::setMinter(alice, minter));
5829 for (
int i = 0; i < 500; i++)
5831 uint256 const nftokenID = token::getNextID(env, alice, 0u);
5833 env(token::mint(minter), token::issuer(alice));
5838 for (
auto const nftokenID : nftIDs)
5840 env(token::burn(minter, nftokenID));
5844 incLgrSeqForAcctDel(env, alice);
5848 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5849 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5851 auto const acctDelFee{drops(env.current()->fees().increment)};
5860 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
5864 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5869 incLgrSeqForFixNftRemint(env, alice);
5872 env(acctdelete(alice, becky), fee(acctDelFee));
5877 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5878 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5881 env.fund(XRP(10000), alice);
5885 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5886 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5887 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5891 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5892 env(token::mint(alice));
5896 env(token::burn(alice, remintNFTokenID));
5909 Env env{*
this, features};
5911 Account
const alice{
"alice"};
5912 Account
const becky{
"becky"};
5913 env.fund(XRP(10000), alice, becky);
5920 env(ticket::create(alice, 100));
5924 BEAST_EXPECT(ownerCount(env, alice) == 100);
5929 for (
int i = 0; i < 50; i++)
5931 nftIDs.
push_back(token::getNextID(env, alice, 0u));
5932 env(token::mint(alice, 0u), ticket::use(aliceTicketSeq++));
5937 for (
auto const nftokenID : nftIDs)
5939 env(token::burn(alice, nftokenID),
5940 ticket::use(aliceTicketSeq++));
5946 incLgrSeqForAcctDel(env, alice);
5950 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5951 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5953 auto const acctDelFee{drops(env.current()->fees().increment)};
5962 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
5966 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5971 incLgrSeqForFixNftRemint(env, alice);
5974 env(acctdelete(alice, becky), fee(acctDelFee));
5979 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5980 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5983 env.fund(XRP(10000), alice);
5987 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5988 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5989 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5993 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5994 env(token::mint(alice));
5998 env(token::burn(alice, remintNFTokenID));
6012 Env env{*
this, features};
6013 Account
const alice(
"alice");
6014 Account
const becky(
"becky");
6015 Account
const minter{
"minter"};
6017 env.fund(XRP(10000), alice, becky, minter);
6021 env(token::setMinter(alice, minter));
6026 env(ticket::create(minter, 100));
6030 BEAST_EXPECT(ownerCount(env, minter) == 100);
6035 for (
int i = 0; i < 50; i++)
6037 uint256 const nftokenID = token::getNextID(env, alice, 0u);
6039 env(token::mint(minter),
6040 token::issuer(alice),
6041 ticket::use(minterTicketSeq++));
6046 for (
auto const nftokenID : nftIDs)
6048 env(token::burn(minter, nftokenID), ticket::use(minterTicketSeq++));
6054 incLgrSeqForAcctDel(env, alice);
6058 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6059 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6068 auto const acctDelFee{drops(env.current()->fees().increment)};
6069 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
6073 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6078 incLgrSeqForFixNftRemint(env, alice);
6081 env(acctdelete(alice, becky), fee(acctDelFee));
6086 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
6087 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
6090 env.fund(XRP(10000), alice);
6094 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6095 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6096 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
6100 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
6101 env(token::mint(alice));
6105 env(token::burn(alice, remintNFTokenID));
6118 testcase(
"NFTokenMint with Create NFTokenOffer");
6120 using namespace test::jtx;
6122 if (!features[featureNFTokenMintOffer])
6124 Env env{*
this, features};
6125 Account
const alice(
"alice");
6126 Account
const buyer(
"buyer");
6128 env.fund(XRP(10000), alice, buyer);
6131 env(token::mint(alice),
6132 token::amount(XRP(10000)),
6136 env(token::mint(alice),
6137 token::destination(
"buyer"),
6141 env(token::mint(alice),
6151 Env env{*
this, features};
6152 auto const baseFee = env.current()->fees().base;
6153 Account
const alice(
"alice");
6154 Account
const buyer{
"buyer"};
6155 Account
const gw(
"gw");
6156 Account
const issuer(
"issuer");
6157 Account
const minter(
"minter");
6158 Account
const bob(
"bob");
6159 IOU
const gwAUD(gw[
"AUD"]);
6161 env.fund(XRP(10000), alice, buyer, gw, issuer, minter);
6166 env(token::mint(alice),
6167 token::destination(buyer),
6170 BEAST_EXPECT(ownerCount(env, alice) == 0);
6173 env(token::mint(alice),
6177 BEAST_EXPECT(ownerCount(env, buyer) == 0);
6183 env(token::mint(alice),
6184 token::amount(XRP(1000)),
6185 token::destination(alice),
6188 BEAST_EXPECT(ownerCount(env, alice) == 0);
6192 env(token::mint(alice),
6193 token::amount(XRP(1000)),
6194 token::destination(Account(
"demon")),
6197 BEAST_EXPECT(ownerCount(env, alice) == 0);
6202 env(token::mint(alice),
6203 token::amount(XRP(1000)),
6204 token::expiration(0),
6207 BEAST_EXPECT(ownerCount(env, alice) == 0);
6210 env(token::mint(alice),
6211 token::amount(XRP(1000)),
6215 BEAST_EXPECT(ownerCount(env, alice) == 0);
6220 env(token::mint(alice),
6221 token::amount(buyer[
"USD"](1)),
6224 env(token::mint(alice),
6225 token::amount(buyer[
"USD"](0)),
6228 BEAST_EXPECT(ownerCount(env, alice) == 0);
6231 env(token::mint(alice),
6232 token::amount(gwAUD(1000)),
6237 BEAST_EXPECT(ownerCount(env, alice) == 0);
6242 env(token::mint(gw),
6243 token::amount(gwAUD(1000)),
6245 token::xferFee(10));
6254 env(token::mint(alice),
6255 token::amount(gwAUD(1000)),
6260 BEAST_EXPECT(ownerCount(env, alice) == 0);
6263 env(token::mint(alice),
6264 token::amount(gwAUD(1000)),
6267 BEAST_EXPECT(ownerCount(env, alice) == 0);
6276 auto const acctReserve = env.current()->fees().reserve;
6277 auto const incReserve = env.current()->fees().increment;
6279 env.fund(acctReserve + incReserve, bob);
6283 env(token::mint(bob),
6284 token::amount(XRP(0)),
6289 env(pay(env.master, bob, incReserve + drops(baseFee)));
6291 env(token::mint(bob), token::amount(XRP(0)));
6295 env(pay(env.master, bob, drops(baseFee)));
6297 env(token::mint(bob),
6298 token::amount(XRP(0)),
6303 env(pay(env.master, bob, incReserve + drops(baseFee)));
6305 env(token::mint(bob), token::amount(XRP(0)));
6310 BEAST_EXPECT(ownerCount(env, alice) == 0);
6311 env(token::mint(alice), token::amount(XRP(10)));
6312 BEAST_EXPECT(ownerCount(env, alice) == 2);
6316 env(token::mint(alice),
6317 token::amount(XRP(10)),
6318 token::destination(buyer),
6319 token::expiration(
lastClose(env) + 25));
6323 env(trust(alice, gwAUD(1000)));
6325 env(token::mint(alice),
6326 token::amount(gwAUD(1)),
6327 token::destination(buyer),
6330 token::xferFee(10));
6334 env(token::mint(alice),
6335 token::amount(XRP(10)),
6336 token::destination(buyer),
6337 token::expiration(
lastClose(env) + 25));
6338 uint256 const offerAliceSellsToBuyer =
6340 env(token::cancelOffer(alice, {offerAliceSellsToBuyer}));
6344 env(token::mint(buyer),
6345 token::amount(XRP(10)),
6346 token::destination(alice),
6347 token::expiration(
lastClose(env) + 25));
6348 uint256 const offerBuyerSellsToAlice =
6350 env(token::cancelOffer(alice, {offerBuyerSellsToAlice}));
6353 env(token::setMinter(issuer, minter));
6357 BEAST_EXPECT(ownerCount(env, minter) == 0);
6358 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6359 env(token::mint(minter),
6360 token::issuer(issuer),
6361 token::amount(drops(1)));
6363 BEAST_EXPECT(ownerCount(env, minter) == 2);
6364 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6367 Env env{*
this, features};
6368 Account
const alice(
"alice");
6370 env.fund(XRP(1000000), alice);
6375 env(token::mint(alice), token::amount(XRP(-2)), ter(offerCreateTER));
6393 testcase(
"Test synthetic fields from JSON response");
6395 using namespace test::jtx;
6397 Account
const alice{
"alice"};
6398 Account
const bob{
"bob"};
6399 Account
const broker{
"broker"};
6401 Env env{*
this, features};
6402 env.fund(XRP(10000), alice, bob, broker);
6408 auto verifyNFTokenID = [&](
uint256 const& actualNftID) {
6415 env.rpc(
"tx", txHash)[jss::result][jss::meta];
6418 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_id)))
6425 BEAST_EXPECT(nftID == actualNftID);
6430 auto verifyNFTokenIDsInCancelOffer =
6438 env.rpc(
"tx", txHash)[jss::result][jss::meta];
6441 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_ids)))
6447 meta[jss::nftoken_ids].begin(),
6448 meta[jss::nftoken_ids].end(),
6452 BEAST_EXPECT(nftID.
parseHex(
id.asString()));
6458 std::sort(actualNftIDs.begin(), actualNftIDs.end());
6461 BEAST_EXPECT(metaIDs.
size() == actualNftIDs.size());
6465 for (
size_t i = 0; i < metaIDs.
size(); ++i)
6466 BEAST_EXPECT(metaIDs[i] == actualNftIDs[i]);
6471 auto verifyNFTokenOfferID = [&](
uint256 const& offerID) {
6478 env.rpc(
"tx", txHash)[jss::result][jss::meta];
6481 if (!BEAST_EXPECT(meta.
isMember(jss::offer_id)))
6486 BEAST_EXPECT(metaOfferID == offerID);
6497 verifyNFTokenID(nftId1);
6503 verifyNFTokenID(nftId2);
6508 uint256 const aliceOfferIndex1 =
6510 env(token::createOffer(alice, nftId1, drops(1)),
6513 verifyNFTokenOfferID(aliceOfferIndex1);
6515 uint256 const aliceOfferIndex2 =
6517 env(token::createOffer(alice, nftId2, drops(1)),
6520 verifyNFTokenOfferID(aliceOfferIndex2);
6525 env(token::cancelOffer(
6526 alice, {aliceOfferIndex1, aliceOfferIndex2}));
6528 verifyNFTokenIDsInCancelOffer({nftId1, nftId2});
6532 auto const bobBuyOfferIndex =
6534 env(token::createOffer(bob, nftId1, drops(1)), token::owner(alice));
6536 verifyNFTokenOfferID(bobBuyOfferIndex);
6540 env(token::acceptBuyOffer(alice, bobBuyOfferIndex));
6542 verifyNFTokenID(nftId1);
6552 verifyNFTokenID(nftId);
6555 uint256 const offerAliceToBroker =
6557 env(token::createOffer(alice, nftId, drops(1)),
6558 token::destination(broker),
6561 verifyNFTokenOfferID(offerAliceToBroker);
6564 uint256 const offerBobToBroker =
6566 env(token::createOffer(bob, nftId, drops(1)), token::owner(alice));
6568 verifyNFTokenOfferID(offerBobToBroker);
6571 env(token::brokerOffers(
6572 broker, offerBobToBroker, offerAliceToBroker));
6574 verifyNFTokenID(nftId);
6585 verifyNFTokenID(nftId);
6588 uint256 const aliceOfferIndex1 =
6590 env(token::createOffer(alice, nftId, drops(1)),
6593 verifyNFTokenOfferID(aliceOfferIndex1);
6595 uint256 const aliceOfferIndex2 =
6597 env(token::createOffer(alice, nftId, drops(1)),
6600 verifyNFTokenOfferID(aliceOfferIndex2);
6604 env(token::cancelOffer(
6605 alice, {aliceOfferIndex1, aliceOfferIndex2}));
6607 verifyNFTokenIDsInCancelOffer({nftId});
6610 if (features[featureNFTokenMintOffer])
6612 uint256 const aliceMintWithOfferIndex1 =
6614 env(token::mint(alice), token::amount(XRP(0)));
6616 verifyNFTokenOfferID(aliceMintWithOfferIndex1);
6623 testcase(
"Test buyer reserve when accepting an offer");
6625 using namespace test::jtx;
6638 uint256 const sellOfferIndex =
6640 env(token::createOffer(acct, nftId, amt), txflags(
tfSellNFToken));
6643 return sellOfferIndex;
6650 Account
const alice{
"alice"};
6651 Account
const bob{
"bob"};
6653 Env env{*
this, features};
6654 auto const acctReserve = env.
current()->fees().reserve;
6655 auto const incReserve = env.
current()->fees().increment;
6656 auto const baseFee = env.
current()->fees().base;
6658 env.
fund(XRP(10000), alice);
6662 env.
fund(acctReserve, bob);
6666 auto const sellOfferIndex =
6667 mintAndCreateSellOffer(env, alice, XRP(0));
6670 BEAST_EXPECT(ownerCount(env, bob) == 0);
6674 if (!features[fixNFTokenReserve])
6677 env(token::acceptSellOffer(bob, sellOfferIndex));
6681 BEAST_EXPECT(ownerCount(env, bob) == 1);
6696 env(token::acceptSellOffer(bob, sellOfferIndex),
6703 BEAST_EXPECT(ownerCount(env, bob) == 0);
6708 env(pay(env.
master, bob, incReserve + drops(baseFee)));
6713 env(token::acceptSellOffer(bob, sellOfferIndex),
6719 env(pay(env.
master, bob, drops(baseFee * 2)));
6723 env(token::acceptSellOffer(bob, sellOfferIndex));
6726 BEAST_EXPECT(ownerCount(env, bob) == 1);
6733 Account
const alice{
"alice"};
6734 Account
const bob{
"bob"};
6736 Env env{*
this, features};
6737 auto const acctReserve = env.
current()->fees().reserve;
6738 auto const incReserve = env.
current()->fees().increment;
6740 env.
fund(XRP(10000), alice);
6743 env.
fund(acctReserve + XRP(1), bob);
6746 if (!features[fixNFTokenReserve])
6749 for (
size_t i = 0; i < 200; i++)
6752 auto const sellOfferIndex =
6753 mintAndCreateSellOffer(env, alice, XRP(0));
6756 env(token::acceptSellOffer(bob, sellOfferIndex));
6763 auto const sellOfferIndex1 =
6764 mintAndCreateSellOffer(env, alice, XRP(0));
6768 env(token::acceptSellOffer(bob, sellOfferIndex1),
6773 env(pay(env.
master, bob, drops(incReserve)));
6776 BEAST_EXPECT(ownerCount(env, bob) == 0);
6779 env(token::acceptSellOffer(bob, sellOfferIndex1));
6782 BEAST_EXPECT(ownerCount(env, bob) == 1);
6786 for (
size_t i = 0; i < 31; i++)
6789 auto const sellOfferIndex =
6790 mintAndCreateSellOffer(env, alice, XRP(0));
6794 env(token::acceptSellOffer(bob, sellOfferIndex));
6798 BEAST_EXPECT(ownerCount(env, bob) == 1);
6802 auto const sellOfferIndex33 =
6803 mintAndCreateSellOffer(env, alice, XRP(0));
6807 env(token::acceptSellOffer(bob, sellOfferIndex33),
6812 env(pay(env.
master, bob, drops(incReserve)));
6817 env(token::acceptSellOffer(bob, sellOfferIndex33));
6820 BEAST_EXPECT(ownerCount(env, bob) == 2);
6830 Account
const alice{
"alice"};
6831 Account
const bob{
"bob"};
6833 Env env{*
this, features};
6834 auto const acctReserve = env.
current()->fees().reserve;
6835 auto const incReserve = env.
current()->fees().increment;
6836 auto const baseFee = env.
current()->fees().base;
6838 env.
fund(XRP(10000), alice);
6844 env.
fund(acctReserve + incReserve + XRP(1), bob);
6855 env(token::createOffer(bob, nftId, XRP(1)), token::owner(alice));
6861 env(token::acceptBuyOffer(alice, buyOfferIndex),
6866 env(pay(env.
master, bob, drops(baseFee)));
6870 env(token::acceptBuyOffer(alice, buyOfferIndex));
6880 Account
const alice{
"alice"};
6881 Account
const bob{
"bob"};
6882 Account
const broker{
"broker"};
6884 Env env{*
this, features};
6885 auto const acctReserve = env.
current()->fees().reserve;
6886 auto const incReserve = env.
current()->fees().increment;
6887 auto const baseFee = env.
current()->fees().base;
6889 env.
fund(XRP(10000), alice, broker);
6894 env.
fund(acctReserve + incReserve + XRP(1), bob);
6904 uint256 const offerAliceToBroker =
6906 env(token::createOffer(alice, nftId, XRP(1)),
6907 token::destination(broker),
6912 uint256 const offerBobToBroker =
6914 env(token::createOffer(bob, nftId, XRP(1)), token::owner(alice));
6921 env(token::brokerOffers(
6922 broker, offerBobToBroker, offerAliceToBroker),
6927 env(pay(env.
master, bob, drops(baseFee)));
6931 env(token::brokerOffers(
6932 broker, offerBobToBroker, offerAliceToBroker));
7270 using namespace test::jtx;
7272 Account
const issuer{
"issuer"};
7273 Account
const alice(
"alice");
7274 Account
const bob(
"bob");
7276 bool const modifyEnabled = features[featureDynamicNFT];
7280 Env env{*
this, features};
7281 env.fund(XRP(10000), issuer);
7284 auto const expectedTer =
7286 env(token::mint(issuer, 0u), txflags(
tfMutable), ter(expectedTer));
7290 Env env{*
this, features};
7291 env.fund(XRP(10000), issuer);
7298 env(token::mint(issuer, 0u), txflags(
tfMutable));
7300 BEAST_EXPECT(ownerCount(env, issuer) == 1);
7301 env(token::modify(issuer, nftId));
7302 BEAST_EXPECT(ownerCount(env, issuer) == 1);
7306 env(token::mint(issuer, 0u));
7308 env(token::modify(issuer, nftId), ter(
temDISABLED));
7316 Env env{*
this, features};
7317 env.fund(XRP(10000), issuer);
7321 env(token::mint(issuer, 0u), txflags(
tfMutable));
7325 env(token::modify(issuer, nftId),
7331 env(token::modify(issuer, nftId),
7332 txflags(0x00000001),
7336 env(token::modify(issuer, nftId),
7337 token::owner(issuer),
7342 env(token::modify(issuer, nftId),
7348 env(token::modify(issuer, nftId),
7354 Env env{*
this, features};
7355 env.fund(XRP(10000), issuer, alice, bob);
7361 token::getNextID(env, issuer, 0u,
tfMutable)};
7364 env(token::modify(issuer, nftIDNotExists), ter(
tecNO_ENTRY));
7369 uint256 const nftIDNotModifiable{
7370 token::getNextID(env, issuer, 0u)};
7371 env(token::mint(issuer, 0u));
7374 env(token::modify(issuer, nftIDNotModifiable),
7381 token::getNextID(env, issuer, 0u,
tfMutable)};
7382 env(token::mint(issuer, 0u), txflags(
tfMutable));
7385 env(token::modify(bob, nftId),
7386 token::owner(issuer),
7390 env(token::setMinter(issuer, alice));
7393 env(token::modify(bob, nftId),
7394 token::owner(issuer),
7400 Env env{*
this, features};
7401 env.fund(XRP(10000), issuer, alice, bob);
7406 env(token::mint(issuer, 0u), txflags(
tfMutable), token::uri(
"uri"));
7413 Env env{*
this, features};
7414 env.fund(XRP(10000), issuer, alice, bob);
7418 auto accountNFTs = [&env](Account
const& acct) {
7420 params[jss::account] = acct.human();
7421 params[jss::type] =
"state";
7423 env.rpc(
"json",
"account_nfts",
to_string(params));
7424 return response[jss::result][jss::account_nfts];
7428 auto checkURI = [&accountNFTs,
this](
7429 Account
const& acct,
7432 auto const nfts = accountNFTs(acct);
7433 if (nfts.size() == 1)
7438 text <<
"checkURI: unexpected NFT count on line " << line;
7439 fail(text.
str(), __FILE__, line);
7445 if (!nfts[0u].isMember(sfURI.jsonName))
7450 text <<
"checkURI: unexpected URI present on line "
7452 fail(text.
str(), __FILE__, line);
7462 text <<
"checkURI: unexpected URI contents on line "
7464 fail(text.
str(), __FILE__, line);
7471 env(token::mint(issuer, 0u), txflags(
tfMutable), token::uri(
"uri"));
7473 checkURI(issuer,
"uri", __LINE__);
7476 env(token::modify(issuer, nftId), token::uri(
"new_uri"));
7478 checkURI(issuer,
"new_uri", __LINE__);
7481 env(token::modify(issuer, nftId));
7483 checkURI(issuer,
nullptr, __LINE__);
7486 env(token::modify(issuer, nftId), token::uri(
"uri"));
7488 checkURI(issuer,
"uri", __LINE__);
7493 env(token::createOffer(issuer, nftId, XRP(0)),
7496 env(token::acceptSellOffer(alice, offerID));
7498 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7499 BEAST_EXPECT(ownerCount(env, alice) == 1);
7500 checkURI(alice,
"uri", __LINE__);
7503 env(token::modify(alice, nftId),
7504 token::uri(
"new_uri"),
7507 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7508 BEAST_EXPECT(ownerCount(env, alice) == 1);
7509 checkURI(alice,
"uri", __LINE__);
7511 env(token::modify(issuer, nftId),
7512 token::owner(alice),
7513 token::uri(
"new_uri"));
7515 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7516 BEAST_EXPECT(ownerCount(env, alice) == 1);
7517 checkURI(alice,
"new_uri", __LINE__);
7519 env(token::modify(issuer, nftId), token::owner(alice));
7521 checkURI(alice,
nullptr, __LINE__);
7523 env(token::modify(issuer, nftId),
7524 token::owner(alice),
7527 checkURI(alice,
"uri", __LINE__);
7530 env(token::setMinter(issuer, bob));
7532 env(token::modify(bob, nftId),
7533 token::owner(alice),
7534 token::uri(
"new_uri"));
7536 checkURI(alice,
"new_uri", __LINE__);
7538 env(token::modify(bob, nftId), token::owner(alice));
7540 checkURI(alice,
nullptr, __LINE__);
7542 env(token::modify(bob, nftId),
7543 token::owner(alice),
7546 checkURI(alice,
"uri", __LINE__);