133 using namespace test::jtx;
135 Env env{*
this, features};
136 Account
const alice{
"alice"};
137 Account
const minter{
"minter"};
141 auto const acctReserve = env.current()->fees().reserve;
142 auto const incReserve = env.current()->fees().increment;
143 auto const baseFee = env.current()->fees().base;
145 env.fund(acctReserve, alice, minter);
148 BEAST_EXPECT(env.balance(alice) == acctReserve);
149 BEAST_EXPECT(env.balance(minter) == acctReserve);
150 BEAST_EXPECT(ownerCount(env, alice) == 0);
151 BEAST_EXPECT(ownerCount(env, minter) == 0);
158 BEAST_EXPECT(ownerCount(env, alice) == 0);
163 env(pay(env.master, alice, incReserve + drops(baseFee - 1)));
168 auto checkAliceOwnerMintedBurned =
176 ss <<
"Wrong " << type <<
" count. Found: " << found <<
"; Expected: " << exp;
177 fail(ss.
str(), __FILE__, line);
180 oneCheck(
"owner", ownerCount(env, alice), owners);
181 oneCheck(
"minted",
mintedCount(env, alice), minted);
182 oneCheck(
"burned",
burnedCount(env, alice), burned);
190 checkAliceOwnerMintedBurned(0, 0, 0, __LINE__);
193 env(pay(env.master, alice, drops(baseFee + 1)));
197 env(token::mint(alice));
200 checkAliceOwnerMintedBurned(1, 1, 0, __LINE__);
204 for (
int i = 1; i < 32; ++i)
206 env(token::mint(alice));
207 checkAliceOwnerMintedBurned(1, i + 1, 0, __LINE__);
214 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
217 env(pay(env.master, alice, incReserve + drops(baseFee * 33 - 1)));
224 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
227 env(pay(env.master, alice, drops(baseFee + 1)));
231 env(token::mint(alice));
233 checkAliceOwnerMintedBurned(2, 33, 0, __LINE__);
240 env(token::burn(alice, token::getID(env, alice, 0, seq++)));
242 checkAliceOwnerMintedBurned((33 - seq) ? 1 : 0, 33, seq, __LINE__);
246 env(token::burn(alice, token::getID(env, alice, 197, 5)), ter(
tecNO_ENTRY));
248 checkAliceOwnerMintedBurned(0, 33, 33, __LINE__);
253 env(token::setMinter(alice, minter));
255 BEAST_EXPECT(env.le(alice)->getAccountID(sfNFTokenMinter) == minter.id());
259 auto checkMintersOwnerMintedBurned = [&env,
this, &alice, &minter](
273 ss <<
"Wrong " << type <<
" count. Found: " << found <<
"; Expected: " << exp;
274 fail(ss.
str(), __FILE__, line);
277 oneCheck(
"alice owner", ownerCount(env, alice), aliceOwners, line);
278 oneCheck(
"alice minted",
mintedCount(env, alice), aliceMinted, line);
279 oneCheck(
"alice burned",
burnedCount(env, alice), aliceBurned, line);
280 oneCheck(
"minter owner", ownerCount(env, minter), minterOwners, line);
281 oneCheck(
"minter minted",
mintedCount(env, minter), minterMinted, line);
282 oneCheck(
"minter burned",
burnedCount(env, minter), minterBurned, line);
288 env(pay(env.master, minter, incReserve - drops(1)));
290 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
297 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
300 env(pay(env.master, minter, drops(baseFee + 1)));
304 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
306 checkMintersOwnerMintedBurned(0, 34, nftSeq, 1, 0, 0, __LINE__);
310 for (
int i = 1; i < 32; ++i)
312 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
313 checkMintersOwnerMintedBurned(0, i + 34, nftSeq, 1, 0, 0, __LINE__);
318 env(pay(env.master, minter, incReserve + drops(baseFee * 32 - 1)));
325 checkMintersOwnerMintedBurned(0, 65, nftSeq, 1, 0, 0, __LINE__);
328 env(pay(env.master, minter, drops(baseFee + 1)));
332 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
334 checkMintersOwnerMintedBurned(0, 66, nftSeq, 2, 0, 0, __LINE__);
339 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
341 checkMintersOwnerMintedBurned(0, 66, nftSeq, (65 - seq) ? 1 : 0, 0, 0, __LINE__);
346 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
348 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
351 env(token::burn(minter, token::getID(env, alice, 2009, 3)), ter(
tecNO_ENTRY));
353 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
539 testcase(
"Invalid NFT offer create");
541 using namespace test::jtx;
543 Env env{*
this, features};
544 Account
const alice{
"alice"};
545 Account
const buyer{
"buyer"};
546 Account
const gw(
"gw");
547 IOU
const gwAUD(gw[
"AUD"]);
552 env.fund(XRP(250), alice, buyer, gw);
554 BEAST_EXPECT(ownerCount(env, alice) == 0);
557 env(token::mint(alice, 0u), txflags(
tfTransferable), token::xferFee(10));
559 BEAST_EXPECT(ownerCount(env, alice) == 1);
564 BEAST_EXPECT(ownerCount(env, alice) == 1);
566 uint256 nftNoXferID = token::getNextID(env, alice, 0);
567 env(token::mint(alice, 0));
569 BEAST_EXPECT(ownerCount(env, alice) == 1);
582 BEAST_EXPECT(ownerCount(env, buyer) == 0);
585 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)), fee(
STAmount(10ull,
true)), ter(
temBAD_FEE));
587 BEAST_EXPECT(ownerCount(env, buyer) == 0);
590 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)), txflags(0x00008000), ter(
temINVALID_FLAG));
592 BEAST_EXPECT(ownerCount(env, buyer) == 0);
595 env(token::createOffer(buyer, nftXrpOnlyID, buyer[
"USD"](1)), ter(
temBAD_AMOUNT));
596 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](0)), ter(
temBAD_AMOUNT));
597 env(token::createOffer(buyer, nftXrpOnlyID, drops(0)), ter(
temBAD_AMOUNT));
599 BEAST_EXPECT(ownerCount(env, buyer) == 0);
602 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](1)), token::expiration(0), ter(
temBAD_EXPIRATION));
604 BEAST_EXPECT(ownerCount(env, buyer) == 0);
608 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)), ter(
temMALFORMED));
610 BEAST_EXPECT(ownerCount(env, buyer) == 0);
613 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
618 BEAST_EXPECT(ownerCount(env, alice) == 1);
621 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)), token::owner(alice), ter(
temMALFORMED));
623 BEAST_EXPECT(ownerCount(env, alice) == 1);
626 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
627 token::destination(alice),
631 BEAST_EXPECT(ownerCount(env, alice) == 1);
634 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
635 token::destination(Account(
"demon")),
639 BEAST_EXPECT(ownerCount(env, alice) == 1);
645 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
650 BEAST_EXPECT(ownerCount(env, buyer) == 0);
653 env(token::createOffer(buyer, token::getID(env, alice, 0, 1), XRP(1000)),
657 BEAST_EXPECT(ownerCount(env, buyer) == 0);
660 env(token::createOffer(alice, token::getID(env, alice, 0, 1), XRP(1000)),
664 BEAST_EXPECT(ownerCount(env, buyer) == 0);
667 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(
tecNO_LINE));
669 BEAST_EXPECT(ownerCount(env, buyer) == 0);
671 env(trust(buyer, gwAUD(1000)));
673 BEAST_EXPECT(ownerCount(env, buyer) == 1);
677 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(
tecNO_LINE));
679 BEAST_EXPECT(ownerCount(env, buyer) == 1);
687 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(
tecFROZEN));
689 BEAST_EXPECT(ownerCount(env, buyer) == 1);
696 env(token::createOffer(buyer, nftNoXferID, gwAUD(1000)),
700 BEAST_EXPECT(ownerCount(env, buyer) == 1);
706 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(
tecFROZEN));
708 BEAST_EXPECT(ownerCount(env, buyer) == 1);
713 env(trust(buyer, gwAUD(1000)));
716 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(
tecUNFUNDED_OFFER));
718 BEAST_EXPECT(ownerCount(env, buyer) == 1);
724 env(pay(gw, buyer, gwAUD(999)));
731 BEAST_EXPECT(ownerCount(env, buyer) == 1);
734 auto const baseFee = env.current()->fees().base;
735 env(pay(env.master, buyer, XRP(50) + drops(baseFee * 12 - 1)));
740 BEAST_EXPECT(ownerCount(env, buyer) == 1);
743 env(pay(env.master, buyer, drops(baseFee + 1)));
748 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(
tesSUCCESS));
750 BEAST_EXPECT(ownerCount(env, buyer) == 2);
866 testcase(
"Invalid NFT offer accept");
868 using namespace test::jtx;
870 Env env{*
this, features};
871 Account
const alice{
"alice"};
872 Account
const buyer{
"buyer"};
873 Account
const gw(
"gw");
874 IOU
const gwAUD(gw[
"AUD"]);
876 env.fund(XRP(1000), alice, buyer, gw);
878 BEAST_EXPECT(ownerCount(env, alice) == 0);
879 BEAST_EXPECT(ownerCount(env, buyer) == 0);
884 uint8_t aliceCount = 1;
885 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
890 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
892 uint256 nftNoXferID = token::getNextID(env, alice, 0);
893 env(token::mint(alice, 0));
895 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
899 env(token::createOffer(alice, nftAlice0ID, XRP(10)), txflags(
tfSellNFToken));
902 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
905 env(token::createOffer(alice, nftAlice0ID, gwAUD(30)), txflags(
tfSellNFToken));
908 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
911 env(token::createOffer(alice, nftXrpOnlyID, XRP(20)), txflags(
tfSellNFToken));
914 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
917 env(token::createOffer(alice, nftNoXferID, XRP(30)), txflags(
tfSellNFToken));
920 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
924 env(token::createOffer(alice, nftNoXferID, XRP(40)),
929 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
933 env(token::createOffer(buyer, nftAlice0ID, XRP(40)),
937 uint8_t buyerCount = 1;
938 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
944 env(token::acceptSellOffer(buyer, noXferOfferIndex), fee(
STAmount(10ull,
true)), ter(
temBAD_FEE));
946 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
949 env(token::acceptSellOffer(buyer, noXferOfferIndex), txflags(0x00008000), ter(
temINVALID_FLAG));
951 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
955 Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
959 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
964 Json::Value jv = token::acceptBuyOffer(buyer, noXferOfferIndex);
968 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
973 Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
977 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
981 env(token::brokerOffers(buyer, noXferOfferIndex, xrpOnlyOfferIndex),
982 token::brokerFee(gwAUD(0)),
985 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
993 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
999 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1004 env(token::acceptBuyOffer(alice, buyerExpOfferIndex), ter(
tecEXPIRED));
1006 if (features[fixExpiredNFTokenOfferRemoval])
1010 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1015 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1020 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1025 env(token::acceptSellOffer(buyer, aliceExpOfferIndex), ter(
tecEXPIRED));
1029 if (features[fixExpiredNFTokenOfferRemoval])
1033 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1034 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1041 env(trust(alice, gwAUD(1000)));
1042 env(trust(buyer, gwAUD(1000)));
1044 env(pay(gw, buyer, gwAUD(30)));
1048 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1049 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1051 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1052 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1059 env(token::createOffer(buyer, nftAlice0ID, gwAUD(29)), token::owner(alice));
1062 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1067 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1072 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1078 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1081 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1084 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1089 env(token::createOffer(buyer, nftAlice0ID, gwAUD(31)), token::owner(alice));
1092 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1096 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1097 token::brokerFee(XRP(40)),
1100 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1103 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1104 token::brokerFee(gwAUD(31)),
1107 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1111 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1112 token::brokerFee(gwAUD(1.5)),
1115 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1118 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1121 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1128 env(token::createOffer(buyer, nftAlice0ID, gwAUD(30)), token::owner(alice));
1131 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1136 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1141 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1144 env(pay(buyer, gw, gwAUD(30)));
1146 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1149 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1154 env(token::createOffer(alice, nftAlice0ID, XRP(0)), txflags(
tfSellNFToken));
1156 env(token::acceptSellOffer(gw, offerIndex));
1158 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1160 env(pay(gw, buyer, gwAUD(30)));
1166 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1169 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1172 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1179 env(token::createOffer(buyer, nftXrpOnlyID, XRP(30)), token::owner(alice));
1182 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1187 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1192 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1196 env(token::acceptSellOffer(buyer, plainOfferIndex), ter(
tecNO_PERMISSION));
1198 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1205 env(token::createOffer(gw, nftAlice0ID, XRP(0)), txflags(
tfSellNFToken));
1207 env(token::acceptSellOffer(alice, offerIndex));
1209 BEAST_EXPECT(ownerCount(env, alice) == aliceCount);
1211 env(pay(buyer, gw, gwAUD(30)));
1213 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1216 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
1417 testcase(
"Mint flagCreateTrustLines");
1419 using namespace test::jtx;
1421 Account
const alice{
"alice"};
1422 Account
const becky{
"becky"};
1423 Account
const cheri{
"cheri"};
1424 Account
const gw(
"gw");
1425 IOU
const gwAUD(gw[
"AUD"]);
1426 IOU
const gwCAD(gw[
"CAD"]);
1427 IOU
const gwEUR(gw[
"EUR"]);
1432 for (
auto const& tweakedFeatures :
1433 {features - fixRemoveNFTokenAutoTrustLine, features | fixRemoveNFTokenAutoTrustLine})
1435 Env env{*
this, tweakedFeatures};
1436 env.fund(XRP(1000), alice, becky, cheri, gw);
1440 env(trust(becky, gwAUD(1000)));
1441 env(trust(cheri, gwAUD(1000)));
1442 env(trust(becky, gwCAD(1000)));
1443 env(trust(cheri, gwCAD(1000)));
1444 env(trust(becky, gwEUR(1000)));
1445 env(trust(cheri, gwEUR(1000)));
1447 env(pay(gw, becky, gwAUD(500)));
1448 env(pay(gw, becky, gwCAD(500)));
1449 env(pay(gw, becky, gwEUR(500)));
1450 env(pay(gw, cheri, gwAUD(500)));
1451 env(pay(gw, cheri, gwCAD(500)));
1459 env(token::mint(alice, 0u), token::xferFee(xferFee), txflags(
tfTransferable));
1464 env(token::createOffer(becky, nftNoAutoTrustID, drops(1)), token::owner(alice));
1466 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1472 env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)),
1474 ter(createOfferTER));
1479 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)), token::owner(becky), ter(createOfferTER));
1483 env(token::cancelOffer(becky, {beckyOfferIndex}));
1484 env(token::cancelOffer(cheri, {cheriOfferIndex}));
1498 TER const mintTER = tweakedFeatures[fixRemoveNFTokenAutoTrustLine]
1502 env(token::mint(alice, 0u),
1503 token::xferFee(transferFee),
1510 if (tweakedFeatures[fixRemoveNFTokenAutoTrustLine])
1515 env(token::createOffer(becky, nftAutoTrustID, drops(1)), token::owner(alice));
1517 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1522 env(token::createOffer(becky, nftAutoTrustID, gwAUD(100)), txflags(
tfSellNFToken));
1524 env(token::acceptSellOffer(cheri, beckySellOfferIndex));
1528 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1532 env(token::createOffer(becky, nftAutoTrustID, gwCAD(50)), token::owner(cheri));
1534 env(token::acceptBuyOffer(cheri, beckyBuyBackOfferIndex));
1538 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1539 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(5));
1546 env(token::mint(alice, 0u), token::xferFee(transferFee), txflags(
tfTransferable));
1551 env(token::createOffer(alice, nftNoAutoTrustID, gwAUD(200)), txflags(
tfSellNFToken));
1553 env(token::acceptSellOffer(cheri, aliceSellOfferIndex));
1559 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(210));
1565 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)), txflags(
tfSellNFToken));
1567 env(token::acceptSellOffer(becky, cheriSellOfferIndex));
1573 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(10));
1584 using namespace test::jtx;
1586 Env env{*
this, features};
1588 Account
const alice{
"alice"};
1589 Account
const becky{
"becky"};
1590 Account
const minter{
"minter"};
1592 env.fund(XRP(1000), alice, becky, minter);
1597 BEAST_EXPECT(ownerCount(env, alice) == 0);
1598 uint256 const nftAliceNoTransferID{token::getNextID(env, alice, 0u)};
1599 env(token::mint(alice, 0u), token::xferFee(0));
1601 BEAST_EXPECT(ownerCount(env, alice) == 1);
1604 BEAST_EXPECT(ownerCount(env, becky) == 0);
1605 env(token::createOffer(becky, nftAliceNoTransferID, XRP(20)),
1606 token::owner(alice),
1611 env(token::createOffer(alice, nftAliceNoTransferID, XRP(20)), txflags(
tfSellNFToken));
1613 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1615 BEAST_EXPECT(ownerCount(env, alice) == 0);
1616 BEAST_EXPECT(ownerCount(env, becky) == 1);
1619 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1623 BEAST_EXPECT(ownerCount(env, alice) == 0);
1624 BEAST_EXPECT(ownerCount(env, becky) == 1);
1628 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1630 token::destination(alice),
1633 BEAST_EXPECT(ownerCount(env, alice) == 0);
1634 BEAST_EXPECT(ownerCount(env, becky) == 1);
1639 env(token::createOffer(alice, nftAliceNoTransferID, XRP(22)), token::owner(becky));
1641 env(token::acceptBuyOffer(becky, aliceBuyOfferIndex));
1643 BEAST_EXPECT(ownerCount(env, alice) == 1);
1644 BEAST_EXPECT(ownerCount(env, becky) == 0);
1647 env(token::burn(alice, nftAliceNoTransferID));
1649 BEAST_EXPECT(ownerCount(env, alice) == 0);
1650 BEAST_EXPECT(ownerCount(env, becky) == 0);
1654 env(token::setMinter(alice, minter));
1657 BEAST_EXPECT(ownerCount(env, minter) == 0);
1658 uint256 const nftMinterNoTransferID{token::getNextID(env, alice, 0u)};
1659 env(token::mint(minter), token::issuer(alice));
1661 BEAST_EXPECT(ownerCount(env, minter) == 1);
1664 BEAST_EXPECT(ownerCount(env, becky) == 0);
1665 env(token::createOffer(becky, nftMinterNoTransferID, XRP(20)),
1666 token::owner(minter),
1669 BEAST_EXPECT(ownerCount(env, becky) == 0);
1672 env(token::clearMinter(alice));
1676 BEAST_EXPECT(ownerCount(env, minter) == 1);
1677 env(token::createOffer(minter, nftMinterNoTransferID, XRP(21)),
1681 BEAST_EXPECT(ownerCount(env, minter) == 1);
1685 for (
int i = 0; i < 10; ++i)
1688 env(token::setMinter(alice, minter));
1690 BEAST_EXPECT(ownerCount(env, minter) == 1);
1693 BEAST_EXPECT(ownerCount(env, minter) == 1);
1695 env(token::createOffer(minter, nftMinterNoTransferID, XRP(22)), txflags(
tfSellNFToken));
1697 BEAST_EXPECT(ownerCount(env, minter) == 2);
1701 env(token::clearMinter(alice));
1706 BEAST_EXPECT(ownerCount(env, becky) == 0);
1707 env(token::acceptSellOffer(becky, minterSellOfferIndex));
1709 BEAST_EXPECT(ownerCount(env, becky) == 1);
1710 BEAST_EXPECT(ownerCount(env, minter) == 0);
1713 env(token::createOffer(becky, nftMinterNoTransferID, XRP(23)),
1720 BEAST_EXPECT(ownerCount(env, minter) == 0);
1721 env(token::createOffer(minter, nftMinterNoTransferID, XRP(24)),
1722 token::owner(becky),
1725 BEAST_EXPECT(ownerCount(env, minter) == 0);
1728 BEAST_EXPECT(ownerCount(env, alice) == 0);
1730 env(token::createOffer(alice, nftMinterNoTransferID, XRP(25)), token::owner(becky));
1732 BEAST_EXPECT(ownerCount(env, alice) == 1);
1736 for (
int i = 0; i < 10; ++i)
1739 env(token::setMinter(alice, minter));
1743 BEAST_EXPECT(ownerCount(env, minter) == 0);
1745 env(token::createOffer(minter, nftMinterNoTransferID, XRP(26)), token::owner(becky));
1747 BEAST_EXPECT(ownerCount(env, minter) == 1);
1751 env(token::clearMinter(alice));
1755 BEAST_EXPECT(ownerCount(env, minter) == 1);
1756 BEAST_EXPECT(ownerCount(env, becky) == 1);
1757 env(token::acceptBuyOffer(becky, minterBuyOfferIndex));
1759 BEAST_EXPECT(ownerCount(env, minter) == 1);
1760 BEAST_EXPECT(ownerCount(env, becky) == 0);
1761 BEAST_EXPECT(ownerCount(env, alice) == 1);
1765 env(token::burn(minter, nftMinterNoTransferID), ter(
tesSUCCESS));
1767 env(token::cancelOffer(alice, {aliceBuyOfferIndex}));
1769 BEAST_EXPECT(ownerCount(env, alice) == 0);
1770 BEAST_EXPECT(ownerCount(env, becky) == 0);
1771 BEAST_EXPECT(ownerCount(env, minter) == 0);
1776 BEAST_EXPECT(ownerCount(env, alice) == 0);
1780 BEAST_EXPECT(ownerCount(env, alice) == 1);
1784 env(token::createOffer(alice, nftAliceID, XRP(20)), txflags(
tfSellNFToken));
1786 BEAST_EXPECT(ownerCount(env, alice) == 2);
1789 env(token::createOffer(becky, nftAliceID, XRP(21)), token::owner(alice));
1791 BEAST_EXPECT(ownerCount(env, alice) == 2);
1794 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1796 BEAST_EXPECT(ownerCount(env, alice) == 0);
1797 BEAST_EXPECT(ownerCount(env, becky) == 2);
1801 env(token::createOffer(becky, nftAliceID, XRP(22)), txflags(
tfSellNFToken));
1803 BEAST_EXPECT(ownerCount(env, alice) == 0);
1804 BEAST_EXPECT(ownerCount(env, becky) == 3);
1808 env(token::acceptSellOffer(minter, beckySellOfferIndex));
1810 BEAST_EXPECT(ownerCount(env, alice) == 0);
1811 BEAST_EXPECT(ownerCount(env, becky) == 1);
1812 BEAST_EXPECT(ownerCount(env, minter) == 1);
1816 env(token::createOffer(minter, nftAliceID, XRP(23)), txflags(
tfSellNFToken));
1818 BEAST_EXPECT(ownerCount(env, alice) == 0);
1819 BEAST_EXPECT(ownerCount(env, becky) == 1);
1820 BEAST_EXPECT(ownerCount(env, minter) == 2);
1823 env(token::acceptSellOffer(alice, minterSellOfferIndex));
1825 BEAST_EXPECT(ownerCount(env, alice) == 1);
1826 BEAST_EXPECT(ownerCount(env, becky) == 1);
1827 BEAST_EXPECT(ownerCount(env, minter) == 0);
1831 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1833 BEAST_EXPECT(ownerCount(env, alice) == 0);
1834 BEAST_EXPECT(ownerCount(env, becky) == 1);
1835 BEAST_EXPECT(ownerCount(env, minter) == 0);
1839 env(token::burn(becky, nftAliceID));
1841 BEAST_EXPECT(ownerCount(env, alice) == 0);
1842 BEAST_EXPECT(ownerCount(env, becky) == 0);
1843 BEAST_EXPECT(ownerCount(env, minter) == 0);
1853 using namespace test::jtx;
1855 Env env{*
this, features};
1856 auto const baseFee = env.current()->fees().base;
1858 Account
const alice{
"alice"};
1859 Account
const becky{
"becky"};
1860 Account
const carol{
"carol"};
1861 Account
const minter{
"minter"};
1862 Account
const gw{
"gw"};
1863 IOU
const gwXAU(gw[
"XAU"]);
1865 env.fund(XRP(1000), alice, becky, carol, minter, gw);
1868 env(trust(alice, gwXAU(2000)));
1869 env(trust(becky, gwXAU(2000)));
1870 env(trust(carol, gwXAU(2000)));
1871 env(trust(minter, gwXAU(2000)));
1873 env(pay(gw, alice, gwXAU(1000)));
1874 env(pay(gw, becky, gwXAU(1000)));
1875 env(pay(gw, carol, gwXAU(1000)));
1876 env(pay(gw, minter, gwXAU(1000)));
1881 env(token::setMinter(alice, minter));
1887 BEAST_EXPECT(ownerCount(env, alice) == 1);
1888 BEAST_EXPECT(ownerCount(env, becky) == 1);
1889 BEAST_EXPECT(ownerCount(env, carol) == 1);
1890 BEAST_EXPECT(ownerCount(env, minter) == 1);
1898 env(token::createOffer(becky, nftID, gwXAU(10)), token::owner(alice));
1900 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
1901 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
1903 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1905 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
1906 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
1910 env(token::createOffer(becky, nftID, gwXAU(10)), txflags(
tfSellNFToken));
1912 env(token::acceptSellOffer(carol, beckySellOfferIndex));
1914 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
1915 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
1916 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
1920 env(token::createOffer(minter, nftID, gwXAU(10)), token::owner(carol));
1922 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
1924 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
1925 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
1926 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
1927 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
1932 env(token::createOffer(minter, nftID, gwXAU(10)), txflags(
tfSellNFToken));
1934 env(token::acceptSellOffer(alice, minterSellOfferIndex));
1936 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
1937 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
1938 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
1939 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
1942 env(token::burn(alice, nftID));
1944 BEAST_EXPECT(ownerCount(env, alice) == 1);
1945 BEAST_EXPECT(ownerCount(env, becky) == 1);
1946 BEAST_EXPECT(ownerCount(env, carol) == 1);
1947 BEAST_EXPECT(ownerCount(env, minter) == 1);
1954 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
1959 env(token::createOffer(becky, nftID, gwXAU(10)), token::owner(alice));
1961 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
1962 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
1964 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1966 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
1967 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
1971 env(token::createOffer(becky, nftID, gwXAU(10)), txflags(
tfSellNFToken));
1973 env(token::acceptSellOffer(carol, beckySellOfferIndex));
1976 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0001));
1977 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
1978 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
1982 env(token::createOffer(minter, nftID, gwXAU(10)), token::owner(carol));
1984 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
1987 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0002));
1988 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
1989 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
1990 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
1995 env(token::createOffer(minter, nftID, gwXAU(10)), txflags(
tfSellNFToken));
1997 env(token::acceptSellOffer(alice, minterSellOfferIndex));
1999 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000.0002));
2000 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2001 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2002 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2006 env(pay(alice, becky, gwXAU(0.0001)));
2007 env(pay(alice, carol, gwXAU(0.0001)));
2010 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2011 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2012 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2013 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2016 env(token::burn(alice, nftID));
2018 BEAST_EXPECT(ownerCount(env, alice) == 1);
2019 BEAST_EXPECT(ownerCount(env, becky) == 1);
2020 BEAST_EXPECT(ownerCount(env, carol) == 1);
2021 BEAST_EXPECT(ownerCount(env, minter) == 1);
2027 env(token::mint(alice),
2040 env(token::createOffer(becky, nftID, gwXAU(10)), token::owner(alice));
2042 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2043 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2045 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2047 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2048 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2052 env(token::createOffer(becky, nftID, gwXAU(100)), txflags(
tfSellNFToken));
2054 env(token::acceptSellOffer(minter, beckySellOfferIndex));
2057 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1060));
2058 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2059 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
2063 env(token::createOffer(carol, nftID, gwXAU(10)), token::owner(minter));
2065 env(token::acceptBuyOffer(minter, carolBuyOfferIndex));
2068 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1065));
2069 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2070 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2071 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2076 env(token::createOffer(carol, nftID, gwXAU(10)), txflags(
tfSellNFToken));
2078 env(token::acceptSellOffer(alice, carolSellOfferIndex));
2081 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1055));
2082 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2083 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2084 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2087 env(pay(alice, minter, gwXAU(55)));
2088 env(pay(becky, minter, gwXAU(40)));
2090 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2091 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2092 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2093 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2096 env(token::burn(alice, nftID));
2098 BEAST_EXPECT(ownerCount(env, alice) == 1);
2099 BEAST_EXPECT(ownerCount(env, becky) == 1);
2100 BEAST_EXPECT(ownerCount(env, carol) == 1);
2101 BEAST_EXPECT(ownerCount(env, minter) == 1);
2106 for (
auto NumberSwitchOver : {
true})
2108 if (NumberSwitchOver)
2109 env.enableFeature(fixUniversalNumber);
2111 env.disableFeature(fixUniversalNumber);
2115 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2120 STAmount aliceBalance = env.balance(alice);
2121 STAmount minterBalance = env.balance(minter);
2123 env(token::createOffer(minter, nftID, XRP(1)), token::owner(alice));
2125 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2127 aliceBalance += XRP(1) - baseFee;
2128 minterBalance -= XRP(1) + baseFee;
2129 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2130 BEAST_EXPECT(env.balance(minter) == minterBalance);
2134 auto pmt = NumberSwitchOver ? drops(50000) : drops(99999);
2135 STAmount carolBalance = env.balance(carol);
2137 env(token::createOffer(minter, nftID, pmt), txflags(
tfSellNFToken));
2139 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2141 minterBalance += pmt - baseFee;
2142 carolBalance -= pmt + baseFee;
2143 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2144 BEAST_EXPECT(env.balance(minter) == minterBalance);
2145 BEAST_EXPECT(env.balance(carol) == carolBalance);
2149 STAmount beckyBalance = env.balance(becky);
2151 pmt = NumberSwitchOver ? drops(50001) : drops(100000);
2152 env(token::createOffer(becky, nftID, pmt), token::owner(carol));
2154 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2156 carolBalance += pmt - drops(1) - baseFee;
2157 beckyBalance -= pmt + baseFee;
2158 aliceBalance += drops(1);
2160 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2161 BEAST_EXPECT(env.balance(minter) == minterBalance);
2162 BEAST_EXPECT(env.balance(carol) == carolBalance);
2163 BEAST_EXPECT(env.balance(becky) == beckyBalance);
2171 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2177 env(pay(alice, gw, env.balance(alice, gwXAU)));
2178 env(pay(minter, gw, env.balance(minter, gwXAU)));
2179 env(pay(becky, gw, env.balance(becky, gwXAU)));
2183 env(pay(gw, alice, startXAUBalance));
2184 env(pay(gw, minter, startXAUBalance));
2185 env(pay(gw, becky, startXAUBalance));
2193 STAmount aliceBalance = env.balance(alice, gwXAU);
2194 STAmount minterBalance = env.balance(minter, gwXAU);
2196 env(token::createOffer(minter, nftID, tinyXAU), token::owner(alice));
2198 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2200 aliceBalance += tinyXAU;
2201 minterBalance -= tinyXAU;
2202 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2203 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2206 STAmount carolBalance = env.balance(carol, gwXAU);
2208 env(token::createOffer(minter, nftID, tinyXAU), txflags(
tfSellNFToken));
2210 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2213 minterBalance += tinyXAU;
2214 carolBalance -= tinyXAU;
2216 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2217 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2218 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2224 STAmount beckyBalance = env.balance(becky, gwXAU);
2226 env(token::createOffer(becky, nftID, cheapNFT), token::owner(carol));
2228 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2231 aliceBalance += tinyXAU;
2232 beckyBalance -= cheapNFT;
2233 carolBalance += cheapNFT - tinyXAU;
2234 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2235 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2236 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2237 BEAST_EXPECT(env.balance(becky, gwXAU) == beckyBalance);
2415 testcase(
"Create offer destination");
2417 using namespace test::jtx;
2419 Env env{*
this, features};
2421 Account
const issuer{
"issuer"};
2422 Account
const minter{
"minter"};
2423 Account
const buyer{
"buyer"};
2424 Account
const broker{
"broker"};
2426 env.fund(XRP(1000), issuer, minter, buyer, broker);
2430 env(token::setMinter(issuer, minter));
2434 env(token::mint(minter, 0), token::issuer(issuer), txflags(
tfTransferable));
2441 env(token::createOffer(minter, nftokenID, drops(1)), token::destination(issuer), txflags(
tfSellNFToken));
2444 env(token::createOffer(minter, nftokenID, drops(1)), token::destination(buyer), txflags(
tfSellNFToken));
2447 env(token::createOffer(issuer, nftokenID, drops(1)), token::owner(minter), token::destination(minter));
2450 env(token::createOffer(issuer, nftokenID, drops(1)), token::owner(minter), token::destination(buyer));
2453 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2454 BEAST_EXPECT(ownerCount(env, minter) == 3);
2455 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2464 env(token::cancelOffer(issuer, {offerMinterToBuyer}), ter(
tecNO_PERMISSION));
2465 env(token::cancelOffer(buyer, {offerMinterToIssuer}), ter(
tecNO_PERMISSION));
2466 env(token::cancelOffer(buyer, {offerIssuerToMinter}), ter(
tecNO_PERMISSION));
2467 env(token::cancelOffer(minter, {offerIssuerToBuyer}), ter(
tecNO_PERMISSION));
2469 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2470 BEAST_EXPECT(ownerCount(env, minter) == 3);
2471 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2475 env(token::cancelOffer(buyer, {offerMinterToBuyer}));
2476 env(token::cancelOffer(minter, {offerMinterToIssuer}));
2477 env(token::cancelOffer(buyer, {offerIssuerToBuyer}));
2478 env(token::cancelOffer(issuer, {offerIssuerToMinter}));
2480 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2481 BEAST_EXPECT(ownerCount(env, minter) == 1);
2482 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2489 env(token::createOffer(minter, nftokenID, drops(1)), token::destination(buyer), txflags(
tfSellNFToken));
2491 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2492 BEAST_EXPECT(ownerCount(env, minter) == 2);
2493 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2497 env(token::acceptSellOffer(issuer, offerMinterSellsToBuyer), ter(
tecNO_PERMISSION));
2499 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2500 BEAST_EXPECT(ownerCount(env, minter) == 2);
2501 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2504 env(token::acceptSellOffer(buyer, offerMinterSellsToBuyer));
2506 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2507 BEAST_EXPECT(ownerCount(env, minter) == 0);
2508 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2515 env(token::createOffer(minter, nftokenID, drops(1)), token::owner(buyer), token::destination(buyer));
2517 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2518 BEAST_EXPECT(ownerCount(env, minter) == 1);
2519 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2523 env(token::acceptBuyOffer(issuer, offerMinterBuysFromBuyer), ter(
tecNO_PERMISSION));
2525 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2526 BEAST_EXPECT(ownerCount(env, minter) == 1);
2527 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2530 env(token::acceptBuyOffer(buyer, offerMinterBuysFromBuyer));
2532 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2533 BEAST_EXPECT(ownerCount(env, minter) == 1);
2534 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2540 env(token::createOffer(buyer, nftokenID, drops(1)), token::owner(minter), token::destination(broker));
2542 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2543 BEAST_EXPECT(ownerCount(env, minter) == 1);
2544 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2546 env(token::acceptBuyOffer(minter, offerBuyerBuysFromMinter), ter(
tecNO_PERMISSION));
2550 env(token::cancelOffer(buyer, {offerBuyerBuysFromMinter}));
2552 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2553 BEAST_EXPECT(ownerCount(env, minter) == 1);
2554 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2561 env(token::createOffer(minter, nftokenID, drops(1)), token::destination(broker), txflags(
tfSellNFToken));
2564 env(token::createOffer(buyer, nftokenID, drops(1)), token::owner(minter));
2567 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2568 BEAST_EXPECT(ownerCount(env, minter) == 2);
2569 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2574 env(token::brokerOffers(issuer, offerBuyerToMinter, offerMinterToBroker), ter(
tecNO_PERMISSION));
2576 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2577 BEAST_EXPECT(ownerCount(env, minter) == 2);
2578 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2583 env(token::brokerOffers(broker, offerBuyerToMinter, offerMinterToBroker));
2585 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2586 BEAST_EXPECT(ownerCount(env, minter) == 0);
2587 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2595 env(token::createOffer(buyer, nftokenID, drops(1)), token::destination(minter), txflags(
tfSellNFToken));
2598 env(token::createOffer(minter, nftokenID, drops(1)), token::owner(buyer));
2601 env(token::createOffer(issuer, nftokenID, drops(1)), token::owner(buyer));
2604 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2605 BEAST_EXPECT(ownerCount(env, minter) == 1);
2606 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2611 env(token::brokerOffers(broker, offerIssuerToBuyer, offerBuyerToMinter), ter(
tecNO_PERMISSION));
2614 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2615 BEAST_EXPECT(ownerCount(env, minter) == 1);
2616 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2618 env(token::brokerOffers(broker, offerMinterToBuyer, offerBuyerToMinter), ter(
tecNO_PERMISSION));
2622 env(token::acceptBuyOffer(buyer, offerMinterToBuyer));
2626 env(token::cancelOffer(buyer, {offerBuyerToMinter}));
2629 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2630 BEAST_EXPECT(ownerCount(env, minter) == 1);
2631 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2634 env(token::cancelOffer(issuer, {offerIssuerToBuyer}));
2636 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2637 BEAST_EXPECT(ownerCount(env, minter) == 1);
2638 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2647 env(token::createOffer(minter, nftokenID, drops(1)), token::destination(broker), txflags(
tfSellNFToken));
2650 env(token::createOffer(buyer, nftokenID, drops(1)), token::owner(minter), token::destination(broker));
2655 env(token::brokerOffers(issuer, offerBuyerToBroker, offerMinterToBroker), ter(
tecNO_PERMISSION));
2657 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2658 BEAST_EXPECT(ownerCount(env, minter) == 2);
2659 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2663 env(token::brokerOffers(broker, offerBuyerToBroker, offerMinterToBroker));
2665 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2666 BEAST_EXPECT(ownerCount(env, minter) == 0);
2667 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2791 testcase(
"Create offer expiration");
2793 using namespace test::jtx;
2795 Env env{*
this, features};
2797 Account
const issuer{
"issuer"};
2798 Account
const minter{
"minter"};
2799 Account
const buyer{
"buyer"};
2801 env.fund(XRP(1000), issuer, minter, buyer);
2805 env(token::setMinter(issuer, minter));
2809 env(token::mint(minter, 0), token::issuer(issuer), txflags(
tfTransferable));
2813 env(token::mint(minter, 0), token::issuer(issuer), txflags(
tfTransferable));
2815 uint8_t issuerCount, minterCount, buyerCount;
2823 env(token::createOffer(minter, nftokenID0, drops(1)),
2824 token::destination(issuer),
2825 token::expiration(expiration),
2829 env(token::createOffer(minter, nftokenID0, drops(1)),
2830 token::expiration(expiration),
2834 env(token::createOffer(issuer, nftokenID0, drops(1)), token::owner(minter), token::expiration(expiration));
2837 env(token::createOffer(buyer, nftokenID0, drops(1)), token::owner(minter), token::expiration(expiration));
2842 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
2843 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
2844 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
2852 env(token::cancelOffer(issuer, {offerMinterToAnyone}), ter(
tecNO_PERMISSION));
2853 env(token::cancelOffer(buyer, {offerIssuerToMinter}), ter(
tecNO_PERMISSION));
2855 BEAST_EXPECT(
lastClose(env) < expiration);
2856 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
2857 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
2858 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
2861 env(token::cancelOffer(minter, {offerMinterToAnyone}));
2866 env(token::cancelOffer(issuer, {offerMinterToIssuer}));
2873 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
2874 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
2875 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
2878 env(token::cancelOffer(issuer, {offerBuyerToMinter}));
2880 env(token::cancelOffer(buyer, {offerIssuerToMinter}));
2883 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
2884 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
2885 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
2895 env(token::createOffer(minter, nftokenID0, drops(1)),
2896 token::expiration(expiration),
2901 env(token::createOffer(minter, nftokenID1, drops(1)),
2902 token::expiration(expiration),
2906 BEAST_EXPECT(
lastClose(env) < expiration);
2907 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
2908 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
2909 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
2912 env(token::acceptSellOffer(buyer, offer0));
2920 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
2921 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
2922 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
2925 env(token::acceptSellOffer(buyer, offer1), ter(
tecEXPIRED));
2930 if (features[fixExpiredNFTokenOfferRemoval])
2940 env(token::acceptSellOffer(issuer, offer1), ter(
tecEXPIRED));
2945 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
2946 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
2947 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
2949 if (!features[fixExpiredNFTokenOfferRemoval])
2953 env(token::cancelOffer(issuer, {offer1}));
2959 BEAST_EXPECT(ownerCount(env, issuer) == 0 && issuerCount == 0);
2960 BEAST_EXPECT(ownerCount(env, minter) == 1 && minterCount == 1);
2961 BEAST_EXPECT(ownerCount(env, buyer) == 1 && buyerCount == 1);
2966 env(token::createOffer(buyer, nftokenID0, XRP(0)), txflags(
tfSellNFToken), token::destination(minter));
2968 env(token::acceptSellOffer(minter, offerSellBack));
2971 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
2972 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
2973 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
2983 env(token::createOffer(buyer, nftokenID0, drops(1)), token::owner(minter), token::expiration(expiration));
2987 env(token::createOffer(buyer, nftokenID1, drops(1)), token::owner(minter), token::expiration(expiration));
2990 BEAST_EXPECT(
lastClose(env) < expiration);
2991 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
2992 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
2993 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
2996 env(token::acceptBuyOffer(minter, offer0));
3002 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3003 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3004 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3007 env(token::acceptBuyOffer(minter, offer1), ter(
tecEXPIRED));
3012 if (features[fixExpiredNFTokenOfferRemoval])
3022 env(token::acceptBuyOffer(issuer, offer1), ter(
tecEXPIRED));
3027 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3028 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3029 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3031 if (!features[fixExpiredNFTokenOfferRemoval])
3035 env(token::cancelOffer(issuer, {offer1}));
3041 BEAST_EXPECT(ownerCount(env, issuer) == 0 && issuerCount == 0);
3042 BEAST_EXPECT(ownerCount(env, minter) == 1 && minterCount == 1);
3043 BEAST_EXPECT(ownerCount(env, buyer) == 1 && buyerCount == 1);
3048 env(token::createOffer(buyer, nftokenID0, XRP(0)), txflags(
tfSellNFToken), token::destination(minter));
3050 env(token::acceptSellOffer(minter, offerSellBack));
3053 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3054 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3055 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3065 env(token::createOffer(minter, nftokenID0, drops(1)),
3066 token::expiration(expiration),
3071 env(token::createOffer(minter, nftokenID1, drops(1)),
3072 token::expiration(expiration),
3077 env(token::createOffer(buyer, nftokenID0, drops(1)), token::owner(minter));
3081 env(token::createOffer(buyer, nftokenID1, drops(1)), token::owner(minter));
3085 BEAST_EXPECT(
lastClose(env) < expiration);
3086 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3087 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3088 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3091 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3098 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3099 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3100 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3103 env(token::brokerOffers(issuer, buyOffer1, sellOffer1), ter(
tecEXPIRED));
3106 if (features[fixExpiredNFTokenOfferRemoval])
3112 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3113 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3114 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3116 if (features[fixExpiredNFTokenOfferRemoval])
3120 env(token::cancelOffer(buyer, {buyOffer1}));
3126 env(token::cancelOffer(buyer, {buyOffer1, sellOffer1}));
3133 BEAST_EXPECT(ownerCount(env, issuer) == 0 && issuerCount == 0);
3134 BEAST_EXPECT(ownerCount(env, minter) == 1 && minterCount == 1);
3135 BEAST_EXPECT(ownerCount(env, buyer) == 1 && buyerCount == 1);
3140 env(token::createOffer(buyer, nftokenID0, XRP(0)), txflags(
tfSellNFToken), token::destination(minter));
3142 env(token::acceptSellOffer(minter, offerSellBack));
3145 BEAST_EXPECT(ownerCount(env, issuer) == issuerCount);
3146 BEAST_EXPECT(ownerCount(env, minter) == minterCount);
3147 BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
3157 env(token::createOffer(minter, nftokenID0, drops(1)), txflags(
tfSellNFToken));
3160 env(token::createOffer(minter, nftokenID1, drops(1)), txflags(
tfSellNFToken));
3163 env(token::createOffer(buyer, nftokenID0, drops(1)), token::expiration(expiration), token::owner(minter));
3166 env(token::createOffer(buyer, nftokenID1, drops(1)), token::expiration(expiration), token::owner(minter));
3169 BEAST_EXPECT(
lastClose(env) < expiration);
3170 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3171 BEAST_EXPECT(ownerCount(env, minter) == 3);
3172 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3175 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3181 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3182 BEAST_EXPECT(ownerCount(env, minter) == 2);
3183 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3185 env(token::brokerOffers(issuer, buyOffer1, sellOffer1), ter(
tecEXPIRED));
3188 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3189 if (features[fixExpiredNFTokenOfferRemoval])
3193 BEAST_EXPECT(ownerCount(env, minter) == 2);
3194 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3197 env(token::cancelOffer(minter, {sellOffer1}));
3202 BEAST_EXPECT(ownerCount(env, minter) == 2);
3203 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3205 env(token::cancelOffer(minter, {buyOffer1, sellOffer1}));
3208 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3209 BEAST_EXPECT(ownerCount(env, minter) == 1);
3210 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3215 env(token::createOffer(buyer, nftokenID0, XRP(0)), txflags(
tfSellNFToken), token::destination(minter));
3217 env(token::acceptSellOffer(minter, offerSellBack));
3219 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3220 BEAST_EXPECT(ownerCount(env, minter) == 1);
3221 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3232 env(token::createOffer(minter, nftokenID0, drops(1)),
3233 token::expiration(expiration),
3237 env(token::createOffer(minter, nftokenID1, drops(1)),
3238 token::expiration(expiration),
3242 env(token::createOffer(buyer, nftokenID0, drops(1)), token::expiration(expiration), token::owner(minter));
3245 env(token::createOffer(buyer, nftokenID1, drops(1)), token::expiration(expiration), token::owner(minter));
3248 BEAST_EXPECT(
lastClose(env) < expiration);
3249 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3250 BEAST_EXPECT(ownerCount(env, minter) == 3);
3251 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3254 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3260 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3261 BEAST_EXPECT(ownerCount(env, minter) == 2);
3262 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3264 env(token::brokerOffers(issuer, buyOffer1, sellOffer1), ter(
tecEXPIRED));
3268 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3269 if (!features[fixExpiredNFTokenOfferRemoval])
3272 BEAST_EXPECT(ownerCount(env, minter) == 2);
3273 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3275 env(token::cancelOffer(issuer, {buyOffer1, sellOffer1}));
3278 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3279 BEAST_EXPECT(ownerCount(env, minter) == 1);
3280 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3285 env(token::createOffer(buyer, nftokenID0, XRP(0)), txflags(
tfSellNFToken), token::destination(minter));
3287 env(token::acceptSellOffer(minter, offerSellBack));
3289 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3290 BEAST_EXPECT(ownerCount(env, minter) == 1);
3291 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3506 testcase(
"Brokered NFT offer accept");
3508 using namespace test::jtx;
3511 Env env{*
this, features};
3512 auto const baseFee = env.current()->fees().base;
3520 Account
const issuer{
"issuer"};
3521 Account
const minter{
"minter"};
3522 Account
const buyer{
"buyer"};
3523 Account
const broker{
"broker"};
3524 Account
const gw{
"gw"};
3525 IOU
const gwXAU(gw[
"XAU"]);
3527 env.fund(XRP(1000), issuer, minter, buyer, broker, gw);
3530 env(trust(issuer, gwXAU(2000)));
3531 env(trust(minter, gwXAU(2000)));
3532 env(trust(buyer, gwXAU(2000)));
3533 env(trust(broker, gwXAU(2000)));
3536 env(token::setMinter(issuer, minter));
3540 auto checkOwnerCountIsOne =
3542 for (Account
const& acct : accounts)
3547 ss <<
"Account " << acct.human() <<
" expected ownerCount == 1. Got " << ownerCount;
3548 fail(ss.
str(), __FILE__, line);
3554 auto mintNFT = [&env, &issuer, &minter](
std::uint16_t xferFee = 0) {
3556 env(token::mint(minter, 0), token::issuer(issuer), token::xferFee(xferFee), txflags(
tfTransferable));
3567 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3569 uint256 const nftID = mintNFT();
3573 env(token::createOffer(minter, nftID, XRP(0)), txflags(
tfSellNFToken));
3579 env(token::createOffer(buyer, nftID, XRP(1)), token::owner(minter));
3582 auto const minterBalance = env.balance(minter);
3583 auto const buyerBalance = env.balance(buyer);
3584 auto const brokerBalance = env.balance(broker);
3585 auto const issuerBalance = env.balance(issuer);
3588 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex));
3593 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(1));
3594 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3595 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
3596 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
3599 env(token::burn(buyer, nftID));
3609 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3611 uint256 const nftID = mintNFT();
3615 env(token::createOffer(minter, nftID, XRP(0)), txflags(
tfSellNFToken));
3621 env(token::createOffer(buyer, nftID, XRP(1)), token::owner(minter));
3625 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
3626 token::brokerFee(XRP(1.1)),
3630 auto const minterBalance = env.balance(minter);
3631 auto const buyerBalance = env.balance(buyer);
3632 auto const brokerBalance = env.balance(broker);
3633 auto const issuerBalance = env.balance(issuer);
3636 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), token::brokerFee(XRP(0.5)));
3641 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
3642 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3643 BEAST_EXPECT(env.balance(broker) == brokerBalance + XRP(0.5) - baseFee);
3644 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
3647 env(token::burn(buyer, nftID));
3657 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3663 env(token::createOffer(minter, nftID, XRP(0)), txflags(
tfSellNFToken));
3669 env(token::createOffer(buyer, nftID, XRP(1)), token::owner(minter));
3672 auto const minterBalance = env.balance(minter);
3673 auto const buyerBalance = env.balance(buyer);
3674 auto const brokerBalance = env.balance(broker);
3675 auto const issuerBalance = env.balance(issuer);
3678 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex));
3683 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
3684 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3685 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
3686 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.5));
3689 env(token::burn(buyer, nftID));
3699 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3705 env(token::createOffer(minter, nftID, XRP(0)), txflags(
tfSellNFToken));
3711 env(token::createOffer(buyer, nftID, XRP(1)), token::owner(minter));
3714 auto const minterBalance = env.balance(minter);
3715 auto const buyerBalance = env.balance(buyer);
3716 auto const brokerBalance = env.balance(broker);
3717 auto const issuerBalance = env.balance(issuer);
3720 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), token::brokerFee(XRP(0.75)));
3726 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.125));
3727 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3728 BEAST_EXPECT(env.balance(broker) == brokerBalance + XRP(0.75) - baseFee);
3729 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.125));
3732 env(token::burn(buyer, nftID));
3738 auto setXAUBalance =
3739 [
this, &gw, &gwXAU, &env](
3741 for (Account
const& acct : accounts)
3743 auto const xauAmt = gwXAU(amount);
3744 auto const balance = env.balance(acct, gwXAU);
3745 if (balance < xauAmt)
3747 env(pay(gw, acct, xauAmt - balance));
3750 else if (balance > xauAmt)
3752 env(pay(acct, gw, balance - xauAmt));
3755 if (env.balance(acct, gwXAU) != xauAmt)
3758 ss <<
"Unable to set " << acct.human() <<
" account balance to gwXAU(" << amount <<
")";
3759 this->
fail(ss.
str(), __FILE__, line);
3767 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3768 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
3770 uint256 const nftID = mintNFT();
3774 env(token::createOffer(minter, nftID, gwXAU(1000)), txflags(
tfSellNFToken));
3781 env(token::createOffer(buyer, nftID, gwXAU(1001)), token::owner(minter));
3790 env(token::cancelOffer(buyer, {buyOfferIndex}));
3797 env(token::createOffer(buyer, nftID, gwXAU(999)), token::owner(minter));
3806 env(token::cancelOffer(buyer, {buyOfferIndex}));
3812 env(token::createOffer(buyer, nftID, gwXAU(1000)), token::owner(minter));
3816 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
3817 token::brokerFee(gwXAU(0.1)),
3822 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex));
3825 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3826 BEAST_EXPECT(ownerCount(env, minter) == 1);
3827 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3828 BEAST_EXPECT(ownerCount(env, broker) == 1);
3829 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1000));
3830 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(2000));
3831 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
3832 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1000));
3835 env(token::burn(buyer, nftID));
3842 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3843 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
3849 env(token::createOffer(minter, nftID, gwXAU(900)), txflags(
tfSellNFToken));
3855 env(token::createOffer(buyer, nftID, gwXAU(1001)), token::owner(minter));
3864 env(token::cancelOffer(buyer, {buyOfferIndex}));
3871 env(token::createOffer(buyer, nftID, gwXAU(899)), token::owner(minter));
3880 env(token::cancelOffer(buyer, {buyOfferIndex}));
3885 env(token::createOffer(buyer, nftID, gwXAU(1000)), token::owner(minter));
3890 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
3891 token::brokerFee(gwXAU(101)),
3897 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), token::brokerFee(gwXAU(100)));
3900 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3901 BEAST_EXPECT(ownerCount(env, minter) == 1);
3902 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3903 BEAST_EXPECT(ownerCount(env, broker) == 1);
3904 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1450));
3905 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1450));
3906 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
3907 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1100));
3910 env(token::burn(buyer, nftID));
3917 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3918 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
3924 env(token::createOffer(minter, nftID, gwXAU(900)), txflags(
tfSellNFToken));
3929 env(token::createOffer(buyer, nftID, gwXAU(1000)), token::owner(minter));
3935 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), token::brokerFee(gwXAU(50)));
3938 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3939 BEAST_EXPECT(ownerCount(env, minter) == 1);
3940 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3941 BEAST_EXPECT(ownerCount(env, broker) == 1);
3942 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
3943 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
3944 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
3945 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1050));
3948 env(token::burn(buyer, nftID));
3953 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3954 setXAUBalance({issuer, minter, buyer}, 1000, __LINE__);
3955 setXAUBalance({broker}, 500, __LINE__);
3960 env(token::createOffer(minter, nftID, gwXAU(900)), txflags(
tfSellNFToken));
3965 env(token::createOffer(buyer, nftID, gwXAU(1000)), token::owner(minter));
3968 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), token::brokerFee(gwXAU(50)));
3970 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3971 BEAST_EXPECT(ownerCount(env, minter) == 1);
3972 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3973 BEAST_EXPECT(ownerCount(env, broker) == 1);
3974 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
3975 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
3976 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
3977 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(550));
3980 env(token::burn(buyer, nftID));
4521 using namespace test::jtx;
4523 testcase(
"Payments with IOU transfer fees");
4526 Env env{*
this, features};
4528 Account
const minter{
"minter"};
4529 Account
const secondarySeller{
"seller"};
4530 Account
const buyer{
"buyer"};
4531 Account
const gw{
"gateway"};
4532 Account
const broker{
"broker"};
4533 IOU
const gwXAU(gw[
"XAU"]);
4534 IOU
const gwXPB(gw[
"XPB"]);
4536 env.fund(XRP(1000), gw, minter, secondarySeller, buyer, broker);
4539 env(trust(minter, gwXAU(2000)));
4540 env(trust(secondarySeller, gwXAU(2000)));
4541 env(trust(broker, gwXAU(10000)));
4542 env(trust(buyer, gwXAU(2000)));
4543 env(trust(buyer, gwXPB(2000)));
4547 env(rate(gw, 1.02));
4550 auto expectInitialState = [
this, &env, &buyer, &minter, &secondarySeller, &broker, &gw, &gwXAU, &gwXPB]() {
4555 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(1000));
4556 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(0));
4557 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(0));
4558 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(0));
4559 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(0));
4560 BEAST_EXPECT(env.balance(secondarySeller, gwXPB) == gwXPB(0));
4561 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5000));
4562 BEAST_EXPECT(env.balance(broker, gwXPB) == gwXPB(0));
4563 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-1000));
4564 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(0));
4565 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(0));
4566 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(0));
4567 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(0));
4568 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XPB"]) == gwXPB(0));
4569 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5000));
4570 BEAST_EXPECT(env.balance(gw, broker[
"XPB"]) == gwXPB(0));
4573 auto reinitializeTrustLineBalances =
4574 [&expectInitialState, &env, &buyer, &minter, &secondarySeller, &broker, &gw, &gwXAU, &gwXPB]() {
4575 if (
auto const difference = gwXAU(1000) - env.balance(buyer, gwXAU); difference > gwXAU(0))
4576 env(pay(gw, buyer, difference));
4577 if (env.balance(buyer, gwXPB) > gwXPB(0))
4578 env(pay(buyer, gw, env.balance(buyer, gwXPB)));
4579 if (env.balance(minter, gwXAU) > gwXAU(0))
4580 env(pay(minter, gw, env.balance(minter, gwXAU)));
4581 if (env.balance(minter, gwXPB) > gwXPB(0))
4582 env(pay(minter, gw, env.balance(minter, gwXPB)));
4583 if (env.balance(secondarySeller, gwXAU) > gwXAU(0))
4584 env(pay(secondarySeller, gw, env.balance(secondarySeller, gwXAU)));
4585 if (env.balance(secondarySeller, gwXPB) > gwXPB(0))
4586 env(pay(secondarySeller, gw, env.balance(secondarySeller, gwXPB)));
4587 auto brokerDiff = gwXAU(5000) - env.balance(broker, gwXAU);
4588 if (brokerDiff > gwXAU(0))
4589 env(pay(gw, broker, brokerDiff));
4590 else if (brokerDiff < gwXAU(0))
4592 brokerDiff.negate();
4593 env(pay(broker, gw, brokerDiff));
4595 if (env.balance(broker, gwXPB) > gwXPB(0))
4596 env(pay(broker, gw, env.balance(broker, gwXPB)));
4598 expectInitialState();
4601 auto mintNFT = [&env](Account
const& minter,
int transferFee = 0) {
4603 env(token::mint(minter), token::xferFee(transferFee), txflags(
tfTransferable));
4608 auto createBuyOffer = [&env](
4609 Account
const& offerer,
4610 Account
const& owner,
4615 env(token::createOffer(offerer, nftID, amount),
4616 token::owner(owner),
4617 terCode ? ter(*terCode) : ter(
static_cast<TER>(
tesSUCCESS)));
4622 auto createSellOffer = [&env](
4623 Account
const& offerer,
4628 env(token::createOffer(offerer, nftID, amount),
4630 terCode ? ter(*terCode) : ter(
static_cast<TER>(
tesSUCCESS)));
4638 reinitializeTrustLineBalances();
4639 auto const nftID = mintNFT(minter);
4640 auto const offerID = createSellOffer(minter, nftID, gwXAU(1000));
4642 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
4645 expectInitialState();
4650 reinitializeTrustLineBalances();
4651 auto const nftID = mintNFT(minter);
4652 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(1000));
4654 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
4657 expectInitialState();
4663 reinitializeTrustLineBalances();
4664 auto const nftID = mintNFT(minter);
4665 auto const offerID = createSellOffer(minter, nftID, gwXAU(995));
4667 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
4670 expectInitialState();
4676 reinitializeTrustLineBalances();
4677 auto const nftID = mintNFT(minter);
4678 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(995));
4680 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
4683 expectInitialState();
4690 reinitializeTrustLineBalances();
4691 auto const nftID = mintNFT(minter);
4692 auto const offerID = createSellOffer(minter, nftID, gwXAU(900));
4693 env(token::acceptSellOffer(buyer, offerID));
4696 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
4697 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
4698 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
4699 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
4706 reinitializeTrustLineBalances();
4707 auto const nftID = mintNFT(minter);
4708 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(900));
4709 env(token::acceptBuyOffer(minter, offerID));
4712 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
4713 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
4714 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
4715 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
4722 reinitializeTrustLineBalances();
4725 env(pay(gw, buyer, gwXAU(20)));
4728 auto const nftID = mintNFT(minter);
4729 auto const offerID = createSellOffer(minter, nftID, gwXAU(1000));
4730 env(token::acceptSellOffer(buyer, offerID));
4733 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
4734 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4735 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
4736 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
4743 reinitializeTrustLineBalances();
4746 env(pay(gw, buyer, gwXAU(20)));
4749 auto const nftID = mintNFT(minter);
4750 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(1000));
4751 env(token::acceptBuyOffer(minter, offerID));
4754 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
4755 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4756 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
4757 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
4762 reinitializeTrustLineBalances();
4764 auto const nftID = mintNFT(minter);
4765 auto const offerID = createSellOffer(minter, nftID, gwXAU(1000));
4767 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
4770 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
4771 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
4776 reinitializeTrustLineBalances();
4778 auto const nftID = mintNFT(minter);
4780 auto const offerID = createBuyOffer(gw, minter, nftID, gwXAU(1000), {offerTER});
4782 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
4785 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
4786 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
4791 reinitializeTrustLineBalances();
4792 auto const nftID = mintNFT(minter);
4793 auto const offerID = createSellOffer(minter, nftID, gwXAU(5000));
4795 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
4798 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
4799 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
4804 reinitializeTrustLineBalances();
4806 auto const nftID = mintNFT(minter);
4808 auto const offerID = createBuyOffer(gw, minter, nftID, gwXAU(5000), {offerTER});
4810 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
4813 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
4814 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
4820 reinitializeTrustLineBalances();
4821 auto const nftID = mintNFT(gw);
4822 auto const offerID = createSellOffer(gw, nftID, gwXAU(1000));
4823 env(token::acceptSellOffer(buyer, offerID));
4826 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4827 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
4833 reinitializeTrustLineBalances();
4835 auto const nftID = mintNFT(gw);
4836 auto const offerID = createBuyOffer(buyer, gw, nftID, gwXAU(1000));
4837 env(token::acceptBuyOffer(gw, offerID));
4840 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4841 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
4847 reinitializeTrustLineBalances();
4848 auto const nftID = mintNFT(gw);
4849 auto const offerID = createSellOffer(gw, nftID, gwXAU(2000));
4852 expectInitialState();
4858 reinitializeTrustLineBalances();
4859 auto const nftID = mintNFT(gw);
4860 auto const offerID = createBuyOffer(buyer, gw, nftID, gwXAU(2000));
4863 expectInitialState();
4868 reinitializeTrustLineBalances();
4869 auto const nftID = mintNFT(minter);
4870 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
4873 expectInitialState();
4878 reinitializeTrustLineBalances();
4879 auto const nftID = mintNFT(minter);
4880 auto const offerID =
4884 expectInitialState();
4890 reinitializeTrustLineBalances();
4891 env(pay(gw, buyer, gwXPB(100)));
4894 auto const nftID = mintNFT(minter);
4895 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
4896 env(token::acceptSellOffer(buyer, offerID));
4899 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
4900 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
4901 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
4902 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
4908 reinitializeTrustLineBalances();
4909 env(pay(gw, buyer, gwXPB(100)));
4912 auto const nftID = mintNFT(minter);
4913 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXPB(10));
4914 env(token::acceptBuyOffer(minter, offerID));
4917 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
4918 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
4919 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
4920 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
4925 reinitializeTrustLineBalances();
4929 auto const nftID = mintNFT(minter, 3000);
4930 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
4931 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
4935 auto const offerID = createSellOffer(secondarySeller, nftID, gwXAU(1000));
4937 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
4940 expectInitialState();
4945 reinitializeTrustLineBalances();
4949 auto const nftID = mintNFT(minter, 3000);
4950 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
4951 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
4955 auto const offerID = createBuyOffer(buyer, secondarySeller, nftID, gwXAU(1000));
4957 env(token::acceptBuyOffer(secondarySeller, offerID), ter(sellTER));
4960 expectInitialState();
4965 reinitializeTrustLineBalances();
4969 auto const nftID = mintNFT(minter, 3000);
4970 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
4971 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
4975 auto const offerID = createSellOffer(secondarySeller, nftID, gwXAU(900));
4976 env(token::acceptSellOffer(buyer, offerID));
4979 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
4980 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
4981 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
4982 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
4983 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
4984 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
4989 reinitializeTrustLineBalances();
4993 auto const nftID = mintNFT(minter, 3000);
4994 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
4995 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
4999 auto const offerID = createBuyOffer(buyer, secondarySeller, nftID, gwXAU(900));
5000 env(token::acceptBuyOffer(secondarySeller, offerID));
5004 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5006 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5008 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5009 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5010 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5011 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5029 reinitializeTrustLineBalances();
5031 auto const nftID = mintNFT(minter);
5032 auto const sellOffer = createSellOffer(minter, nftID, gwXAU(300));
5033 auto const buyOffer = createBuyOffer(buyer, minter, nftID, gwXAU(500));
5034 env(token::brokerOffers(broker, buyOffer, sellOffer), token::brokerFee(gwXAU(100)));
5037 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(400));
5038 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5039 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5040 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-400));
5041 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5042 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5060 reinitializeTrustLineBalances();
5064 auto const nftID = mintNFT(minter, 3000);
5065 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
5066 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5070 auto const sellOffer = createSellOffer(secondarySeller, nftID, gwXAU(300));
5071 auto const buyOffer = createBuyOffer(buyer, secondarySeller, nftID, gwXAU(500));
5072 env(token::brokerOffers(broker, buyOffer, sellOffer), token::brokerFee(gwXAU(100)));
5075 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(12));
5076 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5077 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(388));
5078 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5079 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-12));
5080 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5081 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-388));
5082 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5175 using namespace test::jtx;
5180 auto openLedgerSeq = [](Env& env) {
return env.current()->seq(); };
5184 auto incLgrSeqForAcctDel = [&](Env& env, Account
const& acct) {
5185 int const delta = [&]() ->
int {
5186 if (env.seq(acct) + 255 > openLedgerSeq(env))
5187 return env.seq(acct) - openLedgerSeq(env) + 255;
5190 BEAST_EXPECT(delta >= 0);
5191 for (
int i = 0; i < delta; ++i)
5193 BEAST_EXPECT(openLedgerSeq(env) == env.seq(acct) + 255);
5198 auto incLgrSeqForFixNftRemint = [&](Env& env, Account
const& acct) {
5200 auto const deletableLgrSeq =
5201 (*env.le(acct))[~sfFirstNFTokenSequence].value_or(0) + (*env.le(acct))[sfMintedNFTokens] + 255;
5203 if (deletableLgrSeq > openLedgerSeq(env))
5204 delta = deletableLgrSeq - openLedgerSeq(env);
5206 BEAST_EXPECT(delta >= 0);
5207 for (
int i = 0; i < delta; ++i)
5209 BEAST_EXPECT(openLedgerSeq(env) == deletableLgrSeq);
5215 Env env{*
this, features};
5216 Account
const alice(
"alice");
5217 Account
const becky(
"becky");
5219 env.fund(XRP(10000), alice, becky);
5223 uint256 const prevNFTokenID = token::getNextID(env, alice, 0u);
5224 env(token::mint(alice));
5226 env(token::burn(alice, prevNFTokenID));
5230 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 1);
5233 incLgrSeqForAcctDel(env, alice);
5237 auto const acctDelFee{drops(env.current()->fees().increment)};
5238 env(acctdelete(alice, becky), fee(acctDelFee));
5243 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5244 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5247 env.fund(XRP(10000), alice);
5251 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5252 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5253 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5256 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5257 env(token::mint(alice));
5261 env(token::burn(alice, remintNFTokenID));
5265 BEAST_EXPECT(remintNFTokenID != prevNFTokenID);
5271 Env env{*
this, features};
5272 Account
const alice(
"alice");
5273 Account
const becky(
"becky");
5274 Account
const minter{
"minter"};
5276 env.fund(XRP(10000), alice, becky, minter);
5280 env(token::setMinter(alice, minter));
5286 for (
int i = 0; i < 500; i++)
5288 uint256 const nftokenID = token::getNextID(env, alice, 0u);
5290 env(token::mint(minter), token::issuer(alice));
5295 for (
auto const nftokenID : nftIDs)
5297 env(token::burn(minter, nftokenID));
5301 incLgrSeqForAcctDel(env, alice);
5305 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5306 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5308 auto const acctDelFee{drops(env.current()->fees().increment)};
5317 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
5321 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5326 incLgrSeqForFixNftRemint(env, alice);
5329 env(acctdelete(alice, becky), fee(acctDelFee));
5334 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5335 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5338 env.fund(XRP(10000), alice);
5342 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5343 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5344 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5348 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5349 env(token::mint(alice));
5353 env(token::burn(alice, remintNFTokenID));
5364 Env env{*
this, features};
5366 Account
const alice{
"alice"};
5367 Account
const becky{
"becky"};
5368 env.fund(XRP(10000), alice, becky);
5375 env(ticket::create(alice, 100));
5379 BEAST_EXPECT(ownerCount(env, alice) == 100);
5384 for (
int i = 0; i < 50; i++)
5386 nftIDs.
push_back(token::getNextID(env, alice, 0u));
5387 env(token::mint(alice, 0u), ticket::use(aliceTicketSeq++));
5392 for (
auto const nftokenID : nftIDs)
5394 env(token::burn(alice, nftokenID), ticket::use(aliceTicketSeq++));
5400 incLgrSeqForAcctDel(env, alice);
5404 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5405 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5407 auto const acctDelFee{drops(env.current()->fees().increment)};
5416 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
5420 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5425 incLgrSeqForFixNftRemint(env, alice);
5428 env(acctdelete(alice, becky), fee(acctDelFee));
5433 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5434 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5437 env.fund(XRP(10000), alice);
5441 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5442 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5443 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5447 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5448 env(token::mint(alice));
5452 env(token::burn(alice, remintNFTokenID));
5464 Env env{*
this, features};
5465 Account
const alice(
"alice");
5466 Account
const becky(
"becky");
5467 Account
const minter{
"minter"};
5469 env.fund(XRP(10000), alice, becky, minter);
5473 env(token::setMinter(alice, minter));
5478 env(ticket::create(minter, 100));
5482 BEAST_EXPECT(ownerCount(env, minter) == 100);
5487 for (
int i = 0; i < 50; i++)
5489 uint256 const nftokenID = token::getNextID(env, alice, 0u);
5491 env(token::mint(minter), token::issuer(alice), ticket::use(minterTicketSeq++));
5496 for (
auto const nftokenID : nftIDs)
5498 env(token::burn(minter, nftokenID), ticket::use(minterTicketSeq++));
5504 incLgrSeqForAcctDel(env, alice);
5508 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5509 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5518 auto const acctDelFee{drops(env.current()->fees().increment)};
5519 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
5523 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5528 incLgrSeqForFixNftRemint(env, alice);
5531 env(acctdelete(alice, becky), fee(acctDelFee));
5536 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5537 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5540 env.fund(XRP(10000), alice);
5544 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5545 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5546 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5550 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5551 env(token::mint(alice));
5555 env(token::burn(alice, remintNFTokenID));
5566 testcase(
"NFTokenMint with Create NFTokenOffer");
5568 using namespace test::jtx;
5570 if (!features[featureNFTokenMintOffer])
5572 Env env{*
this, features};
5573 Account
const alice(
"alice");
5574 Account
const buyer(
"buyer");
5576 env.fund(XRP(10000), alice, buyer);
5579 env(token::mint(alice), token::amount(XRP(10000)), ter(
temDISABLED));
5582 env(token::mint(alice), token::destination(
"buyer"), ter(
temDISABLED));
5593 Env env{*
this, features};
5594 auto const baseFee = env.current()->fees().base;
5595 Account
const alice(
"alice");
5596 Account
const buyer{
"buyer"};
5597 Account
const gw(
"gw");
5598 Account
const issuer(
"issuer");
5599 Account
const minter(
"minter");
5600 Account
const bob(
"bob");
5601 IOU
const gwAUD(gw[
"AUD"]);
5603 env.fund(XRP(10000), alice, buyer, gw, issuer, minter);
5608 env(token::mint(alice), token::destination(buyer), ter(
temMALFORMED));
5610 BEAST_EXPECT(ownerCount(env, alice) == 0);
5615 BEAST_EXPECT(ownerCount(env, buyer) == 0);
5621 env(token::mint(alice), token::amount(XRP(1000)), token::destination(alice), ter(
temMALFORMED));
5623 BEAST_EXPECT(ownerCount(env, alice) == 0);
5627 env(token::mint(alice), token::amount(XRP(1000)), token::destination(Account(
"demon")), ter(
tecNO_DST));
5629 BEAST_EXPECT(ownerCount(env, alice) == 0);
5634 env(token::mint(alice), token::amount(XRP(1000)), token::expiration(0), ter(
temBAD_EXPIRATION));
5636 BEAST_EXPECT(ownerCount(env, alice) == 0);
5639 env(token::mint(alice), token::amount(XRP(1000)), token::expiration(
lastClose(env)), ter(
tecEXPIRED));
5641 BEAST_EXPECT(ownerCount(env, alice) == 0);
5647 env(token::mint(alice), token::amount(buyer[
"USD"](0)), ter(
temBAD_AMOUNT));
5649 BEAST_EXPECT(ownerCount(env, alice) == 0);
5652 env(token::mint(alice),
5653 token::amount(gwAUD(1000)),
5658 BEAST_EXPECT(ownerCount(env, alice) == 0);
5663 env(token::mint(gw), token::amount(gwAUD(1000)), txflags(
tfTransferable), token::xferFee(10));
5672 env(token::mint(alice),
5673 token::amount(gwAUD(1000)),
5678 BEAST_EXPECT(ownerCount(env, alice) == 0);
5681 env(token::mint(alice), token::amount(gwAUD(1000)), ter(
tecFROZEN));
5683 BEAST_EXPECT(ownerCount(env, alice) == 0);
5692 auto const acctReserve = env.current()->fees().reserve;
5693 auto const incReserve = env.current()->fees().increment;
5695 env.fund(acctReserve + incReserve, bob);
5703 env(pay(env.master, bob, incReserve + drops(baseFee)));
5705 env(token::mint(bob), token::amount(XRP(0)));
5709 env(pay(env.master, bob, drops(baseFee)));
5715 env(pay(env.master, bob, incReserve + drops(baseFee)));
5717 env(token::mint(bob), token::amount(XRP(0)));
5722 BEAST_EXPECT(ownerCount(env, alice) == 0);
5723 env(token::mint(alice), token::amount(XRP(10)));
5724 BEAST_EXPECT(ownerCount(env, alice) == 2);
5728 env(token::mint(alice),
5729 token::amount(XRP(10)),
5730 token::destination(buyer),
5731 token::expiration(
lastClose(env) + 25));
5735 env(trust(alice, gwAUD(1000)));
5737 env(token::mint(alice),
5738 token::amount(gwAUD(1)),
5739 token::destination(buyer),
5742 token::xferFee(10));
5746 env(token::mint(alice),
5747 token::amount(XRP(10)),
5748 token::destination(buyer),
5749 token::expiration(
lastClose(env) + 25));
5751 env(token::cancelOffer(alice, {offerAliceSellsToBuyer}));
5755 env(token::mint(buyer),
5756 token::amount(XRP(10)),
5757 token::destination(alice),
5758 token::expiration(
lastClose(env) + 25));
5760 env(token::cancelOffer(alice, {offerBuyerSellsToAlice}));
5763 env(token::setMinter(issuer, minter));
5767 BEAST_EXPECT(ownerCount(env, minter) == 0);
5768 BEAST_EXPECT(ownerCount(env, issuer) == 0);
5769 env(token::mint(minter), token::issuer(issuer), token::amount(drops(1)));
5771 BEAST_EXPECT(ownerCount(env, minter) == 2);
5772 BEAST_EXPECT(ownerCount(env, issuer) == 0);
5775 Env env{*
this, features};
5776 Account
const alice(
"alice");
5778 env.fund(XRP(1000000), alice);
5783 env(token::mint(alice), token::amount(XRP(-2)), ter(offerCreateTER));
5801 testcase(
"Test synthetic fields from JSON response");
5803 using namespace test::jtx;
5805 Account
const alice{
"alice"};
5806 Account
const bob{
"bob"};
5807 Account
const broker{
"broker"};
5809 Env env{*
this, features};
5810 env.fund(XRP(10000), alice, bob, broker);
5816 auto verifyNFTokenID = [&](
uint256 const& actualNftID) {
5821 Json::Value const meta = env.rpc(
"tx", txHash)[jss::result][jss::meta];
5824 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_id)))
5831 BEAST_EXPECT(nftID == actualNftID);
5841 Json::Value const meta = env.rpc(
"tx", txHash)[jss::result][jss::meta];
5844 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_ids)))
5850 meta[jss::nftoken_ids].begin(),
5851 meta[jss::nftoken_ids].end(),
5855 BEAST_EXPECT(nftID.
parseHex(
id.asString()));
5861 std::sort(actualNftIDs.begin(), actualNftIDs.end());
5864 BEAST_EXPECT(metaIDs.
size() == actualNftIDs.size());
5868 for (
size_t i = 0; i < metaIDs.
size(); ++i)
5869 BEAST_EXPECT(metaIDs[i] == actualNftIDs[i]);
5874 auto verifyNFTokenOfferID = [&](
uint256 const& offerID) {
5879 Json::Value const meta = env.rpc(
"tx", txHash)[jss::result][jss::meta];
5882 if (!BEAST_EXPECT(meta.
isMember(jss::offer_id)))
5887 BEAST_EXPECT(metaOfferID == offerID);
5897 verifyNFTokenID(nftId1);
5902 verifyNFTokenID(nftId2);
5908 env(token::createOffer(alice, nftId1, drops(1)), txflags(
tfSellNFToken));
5910 verifyNFTokenOfferID(aliceOfferIndex1);
5913 env(token::createOffer(alice, nftId2, drops(1)), txflags(
tfSellNFToken));
5915 verifyNFTokenOfferID(aliceOfferIndex2);
5920 env(token::cancelOffer(alice, {aliceOfferIndex1, aliceOfferIndex2}));
5922 verifyNFTokenIDsInCancelOffer({nftId1, nftId2});
5927 env(token::createOffer(bob, nftId1, drops(1)), token::owner(alice));
5929 verifyNFTokenOfferID(bobBuyOfferIndex);
5933 env(token::acceptBuyOffer(alice, bobBuyOfferIndex));
5935 verifyNFTokenID(nftId1);
5944 verifyNFTokenID(nftId);
5948 env(token::createOffer(alice, nftId, drops(1)), token::destination(broker), txflags(
tfSellNFToken));
5950 verifyNFTokenOfferID(offerAliceToBroker);
5954 env(token::createOffer(bob, nftId, drops(1)), token::owner(alice));
5956 verifyNFTokenOfferID(offerBobToBroker);
5959 env(token::brokerOffers(broker, offerBobToBroker, offerAliceToBroker));
5961 verifyNFTokenID(nftId);
5971 verifyNFTokenID(nftId);
5975 env(token::createOffer(alice, nftId, drops(1)), txflags(
tfSellNFToken));
5977 verifyNFTokenOfferID(aliceOfferIndex1);
5980 env(token::createOffer(alice, nftId, drops(1)), txflags(
tfSellNFToken));
5982 verifyNFTokenOfferID(aliceOfferIndex2);
5986 env(token::cancelOffer(alice, {aliceOfferIndex1, aliceOfferIndex2}));
5988 verifyNFTokenIDsInCancelOffer({nftId});
5991 if (features[featureNFTokenMintOffer])
5994 env(token::mint(alice), token::amount(XRP(0)));
5996 verifyNFTokenOfferID(aliceMintWithOfferIndex1);
6003 testcase(
"Test buyer reserve when accepting an offer");
6005 using namespace test::jtx;
6008 auto mintAndCreateSellOffer =
6017 env(token::createOffer(acct, nftId, amt), txflags(
tfSellNFToken));
6020 return sellOfferIndex;
6027 Account
const alice{
"alice"};
6028 Account
const bob{
"bob"};
6030 Env env{*
this, features};
6031 auto const acctReserve = env.
current()->fees().reserve;
6032 auto const incReserve = env.
current()->fees().increment;
6033 auto const baseFee = env.
current()->fees().base;
6035 env.
fund(XRP(10000), alice);
6039 env.
fund(acctReserve, bob);
6043 auto const sellOfferIndex = mintAndCreateSellOffer(env, alice, XRP(0));
6046 BEAST_EXPECT(ownerCount(env, bob) == 0);
6050 if (!features[fixNFTokenReserve])
6053 env(token::acceptSellOffer(bob, sellOfferIndex));
6057 BEAST_EXPECT(ownerCount(env, bob) == 1);
6078 BEAST_EXPECT(ownerCount(env, bob) == 0);
6083 env(pay(env.
master, bob, incReserve + drops(baseFee)));
6093 env(pay(env.
master, bob, drops(baseFee * 2)));
6097 env(token::acceptSellOffer(bob, sellOfferIndex));
6100 BEAST_EXPECT(ownerCount(env, bob) == 1);
6107 Account
const alice{
"alice"};
6108 Account
const bob{
"bob"};
6110 Env env{*
this, features};
6111 auto const acctReserve = env.
current()->fees().reserve;
6112 auto const incReserve = env.
current()->fees().increment;
6114 env.
fund(XRP(10000), alice);
6117 env.
fund(acctReserve + XRP(1), bob);
6120 if (!features[fixNFTokenReserve])
6123 for (
size_t i = 0; i < 200; i++)
6126 auto const sellOfferIndex = mintAndCreateSellOffer(env, alice, XRP(0));
6129 env(token::acceptSellOffer(bob, sellOfferIndex));
6136 auto const sellOfferIndex1 = mintAndCreateSellOffer(env, alice, XRP(0));
6144 env(pay(env.
master, bob, drops(incReserve)));
6147 BEAST_EXPECT(ownerCount(env, bob) == 0);
6150 env(token::acceptSellOffer(bob, sellOfferIndex1));
6153 BEAST_EXPECT(ownerCount(env, bob) == 1);
6157 for (
size_t i = 0; i < 31; i++)
6160 auto const sellOfferIndex = mintAndCreateSellOffer(env, alice, XRP(0));
6164 env(token::acceptSellOffer(bob, sellOfferIndex));
6168 BEAST_EXPECT(ownerCount(env, bob) == 1);
6172 auto const sellOfferIndex33 = mintAndCreateSellOffer(env, alice, XRP(0));
6180 env(pay(env.
master, bob, drops(incReserve)));
6185 env(token::acceptSellOffer(bob, sellOfferIndex33));
6188 BEAST_EXPECT(ownerCount(env, bob) == 2);
6198 Account
const alice{
"alice"};
6199 Account
const bob{
"bob"};
6201 Env env{*
this, features};
6202 auto const acctReserve = env.
current()->fees().reserve;
6203 auto const incReserve = env.
current()->fees().increment;
6204 auto const baseFee = env.
current()->fees().base;
6206 env.
fund(XRP(10000), alice);
6212 env.
fund(acctReserve + incReserve + XRP(1), bob);
6222 env(token::createOffer(bob, nftId, XRP(1)), token::owner(alice));
6232 env(pay(env.
master, bob, drops(baseFee)));
6236 env(token::acceptBuyOffer(alice, buyOfferIndex));
6246 Account
const alice{
"alice"};
6247 Account
const bob{
"bob"};
6248 Account
const broker{
"broker"};
6250 Env env{*
this, features};
6251 auto const acctReserve = env.
current()->fees().reserve;
6252 auto const incReserve = env.
current()->fees().increment;
6253 auto const baseFee = env.
current()->fees().base;
6255 env.
fund(XRP(10000), alice, broker);
6260 env.
fund(acctReserve + incReserve + XRP(1), bob);
6270 env(token::createOffer(alice, nftId, XRP(1)), token::destination(broker), txflags(
tfSellNFToken));
6275 env(token::createOffer(bob, nftId, XRP(1)), token::owner(alice));
6286 env(pay(env.
master, bob, drops(baseFee)));
6290 env(token::brokerOffers(broker, offerBobToBroker, offerAliceToBroker));
6590 using namespace test::jtx;
6592 Account
const issuer{
"issuer"};
6593 Account
const alice(
"alice");
6594 Account
const bob(
"bob");
6596 bool const modifyEnabled = features[featureDynamicNFT];
6600 Env env{*
this, features};
6601 env.fund(XRP(10000), issuer);
6605 env(token::mint(issuer, 0u), txflags(
tfMutable), ter(expectedTer));
6609 Env env{*
this, features};
6610 env.fund(XRP(10000), issuer);
6617 env(token::mint(issuer, 0u), txflags(
tfMutable));
6619 BEAST_EXPECT(ownerCount(env, issuer) == 1);
6620 env(token::modify(issuer, nftId));
6621 BEAST_EXPECT(ownerCount(env, issuer) == 1);
6625 env(token::mint(issuer, 0u));
6627 env(token::modify(issuer, nftId), ter(
temDISABLED));
6635 Env env{*
this, features};
6636 env.fund(XRP(10000), issuer);
6640 env(token::mint(issuer, 0u), txflags(
tfMutable));
6648 env(token::modify(issuer, nftId), txflags(0x00000001), ter(
temINVALID_FLAG));
6651 env(token::modify(issuer, nftId), token::owner(issuer), ter(
temMALFORMED));
6655 env(token::modify(issuer, nftId), token::uri(
""), ter(
temMALFORMED));
6663 Env env{*
this, features};
6664 env.fund(XRP(10000), issuer, alice, bob);
6669 uint256 const nftIDNotExists{token::getNextID(env, issuer, 0u,
tfMutable)};
6672 env(token::modify(issuer, nftIDNotExists), ter(
tecNO_ENTRY));
6677 uint256 const nftIDNotModifiable{token::getNextID(env, issuer, 0u)};
6678 env(token::mint(issuer, 0u));
6687 env(token::mint(issuer, 0u), txflags(
tfMutable));
6690 env(token::modify(bob, nftId), token::owner(issuer), ter(
tecNO_PERMISSION));
6693 env(token::setMinter(issuer, alice));
6696 env(token::modify(bob, nftId), token::owner(issuer), ter(
tecNO_PERMISSION));
6701 Env env{*
this, features};
6702 env.fund(XRP(10000), issuer, alice, bob);
6707 env(token::mint(issuer, 0u), txflags(
tfMutable), token::uri(
"uri"));
6714 Env env{*
this, features};
6715 env.fund(XRP(10000), issuer, alice, bob);
6719 auto accountNFTs = [&env](Account
const& acct) {
6721 params[jss::account] = acct.human();
6722 params[jss::type] =
"state";
6723 auto response = env.rpc(
"json",
"account_nfts",
to_string(params));
6724 return response[jss::result][jss::account_nfts];
6728 auto checkURI = [&accountNFTs,
this](Account
const& acct,
char const* uri,
int line) {
6729 auto const nfts = accountNFTs(acct);
6730 if (nfts.size() == 1)
6735 text <<
"checkURI: unexpected NFT count on line " << line;
6736 fail(text.
str(), __FILE__, line);
6742 if (!nfts[0u].isMember(sfURI.jsonName))
6747 text <<
"checkURI: unexpected URI present on line " << line;
6748 fail(text.
str(), __FILE__, line);
6758 text <<
"checkURI: unexpected URI contents on line " << line;
6759 fail(text.
str(), __FILE__, line);
6766 env(token::mint(issuer, 0u), txflags(
tfMutable), token::uri(
"uri"));
6768 checkURI(issuer,
"uri", __LINE__);
6771 env(token::modify(issuer, nftId), token::uri(
"new_uri"));
6773 checkURI(issuer,
"new_uri", __LINE__);
6776 env(token::modify(issuer, nftId));
6778 checkURI(issuer,
nullptr, __LINE__);
6781 env(token::modify(issuer, nftId), token::uri(
"uri"));
6783 checkURI(issuer,
"uri", __LINE__);
6787 env(token::createOffer(issuer, nftId, XRP(0)), txflags(
tfSellNFToken));
6789 env(token::acceptSellOffer(alice, offerID));
6791 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6792 BEAST_EXPECT(ownerCount(env, alice) == 1);
6793 checkURI(alice,
"uri", __LINE__);
6796 env(token::modify(alice, nftId), token::uri(
"new_uri"), ter(
tecNO_PERMISSION));
6798 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6799 BEAST_EXPECT(ownerCount(env, alice) == 1);
6800 checkURI(alice,
"uri", __LINE__);
6802 env(token::modify(issuer, nftId), token::owner(alice), token::uri(
"new_uri"));
6804 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6805 BEAST_EXPECT(ownerCount(env, alice) == 1);
6806 checkURI(alice,
"new_uri", __LINE__);
6808 env(token::modify(issuer, nftId), token::owner(alice));
6810 checkURI(alice,
nullptr, __LINE__);
6812 env(token::modify(issuer, nftId), token::owner(alice), token::uri(
"uri"));
6814 checkURI(alice,
"uri", __LINE__);
6817 env(token::setMinter(issuer, bob));
6819 env(token::modify(bob, nftId), token::owner(alice), token::uri(
"new_uri"));
6821 checkURI(alice,
"new_uri", __LINE__);
6823 env(token::modify(bob, nftId), token::owner(alice));
6825 checkURI(alice,
nullptr, __LINE__);
6827 env(token::modify(bob, nftId), token::owner(alice), token::uri(
"uri"));
6829 checkURI(alice,
"uri", __LINE__);