157 using namespace test::jtx;
159 Env env{*
this, features};
160 Account
const alice{
"alice"};
161 Account
const minter{
"minter"};
165 auto const acctReserve = env.current()->fees().reserve;
166 auto const incReserve = env.current()->fees().increment;
167 auto const baseFee = env.current()->fees().base;
169 env.fund(acctReserve, alice, minter);
172 BEAST_EXPECT(env.balance(alice) == acctReserve);
173 BEAST_EXPECT(env.balance(minter) == acctReserve);
174 BEAST_EXPECT(ownerCount(env, alice) == 0);
175 BEAST_EXPECT(ownerCount(env, minter) == 0);
182 BEAST_EXPECT(ownerCount(env, alice) == 0);
187 env(pay(env.master, alice, incReserve + drops(baseFee - 1)));
192 auto checkAliceOwnerMintedBurned = [&env,
this, &alice](
205 ss <<
"Wrong " << type <<
" count. Found: " << found
206 <<
"; Expected: " << exp;
207 fail(ss.
str(), __FILE__, line);
210 oneCheck(
"owner", ownerCount(env, alice), owners);
211 oneCheck(
"minted",
mintedCount(env, alice), minted);
212 oneCheck(
"burned",
burnedCount(env, alice), burned);
220 checkAliceOwnerMintedBurned(0, 0, 0, __LINE__);
223 env(pay(env.master, alice, drops(baseFee + 1)));
227 env(token::mint(alice));
230 checkAliceOwnerMintedBurned(1, 1, 0, __LINE__);
234 for (
int i = 1; i < 32; ++i)
236 env(token::mint(alice));
237 checkAliceOwnerMintedBurned(1, i + 1, 0, __LINE__);
244 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
247 env(pay(env.master, alice, incReserve + drops(baseFee * 33 - 1)));
254 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
257 env(pay(env.master, alice, drops(baseFee + 1)));
261 env(token::mint(alice));
263 checkAliceOwnerMintedBurned(2, 33, 0, __LINE__);
270 env(token::burn(alice, token::getID(env, alice, 0, seq++)));
272 checkAliceOwnerMintedBurned((33 - seq) ? 1 : 0, 33, seq, __LINE__);
276 env(token::burn(alice, token::getID(env, alice, 197, 5)),
279 checkAliceOwnerMintedBurned(0, 33, 33, __LINE__);
284 env(token::setMinter(alice, minter));
287 env.le(alice)->getAccountID(sfNFTokenMinter) == minter.id());
291 auto checkMintersOwnerMintedBurned = [&env,
this, &alice, &minter](
299 auto oneCheck = [
this](
309 ss <<
"Wrong " << type <<
" count. Found: " << found
310 <<
"; Expected: " << exp;
311 fail(ss.
str(), __FILE__, line);
314 oneCheck(
"alice owner", ownerCount(env, alice), aliceOwners, line);
316 "alice minted",
mintedCount(env, alice), aliceMinted, line);
318 "alice burned",
burnedCount(env, alice), aliceBurned, line);
320 "minter owner", ownerCount(env, minter), minterOwners, line);
322 "minter minted",
mintedCount(env, minter), minterMinted, line);
324 "minter burned",
burnedCount(env, minter), minterBurned, line);
330 env(pay(env.master, minter, incReserve - drops(1)));
332 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
337 env(token::mint(minter),
338 token::issuer(alice),
342 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
345 env(pay(env.master, minter, drops(baseFee + 1)));
349 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
351 checkMintersOwnerMintedBurned(0, 34, nftSeq, 1, 0, 0, __LINE__);
355 for (
int i = 1; i < 32; ++i)
357 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
358 checkMintersOwnerMintedBurned(0, i + 34, nftSeq, 1, 0, 0, __LINE__);
363 env(pay(env.master, minter, incReserve + drops(baseFee * 32 - 1)));
368 env(token::mint(minter),
369 token::issuer(alice),
373 checkMintersOwnerMintedBurned(0, 65, nftSeq, 1, 0, 0, __LINE__);
376 env(pay(env.master, minter, drops(baseFee + 1)));
380 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
382 checkMintersOwnerMintedBurned(0, 66, nftSeq, 2, 0, 0, __LINE__);
387 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
389 checkMintersOwnerMintedBurned(
390 0, 66, nftSeq, (65 - seq) ? 1 : 0, 0, 0, __LINE__);
395 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
397 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
400 env(token::burn(minter, token::getID(env, alice, 2009, 3)),
403 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
606 testcase(
"Invalid NFT offer create");
608 using namespace test::jtx;
610 Env env{*
this, features};
611 Account
const alice{
"alice"};
612 Account
const buyer{
"buyer"};
613 Account
const gw(
"gw");
614 IOU
const gwAUD(gw[
"AUD"]);
619 env.fund(XRP(250), alice, buyer, gw);
621 BEAST_EXPECT(ownerCount(env, alice) == 0);
625 env(token::mint(alice, 0u),
629 BEAST_EXPECT(ownerCount(env, alice) == 1);
635 BEAST_EXPECT(ownerCount(env, alice) == 1);
637 uint256 nftNoXferID = token::getNextID(env, alice, 0);
638 env(token::mint(alice, 0));
640 BEAST_EXPECT(ownerCount(env, alice) == 1);
651 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
655 BEAST_EXPECT(ownerCount(env, buyer) == 0);
658 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
662 BEAST_EXPECT(ownerCount(env, buyer) == 0);
665 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
669 BEAST_EXPECT(ownerCount(env, buyer) == 0);
672 env(token::createOffer(buyer, nftXrpOnlyID, buyer[
"USD"](1)),
674 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](0)),
676 env(token::createOffer(buyer, nftXrpOnlyID, drops(0)),
679 BEAST_EXPECT(ownerCount(env, buyer) == 0);
682 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](1)),
683 token::expiration(0),
686 BEAST_EXPECT(ownerCount(env, buyer) == 0);
690 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
693 BEAST_EXPECT(ownerCount(env, buyer) == 0);
696 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
701 BEAST_EXPECT(ownerCount(env, alice) == 1);
704 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
708 BEAST_EXPECT(ownerCount(env, alice) == 1);
711 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
712 token::destination(alice),
716 BEAST_EXPECT(ownerCount(env, alice) == 1);
719 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
720 token::destination(Account(
"demon")),
724 BEAST_EXPECT(ownerCount(env, alice) == 1);
730 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
735 BEAST_EXPECT(ownerCount(env, buyer) == 0);
738 env(token::createOffer(
739 buyer, token::getID(env, alice, 0, 1), XRP(1000)),
743 BEAST_EXPECT(ownerCount(env, buyer) == 0);
746 env(token::createOffer(
747 alice, token::getID(env, alice, 0, 1), XRP(1000)),
751 BEAST_EXPECT(ownerCount(env, buyer) == 0);
754 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
758 BEAST_EXPECT(ownerCount(env, buyer) == 0);
760 env(trust(buyer, gwAUD(1000)));
762 BEAST_EXPECT(ownerCount(env, buyer) == 1);
766 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
770 BEAST_EXPECT(ownerCount(env, buyer) == 1);
778 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
782 BEAST_EXPECT(ownerCount(env, buyer) == 1);
789 env(token::createOffer(buyer, nftNoXferID, gwAUD(1000)),
793 BEAST_EXPECT(ownerCount(env, buyer) == 1);
799 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
803 BEAST_EXPECT(ownerCount(env, buyer) == 1);
808 env(trust(buyer, gwAUD(1000)));
811 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
815 BEAST_EXPECT(ownerCount(env, buyer) == 1);
821 env(pay(gw, buyer, gwAUD(999)));
826 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
830 BEAST_EXPECT(ownerCount(env, buyer) == 1);
833 auto const baseFee = env.current()->fees().base;
834 env(pay(env.master, buyer, XRP(50) + drops(baseFee * 12 - 1)));
837 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
841 BEAST_EXPECT(ownerCount(env, buyer) == 1);
844 env(pay(env.master, buyer, drops(baseFee + 1)));
849 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
853 BEAST_EXPECT(ownerCount(env, buyer) == 2);
979 testcase(
"Invalid NFT offer accept");
981 using namespace test::jtx;
983 Env env{*
this, features};
984 Account
const alice{
"alice"};
985 Account
const buyer{
"buyer"};
986 Account
const gw(
"gw");
987 IOU
const gwAUD(gw[
"AUD"]);
989 env.fund(XRP(1000), alice, buyer, gw);
991 BEAST_EXPECT(ownerCount(env, alice) == 0);
997 BEAST_EXPECT(ownerCount(env, alice) == 1);
1003 BEAST_EXPECT(ownerCount(env, alice) == 1);
1005 uint256 nftNoXferID = token::getNextID(env, alice, 0);
1006 env(token::mint(alice, 0));
1008 BEAST_EXPECT(ownerCount(env, alice) == 1);
1011 uint256 const plainOfferIndex =
1013 env(token::createOffer(alice, nftAlice0ID, XRP(10)),
1016 BEAST_EXPECT(ownerCount(env, alice) == 2);
1020 env(token::createOffer(alice, nftAlice0ID, gwAUD(30)),
1023 BEAST_EXPECT(ownerCount(env, alice) == 3);
1025 uint256 const xrpOnlyOfferIndex =
1027 env(token::createOffer(alice, nftXrpOnlyID, XRP(20)),
1030 BEAST_EXPECT(ownerCount(env, alice) == 4);
1032 uint256 const noXferOfferIndex =
1034 env(token::createOffer(alice, nftNoXferID, XRP(30)),
1037 BEAST_EXPECT(ownerCount(env, alice) == 5);
1040 uint256 const aliceExpOfferIndex =
1042 env(token::createOffer(alice, nftNoXferID, XRP(40)),
1046 BEAST_EXPECT(ownerCount(env, alice) == 6);
1052 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1056 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1059 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1060 txflags(0x00008000),
1063 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1067 Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1071 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1076 Json::Value jv = token::acceptBuyOffer(buyer, noXferOfferIndex);
1077 jv[sfNFTokenBrokerFee.jsonName] =
1081 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1086 Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1087 jv[sfNFTokenBrokerFee.jsonName] =
1091 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1095 env(token::brokerOffers(buyer, noXferOfferIndex, xrpOnlyOfferIndex),
1096 token::brokerFee(gwAUD(0)),
1099 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1105 env(token::acceptBuyOffer(buyer, beast::zero),
1108 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1112 env(token::acceptBuyOffer(buyer, missingOfferIndex),
1115 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1118 env(token::acceptBuyOffer(buyer, aliceExpOfferIndex), ter(
tecEXPIRED));
1120 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1123 env(token::acceptSellOffer(buyer, beast::zero),
1126 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1129 env(token::acceptSellOffer(buyer, missingOfferIndex),
1132 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1135 env(token::acceptSellOffer(buyer, aliceExpOfferIndex), ter(
tecEXPIRED));
1137 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1144 env(trust(alice, gwAUD(1000)));
1145 env(trust(buyer, gwAUD(1000)));
1147 env(pay(gw, buyer, gwAUD(30)));
1149 BEAST_EXPECT(ownerCount(env, alice) == 7);
1150 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1156 uint256 const buyerOfferIndex =
1158 env(token::createOffer(buyer, nftAlice0ID, gwAUD(29)),
1159 token::owner(alice));
1161 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1164 env(token::brokerOffers(gw, buyerOfferIndex, xrpOnlyOfferIndex),
1167 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1170 env(token::brokerOffers(gw, buyerOfferIndex, plainOfferIndex),
1173 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1177 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1180 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1183 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1185 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1189 uint256 const buyerOfferIndex =
1191 env(token::createOffer(buyer, nftAlice0ID, gwAUD(31)),
1192 token::owner(alice));
1194 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1198 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1199 token::brokerFee(XRP(40)),
1202 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1205 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1206 token::brokerFee(gwAUD(31)),
1209 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1213 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1214 token::brokerFee(gwAUD(1.5)),
1217 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1220 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1222 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1228 uint256 const buyerOfferIndex =
1230 env(token::createOffer(buyer, nftAlice0ID, gwAUD(30)),
1231 token::owner(alice));
1233 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1236 env(token::acceptBuyOffer(buyer, plainOfferIndex),
1239 BEAST_EXPECT(ownerCount(env, alice) == 7);
1242 env(token::acceptBuyOffer(buyer, buyerOfferIndex),
1245 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1248 env(pay(buyer, gw, gwAUD(30)));
1250 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1251 env(token::acceptBuyOffer(alice, buyerOfferIndex),
1254 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1260 env(token::createOffer(alice, nftAlice0ID, XRP(0)),
1263 env(token::acceptSellOffer(gw, offerIndex));
1265 BEAST_EXPECT(ownerCount(env, alice) == 7);
1267 env(pay(gw, buyer, gwAUD(30)));
1271 env(token::acceptBuyOffer(alice, buyerOfferIndex),
1274 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1277 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1279 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1285 uint256 const buyerOfferIndex =
1287 env(token::createOffer(buyer, nftXrpOnlyID, XRP(30)),
1288 token::owner(alice));
1290 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1293 env(token::acceptSellOffer(alice, buyerOfferIndex),
1296 BEAST_EXPECT(ownerCount(env, alice) == 7);
1299 env(token::acceptSellOffer(alice, plainOfferIndex),
1302 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1306 env(token::acceptSellOffer(buyer, plainOfferIndex),
1309 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1317 env(token::createOffer(gw, nftAlice0ID, XRP(0)),
1320 env(token::acceptSellOffer(alice, offerIndex));
1322 BEAST_EXPECT(ownerCount(env, alice) == 7);
1324 env(pay(buyer, gw, gwAUD(30)));
1326 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1327 env(token::acceptSellOffer(buyer, audOfferIndex),
1330 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1556 testcase(
"Mint flagCreateTrustLines");
1558 using namespace test::jtx;
1560 Account
const alice{
"alice"};
1561 Account
const becky{
"becky"};
1562 Account
const cheri{
"cheri"};
1563 Account
const gw(
"gw");
1564 IOU
const gwAUD(gw[
"AUD"]);
1565 IOU
const gwCAD(gw[
"CAD"]);
1566 IOU
const gwEUR(gw[
"EUR"]);
1571 for (
auto const& tweakedFeatures :
1572 {features - fixRemoveNFTokenAutoTrustLine,
1573 features | fixRemoveNFTokenAutoTrustLine})
1575 Env env{*
this, tweakedFeatures};
1576 env.fund(XRP(1000), alice, becky, cheri, gw);
1580 env(trust(becky, gwAUD(1000)));
1581 env(trust(cheri, gwAUD(1000)));
1582 env(trust(becky, gwCAD(1000)));
1583 env(trust(cheri, gwCAD(1000)));
1584 env(trust(becky, gwEUR(1000)));
1585 env(trust(cheri, gwEUR(1000)));
1587 env(pay(gw, becky, gwAUD(500)));
1588 env(pay(gw, becky, gwCAD(500)));
1589 env(pay(gw, becky, gwEUR(500)));
1590 env(pay(gw, cheri, gwAUD(500)));
1591 env(pay(gw, cheri, gwCAD(500)));
1598 uint256 const nftNoAutoTrustID{
1600 env(token::mint(alice, 0u),
1601 token::xferFee(xferFee),
1606 uint256 const beckyBuyOfferIndex =
1608 env(token::createOffer(becky, nftNoAutoTrustID, drops(1)),
1609 token::owner(alice));
1611 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1615 TER const createOfferTER =
1617 uint256 const beckyOfferIndex =
1619 env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)),
1621 ter(createOfferTER));
1625 uint256 const cheriOfferIndex =
1627 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
1628 token::owner(becky),
1629 ter(createOfferTER));
1633 env(token::cancelOffer(becky, {beckyOfferIndex}));
1634 env(token::cancelOffer(cheri, {cheriOfferIndex}));
1642 uint256 const nftAutoTrustID{token::getNextID(
1649 tweakedFeatures[fixRemoveNFTokenAutoTrustLine]
1653 env(token::mint(alice, 0u),
1654 token::xferFee(transferFee),
1661 if (tweakedFeatures[fixRemoveNFTokenAutoTrustLine])
1665 uint256 const beckyBuyOfferIndex =
1667 env(token::createOffer(becky, nftAutoTrustID, drops(1)),
1668 token::owner(alice));
1670 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1674 uint256 const beckySellOfferIndex =
1676 env(token::createOffer(becky, nftAutoTrustID, gwAUD(100)),
1679 env(token::acceptSellOffer(cheri, beckySellOfferIndex));
1683 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1686 uint256 const beckyBuyBackOfferIndex =
1688 env(token::createOffer(becky, nftAutoTrustID, gwCAD(50)),
1689 token::owner(cheri));
1691 env(token::acceptBuyOffer(cheri, beckyBuyBackOfferIndex));
1695 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1696 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(5));
1702 uint256 const nftNoAutoTrustID{token::getNextID(
1704 env(token::mint(alice, 0u),
1705 token::xferFee(transferFee),
1710 uint256 const aliceSellOfferIndex =
1712 env(token::createOffer(alice, nftNoAutoTrustID, gwAUD(200)),
1715 env(token::acceptSellOffer(cheri, aliceSellOfferIndex));
1721 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(210));
1724 env(token::createOffer(cheri, nftNoAutoTrustID, gwEUR(50)),
1728 uint256 const cheriSellOfferIndex =
1730 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
1733 env(token::acceptSellOffer(becky, cheriSellOfferIndex));
1739 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(10));
1750 using namespace test::jtx;
1752 Env env{*
this, features};
1754 Account
const alice{
"alice"};
1755 Account
const becky{
"becky"};
1756 Account
const minter{
"minter"};
1758 env.fund(XRP(1000), alice, becky, minter);
1763 BEAST_EXPECT(ownerCount(env, alice) == 0);
1764 uint256 const nftAliceNoTransferID{
1765 token::getNextID(env, alice, 0u)};
1766 env(token::mint(alice, 0u), token::xferFee(0));
1768 BEAST_EXPECT(ownerCount(env, alice) == 1);
1771 BEAST_EXPECT(ownerCount(env, becky) == 0);
1772 env(token::createOffer(becky, nftAliceNoTransferID, XRP(20)),
1773 token::owner(alice),
1777 uint256 const aliceSellOfferIndex =
1779 env(token::createOffer(alice, nftAliceNoTransferID, XRP(20)),
1782 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1784 BEAST_EXPECT(ownerCount(env, alice) == 0);
1785 BEAST_EXPECT(ownerCount(env, becky) == 1);
1788 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1792 BEAST_EXPECT(ownerCount(env, alice) == 0);
1793 BEAST_EXPECT(ownerCount(env, becky) == 1);
1797 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1799 token::destination(alice),
1802 BEAST_EXPECT(ownerCount(env, alice) == 0);
1803 BEAST_EXPECT(ownerCount(env, becky) == 1);
1807 uint256 const aliceBuyOfferIndex =
1809 env(token::createOffer(alice, nftAliceNoTransferID, XRP(22)),
1810 token::owner(becky));
1812 env(token::acceptBuyOffer(becky, aliceBuyOfferIndex));
1814 BEAST_EXPECT(ownerCount(env, alice) == 1);
1815 BEAST_EXPECT(ownerCount(env, becky) == 0);
1818 env(token::burn(alice, nftAliceNoTransferID));
1820 BEAST_EXPECT(ownerCount(env, alice) == 0);
1821 BEAST_EXPECT(ownerCount(env, becky) == 0);
1825 env(token::setMinter(alice, minter));
1828 BEAST_EXPECT(ownerCount(env, minter) == 0);
1829 uint256 const nftMinterNoTransferID{
1830 token::getNextID(env, alice, 0u)};
1831 env(token::mint(minter), token::issuer(alice));
1833 BEAST_EXPECT(ownerCount(env, minter) == 1);
1836 BEAST_EXPECT(ownerCount(env, becky) == 0);
1837 env(token::createOffer(becky, nftMinterNoTransferID, XRP(20)),
1838 token::owner(minter),
1841 BEAST_EXPECT(ownerCount(env, becky) == 0);
1844 env(token::clearMinter(alice));
1848 BEAST_EXPECT(ownerCount(env, minter) == 1);
1849 env(token::createOffer(minter, nftMinterNoTransferID, XRP(21)),
1853 BEAST_EXPECT(ownerCount(env, minter) == 1);
1857 for (
int i = 0; i < 10; ++i)
1860 env(token::setMinter(alice, minter));
1862 BEAST_EXPECT(ownerCount(env, minter) == 1);
1865 BEAST_EXPECT(ownerCount(env, minter) == 1);
1866 uint256 const minterSellOfferIndex =
1868 env(token::createOffer(minter, nftMinterNoTransferID, XRP(22)),
1871 BEAST_EXPECT(ownerCount(env, minter) == 2);
1875 env(token::clearMinter(alice));
1880 BEAST_EXPECT(ownerCount(env, becky) == 0);
1881 env(token::acceptSellOffer(becky, minterSellOfferIndex));
1883 BEAST_EXPECT(ownerCount(env, becky) == 1);
1884 BEAST_EXPECT(ownerCount(env, minter) == 0);
1887 env(token::createOffer(becky, nftMinterNoTransferID, XRP(23)),
1894 BEAST_EXPECT(ownerCount(env, minter) == 0);
1895 env(token::createOffer(minter, nftMinterNoTransferID, XRP(24)),
1896 token::owner(becky),
1899 BEAST_EXPECT(ownerCount(env, minter) == 0);
1902 BEAST_EXPECT(ownerCount(env, alice) == 0);
1903 uint256 const aliceBuyOfferIndex =
1905 env(token::createOffer(alice, nftMinterNoTransferID, XRP(25)),
1906 token::owner(becky));
1908 BEAST_EXPECT(ownerCount(env, alice) == 1);
1912 for (
int i = 0; i < 10; ++i)
1915 env(token::setMinter(alice, minter));
1919 BEAST_EXPECT(ownerCount(env, minter) == 0);
1920 uint256 const minterBuyOfferIndex =
1922 env(token::createOffer(minter, nftMinterNoTransferID, XRP(26)),
1923 token::owner(becky));
1925 BEAST_EXPECT(ownerCount(env, minter) == 1);
1929 env(token::clearMinter(alice));
1933 BEAST_EXPECT(ownerCount(env, minter) == 1);
1934 BEAST_EXPECT(ownerCount(env, becky) == 1);
1935 env(token::acceptBuyOffer(becky, minterBuyOfferIndex));
1937 BEAST_EXPECT(ownerCount(env, minter) == 1);
1938 BEAST_EXPECT(ownerCount(env, becky) == 0);
1939 BEAST_EXPECT(ownerCount(env, alice) == 1);
1943 env(token::burn(minter, nftMinterNoTransferID), ter(
tesSUCCESS));
1945 env(token::cancelOffer(alice, {aliceBuyOfferIndex}));
1947 BEAST_EXPECT(ownerCount(env, alice) == 0);
1948 BEAST_EXPECT(ownerCount(env, becky) == 0);
1949 BEAST_EXPECT(ownerCount(env, minter) == 0);
1954 BEAST_EXPECT(ownerCount(env, alice) == 0);
1959 BEAST_EXPECT(ownerCount(env, alice) == 1);
1962 uint256 const aliceSellOfferIndex =
1964 env(token::createOffer(alice, nftAliceID, XRP(20)),
1967 BEAST_EXPECT(ownerCount(env, alice) == 2);
1969 uint256 const beckyBuyOfferIndex =
1971 env(token::createOffer(becky, nftAliceID, XRP(21)),
1972 token::owner(alice));
1974 BEAST_EXPECT(ownerCount(env, alice) == 2);
1977 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1979 BEAST_EXPECT(ownerCount(env, alice) == 0);
1980 BEAST_EXPECT(ownerCount(env, becky) == 2);
1983 uint256 const beckySellOfferIndex =
1985 env(token::createOffer(becky, nftAliceID, XRP(22)),
1988 BEAST_EXPECT(ownerCount(env, alice) == 0);
1989 BEAST_EXPECT(ownerCount(env, becky) == 3);
1993 env(token::acceptSellOffer(minter, beckySellOfferIndex));
1995 BEAST_EXPECT(ownerCount(env, alice) == 0);
1996 BEAST_EXPECT(ownerCount(env, becky) == 1);
1997 BEAST_EXPECT(ownerCount(env, minter) == 1);
2000 uint256 const minterSellOfferIndex =
2002 env(token::createOffer(minter, nftAliceID, XRP(23)),
2005 BEAST_EXPECT(ownerCount(env, alice) == 0);
2006 BEAST_EXPECT(ownerCount(env, becky) == 1);
2007 BEAST_EXPECT(ownerCount(env, minter) == 2);
2010 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2012 BEAST_EXPECT(ownerCount(env, alice) == 1);
2013 BEAST_EXPECT(ownerCount(env, becky) == 1);
2014 BEAST_EXPECT(ownerCount(env, minter) == 0);
2018 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2020 BEAST_EXPECT(ownerCount(env, alice) == 0);
2021 BEAST_EXPECT(ownerCount(env, becky) == 1);
2022 BEAST_EXPECT(ownerCount(env, minter) == 0);
2026 env(token::burn(becky, nftAliceID));
2028 BEAST_EXPECT(ownerCount(env, alice) == 0);
2029 BEAST_EXPECT(ownerCount(env, becky) == 0);
2030 BEAST_EXPECT(ownerCount(env, minter) == 0);
2040 using namespace test::jtx;
2042 Env env{*
this, features};
2043 auto const baseFee = env.current()->fees().base;
2045 Account
const alice{
"alice"};
2046 Account
const becky{
"becky"};
2047 Account
const carol{
"carol"};
2048 Account
const minter{
"minter"};
2049 Account
const gw{
"gw"};
2050 IOU
const gwXAU(gw[
"XAU"]);
2052 env.fund(XRP(1000), alice, becky, carol, minter, gw);
2055 env(trust(alice, gwXAU(2000)));
2056 env(trust(becky, gwXAU(2000)));
2057 env(trust(carol, gwXAU(2000)));
2058 env(trust(minter, gwXAU(2000)));
2060 env(pay(gw, alice, gwXAU(1000)));
2061 env(pay(gw, becky, gwXAU(1000)));
2062 env(pay(gw, carol, gwXAU(1000)));
2063 env(pay(gw, minter, gwXAU(1000)));
2068 env(token::setMinter(alice, minter));
2074 BEAST_EXPECT(ownerCount(env, alice) == 1);
2075 BEAST_EXPECT(ownerCount(env, becky) == 1);
2076 BEAST_EXPECT(ownerCount(env, carol) == 1);
2077 BEAST_EXPECT(ownerCount(env, minter) == 1);
2085 uint256 const beckyBuyOfferIndex =
2087 env(token::createOffer(becky, nftID, gwXAU(10)),
2088 token::owner(alice));
2090 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2091 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2093 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2095 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2096 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2099 uint256 const beckySellOfferIndex =
2101 env(token::createOffer(becky, nftID, gwXAU(10)),
2104 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2106 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2107 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2108 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2111 uint256 const minterBuyOfferIndex =
2113 env(token::createOffer(minter, nftID, gwXAU(10)),
2114 token::owner(carol));
2116 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2118 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2119 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2120 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2121 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2125 uint256 const minterSellOfferIndex =
2127 env(token::createOffer(minter, nftID, gwXAU(10)),
2130 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2132 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2133 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2134 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2135 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2138 env(token::burn(alice, nftID));
2140 BEAST_EXPECT(ownerCount(env, alice) == 1);
2141 BEAST_EXPECT(ownerCount(env, becky) == 1);
2142 BEAST_EXPECT(ownerCount(env, carol) == 1);
2143 BEAST_EXPECT(ownerCount(env, minter) == 1);
2151 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2155 uint256 const beckyBuyOfferIndex =
2157 env(token::createOffer(becky, nftID, gwXAU(10)),
2158 token::owner(alice));
2160 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2161 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2163 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2165 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2166 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2169 uint256 const beckySellOfferIndex =
2171 env(token::createOffer(becky, nftID, gwXAU(10)),
2174 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2177 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0001));
2178 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2179 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2182 uint256 const minterBuyOfferIndex =
2184 env(token::createOffer(minter, nftID, gwXAU(10)),
2185 token::owner(carol));
2187 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2190 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0002));
2191 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2192 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2193 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2197 uint256 const minterSellOfferIndex =
2199 env(token::createOffer(minter, nftID, gwXAU(10)),
2202 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2204 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000.0002));
2205 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2206 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2207 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2211 env(pay(alice, becky, gwXAU(0.0001)));
2212 env(pay(alice, carol, gwXAU(0.0001)));
2215 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2216 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2217 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2218 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2221 env(token::burn(alice, nftID));
2223 BEAST_EXPECT(ownerCount(env, alice) == 1);
2224 BEAST_EXPECT(ownerCount(env, becky) == 1);
2225 BEAST_EXPECT(ownerCount(env, carol) == 1);
2226 BEAST_EXPECT(ownerCount(env, minter) == 1);
2232 env(token::mint(alice),
2239 uint256 const nftID = token::getNextID(
2241 env(token::mint(alice),
2247 uint256 const beckyBuyOfferIndex =
2249 env(token::createOffer(becky, nftID, gwXAU(10)),
2250 token::owner(alice));
2252 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2253 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2255 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2257 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2258 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2261 uint256 const beckySellOfferIndex =
2263 env(token::createOffer(becky, nftID, gwXAU(100)),
2266 env(token::acceptSellOffer(minter, beckySellOfferIndex));
2269 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1060));
2270 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2271 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
2274 uint256 const carolBuyOfferIndex =
2276 env(token::createOffer(carol, nftID, gwXAU(10)),
2277 token::owner(minter));
2279 env(token::acceptBuyOffer(minter, carolBuyOfferIndex));
2282 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1065));
2283 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2284 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2285 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2289 uint256 const carolSellOfferIndex =
2291 env(token::createOffer(carol, nftID, gwXAU(10)),
2294 env(token::acceptSellOffer(alice, carolSellOfferIndex));
2297 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1055));
2298 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2299 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2300 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2303 env(pay(alice, minter, gwXAU(55)));
2304 env(pay(becky, minter, gwXAU(40)));
2306 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2307 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2308 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2309 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2312 env(token::burn(alice, nftID));
2314 BEAST_EXPECT(ownerCount(env, alice) == 1);
2315 BEAST_EXPECT(ownerCount(env, becky) == 1);
2316 BEAST_EXPECT(ownerCount(env, carol) == 1);
2317 BEAST_EXPECT(ownerCount(env, minter) == 1);
2322 for (
auto NumberSwitchOver : {
true})
2324 if (NumberSwitchOver)
2325 env.enableFeature(fixUniversalNumber);
2327 env.disableFeature(fixUniversalNumber);
2332 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2337 STAmount aliceBalance = env.balance(alice);
2338 STAmount minterBalance = env.balance(minter);
2339 uint256 const minterBuyOfferIndex =
2341 env(token::createOffer(minter, nftID, XRP(1)), token::owner(alice));
2343 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2345 aliceBalance += XRP(1) - baseFee;
2346 minterBalance -= XRP(1) + baseFee;
2347 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2348 BEAST_EXPECT(env.balance(minter) == minterBalance);
2352 auto pmt = NumberSwitchOver ? drops(50000) : drops(99999);
2353 STAmount carolBalance = env.balance(carol);
2354 uint256 const minterSellOfferIndex =
2356 env(token::createOffer(minter, nftID, pmt), txflags(
tfSellNFToken));
2358 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2360 minterBalance += pmt - baseFee;
2361 carolBalance -= pmt + baseFee;
2362 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2363 BEAST_EXPECT(env.balance(minter) == minterBalance);
2364 BEAST_EXPECT(env.balance(carol) == carolBalance);
2368 STAmount beckyBalance = env.balance(becky);
2369 uint256 const beckyBuyOfferIndex =
2371 pmt = NumberSwitchOver ? drops(50001) : drops(100000);
2372 env(token::createOffer(becky, nftID, pmt), token::owner(carol));
2374 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2376 carolBalance += pmt - drops(1) - baseFee;
2377 beckyBalance -= pmt + baseFee;
2378 aliceBalance += drops(1);
2380 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2381 BEAST_EXPECT(env.balance(minter) == minterBalance);
2382 BEAST_EXPECT(env.balance(carol) == carolBalance);
2383 BEAST_EXPECT(env.balance(becky) == beckyBalance);
2392 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2398 env(pay(alice, gw, env.balance(alice, gwXAU)));
2399 env(pay(minter, gw, env.balance(minter, gwXAU)));
2400 env(pay(becky, gw, env.balance(becky, gwXAU)));
2405 env(pay(gw, alice, startXAUBalance));
2406 env(pay(gw, minter, startXAUBalance));
2407 env(pay(gw, becky, startXAUBalance));
2416 STAmount aliceBalance = env.balance(alice, gwXAU);
2417 STAmount minterBalance = env.balance(minter, gwXAU);
2418 uint256 const minterBuyOfferIndex =
2420 env(token::createOffer(minter, nftID, tinyXAU),
2421 token::owner(alice));
2423 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2425 aliceBalance += tinyXAU;
2426 minterBalance -= tinyXAU;
2427 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2428 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2431 STAmount carolBalance = env.balance(carol, gwXAU);
2432 uint256 const minterSellOfferIndex =
2434 env(token::createOffer(minter, nftID, tinyXAU),
2437 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2440 minterBalance += tinyXAU;
2441 carolBalance -= tinyXAU;
2443 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2444 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2445 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2452 STAmount beckyBalance = env.balance(becky, gwXAU);
2453 uint256 const beckyBuyOfferIndex =
2455 env(token::createOffer(becky, nftID, cheapNFT),
2456 token::owner(carol));
2458 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2461 aliceBalance += tinyXAU;
2462 beckyBalance -= cheapNFT;
2463 carolBalance += cheapNFT - tinyXAU;
2464 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2465 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2466 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2467 BEAST_EXPECT(env.balance(becky, gwXAU) == beckyBalance);
2660 testcase(
"Create offer destination");
2662 using namespace test::jtx;
2664 Env env{*
this, features};
2666 Account
const issuer{
"issuer"};
2667 Account
const minter{
"minter"};
2668 Account
const buyer{
"buyer"};
2669 Account
const broker{
"broker"};
2671 env.fund(XRP(1000), issuer, minter, buyer, broker);
2675 env(token::setMinter(issuer, minter));
2680 env(token::mint(minter, 0),
2681 token::issuer(issuer),
2688 uint256 const offerMinterToIssuer =
2690 env(token::createOffer(minter, nftokenID, drops(1)),
2691 token::destination(issuer),
2694 uint256 const offerMinterToBuyer =
2696 env(token::createOffer(minter, nftokenID, drops(1)),
2697 token::destination(buyer),
2700 uint256 const offerIssuerToMinter =
2702 env(token::createOffer(issuer, nftokenID, drops(1)),
2703 token::owner(minter),
2704 token::destination(minter));
2706 uint256 const offerIssuerToBuyer =
2708 env(token::createOffer(issuer, nftokenID, drops(1)),
2709 token::owner(minter),
2710 token::destination(buyer));
2713 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2714 BEAST_EXPECT(ownerCount(env, minter) == 3);
2715 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2724 env(token::cancelOffer(issuer, {offerMinterToBuyer}),
2726 env(token::cancelOffer(buyer, {offerMinterToIssuer}),
2728 env(token::cancelOffer(buyer, {offerIssuerToMinter}),
2730 env(token::cancelOffer(minter, {offerIssuerToBuyer}),
2733 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2734 BEAST_EXPECT(ownerCount(env, minter) == 3);
2735 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2739 env(token::cancelOffer(buyer, {offerMinterToBuyer}));
2740 env(token::cancelOffer(minter, {offerMinterToIssuer}));
2741 env(token::cancelOffer(buyer, {offerIssuerToBuyer}));
2742 env(token::cancelOffer(issuer, {offerIssuerToMinter}));
2744 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2745 BEAST_EXPECT(ownerCount(env, minter) == 1);
2746 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2752 uint256 const offerMinterSellsToBuyer =
2754 env(token::createOffer(minter, nftokenID, drops(1)),
2755 token::destination(buyer),
2758 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2759 BEAST_EXPECT(ownerCount(env, minter) == 2);
2760 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2764 env(token::acceptSellOffer(issuer, offerMinterSellsToBuyer),
2767 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2768 BEAST_EXPECT(ownerCount(env, minter) == 2);
2769 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2772 env(token::acceptSellOffer(buyer, offerMinterSellsToBuyer));
2774 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2775 BEAST_EXPECT(ownerCount(env, minter) == 0);
2776 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2782 uint256 const offerMinterBuysFromBuyer =
2784 env(token::createOffer(minter, nftokenID, drops(1)),
2785 token::owner(buyer),
2786 token::destination(buyer));
2788 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2789 BEAST_EXPECT(ownerCount(env, minter) == 1);
2790 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2794 env(token::acceptBuyOffer(issuer, offerMinterBuysFromBuyer),
2797 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2798 BEAST_EXPECT(ownerCount(env, minter) == 1);
2799 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2802 env(token::acceptBuyOffer(buyer, offerMinterBuysFromBuyer));
2804 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2805 BEAST_EXPECT(ownerCount(env, minter) == 1);
2806 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2811 uint256 const offerBuyerBuysFromMinter =
2813 env(token::createOffer(buyer, nftokenID, drops(1)),
2814 token::owner(minter),
2815 token::destination(broker));
2817 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2818 BEAST_EXPECT(ownerCount(env, minter) == 1);
2819 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2821 env(token::acceptBuyOffer(minter, offerBuyerBuysFromMinter),
2826 env(token::cancelOffer(buyer, {offerBuyerBuysFromMinter}));
2828 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2829 BEAST_EXPECT(ownerCount(env, minter) == 1);
2830 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2836 uint256 const offerMinterToBroker =
2838 env(token::createOffer(minter, nftokenID, drops(1)),
2839 token::destination(broker),
2842 uint256 const offerBuyerToMinter =
2844 env(token::createOffer(buyer, nftokenID, drops(1)),
2845 token::owner(minter));
2848 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2849 BEAST_EXPECT(ownerCount(env, minter) == 2);
2850 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2855 env(token::brokerOffers(
2856 issuer, offerBuyerToMinter, offerMinterToBroker),
2859 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2860 BEAST_EXPECT(ownerCount(env, minter) == 2);
2861 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2866 env(token::brokerOffers(
2867 broker, offerBuyerToMinter, offerMinterToBroker));
2869 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2870 BEAST_EXPECT(ownerCount(env, minter) == 0);
2871 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2878 uint256 const offerBuyerToMinter =
2880 env(token::createOffer(buyer, nftokenID, drops(1)),
2881 token::destination(minter),
2884 uint256 const offerMinterToBuyer =
2886 env(token::createOffer(minter, nftokenID, drops(1)),
2887 token::owner(buyer));
2889 uint256 const offerIssuerToBuyer =
2891 env(token::createOffer(issuer, nftokenID, drops(1)),
2892 token::owner(buyer));
2895 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2896 BEAST_EXPECT(ownerCount(env, minter) == 1);
2897 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2902 env(token::brokerOffers(
2903 broker, offerIssuerToBuyer, offerBuyerToMinter),
2907 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2908 BEAST_EXPECT(ownerCount(env, minter) == 1);
2909 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2911 env(token::brokerOffers(
2912 broker, offerMinterToBuyer, offerBuyerToMinter),
2917 env(token::acceptBuyOffer(buyer, offerMinterToBuyer));
2921 env(token::cancelOffer(buyer, {offerBuyerToMinter}));
2924 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2925 BEAST_EXPECT(ownerCount(env, minter) == 1);
2926 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2929 env(token::cancelOffer(issuer, {offerIssuerToBuyer}));
2931 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2932 BEAST_EXPECT(ownerCount(env, minter) == 1);
2933 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2941 uint256 const offerMinterToBroker =
2943 env(token::createOffer(minter, nftokenID, drops(1)),
2944 token::destination(broker),
2947 uint256 const offerBuyerToBroker =
2949 env(token::createOffer(buyer, nftokenID, drops(1)),
2950 token::owner(minter),
2951 token::destination(broker));
2956 env(token::brokerOffers(
2957 issuer, offerBuyerToBroker, offerMinterToBroker),
2960 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2961 BEAST_EXPECT(ownerCount(env, minter) == 2);
2962 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2966 env(token::brokerOffers(
2967 broker, offerBuyerToBroker, offerMinterToBroker));
2969 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2970 BEAST_EXPECT(ownerCount(env, minter) == 0);
2971 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3128 testcase(
"Create offer expiration");
3130 using namespace test::jtx;
3132 Env env{*
this, features};
3134 Account
const issuer{
"issuer"};
3135 Account
const minter{
"minter"};
3136 Account
const buyer{
"buyer"};
3138 env.fund(XRP(1000), issuer, minter, buyer);
3142 env(token::setMinter(issuer, minter));
3147 env(token::mint(minter, 0),
3148 token::issuer(issuer),
3154 env(token::mint(minter, 0),
3155 token::issuer(issuer),
3164 uint256 const offerMinterToIssuer =
3166 env(token::createOffer(minter, nftokenID0, drops(1)),
3167 token::destination(issuer),
3168 token::expiration(expiration),
3171 uint256 const offerMinterToAnyone =
3173 env(token::createOffer(minter, nftokenID0, drops(1)),
3174 token::expiration(expiration),
3177 uint256 const offerIssuerToMinter =
3179 env(token::createOffer(issuer, nftokenID0, drops(1)),
3180 token::owner(minter),
3181 token::expiration(expiration));
3183 uint256 const offerBuyerToMinter =
3185 env(token::createOffer(buyer, nftokenID0, drops(1)),
3186 token::owner(minter),
3187 token::expiration(expiration));
3189 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3190 BEAST_EXPECT(ownerCount(env, minter) == 3);
3191 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3199 env(token::cancelOffer(issuer, {offerMinterToAnyone}),
3201 env(token::cancelOffer(buyer, {offerIssuerToMinter}),
3204 BEAST_EXPECT(
lastClose(env) < expiration);
3205 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3206 BEAST_EXPECT(ownerCount(env, minter) == 3);
3207 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3210 env(token::cancelOffer(minter, {offerMinterToAnyone}));
3214 env(token::cancelOffer(issuer, {offerMinterToIssuer}));
3220 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3221 BEAST_EXPECT(ownerCount(env, minter) == 1);
3222 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3225 env(token::cancelOffer(issuer, {offerBuyerToMinter}));
3226 env(token::cancelOffer(buyer, {offerIssuerToMinter}));
3228 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3229 BEAST_EXPECT(ownerCount(env, minter) == 1);
3230 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3241 env(token::createOffer(minter, nftokenID0, drops(1)),
3242 token::expiration(expiration),
3247 env(token::createOffer(minter, nftokenID1, drops(1)),
3248 token::expiration(expiration),
3251 BEAST_EXPECT(
lastClose(env) < expiration);
3252 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3253 BEAST_EXPECT(ownerCount(env, minter) == 3);
3254 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3257 env(token::acceptSellOffer(buyer, offer0));
3263 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3264 BEAST_EXPECT(ownerCount(env, minter) == 2);
3265 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3268 env(token::acceptSellOffer(buyer, offer1), ter(
tecEXPIRED));
3269 env(token::acceptSellOffer(issuer, offer1), ter(
tecEXPIRED));
3273 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3274 BEAST_EXPECT(ownerCount(env, minter) == 2);
3275 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3278 env(token::cancelOffer(issuer, {offer1}));
3280 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3281 BEAST_EXPECT(ownerCount(env, minter) == 1);
3282 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3288 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3290 token::destination(minter));
3292 env(token::acceptSellOffer(minter, offerSellBack));
3294 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3295 BEAST_EXPECT(ownerCount(env, minter) == 1);
3296 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3306 env(token::createOffer(buyer, nftokenID0, drops(1)),
3307 token::owner(minter),
3308 token::expiration(expiration));
3311 env(token::createOffer(buyer, nftokenID1, drops(1)),
3312 token::owner(minter),
3313 token::expiration(expiration));
3315 BEAST_EXPECT(
lastClose(env) < expiration);
3316 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3317 BEAST_EXPECT(ownerCount(env, minter) == 1);
3318 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3321 env(token::acceptBuyOffer(minter, offer0));
3327 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3328 BEAST_EXPECT(ownerCount(env, minter) == 1);
3329 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3332 env(token::acceptBuyOffer(minter, offer1), ter(
tecEXPIRED));
3333 env(token::acceptBuyOffer(issuer, offer1), ter(
tecEXPIRED));
3337 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3338 BEAST_EXPECT(ownerCount(env, minter) == 1);
3339 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3342 env(token::cancelOffer(issuer, {offer1}));
3344 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3345 BEAST_EXPECT(ownerCount(env, minter) == 1);
3346 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3352 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3354 token::destination(minter));
3356 env(token::acceptSellOffer(minter, offerSellBack));
3358 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3359 BEAST_EXPECT(ownerCount(env, minter) == 1);
3360 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3371 env(token::createOffer(minter, nftokenID0, drops(1)),
3372 token::expiration(expiration),
3377 env(token::createOffer(minter, nftokenID1, drops(1)),
3378 token::expiration(expiration),
3383 env(token::createOffer(buyer, nftokenID0, drops(1)),
3384 token::owner(minter));
3388 env(token::createOffer(buyer, nftokenID1, drops(1)),
3389 token::owner(minter));
3392 BEAST_EXPECT(
lastClose(env) < expiration);
3393 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3394 BEAST_EXPECT(ownerCount(env, minter) == 3);
3395 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3398 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3404 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3405 BEAST_EXPECT(ownerCount(env, minter) == 2);
3406 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3409 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3414 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3415 BEAST_EXPECT(ownerCount(env, minter) == 2);
3416 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3419 env(token::cancelOffer(buyer, {buyOffer1, sellOffer1}));
3421 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3422 BEAST_EXPECT(ownerCount(env, minter) == 1);
3423 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3429 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3431 token::destination(minter));
3433 env(token::acceptSellOffer(minter, offerSellBack));
3435 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3436 BEAST_EXPECT(ownerCount(env, minter) == 1);
3437 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3448 env(token::createOffer(minter, nftokenID0, drops(1)),
3453 env(token::createOffer(minter, nftokenID1, drops(1)),
3458 env(token::createOffer(buyer, nftokenID0, drops(1)),
3459 token::expiration(expiration),
3460 token::owner(minter));
3464 env(token::createOffer(buyer, nftokenID1, drops(1)),
3465 token::expiration(expiration),
3466 token::owner(minter));
3469 BEAST_EXPECT(
lastClose(env) < expiration);
3470 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3471 BEAST_EXPECT(ownerCount(env, minter) == 3);
3472 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3475 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3481 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3482 BEAST_EXPECT(ownerCount(env, minter) == 2);
3483 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3486 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3491 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3492 BEAST_EXPECT(ownerCount(env, minter) == 2);
3493 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3496 env(token::cancelOffer(minter, {buyOffer1, sellOffer1}));
3498 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3499 BEAST_EXPECT(ownerCount(env, minter) == 1);
3500 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3506 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3508 token::destination(minter));
3510 env(token::acceptSellOffer(minter, offerSellBack));
3512 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3513 BEAST_EXPECT(ownerCount(env, minter) == 1);
3514 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3526 env(token::createOffer(minter, nftokenID0, drops(1)),
3527 token::expiration(expiration),
3532 env(token::createOffer(minter, nftokenID1, drops(1)),
3533 token::expiration(expiration),
3538 env(token::createOffer(buyer, nftokenID0, drops(1)),
3539 token::expiration(expiration),
3540 token::owner(minter));
3544 env(token::createOffer(buyer, nftokenID1, drops(1)),
3545 token::expiration(expiration),
3546 token::owner(minter));
3549 BEAST_EXPECT(
lastClose(env) < expiration);
3550 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3551 BEAST_EXPECT(ownerCount(env, minter) == 3);
3552 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3555 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3561 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3562 BEAST_EXPECT(ownerCount(env, minter) == 2);
3563 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3566 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3571 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3572 BEAST_EXPECT(ownerCount(env, minter) == 2);
3573 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3576 env(token::cancelOffer(issuer, {buyOffer1, sellOffer1}));
3578 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3579 BEAST_EXPECT(ownerCount(env, minter) == 1);
3580 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3586 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3588 token::destination(minter));
3590 env(token::acceptSellOffer(minter, offerSellBack));
3592 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3593 BEAST_EXPECT(ownerCount(env, minter) == 1);
3594 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3835 testcase(
"Brokered NFT offer accept");
3837 using namespace test::jtx;
3840 Env env{*
this, features};
3841 auto const baseFee = env.current()->fees().base;
3849 Account
const issuer{
"issuer"};
3850 Account
const minter{
"minter"};
3851 Account
const buyer{
"buyer"};
3852 Account
const broker{
"broker"};
3853 Account
const gw{
"gw"};
3854 IOU
const gwXAU(gw[
"XAU"]);
3856 env.fund(XRP(1000), issuer, minter, buyer, broker, gw);
3859 env(trust(issuer, gwXAU(2000)));
3860 env(trust(minter, gwXAU(2000)));
3861 env(trust(buyer, gwXAU(2000)));
3862 env(trust(broker, gwXAU(2000)));
3865 env(token::setMinter(issuer, minter));
3869 auto checkOwnerCountIsOne =
3874 for (Account
const& acct : accounts)
3881 ss <<
"Account " << acct.human()
3882 <<
" expected ownerCount == 1. Got "
3884 fail(ss.
str(), __FILE__, line);
3890 auto mintNFT = [&env, &issuer, &minter](
std::uint16_t xferFee = 0) {
3893 env(token::mint(minter, 0),
3894 token::issuer(issuer),
3895 token::xferFee(xferFee),
3907 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3909 uint256 const nftID = mintNFT();
3912 uint256 const minterOfferIndex =
3914 env(token::createOffer(minter, nftID, XRP(0)),
3922 env(token::createOffer(buyer, nftID, XRP(1)),
3923 token::owner(minter));
3926 auto const minterBalance = env.balance(minter);
3927 auto const buyerBalance = env.balance(buyer);
3928 auto const brokerBalance = env.balance(broker);
3929 auto const issuerBalance = env.balance(issuer);
3932 env(token::brokerOffers(
3933 broker, buyOfferIndex, minterOfferIndex));
3938 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(1));
3939 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3940 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
3941 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
3944 env(token::burn(buyer, nftID));
3954 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3956 uint256 const nftID = mintNFT();
3959 uint256 const minterOfferIndex =
3961 env(token::createOffer(minter, nftID, XRP(0)),
3969 env(token::createOffer(buyer, nftID, XRP(1)),
3970 token::owner(minter));
3974 env(token::brokerOffers(
3975 broker, buyOfferIndex, minterOfferIndex),
3976 token::brokerFee(XRP(1.1)),
3980 auto const minterBalance = env.balance(minter);
3981 auto const buyerBalance = env.balance(buyer);
3982 auto const brokerBalance = env.balance(broker);
3983 auto const issuerBalance = env.balance(issuer);
3986 env(token::brokerOffers(
3987 broker, buyOfferIndex, minterOfferIndex),
3988 token::brokerFee(XRP(0.5)));
3993 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
3994 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3996 env.balance(broker) == brokerBalance + XRP(0.5) - baseFee);
3997 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
4000 env(token::burn(buyer, nftID));
4010 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4015 uint256 const minterOfferIndex =
4017 env(token::createOffer(minter, nftID, XRP(0)),
4025 env(token::createOffer(buyer, nftID, XRP(1)),
4026 token::owner(minter));
4029 auto const minterBalance = env.balance(minter);
4030 auto const buyerBalance = env.balance(buyer);
4031 auto const brokerBalance = env.balance(broker);
4032 auto const issuerBalance = env.balance(issuer);
4035 env(token::brokerOffers(
4036 broker, buyOfferIndex, minterOfferIndex));
4041 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
4042 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4043 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
4044 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.5));
4047 env(token::burn(buyer, nftID));
4057 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4062 uint256 const minterOfferIndex =
4064 env(token::createOffer(minter, nftID, XRP(0)),
4072 env(token::createOffer(buyer, nftID, XRP(1)),
4073 token::owner(minter));
4076 auto const minterBalance = env.balance(minter);
4077 auto const buyerBalance = env.balance(buyer);
4078 auto const brokerBalance = env.balance(broker);
4079 auto const issuerBalance = env.balance(issuer);
4082 env(token::brokerOffers(
4083 broker, buyOfferIndex, minterOfferIndex),
4084 token::brokerFee(XRP(0.75)));
4090 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.125));
4091 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4093 env.balance(broker) == brokerBalance + XRP(0.75) - baseFee);
4094 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.125));
4097 env(token::burn(buyer, nftID));
4103 auto setXAUBalance =
4104 [
this, &gw, &gwXAU, &env](
4109 for (Account
const& acct : accounts)
4111 auto const xauAmt = gwXAU(amount);
4112 auto const balance = env.balance(acct, gwXAU);
4113 if (balance < xauAmt)
4115 env(pay(gw, acct, xauAmt - balance));
4118 else if (balance > xauAmt)
4120 env(pay(acct, gw, balance - xauAmt));
4123 if (env.balance(acct, gwXAU) != xauAmt)
4126 ss <<
"Unable to set " << acct.human()
4127 <<
" account balance to gwXAU(" << amount <<
")";
4128 this->
fail(ss.
str(), __FILE__, line);
4136 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4137 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4139 uint256 const nftID = mintNFT();
4142 uint256 const minterOfferIndex =
4144 env(token::createOffer(minter, nftID, gwXAU(1000)),
4153 env(token::createOffer(buyer, nftID, gwXAU(1001)),
4154 token::owner(minter));
4158 env(token::brokerOffers(
4159 broker, buyOfferIndex, minterOfferIndex),
4165 env(token::cancelOffer(buyer, {buyOfferIndex}));
4173 env(token::createOffer(buyer, nftID, gwXAU(999)),
4174 token::owner(minter));
4178 env(token::brokerOffers(
4179 broker, buyOfferIndex, minterOfferIndex),
4185 env(token::cancelOffer(buyer, {buyOfferIndex}));
4192 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4193 token::owner(minter));
4197 env(token::brokerOffers(
4198 broker, buyOfferIndex, minterOfferIndex),
4199 token::brokerFee(gwXAU(0.1)),
4204 env(token::brokerOffers(
4205 broker, buyOfferIndex, minterOfferIndex));
4208 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4209 BEAST_EXPECT(ownerCount(env, minter) == 1);
4210 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4211 BEAST_EXPECT(ownerCount(env, broker) == 1);
4212 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1000));
4213 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(2000));
4214 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4215 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1000));
4218 env(token::burn(buyer, nftID));
4225 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4226 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4231 uint256 const minterOfferIndex =
4233 env(token::createOffer(minter, nftID, gwXAU(900)),
4241 env(token::createOffer(buyer, nftID, gwXAU(1001)),
4242 token::owner(minter));
4246 env(token::brokerOffers(
4247 broker, buyOfferIndex, minterOfferIndex),
4253 env(token::cancelOffer(buyer, {buyOfferIndex}));
4261 env(token::createOffer(buyer, nftID, gwXAU(899)),
4262 token::owner(minter));
4266 env(token::brokerOffers(
4267 broker, buyOfferIndex, minterOfferIndex),
4273 env(token::cancelOffer(buyer, {buyOfferIndex}));
4279 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4280 token::owner(minter));
4285 env(token::brokerOffers(
4286 broker, buyOfferIndex, minterOfferIndex),
4287 token::brokerFee(gwXAU(101)),
4293 env(token::brokerOffers(
4294 broker, buyOfferIndex, minterOfferIndex),
4295 token::brokerFee(gwXAU(100)));
4298 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4299 BEAST_EXPECT(ownerCount(env, minter) == 1);
4300 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4301 BEAST_EXPECT(ownerCount(env, broker) == 1);
4302 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1450));
4303 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1450));
4304 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4305 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1100));
4308 env(token::burn(buyer, nftID));
4315 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4316 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4321 uint256 const minterOfferIndex =
4323 env(token::createOffer(minter, nftID, gwXAU(900)),
4330 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4331 token::owner(minter));
4337 env(token::brokerOffers(
4338 broker, buyOfferIndex, minterOfferIndex),
4339 token::brokerFee(gwXAU(50)));
4342 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4343 BEAST_EXPECT(ownerCount(env, minter) == 1);
4344 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4345 BEAST_EXPECT(ownerCount(env, broker) == 1);
4346 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4347 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4348 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4349 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1050));
4352 env(token::burn(buyer, nftID));
4357 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4358 setXAUBalance({issuer, minter, buyer}, 1000, __LINE__);
4359 setXAUBalance({broker}, 500, __LINE__);
4363 uint256 const minterOfferIndex =
4365 env(token::createOffer(minter, nftID, gwXAU(900)),
4372 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4373 token::owner(minter));
4376 env(token::brokerOffers(
4377 broker, buyOfferIndex, minterOfferIndex),
4378 token::brokerFee(gwXAU(50)));
4380 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4381 BEAST_EXPECT(ownerCount(env, minter) == 1);
4382 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4383 BEAST_EXPECT(ownerCount(env, broker) == 1);
4384 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4385 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4386 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4387 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(550));
4390 env(token::burn(buyer, nftID));
5014 using namespace test::jtx;
5016 testcase(
"Payments with IOU transfer fees");
5019 Env env{*
this, features};
5021 Account
const minter{
"minter"};
5022 Account
const secondarySeller{
"seller"};
5023 Account
const buyer{
"buyer"};
5024 Account
const gw{
"gateway"};
5025 Account
const broker{
"broker"};
5026 IOU
const gwXAU(gw[
"XAU"]);
5027 IOU
const gwXPB(gw[
"XPB"]);
5029 env.fund(XRP(1000), gw, minter, secondarySeller, buyer, broker);
5032 env(trust(minter, gwXAU(2000)));
5033 env(trust(secondarySeller, gwXAU(2000)));
5034 env(trust(broker, gwXAU(10000)));
5035 env(trust(buyer, gwXAU(2000)));
5036 env(trust(buyer, gwXPB(2000)));
5040 env(rate(gw, 1.02));
5043 auto expectInitialState = [
this,
5056 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(1000));
5057 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(0));
5058 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(0));
5059 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(0));
5060 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(0));
5061 BEAST_EXPECT(env.balance(secondarySeller, gwXPB) == gwXPB(0));
5062 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5000));
5063 BEAST_EXPECT(env.balance(broker, gwXPB) == gwXPB(0));
5064 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-1000));
5065 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(0));
5066 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(0));
5067 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(0));
5069 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(0));
5071 env.balance(gw, secondarySeller[
"XPB"]) == gwXPB(0));
5072 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5000));
5073 BEAST_EXPECT(env.balance(gw, broker[
"XPB"]) == gwXPB(0));
5076 auto reinitializeTrustLineBalances = [&expectInitialState,
5085 if (
auto const difference =
5086 gwXAU(1000) - env.balance(buyer, gwXAU);
5087 difference > gwXAU(0))
5088 env(pay(gw, buyer, difference));
5089 if (env.balance(buyer, gwXPB) > gwXPB(0))
5090 env(pay(buyer, gw, env.balance(buyer, gwXPB)));
5091 if (env.balance(minter, gwXAU) > gwXAU(0))
5092 env(pay(minter, gw, env.balance(minter, gwXAU)));
5093 if (env.balance(minter, gwXPB) > gwXPB(0))
5094 env(pay(minter, gw, env.balance(minter, gwXPB)));
5095 if (env.balance(secondarySeller, gwXAU) > gwXAU(0))
5097 pay(secondarySeller,
5099 env.balance(secondarySeller, gwXAU)));
5100 if (env.balance(secondarySeller, gwXPB) > gwXPB(0))
5102 pay(secondarySeller,
5104 env.balance(secondarySeller, gwXPB)));
5105 auto brokerDiff = gwXAU(5000) - env.balance(broker, gwXAU);
5106 if (brokerDiff > gwXAU(0))
5107 env(pay(gw, broker, brokerDiff));
5108 else if (brokerDiff < gwXAU(0))
5110 brokerDiff.negate();
5111 env(pay(broker, gw, brokerDiff));
5113 if (env.balance(broker, gwXPB) > gwXPB(0))
5114 env(pay(broker, gw, env.balance(broker, gwXPB)));
5116 expectInitialState();
5119 auto mintNFT = [&env](Account
const& minter,
int transferFee = 0) {
5120 uint256 const nftID = token::getNextID(
5122 env(token::mint(minter),
5123 token::xferFee(transferFee),
5129 auto createBuyOffer =
5131 Account
const& offerer,
5132 Account
const& owner,
5138 env(token::createOffer(offerer, nftID, amount),
5139 token::owner(owner),
5140 terCode ? ter(*terCode)
5146 auto createSellOffer =
5148 Account
const& offerer,
5154 env(token::createOffer(offerer, nftID, amount),
5156 terCode ? ter(*terCode)
5165 reinitializeTrustLineBalances();
5166 auto const nftID = mintNFT(minter);
5167 auto const offerID =
5168 createSellOffer(minter, nftID, gwXAU(1000));
5170 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5173 expectInitialState();
5178 reinitializeTrustLineBalances();
5179 auto const nftID = mintNFT(minter);
5180 auto const offerID =
5181 createBuyOffer(buyer, minter, nftID, gwXAU(1000));
5183 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5186 expectInitialState();
5192 reinitializeTrustLineBalances();
5193 auto const nftID = mintNFT(minter);
5194 auto const offerID = createSellOffer(minter, nftID, gwXAU(995));
5196 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5199 expectInitialState();
5205 reinitializeTrustLineBalances();
5206 auto const nftID = mintNFT(minter);
5207 auto const offerID =
5208 createBuyOffer(buyer, minter, nftID, gwXAU(995));
5210 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5213 expectInitialState();
5220 reinitializeTrustLineBalances();
5221 auto const nftID = mintNFT(minter);
5222 auto const offerID = createSellOffer(minter, nftID, gwXAU(900));
5223 env(token::acceptSellOffer(buyer, offerID));
5226 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
5227 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5228 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
5229 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5236 reinitializeTrustLineBalances();
5237 auto const nftID = mintNFT(minter);
5238 auto const offerID =
5239 createBuyOffer(buyer, minter, nftID, gwXAU(900));
5240 env(token::acceptBuyOffer(minter, offerID));
5243 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
5244 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5245 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
5246 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5253 reinitializeTrustLineBalances();
5256 env(pay(gw, buyer, gwXAU(20)));
5259 auto const nftID = mintNFT(minter);
5260 auto const offerID =
5261 createSellOffer(minter, nftID, gwXAU(1000));
5262 env(token::acceptSellOffer(buyer, offerID));
5265 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5266 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5267 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5268 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5275 reinitializeTrustLineBalances();
5278 env(pay(gw, buyer, gwXAU(20)));
5281 auto const nftID = mintNFT(minter);
5282 auto const offerID =
5283 createBuyOffer(buyer, minter, nftID, gwXAU(1000));
5284 env(token::acceptBuyOffer(minter, offerID));
5287 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5288 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5289 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5290 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5295 reinitializeTrustLineBalances();
5297 auto const nftID = mintNFT(minter);
5298 auto const offerID =
5299 createSellOffer(minter, nftID, gwXAU(1000));
5301 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
5304 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5305 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5310 reinitializeTrustLineBalances();
5312 auto const nftID = mintNFT(minter);
5314 auto const offerID =
5315 createBuyOffer(gw, minter, nftID, gwXAU(1000), {offerTER});
5317 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5320 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5321 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5326 reinitializeTrustLineBalances();
5327 auto const nftID = mintNFT(minter);
5328 auto const offerID =
5329 createSellOffer(minter, nftID, gwXAU(5000));
5331 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
5334 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5335 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5340 reinitializeTrustLineBalances();
5342 auto const nftID = mintNFT(minter);
5344 auto const offerID =
5345 createBuyOffer(gw, minter, nftID, gwXAU(5000), {offerTER});
5347 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5350 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5351 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5357 reinitializeTrustLineBalances();
5358 auto const nftID = mintNFT(gw);
5359 auto const offerID = createSellOffer(gw, nftID, gwXAU(1000));
5360 env(token::acceptSellOffer(buyer, offerID));
5363 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5364 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5370 reinitializeTrustLineBalances();
5372 auto const nftID = mintNFT(gw);
5373 auto const offerID =
5374 createBuyOffer(buyer, gw, nftID, gwXAU(1000));
5375 env(token::acceptBuyOffer(gw, offerID));
5378 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5379 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5385 reinitializeTrustLineBalances();
5386 auto const nftID = mintNFT(gw);
5387 auto const offerID = createSellOffer(gw, nftID, gwXAU(2000));
5388 env(token::acceptSellOffer(buyer, offerID),
5391 expectInitialState();
5397 reinitializeTrustLineBalances();
5398 auto const nftID = mintNFT(gw);
5399 auto const offerID =
5400 createBuyOffer(buyer, gw, nftID, gwXAU(2000));
5401 env(token::acceptBuyOffer(gw, offerID),
5404 expectInitialState();
5409 reinitializeTrustLineBalances();
5410 auto const nftID = mintNFT(minter);
5411 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5412 env(token::acceptSellOffer(buyer, offerID),
5415 expectInitialState();
5420 reinitializeTrustLineBalances();
5421 auto const nftID = mintNFT(minter);
5422 auto const offerID = createBuyOffer(
5428 env(token::acceptBuyOffer(minter, offerID),
5431 expectInitialState();
5437 reinitializeTrustLineBalances();
5438 env(pay(gw, buyer, gwXPB(100)));
5441 auto const nftID = mintNFT(minter);
5442 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5443 env(token::acceptSellOffer(buyer, offerID));
5446 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5447 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5448 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5449 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5455 reinitializeTrustLineBalances();
5456 env(pay(gw, buyer, gwXPB(100)));
5459 auto const nftID = mintNFT(minter);
5460 auto const offerID =
5461 createBuyOffer(buyer, minter, nftID, gwXPB(10));
5462 env(token::acceptBuyOffer(minter, offerID));
5465 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5466 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5467 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5468 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5473 reinitializeTrustLineBalances();
5477 auto const nftID = mintNFT(minter, 3000);
5478 auto const primaryOfferID =
5479 createSellOffer(minter, nftID, XRP(0));
5480 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5484 auto const offerID =
5485 createSellOffer(secondarySeller, nftID, gwXAU(1000));
5487 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5490 expectInitialState();
5495 reinitializeTrustLineBalances();
5499 auto const nftID = mintNFT(minter, 3000);
5500 auto const primaryOfferID =
5501 createSellOffer(minter, nftID, XRP(0));
5502 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5506 auto const offerID =
5507 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(1000));
5509 env(token::acceptBuyOffer(secondarySeller, offerID),
5513 expectInitialState();
5518 reinitializeTrustLineBalances();
5522 auto const nftID = mintNFT(minter, 3000);
5523 auto const primaryOfferID =
5524 createSellOffer(minter, nftID, XRP(0));
5525 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5529 auto const offerID =
5530 createSellOffer(secondarySeller, nftID, gwXAU(900));
5531 env(token::acceptSellOffer(buyer, offerID));
5534 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5535 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));
5545 reinitializeTrustLineBalances();
5549 auto const nftID = mintNFT(minter, 3000);
5550 auto const primaryOfferID =
5551 createSellOffer(minter, nftID, XRP(0));
5552 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5556 auto const offerID =
5557 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(900));
5558 env(token::acceptBuyOffer(secondarySeller, offerID));
5562 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5564 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5566 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5567 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5569 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5570 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5588 reinitializeTrustLineBalances();
5590 auto const nftID = mintNFT(minter);
5591 auto const sellOffer =
5592 createSellOffer(minter, nftID, gwXAU(300));
5593 auto const buyOffer =
5594 createBuyOffer(buyer, minter, nftID, gwXAU(500));
5595 env(token::brokerOffers(broker, buyOffer, sellOffer),
5596 token::brokerFee(gwXAU(100)));
5599 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(400));
5600 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5601 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5602 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-400));
5603 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5604 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5622 reinitializeTrustLineBalances();
5626 auto const nftID = mintNFT(minter, 3000);
5627 auto const primaryOfferID =
5628 createSellOffer(minter, nftID, XRP(0));
5629 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5633 auto const sellOffer =
5634 createSellOffer(secondarySeller, nftID, gwXAU(300));
5635 auto const buyOffer =
5636 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(500));
5637 env(token::brokerOffers(broker, buyOffer, sellOffer),
5638 token::brokerFee(gwXAU(100)));
5641 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(12));
5642 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5643 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(388));
5644 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5645 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-12));
5646 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5648 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-388));
5649 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5747 using namespace test::jtx;
5752 auto openLedgerSeq = [](Env& env) {
return env.current()->seq(); };
5757 auto incLgrSeqForAcctDel = [&](Env& env, Account
const& acct) {
5758 int const delta = [&]() ->
int {
5759 if (env.seq(acct) + 255 > openLedgerSeq(env))
5760 return env.seq(acct) - openLedgerSeq(env) + 255;
5763 BEAST_EXPECT(delta >= 0);
5764 for (
int i = 0; i < delta; ++i)
5766 BEAST_EXPECT(openLedgerSeq(env) == env.seq(acct) + 255);
5771 auto incLgrSeqForFixNftRemint = [&](Env& env, Account
const& acct) {
5773 auto const deletableLgrSeq =
5774 (*env.le(acct))[~sfFirstNFTokenSequence].value_or(0) +
5775 (*env.le(acct))[sfMintedNFTokens] + 255;
5777 if (deletableLgrSeq > openLedgerSeq(env))
5778 delta = deletableLgrSeq - openLedgerSeq(env);
5780 BEAST_EXPECT(delta >= 0);
5781 for (
int i = 0; i < delta; ++i)
5783 BEAST_EXPECT(openLedgerSeq(env) == deletableLgrSeq);
5789 Env env{*
this, features};
5790 Account
const alice(
"alice");
5791 Account
const becky(
"becky");
5793 env.fund(XRP(10000), alice, becky);
5797 uint256 const prevNFTokenID = token::getNextID(env, alice, 0u);
5798 env(token::mint(alice));
5800 env(token::burn(alice, prevNFTokenID));
5804 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 1);
5807 incLgrSeqForAcctDel(env, alice);
5811 auto const acctDelFee{drops(env.current()->fees().increment)};
5812 env(acctdelete(alice, becky), fee(acctDelFee));
5817 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5818 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5821 env.fund(XRP(10000), alice);
5825 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5826 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5827 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5830 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5831 env(token::mint(alice));
5835 env(token::burn(alice, remintNFTokenID));
5839 BEAST_EXPECT(remintNFTokenID != prevNFTokenID);
5845 Env env{*
this, features};
5846 Account
const alice(
"alice");
5847 Account
const becky(
"becky");
5848 Account
const minter{
"minter"};
5850 env.fund(XRP(10000), alice, becky, minter);
5854 env(token::setMinter(alice, minter));
5860 for (
int i = 0; i < 500; i++)
5862 uint256 const nftokenID = token::getNextID(env, alice, 0u);
5864 env(token::mint(minter), token::issuer(alice));
5869 for (
auto const nftokenID : nftIDs)
5871 env(token::burn(minter, nftokenID));
5877 incLgrSeqForAcctDel(env, alice);
5881 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5882 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5884 auto const acctDelFee{drops(env.current()->fees().increment)};
5893 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
5897 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5902 incLgrSeqForFixNftRemint(env, alice);
5905 env(acctdelete(alice, becky), fee(acctDelFee));
5910 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5911 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5914 env.fund(XRP(10000), alice);
5918 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5919 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5920 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5924 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5925 env(token::mint(alice));
5929 env(token::burn(alice, remintNFTokenID));
5942 Env env{*
this, features};
5944 Account
const alice{
"alice"};
5945 Account
const becky{
"becky"};
5946 env.fund(XRP(10000), alice, becky);
5953 env(ticket::create(alice, 100));
5957 BEAST_EXPECT(ownerCount(env, alice) == 100);
5962 for (
int i = 0; i < 50; i++)
5964 nftIDs.
push_back(token::getNextID(env, alice, 0u));
5965 env(token::mint(alice, 0u), ticket::use(aliceTicketSeq++));
5970 for (
auto const nftokenID : nftIDs)
5972 env(token::burn(alice, nftokenID),
5973 ticket::use(aliceTicketSeq++));
5981 incLgrSeqForAcctDel(env, alice);
5985 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5986 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5988 auto const acctDelFee{drops(env.current()->fees().increment)};
5997 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
6001 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6006 incLgrSeqForFixNftRemint(env, alice);
6009 env(acctdelete(alice, becky), fee(acctDelFee));
6014 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
6015 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
6018 env.fund(XRP(10000), alice);
6022 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6023 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6024 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
6028 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
6029 env(token::mint(alice));
6033 env(token::burn(alice, remintNFTokenID));
6047 Env env{*
this, features};
6048 Account
const alice(
"alice");
6049 Account
const becky(
"becky");
6050 Account
const minter{
"minter"};
6052 env.fund(XRP(10000), alice, becky, minter);
6056 env(token::setMinter(alice, minter));
6061 env(ticket::create(minter, 100));
6065 BEAST_EXPECT(ownerCount(env, minter) == 100);
6070 for (
int i = 0; i < 50; i++)
6072 uint256 const nftokenID = token::getNextID(env, alice, 0u);
6074 env(token::mint(minter),
6075 token::issuer(alice),
6076 ticket::use(minterTicketSeq++));
6081 for (
auto const nftokenID : nftIDs)
6083 env(token::burn(minter, nftokenID), ticket::use(minterTicketSeq++));
6091 incLgrSeqForAcctDel(env, alice);
6095 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6096 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6105 auto const acctDelFee{drops(env.current()->fees().increment)};
6106 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
6110 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6115 incLgrSeqForFixNftRemint(env, alice);
6118 env(acctdelete(alice, becky), fee(acctDelFee));
6123 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
6124 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
6127 env.fund(XRP(10000), alice);
6131 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6132 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6133 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
6137 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
6138 env(token::mint(alice));
6142 env(token::burn(alice, remintNFTokenID));
6155 testcase(
"NFTokenMint with Create NFTokenOffer");
6157 using namespace test::jtx;
6159 if (!features[featureNFTokenMintOffer])
6161 Env env{*
this, features};
6162 Account
const alice(
"alice");
6163 Account
const buyer(
"buyer");
6165 env.fund(XRP(10000), alice, buyer);
6168 env(token::mint(alice),
6169 token::amount(XRP(10000)),
6173 env(token::mint(alice),
6174 token::destination(
"buyer"),
6178 env(token::mint(alice),
6188 Env env{*
this, features};
6189 auto const baseFee = env.current()->fees().base;
6190 Account
const alice(
"alice");
6191 Account
const buyer{
"buyer"};
6192 Account
const gw(
"gw");
6193 Account
const issuer(
"issuer");
6194 Account
const minter(
"minter");
6195 Account
const bob(
"bob");
6196 IOU
const gwAUD(gw[
"AUD"]);
6198 env.fund(XRP(10000), alice, buyer, gw, issuer, minter);
6203 env(token::mint(alice),
6204 token::destination(buyer),
6207 BEAST_EXPECT(ownerCount(env, alice) == 0);
6210 env(token::mint(alice),
6214 BEAST_EXPECT(ownerCount(env, buyer) == 0);
6220 env(token::mint(alice),
6221 token::amount(XRP(1000)),
6222 token::destination(alice),
6225 BEAST_EXPECT(ownerCount(env, alice) == 0);
6229 env(token::mint(alice),
6230 token::amount(XRP(1000)),
6231 token::destination(Account(
"demon")),
6234 BEAST_EXPECT(ownerCount(env, alice) == 0);
6239 env(token::mint(alice),
6240 token::amount(XRP(1000)),
6241 token::expiration(0),
6244 BEAST_EXPECT(ownerCount(env, alice) == 0);
6247 env(token::mint(alice),
6248 token::amount(XRP(1000)),
6252 BEAST_EXPECT(ownerCount(env, alice) == 0);
6257 env(token::mint(alice),
6258 token::amount(buyer[
"USD"](1)),
6261 env(token::mint(alice),
6262 token::amount(buyer[
"USD"](0)),
6265 BEAST_EXPECT(ownerCount(env, alice) == 0);
6268 env(token::mint(alice),
6269 token::amount(gwAUD(1000)),
6274 BEAST_EXPECT(ownerCount(env, alice) == 0);
6279 env(token::mint(gw),
6280 token::amount(gwAUD(1000)),
6282 token::xferFee(10));
6291 env(token::mint(alice),
6292 token::amount(gwAUD(1000)),
6297 BEAST_EXPECT(ownerCount(env, alice) == 0);
6300 env(token::mint(alice),
6301 token::amount(gwAUD(1000)),
6304 BEAST_EXPECT(ownerCount(env, alice) == 0);
6313 auto const acctReserve = env.current()->fees().reserve;
6314 auto const incReserve = env.current()->fees().increment;
6316 env.fund(acctReserve + incReserve, bob);
6320 env(token::mint(bob),
6321 token::amount(XRP(0)),
6326 env(pay(env.master, bob, incReserve + drops(baseFee)));
6328 env(token::mint(bob), token::amount(XRP(0)));
6332 env(pay(env.master, bob, drops(baseFee)));
6334 env(token::mint(bob),
6335 token::amount(XRP(0)),
6340 env(pay(env.master, bob, incReserve + drops(baseFee)));
6342 env(token::mint(bob), token::amount(XRP(0)));
6347 BEAST_EXPECT(ownerCount(env, alice) == 0);
6348 env(token::mint(alice), token::amount(XRP(10)));
6349 BEAST_EXPECT(ownerCount(env, alice) == 2);
6353 env(token::mint(alice),
6354 token::amount(XRP(10)),
6355 token::destination(buyer),
6356 token::expiration(
lastClose(env) + 25));
6360 env(trust(alice, gwAUD(1000)));
6362 env(token::mint(alice),
6363 token::amount(gwAUD(1)),
6364 token::destination(buyer),
6367 token::xferFee(10));
6371 env(token::mint(alice),
6372 token::amount(XRP(10)),
6373 token::destination(buyer),
6374 token::expiration(
lastClose(env) + 25));
6375 uint256 const offerAliceSellsToBuyer =
6377 env(token::cancelOffer(alice, {offerAliceSellsToBuyer}));
6381 env(token::mint(buyer),
6382 token::amount(XRP(10)),
6383 token::destination(alice),
6384 token::expiration(
lastClose(env) + 25));
6385 uint256 const offerBuyerSellsToAlice =
6387 env(token::cancelOffer(alice, {offerBuyerSellsToAlice}));
6390 env(token::setMinter(issuer, minter));
6394 BEAST_EXPECT(ownerCount(env, minter) == 0);
6395 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6396 env(token::mint(minter),
6397 token::issuer(issuer),
6398 token::amount(drops(1)));
6400 BEAST_EXPECT(ownerCount(env, minter) == 2);
6401 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6404 Env env{*
this, features};
6405 Account
const alice(
"alice");
6407 env.fund(XRP(1000000), alice);
6412 env(token::mint(alice), token::amount(XRP(-2)), ter(offerCreateTER));
6430 testcase(
"Test synthetic fields from JSON response");
6432 using namespace test::jtx;
6434 Account
const alice{
"alice"};
6435 Account
const bob{
"bob"};
6436 Account
const broker{
"broker"};
6438 Env env{*
this, features};
6439 env.fund(XRP(10000), alice, bob, broker);
6445 auto verifyNFTokenID = [&](
uint256 const& actualNftID) {
6452 env.rpc(
"tx", txHash)[jss::result][jss::meta];
6455 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_id)))
6462 BEAST_EXPECT(nftID == actualNftID);
6467 auto verifyNFTokenIDsInCancelOffer =
6475 env.rpc(
"tx", txHash)[jss::result][jss::meta];
6478 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_ids)))
6484 meta[jss::nftoken_ids].begin(),
6485 meta[jss::nftoken_ids].end(),
6489 BEAST_EXPECT(nftID.
parseHex(
id.asString()));
6495 std::sort(actualNftIDs.begin(), actualNftIDs.end());
6498 BEAST_EXPECT(metaIDs.
size() == actualNftIDs.size());
6502 for (
size_t i = 0; i < metaIDs.
size(); ++i)
6503 BEAST_EXPECT(metaIDs[i] == actualNftIDs[i]);
6508 auto verifyNFTokenOfferID = [&](
uint256 const& offerID) {
6515 env.rpc(
"tx", txHash)[jss::result][jss::meta];
6518 if (!BEAST_EXPECT(meta.
isMember(jss::offer_id)))
6523 BEAST_EXPECT(metaOfferID == offerID);
6534 verifyNFTokenID(nftId1);
6540 verifyNFTokenID(nftId2);
6545 uint256 const aliceOfferIndex1 =
6547 env(token::createOffer(alice, nftId1, drops(1)),
6550 verifyNFTokenOfferID(aliceOfferIndex1);
6552 uint256 const aliceOfferIndex2 =
6554 env(token::createOffer(alice, nftId2, drops(1)),
6557 verifyNFTokenOfferID(aliceOfferIndex2);
6562 env(token::cancelOffer(
6563 alice, {aliceOfferIndex1, aliceOfferIndex2}));
6565 verifyNFTokenIDsInCancelOffer({nftId1, nftId2});
6569 auto const bobBuyOfferIndex =
6571 env(token::createOffer(bob, nftId1, drops(1)), token::owner(alice));
6573 verifyNFTokenOfferID(bobBuyOfferIndex);
6577 env(token::acceptBuyOffer(alice, bobBuyOfferIndex));
6579 verifyNFTokenID(nftId1);
6589 verifyNFTokenID(nftId);
6592 uint256 const offerAliceToBroker =
6594 env(token::createOffer(alice, nftId, drops(1)),
6595 token::destination(broker),
6598 verifyNFTokenOfferID(offerAliceToBroker);
6601 uint256 const offerBobToBroker =
6603 env(token::createOffer(bob, nftId, drops(1)), token::owner(alice));
6605 verifyNFTokenOfferID(offerBobToBroker);
6608 env(token::brokerOffers(
6609 broker, offerBobToBroker, offerAliceToBroker));
6611 verifyNFTokenID(nftId);
6622 verifyNFTokenID(nftId);
6625 uint256 const aliceOfferIndex1 =
6627 env(token::createOffer(alice, nftId, drops(1)),
6630 verifyNFTokenOfferID(aliceOfferIndex1);
6632 uint256 const aliceOfferIndex2 =
6634 env(token::createOffer(alice, nftId, drops(1)),
6637 verifyNFTokenOfferID(aliceOfferIndex2);
6641 env(token::cancelOffer(
6642 alice, {aliceOfferIndex1, aliceOfferIndex2}));
6644 verifyNFTokenIDsInCancelOffer({nftId});
6647 if (features[featureNFTokenMintOffer])
6649 uint256 const aliceMintWithOfferIndex1 =
6651 env(token::mint(alice), token::amount(XRP(0)));
6653 verifyNFTokenOfferID(aliceMintWithOfferIndex1);
6660 testcase(
"Test buyer reserve when accepting an offer");
6662 using namespace test::jtx;
6675 uint256 const sellOfferIndex =
6677 env(token::createOffer(acct, nftId, amt), txflags(
tfSellNFToken));
6680 return sellOfferIndex;
6687 Account
const alice{
"alice"};
6688 Account
const bob{
"bob"};
6690 Env env{*
this, features};
6691 auto const acctReserve = env.
current()->fees().reserve;
6692 auto const incReserve = env.
current()->fees().increment;
6693 auto const baseFee = env.
current()->fees().base;
6695 env.
fund(XRP(10000), alice);
6699 env.
fund(acctReserve, bob);
6703 auto const sellOfferIndex =
6704 mintAndCreateSellOffer(env, alice, XRP(0));
6707 BEAST_EXPECT(ownerCount(env, bob) == 0);
6711 if (!features[fixNFTokenReserve])
6714 env(token::acceptSellOffer(bob, sellOfferIndex));
6718 BEAST_EXPECT(ownerCount(env, bob) == 1);
6733 env(token::acceptSellOffer(bob, sellOfferIndex),
6740 BEAST_EXPECT(ownerCount(env, bob) == 0);
6745 env(pay(env.
master, bob, incReserve + drops(baseFee)));
6750 env(token::acceptSellOffer(bob, sellOfferIndex),
6756 env(pay(env.
master, bob, drops(baseFee * 2)));
6760 env(token::acceptSellOffer(bob, sellOfferIndex));
6763 BEAST_EXPECT(ownerCount(env, bob) == 1);
6770 Account
const alice{
"alice"};
6771 Account
const bob{
"bob"};
6773 Env env{*
this, features};
6774 auto const acctReserve = env.
current()->fees().reserve;
6775 auto const incReserve = env.
current()->fees().increment;
6777 env.
fund(XRP(10000), alice);
6780 env.
fund(acctReserve + XRP(1), bob);
6783 if (!features[fixNFTokenReserve])
6786 for (
size_t i = 0; i < 200; i++)
6789 auto const sellOfferIndex =
6790 mintAndCreateSellOffer(env, alice, XRP(0));
6793 env(token::acceptSellOffer(bob, sellOfferIndex));
6800 auto const sellOfferIndex1 =
6801 mintAndCreateSellOffer(env, alice, XRP(0));
6805 env(token::acceptSellOffer(bob, sellOfferIndex1),
6810 env(pay(env.
master, bob, drops(incReserve)));
6813 BEAST_EXPECT(ownerCount(env, bob) == 0);
6816 env(token::acceptSellOffer(bob, sellOfferIndex1));
6819 BEAST_EXPECT(ownerCount(env, bob) == 1);
6823 for (
size_t i = 0; i < 31; i++)
6826 auto const sellOfferIndex =
6827 mintAndCreateSellOffer(env, alice, XRP(0));
6831 env(token::acceptSellOffer(bob, sellOfferIndex));
6835 BEAST_EXPECT(ownerCount(env, bob) == 1);
6839 auto const sellOfferIndex33 =
6840 mintAndCreateSellOffer(env, alice, XRP(0));
6844 env(token::acceptSellOffer(bob, sellOfferIndex33),
6849 env(pay(env.
master, bob, drops(incReserve)));
6854 env(token::acceptSellOffer(bob, sellOfferIndex33));
6857 BEAST_EXPECT(ownerCount(env, bob) == 2);
6867 Account
const alice{
"alice"};
6868 Account
const bob{
"bob"};
6870 Env env{*
this, features};
6871 auto const acctReserve = env.
current()->fees().reserve;
6872 auto const incReserve = env.
current()->fees().increment;
6873 auto const baseFee = env.
current()->fees().base;
6875 env.
fund(XRP(10000), alice);
6881 env.
fund(acctReserve + incReserve + XRP(1), bob);
6892 env(token::createOffer(bob, nftId, XRP(1)), token::owner(alice));
6898 env(token::acceptBuyOffer(alice, buyOfferIndex),
6903 env(pay(env.
master, bob, drops(baseFee)));
6907 env(token::acceptBuyOffer(alice, buyOfferIndex));
6917 Account
const alice{
"alice"};
6918 Account
const bob{
"bob"};
6919 Account
const broker{
"broker"};
6921 Env env{*
this, features};
6922 auto const acctReserve = env.
current()->fees().reserve;
6923 auto const incReserve = env.
current()->fees().increment;
6924 auto const baseFee = env.
current()->fees().base;
6926 env.
fund(XRP(10000), alice, broker);
6931 env.
fund(acctReserve + incReserve + XRP(1), bob);
6941 uint256 const offerAliceToBroker =
6943 env(token::createOffer(alice, nftId, XRP(1)),
6944 token::destination(broker),
6949 uint256 const offerBobToBroker =
6951 env(token::createOffer(bob, nftId, XRP(1)), token::owner(alice));
6958 env(token::brokerOffers(
6959 broker, offerBobToBroker, offerAliceToBroker),
6964 env(pay(env.
master, bob, drops(baseFee)));
6968 env(token::brokerOffers(
6969 broker, offerBobToBroker, offerAliceToBroker));
7307 using namespace test::jtx;
7309 Account
const issuer{
"issuer"};
7310 Account
const alice(
"alice");
7311 Account
const bob(
"bob");
7313 bool const modifyEnabled = features[featureDynamicNFT];
7317 Env env{*
this, features};
7318 env.fund(XRP(10000), issuer);
7321 auto const expectedTer =
7323 env(token::mint(issuer, 0u), txflags(
tfMutable), ter(expectedTer));
7327 Env env{*
this, features};
7328 env.fund(XRP(10000), issuer);
7335 env(token::mint(issuer, 0u), txflags(
tfMutable));
7337 BEAST_EXPECT(ownerCount(env, issuer) == 1);
7338 env(token::modify(issuer, nftId));
7339 BEAST_EXPECT(ownerCount(env, issuer) == 1);
7343 env(token::mint(issuer, 0u));
7345 env(token::modify(issuer, nftId), ter(
temDISABLED));
7353 Env env{*
this, features};
7354 env.fund(XRP(10000), issuer);
7358 env(token::mint(issuer, 0u), txflags(
tfMutable));
7362 env(token::modify(issuer, nftId),
7368 env(token::modify(issuer, nftId),
7369 txflags(0x00000001),
7373 env(token::modify(issuer, nftId),
7374 token::owner(issuer),
7379 env(token::modify(issuer, nftId),
7385 env(token::modify(issuer, nftId),
7391 Env env{*
this, features};
7392 env.fund(XRP(10000), issuer, alice, bob);
7398 token::getNextID(env, issuer, 0u,
tfMutable)};
7401 env(token::modify(issuer, nftIDNotExists), ter(
tecNO_ENTRY));
7406 uint256 const nftIDNotModifiable{
7407 token::getNextID(env, issuer, 0u)};
7408 env(token::mint(issuer, 0u));
7411 env(token::modify(issuer, nftIDNotModifiable),
7418 token::getNextID(env, issuer, 0u,
tfMutable)};
7419 env(token::mint(issuer, 0u), txflags(
tfMutable));
7422 env(token::modify(bob, nftId),
7423 token::owner(issuer),
7427 env(token::setMinter(issuer, alice));
7430 env(token::modify(bob, nftId),
7431 token::owner(issuer),
7437 Env env{*
this, features};
7438 env.fund(XRP(10000), issuer, alice, bob);
7443 env(token::mint(issuer, 0u), txflags(
tfMutable), token::uri(
"uri"));
7450 Env env{*
this, features};
7451 env.fund(XRP(10000), issuer, alice, bob);
7455 auto accountNFTs = [&env](Account
const& acct) {
7457 params[jss::account] = acct.human();
7458 params[jss::type] =
"state";
7460 env.rpc(
"json",
"account_nfts",
to_string(params));
7461 return response[jss::result][jss::account_nfts];
7465 auto checkURI = [&accountNFTs,
this](
7466 Account
const& acct,
7469 auto const nfts = accountNFTs(acct);
7470 if (nfts.size() == 1)
7475 text <<
"checkURI: unexpected NFT count on line " << line;
7476 fail(text.
str(), __FILE__, line);
7482 if (!nfts[0u].isMember(sfURI.jsonName))
7487 text <<
"checkURI: unexpected URI present on line "
7489 fail(text.
str(), __FILE__, line);
7499 text <<
"checkURI: unexpected URI contents on line "
7501 fail(text.
str(), __FILE__, line);
7508 env(token::mint(issuer, 0u), txflags(
tfMutable), token::uri(
"uri"));
7510 checkURI(issuer,
"uri", __LINE__);
7513 env(token::modify(issuer, nftId), token::uri(
"new_uri"));
7515 checkURI(issuer,
"new_uri", __LINE__);
7518 env(token::modify(issuer, nftId));
7520 checkURI(issuer,
nullptr, __LINE__);
7523 env(token::modify(issuer, nftId), token::uri(
"uri"));
7525 checkURI(issuer,
"uri", __LINE__);
7530 env(token::createOffer(issuer, nftId, XRP(0)),
7533 env(token::acceptSellOffer(alice, offerID));
7535 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7536 BEAST_EXPECT(ownerCount(env, alice) == 1);
7537 checkURI(alice,
"uri", __LINE__);
7540 env(token::modify(alice, nftId),
7541 token::uri(
"new_uri"),
7544 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7545 BEAST_EXPECT(ownerCount(env, alice) == 1);
7546 checkURI(alice,
"uri", __LINE__);
7548 env(token::modify(issuer, nftId),
7549 token::owner(alice),
7550 token::uri(
"new_uri"));
7552 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7553 BEAST_EXPECT(ownerCount(env, alice) == 1);
7554 checkURI(alice,
"new_uri", __LINE__);
7556 env(token::modify(issuer, nftId), token::owner(alice));
7558 checkURI(alice,
nullptr, __LINE__);
7560 env(token::modify(issuer, nftId),
7561 token::owner(alice),
7564 checkURI(alice,
"uri", __LINE__);
7567 env(token::setMinter(issuer, bob));
7569 env(token::modify(bob, nftId),
7570 token::owner(alice),
7571 token::uri(
"new_uri"));
7573 checkURI(alice,
"new_uri", __LINE__);
7575 env(token::modify(bob, nftId), token::owner(alice));
7577 checkURI(alice,
nullptr, __LINE__);
7579 env(token::modify(bob, nftId),
7580 token::owner(alice),
7583 checkURI(alice,
"uri", __LINE__);