181 Env env{*
this, features};
183 Account const minter{
"minter"};
187 auto const acctReserve = env.current()->fees().reserve;
188 auto const incReserve = env.current()->fees().increment;
189 auto const baseFee = env.current()->fees().base;
191 env.fund(acctReserve, alice, minter);
194 BEAST_EXPECT(env.balance(alice) == acctReserve);
195 BEAST_EXPECT(env.balance(minter) == acctReserve);
209 env(pay(env.master, alice, incReserve + drops(baseFee - 1)));
214 auto checkAliceOwnerMintedBurned = [&env,
this, &alice](
227 ss <<
"Wrong " << type <<
" count. Found: " << found <<
"; Expected: " << exp;
228 fail(ss.
str(), __FILE__, line);
231 oneCheck(
"owner",
ownerCount(env, alice), owners);
232 oneCheck(
"minted",
mintedCount(env, alice), minted);
233 oneCheck(
"burned",
burnedCount(env, alice), burned);
241 checkAliceOwnerMintedBurned(0, 0, 0, __LINE__);
244 env(pay(env.master, alice, drops(baseFee + 1)));
248 env(token::mint(alice));
251 checkAliceOwnerMintedBurned(1, 1, 0, __LINE__);
255 for (
int i = 1; i < 32; ++i)
257 env(token::mint(alice));
258 checkAliceOwnerMintedBurned(1, i + 1, 0, __LINE__);
265 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
268 env(pay(env.master, alice, incReserve + drops(baseFee * 33 - 1)));
275 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
278 env(pay(env.master, alice, drops(baseFee + 1)));
282 env(token::mint(alice));
284 checkAliceOwnerMintedBurned(2, 33, 0, __LINE__);
291 env(token::burn(alice, token::getID(env, alice, 0, seq++)));
293 checkAliceOwnerMintedBurned(((33 - seq) != 0u) ? 1 : 0, 33, seq, __LINE__);
297 env(token::burn(alice, token::getID(env, alice, 197, 5)), Ter(
tecNO_ENTRY));
299 checkAliceOwnerMintedBurned(0, 33, 33, __LINE__);
304 env(token::setMinter(alice, minter));
306 BEAST_EXPECT(env.le(alice)->getAccountID(sfNFTokenMinter) == minter.id());
310 auto checkMintersOwnerMintedBurned = [&env,
this, &alice, &minter](
327 ss <<
"Wrong " << type <<
" count. Found: " << found
328 <<
"; Expected: " << exp;
329 fail(ss.
str(), __FILE__, line);
332 oneCheck(
"alice owner",
ownerCount(env, alice), aliceOwners, line);
333 oneCheck(
"alice minted",
mintedCount(env, alice), aliceMinted, line);
334 oneCheck(
"alice burned",
burnedCount(env, alice), aliceBurned, line);
335 oneCheck(
"minter owner",
ownerCount(env, minter), minterOwners, line);
336 oneCheck(
"minter minted",
mintedCount(env, minter), minterMinted, line);
337 oneCheck(
"minter burned",
burnedCount(env, minter), minterBurned, line);
343 env(pay(env.master, minter, incReserve - drops(1)));
345 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
350 env(token::mint(minter),
351 token::Issuer(alice),
355 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
358 env(pay(env.master, minter, drops(baseFee + 1)));
362 env(token::mint(minter), token::Issuer(alice), token::Uri(
"uri"));
364 checkMintersOwnerMintedBurned(0, 34, nftSeq, 1, 0, 0, __LINE__);
368 for (
int i = 1; i < 32; ++i)
370 env(token::mint(minter), token::Issuer(alice), token::Uri(
"uri"));
371 checkMintersOwnerMintedBurned(0, i + 34, nftSeq, 1, 0, 0, __LINE__);
376 env(pay(env.master, minter, incReserve + drops(baseFee * 32 - 1)));
381 env(token::mint(minter),
382 token::Issuer(alice),
386 checkMintersOwnerMintedBurned(0, 65, nftSeq, 1, 0, 0, __LINE__);
389 env(pay(env.master, minter, drops(baseFee + 1)));
393 env(token::mint(minter), token::Issuer(alice), token::Uri(
"uri"));
395 checkMintersOwnerMintedBurned(0, 66, nftSeq, 2, 0, 0, __LINE__);
400 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
402 checkMintersOwnerMintedBurned(
403 0, 66, nftSeq, ((65 - seq) != 0u) ? 1 : 0, 0, 0, __LINE__);
408 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
410 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
413 env(token::burn(minter, token::getID(env, alice, 2009, 3)), Ter(
tecNO_ENTRY));
415 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
603 testcase(
"Invalid NFT offer create");
607 Env env{*
this, features};
611 IOU
const gwAUD(gw[
"AUD"]);
616 env.fund(XRP(250), alice, buyer, gw);
620 uint256 const nftAlice0ID = token::getNextID(env, alice, 0, tfTransferable, 10);
621 env(token::mint(alice, 0u), Txflags(tfTransferable), token::XferFee(10));
625 uint256 const nftXrpOnlyID = token::getNextID(env, alice, 0, tfOnlyXRP | tfTransferable);
626 env(token::mint(alice, 0), Txflags(tfOnlyXRP | tfTransferable));
630 uint256 const nftNoXferID = token::getNextID(env, alice, 0);
631 env(token::mint(alice, 0));
644 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
651 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
658 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
665 env(token::createOffer(buyer, nftXrpOnlyID, buyer[
"USD"](1)), Ter(
temBAD_AMOUNT));
666 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](0)), Ter(
temBAD_AMOUNT));
667 env(token::createOffer(buyer, nftXrpOnlyID, drops(0)), Ter(
temBAD_AMOUNT));
672 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](1)),
673 token::Expiration(0),
680 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)), Ter(
temMALFORMED));
685 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
687 Txflags(tfSellNFToken),
693 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
700 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
701 token::Destination(alice),
702 Txflags(tfSellNFToken),
708 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
709 token::Destination(
Account(
"demon")),
710 Txflags(tfSellNFToken),
719 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
727 env(token::createOffer(buyer, token::getID(env, alice, 0, 1), XRP(1000)),
734 env(token::createOffer(alice, token::getID(env, alice, 0, 1), XRP(1000)),
735 Txflags(tfSellNFToken),
741 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
747 env(trust(buyer, gwAUD(1000)));
753 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
760 env(trust(gw, alice[
"AUD"](999), tfSetFreeze));
765 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
772 env(trust(gw, alice[
"AUD"](999), tfClearFreeze));
776 env(token::createOffer(buyer, nftNoXferID, gwAUD(1000)),
783 env(trust(gw, buyer[
"AUD"](999), tfSetFreeze));
786 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
794 env(trust(gw, buyer[
"AUD"](999), tfClearFreeze));
795 env(trust(buyer, gwAUD(1000)));
798 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
808 env(pay(gw, buyer, gwAUD(999)));
813 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
820 auto const baseFee = env.current()->fees().base;
821 env(pay(env.master, buyer, XRP(50) + drops(baseFee * 12 - 1)));
824 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
831 env(pay(env.master, buyer, drops(baseFee + 1)));
836 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
981 testcase(
"Invalid NFT offer accept");
985 Env env{*
this, features};
989 IOU
const gwAUD(gw[
"AUD"]);
991 env.fund(XRP(1000), alice, buyer, gw);
996 uint256 const nftAlice0ID = token::getNextID(env, alice, 0, tfTransferable);
997 env(token::mint(alice, 0u), Txflags(tfTransferable));
999 uint8_t aliceCount = 1;
1000 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1002 uint256 const nftXrpOnlyID = token::getNextID(env, alice, 0, tfOnlyXRP | tfTransferable);
1003 env(token::mint(alice, 0), Txflags(tfOnlyXRP | tfTransferable));
1005 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1007 uint256 const nftNoXferID = token::getNextID(env, alice, 0);
1008 env(token::mint(alice, 0));
1010 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1013 uint256 const plainOfferIndex =
1015 env(token::createOffer(alice, nftAlice0ID, XRP(10)), Txflags(tfSellNFToken));
1018 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1022 env(token::createOffer(alice, nftAlice0ID, gwAUD(30)), Txflags(tfSellNFToken));
1025 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1027 uint256 const xrpOnlyOfferIndex =
1029 env(token::createOffer(alice, nftXrpOnlyID, XRP(20)), Txflags(tfSellNFToken));
1032 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1034 uint256 const noXferOfferIndex =
1036 env(token::createOffer(alice, nftNoXferID, XRP(30)), Txflags(tfSellNFToken));
1039 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1042 uint256 const aliceExpOfferIndex =
1044 env(token::createOffer(alice, nftNoXferID, XRP(40)),
1045 Txflags(tfSellNFToken),
1049 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1052 uint256 const buyerExpOfferIndex =
1054 env(token::createOffer(buyer, nftAlice0ID, XRP(40)),
1055 token::Owner(alice),
1058 uint8_t buyerCount = 1;
1059 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1065 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1069 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1072 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1073 Txflags(0x00008000),
1076 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1080 json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1084 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1089 json::Value jv = token::acceptBuyOffer(buyer, noXferOfferIndex);
1093 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1098 json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1102 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1106 env(token::brokerOffers(buyer, noXferOfferIndex, xrpOnlyOfferIndex),
1107 token::BrokerFee(gwAUD(0)),
1110 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1118 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1124 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1128 env(token::acceptBuyOffer(alice, buyerExpOfferIndex), Ter(
tecEXPIRED));
1130 if (features[fixCleanup3_1_3])
1135 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1140 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1145 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1149 env(token::acceptSellOffer(buyer, aliceExpOfferIndex), Ter(
tecEXPIRED));
1154 if (features[fixCleanup3_1_3])
1159 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1160 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1167 env(trust(alice, gwAUD(1000)));
1168 env(trust(buyer, gwAUD(1000)));
1170 env(pay(gw, buyer, gwAUD(30)));
1174 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1175 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1177 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1178 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1184 uint256 const buyerOfferIndex =
1186 env(token::createOffer(buyer, nftAlice0ID, gwAUD(29)), token::Owner(alice));
1189 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1192 env(token::brokerOffers(gw, buyerOfferIndex, xrpOnlyOfferIndex),
1195 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1198 env(token::brokerOffers(gw, buyerOfferIndex, plainOfferIndex),
1201 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1205 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1208 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1211 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1214 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1218 uint256 const buyerOfferIndex =
1220 env(token::createOffer(buyer, nftAlice0ID, gwAUD(31)), token::Owner(alice));
1223 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1227 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1228 token::BrokerFee(XRP(40)),
1231 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1234 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1235 token::BrokerFee(gwAUD(31)),
1238 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1242 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1243 token::BrokerFee(gwAUD(1.5)),
1246 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1249 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1252 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1258 uint256 const buyerOfferIndex =
1260 env(token::createOffer(buyer, nftAlice0ID, gwAUD(30)), token::Owner(alice));
1263 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1268 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1271 env(token::acceptBuyOffer(buyer, buyerOfferIndex),
1274 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1277 env(pay(buyer, gw, gwAUD(30)));
1279 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1282 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1288 env(token::createOffer(alice, nftAlice0ID, XRP(0)), Txflags(tfSellNFToken));
1290 env(token::acceptSellOffer(gw, offerIndex));
1292 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1294 env(pay(gw, buyer, gwAUD(30)));
1300 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1303 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1306 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1312 uint256 const buyerOfferIndex =
1314 env(token::createOffer(buyer, nftXrpOnlyID, XRP(30)), token::Owner(alice));
1317 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1320 env(token::acceptSellOffer(alice, buyerOfferIndex),
1323 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1326 env(token::acceptSellOffer(alice, plainOfferIndex),
1329 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1333 env(token::acceptSellOffer(buyer, plainOfferIndex), Ter(
tecNO_PERMISSION));
1335 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1343 env(token::createOffer(gw, nftAlice0ID, XRP(0)), Txflags(tfSellNFToken));
1345 env(token::acceptSellOffer(alice, offerIndex));
1347 BEAST_EXPECT(
ownerCount(env, alice) == aliceCount);
1349 env(pay(buyer, gw, gwAUD(30)));
1351 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1354 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
1563 testcase(
"Mint flagCreateTrustLines");
1571 IOU
const gwAUD(gw[
"AUD"]);
1572 IOU
const gwCAD(gw[
"CAD"]);
1573 IOU
const gwEUR(gw[
"EUR"]);
1578 for (
auto const& tweakedFeatures :
1579 {features - fixRemoveNFTokenAutoTrustLine, features | fixRemoveNFTokenAutoTrustLine})
1581 Env env{*
this, tweakedFeatures};
1582 env.fund(XRP(1000), alice, becky, cheri, gw);
1586 env(trust(becky, gwAUD(1000)));
1587 env(trust(cheri, gwAUD(1000)));
1588 env(trust(becky, gwCAD(1000)));
1589 env(trust(cheri, gwCAD(1000)));
1590 env(trust(becky, gwEUR(1000)));
1591 env(trust(cheri, gwEUR(1000)));
1593 env(pay(gw, becky, gwAUD(500)));
1594 env(pay(gw, becky, gwCAD(500)));
1595 env(pay(gw, becky, gwEUR(500)));
1596 env(pay(gw, cheri, gwAUD(500)));
1597 env(pay(gw, cheri, gwCAD(500)));
1604 uint256 const nftNoAutoTrustID{
1605 token::getNextID(env, alice, 0u, tfTransferable, xferFee)};
1606 env(token::mint(alice, 0u), token::XferFee(xferFee), Txflags(tfTransferable));
1610 uint256 const beckyBuyOfferIndex =
1612 env(token::createOffer(becky, nftNoAutoTrustID, drops(1)), token::Owner(alice));
1614 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1619 uint256 const beckyOfferIndex =
1621 env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)),
1622 Txflags(tfSellNFToken),
1623 Ter(createOfferTER));
1627 uint256 const cheriOfferIndex =
1629 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
1630 token::Owner(becky),
1631 Ter(createOfferTER));
1635 env(token::cancelOffer(becky, {beckyOfferIndex}));
1636 env(token::cancelOffer(cheri, {cheriOfferIndex}));
1645 token::getNextID(env, alice, 0u, tfTransferable |
tfTrustLine, transferFee)};
1650 TER const mintTER = tweakedFeatures[fixRemoveNFTokenAutoTrustLine]
1654 env(token::mint(alice, 0u),
1655 token::XferFee(transferFee),
1662 if (tweakedFeatures[fixRemoveNFTokenAutoTrustLine])
1666 uint256 const beckyBuyOfferIndex =
1668 env(token::createOffer(becky, nftAutoTrustID, drops(1)), token::Owner(alice));
1670 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1674 uint256 const beckySellOfferIndex =
1676 env(token::createOffer(becky, nftAutoTrustID, gwAUD(100)), Txflags(tfSellNFToken));
1678 env(token::acceptSellOffer(cheri, beckySellOfferIndex));
1682 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1685 uint256 const beckyBuyBackOfferIndex =
1687 env(token::createOffer(becky, nftAutoTrustID, gwCAD(50)), token::Owner(cheri));
1689 env(token::acceptBuyOffer(cheri, beckyBuyBackOfferIndex));
1693 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1694 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(5));
1700 uint256 const nftNoAutoTrustID{
1701 token::getNextID(env, alice, 0u, tfTransferable, transferFee)};
1702 env(token::mint(alice, 0u), token::XferFee(transferFee), Txflags(tfTransferable));
1706 uint256 const aliceSellOfferIndex =
1708 env(token::createOffer(alice, nftNoAutoTrustID, gwAUD(200)),
1709 Txflags(tfSellNFToken));
1711 env(token::acceptSellOffer(cheri, aliceSellOfferIndex));
1717 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(210));
1720 env(token::createOffer(cheri, nftNoAutoTrustID, gwEUR(50)),
1721 Txflags(tfSellNFToken),
1724 uint256 const cheriSellOfferIndex =
1726 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
1727 Txflags(tfSellNFToken));
1729 env(token::acceptSellOffer(becky, cheriSellOfferIndex));
1735 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(10));
1748 Env env{*
this, features};
1752 Account const minter{
"minter"};
1754 env.fund(XRP(1000), alice, becky, minter);
1760 uint256 const nftAliceNoTransferID{token::getNextID(env, alice, 0u)};
1761 env(token::mint(alice, 0u), token::XferFee(0));
1767 env(token::createOffer(becky, nftAliceNoTransferID, XRP(20)),
1768 token::Owner(alice),
1772 uint256 const aliceSellOfferIndex =
1774 env(token::createOffer(alice, nftAliceNoTransferID, XRP(20)), Txflags(tfSellNFToken));
1776 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1782 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1783 Txflags(tfSellNFToken),
1791 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1792 Txflags(tfSellNFToken),
1793 token::Destination(alice),
1801 uint256 const aliceBuyOfferIndex =
1803 env(token::createOffer(alice, nftAliceNoTransferID, XRP(22)), token::Owner(becky));
1805 env(token::acceptBuyOffer(becky, aliceBuyOfferIndex));
1811 env(token::burn(alice, nftAliceNoTransferID));
1818 env(token::setMinter(alice, minter));
1822 uint256 const nftMinterNoTransferID{token::getNextID(env, alice, 0u)};
1823 env(token::mint(minter), token::Issuer(alice));
1829 env(token::createOffer(becky, nftMinterNoTransferID, XRP(20)),
1830 token::Owner(minter),
1836 env(token::clearMinter(alice));
1841 env(token::createOffer(minter, nftMinterNoTransferID, XRP(21)),
1842 Txflags(tfSellNFToken),
1849 for (
int i = 0; i < 10; ++i)
1852 env(token::setMinter(alice, minter));
1858 uint256 const minterSellOfferIndex =
1860 env(token::createOffer(minter, nftMinterNoTransferID, XRP(22)), Txflags(tfSellNFToken));
1866 env(token::clearMinter(alice));
1872 env(token::acceptSellOffer(becky, minterSellOfferIndex));
1878 env(token::createOffer(becky, nftMinterNoTransferID, XRP(23)),
1879 Txflags(tfSellNFToken),
1886 env(token::createOffer(minter, nftMinterNoTransferID, XRP(24)),
1887 token::Owner(becky),
1894 uint256 const aliceBuyOfferIndex =
1896 env(token::createOffer(alice, nftMinterNoTransferID, XRP(25)), token::Owner(becky));
1902 for (
int i = 0; i < 10; ++i)
1905 env(token::setMinter(alice, minter));
1910 uint256 const minterBuyOfferIndex =
1912 env(token::createOffer(minter, nftMinterNoTransferID, XRP(26)), token::Owner(becky));
1918 env(token::clearMinter(alice));
1924 env(token::acceptBuyOffer(becky, minterBuyOfferIndex));
1932 env(token::burn(minter, nftMinterNoTransferID), Ter(
tesSUCCESS));
1934 env(token::cancelOffer(alice, {aliceBuyOfferIndex}));
1944 uint256 const nftAliceID{token::getNextID(env, alice, 0u, tfTransferable)};
1945 env(token::mint(alice, 0u), Txflags(tfTransferable));
1950 uint256 const aliceSellOfferIndex =
1952 env(token::createOffer(alice, nftAliceID, XRP(20)), Txflags(tfSellNFToken));
1956 uint256 const beckyBuyOfferIndex =
1958 env(token::createOffer(becky, nftAliceID, XRP(21)), token::Owner(alice));
1963 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1969 uint256 const beckySellOfferIndex =
1971 env(token::createOffer(becky, nftAliceID, XRP(22)), Txflags(tfSellNFToken));
1978 env(token::acceptSellOffer(minter, beckySellOfferIndex));
1985 uint256 const minterSellOfferIndex =
1987 env(token::createOffer(minter, nftAliceID, XRP(23)), Txflags(tfSellNFToken));
1994 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2002 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2010 env(token::burn(becky, nftAliceID));
2026 Env env{*
this, features};
2027 auto const baseFee = env.current()->fees().base;
2032 Account const minter{
"minter"};
2034 IOU
const gwXAU(gw[
"XAU"]);
2036 env.fund(XRP(1000), alice, becky, carol, minter, gw);
2039 env(trust(alice, gwXAU(2000)));
2040 env(trust(becky, gwXAU(2000)));
2041 env(trust(carol, gwXAU(2000)));
2042 env(trust(minter, gwXAU(2000)));
2044 env(pay(gw, alice, gwXAU(1000)));
2045 env(pay(gw, becky, gwXAU(1000)));
2046 env(pay(gw, carol, gwXAU(1000)));
2047 env(pay(gw, minter, gwXAU(1000)));
2052 env(token::setMinter(alice, minter));
2063 uint256 const nftID = token::getNextID(env, alice, 0u, tfTransferable);
2064 env(token::mint(alice), Txflags(tfTransferable));
2068 uint256 const beckyBuyOfferIndex =
2070 env(token::createOffer(becky, nftID, gwXAU(10)), token::Owner(alice));
2072 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2073 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2075 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2077 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2078 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2081 uint256 const beckySellOfferIndex =
2083 env(token::createOffer(becky, nftID, gwXAU(10)), Txflags(tfSellNFToken));
2085 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2087 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2088 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2089 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2092 uint256 const minterBuyOfferIndex =
2094 env(token::createOffer(minter, nftID, gwXAU(10)), token::Owner(carol));
2096 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2098 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2099 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2100 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2101 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2105 uint256 const minterSellOfferIndex =
2107 env(token::createOffer(minter, nftID, gwXAU(10)), Txflags(tfSellNFToken));
2109 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2111 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2112 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2113 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2114 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2117 env(token::burn(alice, nftID));
2128 uint256 const nftID = token::getNextID(env, alice, 0u, tfTransferable, 1);
2129 env(token::mint(alice), Txflags(tfTransferable), token::XferFee(1));
2133 uint256 const beckyBuyOfferIndex =
2135 env(token::createOffer(becky, nftID, gwXAU(10)), token::Owner(alice));
2137 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2138 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2140 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2142 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2143 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2146 uint256 const beckySellOfferIndex =
2148 env(token::createOffer(becky, nftID, gwXAU(10)), Txflags(tfSellNFToken));
2150 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2153 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0001));
2154 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2155 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2158 uint256 const minterBuyOfferIndex =
2160 env(token::createOffer(minter, nftID, gwXAU(10)), token::Owner(carol));
2162 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2165 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0002));
2166 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2167 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2168 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2172 uint256 const minterSellOfferIndex =
2174 env(token::createOffer(minter, nftID, gwXAU(10)), Txflags(tfSellNFToken));
2176 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2178 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000.0002));
2179 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2180 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2181 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2185 env(pay(alice, becky, gwXAU(0.0001)));
2186 env(pay(alice, carol, gwXAU(0.0001)));
2189 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2190 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2191 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2192 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2195 env(token::burn(alice, nftID));
2206 env(token::mint(alice),
2207 Txflags(tfTransferable),
2214 env(token::mint(alice), Txflags(tfTransferable), token::XferFee(
kMaxTransferFee));
2218 uint256 const beckyBuyOfferIndex =
2220 env(token::createOffer(becky, nftID, gwXAU(10)), token::Owner(alice));
2222 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2223 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2225 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2227 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2228 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2231 uint256 const beckySellOfferIndex =
2233 env(token::createOffer(becky, nftID, gwXAU(100)), Txflags(tfSellNFToken));
2235 env(token::acceptSellOffer(minter, beckySellOfferIndex));
2238 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1060));
2239 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2240 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
2243 uint256 const carolBuyOfferIndex =
2245 env(token::createOffer(carol, nftID, gwXAU(10)), token::Owner(minter));
2247 env(token::acceptBuyOffer(minter, carolBuyOfferIndex));
2250 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1065));
2251 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2252 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2253 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2257 uint256 const carolSellOfferIndex =
2259 env(token::createOffer(carol, nftID, gwXAU(10)), Txflags(tfSellNFToken));
2261 env(token::acceptSellOffer(alice, carolSellOfferIndex));
2264 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1055));
2265 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2266 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2267 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2270 env(pay(alice, minter, gwXAU(55)));
2271 env(pay(becky, minter, gwXAU(40)));
2273 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2274 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2275 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2276 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2279 env(token::burn(alice, nftID));
2291 uint256 const nftID = token::getNextID(env, alice, 0u, tfTransferable, 1);
2292 env(token::mint(alice), Txflags(tfTransferable), token::XferFee(1));
2297 STAmount aliceBalance = env.balance(alice);
2298 STAmount minterBalance = env.balance(minter);
2299 uint256 const minterBuyOfferIndex =
2301 env(token::createOffer(minter, nftID, XRP(1)), token::Owner(alice));
2303 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2305 aliceBalance += XRP(1) - baseFee;
2306 minterBalance -= XRP(1) + baseFee;
2307 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2308 BEAST_EXPECT(env.balance(minter) == minterBalance);
2312 auto pmt = drops(50000);
2313 STAmount carolBalance = env.balance(carol);
2314 uint256 const minterSellOfferIndex =
2316 env(token::createOffer(minter, nftID, pmt), Txflags(tfSellNFToken));
2318 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2320 minterBalance += pmt - baseFee;
2321 carolBalance -= pmt + baseFee;
2322 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2323 BEAST_EXPECT(env.balance(minter) == minterBalance);
2324 BEAST_EXPECT(env.balance(carol) == carolBalance);
2328 STAmount beckyBalance = env.balance(becky);
2329 uint256 const beckyBuyOfferIndex =
2332 env(token::createOffer(becky, nftID, pmt), token::Owner(carol));
2334 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2336 carolBalance += pmt - drops(1) - baseFee;
2337 beckyBalance -= pmt + baseFee;
2338 aliceBalance += drops(1);
2340 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2341 BEAST_EXPECT(env.balance(minter) == minterBalance);
2342 BEAST_EXPECT(env.balance(carol) == carolBalance);
2343 BEAST_EXPECT(env.balance(becky) == beckyBalance);
2350 uint256 const nftID = token::getNextID(env, alice, 0u, tfTransferable, 1);
2351 env(token::mint(alice), Txflags(tfTransferable), token::XferFee(1));
2357 env(pay(alice, gw, env.balance(alice, gwXAU)));
2358 env(pay(minter, gw, env.balance(minter, gwXAU)));
2359 env(pay(becky, gw, env.balance(becky, gwXAU)));
2363 env(pay(gw, alice, startXAUBalance));
2364 env(pay(gw, minter, startXAUBalance));
2365 env(pay(gw, becky, startXAUBalance));
2373 STAmount aliceBalance = env.balance(alice, gwXAU);
2374 STAmount minterBalance = env.balance(minter, gwXAU);
2375 uint256 const minterBuyOfferIndex =
2377 env(token::createOffer(minter, nftID, tinyXAU), token::Owner(alice));
2379 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2381 aliceBalance += tinyXAU;
2382 minterBalance -= tinyXAU;
2383 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2384 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2387 STAmount carolBalance = env.balance(carol, gwXAU);
2388 uint256 const minterSellOfferIndex =
2390 env(token::createOffer(minter, nftID, tinyXAU), Txflags(tfSellNFToken));
2392 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2395 minterBalance += tinyXAU;
2396 carolBalance -= tinyXAU;
2398 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2399 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2400 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2406 STAmount beckyBalance = env.balance(becky, gwXAU);
2407 uint256 const beckyBuyOfferIndex =
2409 env(token::createOffer(becky, nftID, cheapNFT), token::Owner(carol));
2411 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2414 aliceBalance += tinyXAU;
2415 beckyBalance -= cheapNFT;
2416 carolBalance += cheapNFT - tinyXAU;
2417 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2418 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2419 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2420 BEAST_EXPECT(env.balance(becky, gwXAU) == beckyBalance);
2613 testcase(
"Create offer destination");
2617 Env env{*
this, features};
2619 Account const issuer{
"issuer"};
2620 Account const minter{
"minter"};
2622 Account const broker{
"broker"};
2624 env.fund(XRP(1000), issuer, minter, buyer, broker);
2628 env(token::setMinter(issuer, minter));
2631 uint256 const nftokenID = token::getNextID(env, issuer, 0, tfTransferable);
2632 env(token::mint(minter, 0), token::Issuer(issuer), Txflags(tfTransferable));
2638 uint256 const offerMinterToIssuer =
2640 env(token::createOffer(minter, nftokenID, drops(1)),
2641 token::Destination(issuer),
2642 Txflags(tfSellNFToken));
2644 uint256 const offerMinterToBuyer =
2646 env(token::createOffer(minter, nftokenID, drops(1)),
2647 token::Destination(buyer),
2648 Txflags(tfSellNFToken));
2650 uint256 const offerIssuerToMinter =
2652 env(token::createOffer(issuer, nftokenID, drops(1)),
2653 token::Owner(minter),
2654 token::Destination(minter));
2656 uint256 const offerIssuerToBuyer =
2658 env(token::createOffer(issuer, nftokenID, drops(1)),
2659 token::Owner(minter),
2660 token::Destination(buyer));
2674 env(token::cancelOffer(issuer, {offerMinterToBuyer}), Ter(
tecNO_PERMISSION));
2675 env(token::cancelOffer(buyer, {offerMinterToIssuer}), Ter(
tecNO_PERMISSION));
2676 env(token::cancelOffer(buyer, {offerIssuerToMinter}), Ter(
tecNO_PERMISSION));
2677 env(token::cancelOffer(minter, {offerIssuerToBuyer}), Ter(
tecNO_PERMISSION));
2685 env(token::cancelOffer(buyer, {offerMinterToBuyer}));
2686 env(token::cancelOffer(minter, {offerMinterToIssuer}));
2687 env(token::cancelOffer(buyer, {offerIssuerToBuyer}));
2688 env(token::cancelOffer(issuer, {offerIssuerToMinter}));
2698 uint256 const offerMinterSellsToBuyer =
2700 env(token::createOffer(minter, nftokenID, drops(1)),
2701 token::Destination(buyer),
2702 Txflags(tfSellNFToken));
2710 env(token::acceptSellOffer(issuer, offerMinterSellsToBuyer), Ter(
tecNO_PERMISSION));
2717 env(token::acceptSellOffer(buyer, offerMinterSellsToBuyer));
2727 uint256 const offerMinterBuysFromBuyer =
2729 env(token::createOffer(minter, nftokenID, drops(1)),
2730 token::Owner(buyer),
2731 token::Destination(buyer));
2739 env(token::acceptBuyOffer(issuer, offerMinterBuysFromBuyer), Ter(
tecNO_PERMISSION));
2746 env(token::acceptBuyOffer(buyer, offerMinterBuysFromBuyer));
2755 uint256 const offerBuyerBuysFromMinter =
2757 env(token::createOffer(buyer, nftokenID, drops(1)),
2758 token::Owner(minter),
2759 token::Destination(broker));
2765 env(token::acceptBuyOffer(minter, offerBuyerBuysFromMinter), Ter(
tecNO_PERMISSION));
2769 env(token::cancelOffer(buyer, {offerBuyerBuysFromMinter}));
2779 uint256 const offerMinterToBroker =
2781 env(token::createOffer(minter, nftokenID, drops(1)),
2782 token::Destination(broker),
2783 Txflags(tfSellNFToken));
2785 uint256 const offerBuyerToMinter =
2787 env(token::createOffer(buyer, nftokenID, drops(1)), token::Owner(minter));
2797 env(token::brokerOffers(issuer, offerBuyerToMinter, offerMinterToBroker),
2807 env(token::brokerOffers(broker, offerBuyerToMinter, offerMinterToBroker));
2818 uint256 const offerBuyerToMinter =
2820 env(token::createOffer(buyer, nftokenID, drops(1)),
2821 token::Destination(minter),
2822 Txflags(tfSellNFToken));
2824 uint256 const offerMinterToBuyer =
2826 env(token::createOffer(minter, nftokenID, drops(1)), token::Owner(buyer));
2828 uint256 const offerIssuerToBuyer =
2830 env(token::createOffer(issuer, nftokenID, drops(1)), token::Owner(buyer));
2840 env(token::brokerOffers(broker, offerIssuerToBuyer, offerBuyerToMinter),
2848 env(token::brokerOffers(broker, offerMinterToBuyer, offerBuyerToMinter),
2853 env(token::acceptBuyOffer(buyer, offerMinterToBuyer));
2857 env(token::cancelOffer(buyer, {offerBuyerToMinter}));
2865 env(token::cancelOffer(issuer, {offerIssuerToBuyer}));
2877 uint256 const offerMinterToBroker =
2879 env(token::createOffer(minter, nftokenID, drops(1)),
2880 token::Destination(broker),
2881 Txflags(tfSellNFToken));
2883 uint256 const offerBuyerToBroker =
2885 env(token::createOffer(buyer, nftokenID, drops(1)),
2886 token::Owner(minter),
2887 token::Destination(broker));
2892 env(token::brokerOffers(issuer, offerBuyerToBroker, offerMinterToBroker),
2901 env(token::brokerOffers(broker, offerBuyerToBroker, offerMinterToBroker));
3045 testcase(
"Create offer expiration");
3049 Env env{*
this, features};
3051 Account const issuer{
"issuer"};
3052 Account const minter{
"minter"};
3055 env.fund(XRP(1000), issuer, minter, buyer);
3059 env(token::setMinter(issuer, minter));
3062 uint256 const nftokenID0 = token::getNextID(env, issuer, 0, tfTransferable);
3063 env(token::mint(minter, 0), token::Issuer(issuer), Txflags(tfTransferable));
3066 uint256 const nftokenID1 = token::getNextID(env, issuer, 0, tfTransferable);
3067 env(token::mint(minter, 0), token::Issuer(issuer), Txflags(tfTransferable));
3069 uint8_t issuerCount = 0, minterCount = 0, buyerCount = 0;
3076 uint256 const offerMinterToIssuer =
3078 env(token::createOffer(minter, nftokenID0, drops(1)),
3079 token::Destination(issuer),
3080 token::Expiration(expiration),
3081 Txflags(tfSellNFToken));
3083 uint256 const offerMinterToAnyone =
3085 env(token::createOffer(minter, nftokenID0, drops(1)),
3086 token::Expiration(expiration),
3087 Txflags(tfSellNFToken));
3089 uint256 const offerIssuerToMinter =
3091 env(token::createOffer(issuer, nftokenID0, drops(1)),
3092 token::Owner(minter),
3093 token::Expiration(expiration));
3095 uint256 const offerBuyerToMinter =
3097 env(token::createOffer(buyer, nftokenID0, drops(1)),
3098 token::Owner(minter),
3099 token::Expiration(expiration));
3104 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3105 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3106 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3114 env(token::cancelOffer(issuer, {offerMinterToAnyone}), Ter(
tecNO_PERMISSION));
3115 env(token::cancelOffer(buyer, {offerIssuerToMinter}), Ter(
tecNO_PERMISSION));
3117 BEAST_EXPECT(
lastClose(env) < expiration);
3118 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3119 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3120 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3123 env(token::cancelOffer(minter, {offerMinterToAnyone}));
3128 env(token::cancelOffer(issuer, {offerMinterToIssuer}));
3135 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3136 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3137 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3140 env(token::cancelOffer(issuer, {offerBuyerToMinter}));
3142 env(token::cancelOffer(buyer, {offerIssuerToMinter}));
3145 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3146 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3147 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3158 env(token::createOffer(minter, nftokenID0, drops(1)),
3159 token::Expiration(expiration),
3160 Txflags(tfSellNFToken));
3165 env(token::createOffer(minter, nftokenID1, drops(1)),
3166 token::Expiration(expiration),
3167 Txflags(tfSellNFToken));
3170 BEAST_EXPECT(
lastClose(env) < expiration);
3171 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3172 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3173 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3176 env(token::acceptSellOffer(buyer, offer0));
3184 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3185 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3186 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3189 env(token::acceptSellOffer(buyer, offer1), Ter(
tecEXPIRED));
3194 if (features[fixCleanup3_1_3])
3204 env(token::acceptSellOffer(issuer, offer1), Ter(
tecEXPIRED));
3209 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3210 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3211 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3213 if (!features[fixCleanup3_1_3])
3217 env(token::cancelOffer(issuer, {offer1}));
3223 BEAST_EXPECT(
ownerCount(env, issuer) == 0 && issuerCount == 0);
3224 BEAST_EXPECT(
ownerCount(env, minter) == 1 && minterCount == 1);
3225 BEAST_EXPECT(
ownerCount(env, buyer) == 1 && buyerCount == 1);
3231 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3232 Txflags(tfSellNFToken),
3233 token::Destination(minter));
3235 env(token::acceptSellOffer(minter, offerSellBack));
3238 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3239 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3240 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3251 env(token::createOffer(buyer, nftokenID0, drops(1)),
3252 token::Owner(minter),
3253 token::Expiration(expiration));
3258 env(token::createOffer(buyer, nftokenID1, drops(1)),
3259 token::Owner(minter),
3260 token::Expiration(expiration));
3263 BEAST_EXPECT(
lastClose(env) < expiration);
3264 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3265 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3266 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3269 env(token::acceptBuyOffer(minter, offer0));
3275 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3276 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3277 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3280 env(token::acceptBuyOffer(minter, offer1), Ter(
tecEXPIRED));
3285 if (features[fixCleanup3_1_3])
3295 env(token::acceptBuyOffer(issuer, offer1), Ter(
tecEXPIRED));
3300 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3301 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3302 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3304 if (!features[fixCleanup3_1_3])
3308 env(token::cancelOffer(issuer, {offer1}));
3314 BEAST_EXPECT(
ownerCount(env, issuer) == 0 && issuerCount == 0);
3315 BEAST_EXPECT(
ownerCount(env, minter) == 1 && minterCount == 1);
3316 BEAST_EXPECT(
ownerCount(env, buyer) == 1 && buyerCount == 1);
3322 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3323 Txflags(tfSellNFToken),
3324 token::Destination(minter));
3326 env(token::acceptSellOffer(minter, offerSellBack));
3329 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3330 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3331 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3342 env(token::createOffer(minter, nftokenID0, drops(1)),
3343 token::Expiration(expiration),
3344 Txflags(tfSellNFToken));
3349 env(token::createOffer(minter, nftokenID1, drops(1)),
3350 token::Expiration(expiration),
3351 Txflags(tfSellNFToken));
3356 env(token::createOffer(buyer, nftokenID0, drops(1)), token::Owner(minter));
3361 env(token::createOffer(buyer, nftokenID1, drops(1)), token::Owner(minter));
3365 BEAST_EXPECT(
lastClose(env) < expiration);
3366 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3367 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3368 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3371 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3378 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3379 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3380 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3383 env(token::brokerOffers(issuer, buyOffer1, sellOffer1), Ter(
tecEXPIRED));
3386 if (features[fixCleanup3_1_3])
3392 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3393 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3394 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3396 if (features[fixCleanup3_1_3])
3400 env(token::cancelOffer(buyer, {buyOffer1}));
3406 env(token::cancelOffer(buyer, {buyOffer1, sellOffer1}));
3413 BEAST_EXPECT(
ownerCount(env, issuer) == 0 && issuerCount == 0);
3414 BEAST_EXPECT(
ownerCount(env, minter) == 1 && minterCount == 1);
3415 BEAST_EXPECT(
ownerCount(env, buyer) == 1 && buyerCount == 1);
3421 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3422 Txflags(tfSellNFToken),
3423 token::Destination(minter));
3425 env(token::acceptSellOffer(minter, offerSellBack));
3428 BEAST_EXPECT(
ownerCount(env, issuer) == issuerCount);
3429 BEAST_EXPECT(
ownerCount(env, minter) == minterCount);
3430 BEAST_EXPECT(
ownerCount(env, buyer) == buyerCount);
3441 env(token::createOffer(minter, nftokenID0, drops(1)), Txflags(tfSellNFToken));
3445 env(token::createOffer(minter, nftokenID1, drops(1)), Txflags(tfSellNFToken));
3449 env(token::createOffer(buyer, nftokenID0, drops(1)),
3450 token::Expiration(expiration),
3451 token::Owner(minter));
3455 env(token::createOffer(buyer, nftokenID1, drops(1)),
3456 token::Expiration(expiration),
3457 token::Owner(minter));
3460 BEAST_EXPECT(
lastClose(env) < expiration);
3466 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3476 env(token::brokerOffers(issuer, buyOffer1, sellOffer1), Ter(
tecEXPIRED));
3480 if (features[fixCleanup3_1_3])
3488 env(token::cancelOffer(minter, {sellOffer1}));
3496 env(token::cancelOffer(minter, {buyOffer1, sellOffer1}));
3507 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3508 Txflags(tfSellNFToken),
3509 token::Destination(minter));
3511 env(token::acceptSellOffer(minter, offerSellBack));
3527 env(token::createOffer(minter, nftokenID0, drops(1)),
3528 token::Expiration(expiration),
3529 Txflags(tfSellNFToken));
3533 env(token::createOffer(minter, nftokenID1, drops(1)),
3534 token::Expiration(expiration),
3535 Txflags(tfSellNFToken));
3539 env(token::createOffer(buyer, nftokenID0, drops(1)),
3540 token::Expiration(expiration),
3541 token::Owner(minter));
3545 env(token::createOffer(buyer, nftokenID1, drops(1)),
3546 token::Expiration(expiration),
3547 token::Owner(minter));
3550 BEAST_EXPECT(
lastClose(env) < expiration);
3556 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3566 env(token::brokerOffers(issuer, buyOffer1, sellOffer1), Ter(
tecEXPIRED));
3571 if (!features[fixCleanup3_1_3])
3577 env(token::cancelOffer(issuer, {buyOffer1, sellOffer1}));
3588 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3589 Txflags(tfSellNFToken),
3590 token::Destination(minter));
3592 env(token::acceptSellOffer(minter, offerSellBack));
3821 testcase(
"Brokered NFT offer accept");
3826 Env env{*
this, features};
3827 auto const baseFee = env.current()->fees().base;
3835 Account const issuer{
"issuer"};
3836 Account const minter{
"minter"};
3838 Account const broker{
"broker"};
3840 IOU
const gwXAU(gw[
"XAU"]);
3842 env.fund(XRP(1000), issuer, minter, buyer, broker, gw);
3845 env(trust(issuer, gwXAU(2000)));
3846 env(trust(minter, gwXAU(2000)));
3847 env(trust(buyer, gwXAU(2000)));
3848 env(trust(broker, gwXAU(2000)));
3851 env(token::setMinter(issuer, minter));
3855 auto checkOwnerCountIsOne =
3859 for (
Account const& acct : accounts)
3865 ss <<
"Account " << acct.human() <<
" expected ownerCount == 1. Got "
3867 fail(ss.
str(), __FILE__, line);
3873 auto mintNFT = [&env, &issuer, &minter](
std::uint16_t xferFee = 0) {
3874 uint256 const nftID = token::getNextID(env, issuer, 0, tfTransferable, xferFee);
3875 env(token::mint(minter, 0),
3876 token::Issuer(issuer),
3877 token::XferFee(xferFee),
3878 Txflags(tfTransferable));
3889 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3891 uint256 const nftID = mintNFT();
3894 uint256 const minterOfferIndex =
3896 env(token::createOffer(minter, nftID, XRP(0)), Txflags(tfSellNFToken));
3903 env(token::createOffer(buyer, nftID, XRP(1)), token::Owner(minter));
3906 auto const minterBalance = env.balance(minter);
3907 auto const buyerBalance = env.balance(buyer);
3908 auto const brokerBalance = env.balance(broker);
3909 auto const issuerBalance = env.balance(issuer);
3912 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex));
3917 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(1));
3918 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3919 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
3920 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
3923 env(token::burn(buyer, nftID));
3933 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3935 uint256 const nftID = mintNFT();
3938 uint256 const minterOfferIndex =
3940 env(token::createOffer(minter, nftID, XRP(0)), Txflags(tfSellNFToken));
3947 env(token::createOffer(buyer, nftID, XRP(1)), token::Owner(minter));
3951 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
3952 token::BrokerFee(XRP(1.1)),
3956 auto const minterBalance = env.balance(minter);
3957 auto const buyerBalance = env.balance(buyer);
3958 auto const brokerBalance = env.balance(broker);
3959 auto const issuerBalance = env.balance(issuer);
3962 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
3963 token::BrokerFee(XRP(0.5)));
3968 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
3969 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3970 BEAST_EXPECT(env.balance(broker) == brokerBalance + XRP(0.5) - baseFee);
3971 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
3974 env(token::burn(buyer, nftID));
3984 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3989 uint256 const minterOfferIndex =
3991 env(token::createOffer(minter, nftID, XRP(0)), Txflags(tfSellNFToken));
3998 env(token::createOffer(buyer, nftID, XRP(1)), token::Owner(minter));
4001 auto const minterBalance = env.balance(minter);
4002 auto const buyerBalance = env.balance(buyer);
4003 auto const brokerBalance = env.balance(broker);
4004 auto const issuerBalance = env.balance(issuer);
4007 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex));
4012 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
4013 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4014 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
4015 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.5));
4018 env(token::burn(buyer, nftID));
4028 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4033 uint256 const minterOfferIndex =
4035 env(token::createOffer(minter, nftID, XRP(0)), Txflags(tfSellNFToken));
4042 env(token::createOffer(buyer, nftID, XRP(1)), token::Owner(minter));
4045 auto const minterBalance = env.balance(minter);
4046 auto const buyerBalance = env.balance(buyer);
4047 auto const brokerBalance = env.balance(broker);
4048 auto const issuerBalance = env.balance(issuer);
4051 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4052 token::BrokerFee(XRP(0.75)));
4058 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.125));
4059 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4060 BEAST_EXPECT(env.balance(broker) == brokerBalance + XRP(0.75) - baseFee);
4061 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.125));
4064 env(token::burn(buyer, nftID));
4070 auto setXAUBalance =
4071 [
this, &gw, &gwXAU, &env](
4075 for (
Account const& acct : accounts)
4077 auto const xauAmt = gwXAU(amount);
4078 auto const balance = env.balance(acct, gwXAU);
4079 if (balance < xauAmt)
4081 env(pay(gw, acct, xauAmt - balance));
4084 else if (balance > xauAmt)
4086 env(pay(acct, gw, balance - xauAmt));
4089 if (env.balance(acct, gwXAU) != xauAmt)
4092 ss <<
"Unable to set " << acct.human() <<
" account balance to gwXAU("
4094 this->
fail(ss.
str(), __FILE__, line);
4102 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4103 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4105 uint256 const nftID = mintNFT();
4108 uint256 const minterOfferIndex =
4110 env(token::createOffer(minter, nftID, gwXAU(1000)), Txflags(tfSellNFToken));
4118 env(token::createOffer(buyer, nftID, gwXAU(1001)), token::Owner(minter));
4122 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4128 env(token::cancelOffer(buyer, {buyOfferIndex}));
4136 env(token::createOffer(buyer, nftID, gwXAU(999)), token::Owner(minter));
4140 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4146 env(token::cancelOffer(buyer, {buyOfferIndex}));
4153 env(token::createOffer(buyer, nftID, gwXAU(1000)), token::Owner(minter));
4157 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4158 token::BrokerFee(gwXAU(0.1)),
4163 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex));
4170 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1000));
4171 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(2000));
4172 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4173 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1000));
4176 env(token::burn(buyer, nftID));
4183 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4184 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4189 uint256 const minterOfferIndex =
4191 env(token::createOffer(minter, nftID, gwXAU(900)), Txflags(tfSellNFToken));
4198 env(token::createOffer(buyer, nftID, gwXAU(1001)), token::Owner(minter));
4202 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4208 env(token::cancelOffer(buyer, {buyOfferIndex}));
4216 env(token::createOffer(buyer, nftID, gwXAU(899)), token::Owner(minter));
4220 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4226 env(token::cancelOffer(buyer, {buyOfferIndex}));
4232 env(token::createOffer(buyer, nftID, gwXAU(1000)), token::Owner(minter));
4237 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4238 token::BrokerFee(gwXAU(101)),
4244 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4245 token::BrokerFee(gwXAU(100)));
4252 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1450));
4253 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1450));
4254 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4255 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1100));
4258 env(token::burn(buyer, nftID));
4265 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4266 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4271 uint256 const minterOfferIndex =
4273 env(token::createOffer(minter, nftID, gwXAU(900)), Txflags(tfSellNFToken));
4279 env(token::createOffer(buyer, nftID, gwXAU(1000)), token::Owner(minter));
4285 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4286 token::BrokerFee(gwXAU(50)));
4293 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4294 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4295 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4296 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1050));
4299 env(token::burn(buyer, nftID));
4304 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4305 setXAUBalance({issuer, minter, buyer}, 1000, __LINE__);
4306 setXAUBalance({broker}, 500, __LINE__);
4310 uint256 const minterOfferIndex =
4312 env(token::createOffer(minter, nftID, gwXAU(900)), Txflags(tfSellNFToken));
4318 env(token::createOffer(buyer, nftID, gwXAU(1000)), token::Owner(minter));
4321 env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex),
4322 token::BrokerFee(gwXAU(50)));
4328 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4329 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4330 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4331 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(550));
4334 env(token::burn(buyer, nftID));
4996 testcase(
"Payments with IOU transfer fees");
4999 Env env{*
this, features};
5001 Account const minter{
"minter"};
5002 Account const secondarySeller{
"seller"};
5005 Account const broker{
"broker"};
5006 IOU
const gwXAU(gw[
"XAU"]);
5007 IOU
const gwXPB(gw[
"XPB"]);
5009 env.fund(XRP(1000), gw, minter, secondarySeller, buyer, broker);
5012 env(trust(minter, gwXAU(2000)));
5013 env(trust(secondarySeller, gwXAU(2000)));
5014 env(trust(broker, gwXAU(10000)));
5015 env(trust(buyer, gwXAU(2000)));
5016 env(trust(buyer, gwXPB(2000)));
5020 env(rate(gw, 1.02));
5023 auto expectInitialState =
5024 [
this, &env, &buyer, &minter, &secondarySeller, &broker, &gw, &gwXAU, &gwXPB]() {
5029 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(1000));
5030 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(0));
5031 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(0));
5032 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(0));
5033 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(0));
5034 BEAST_EXPECT(env.balance(secondarySeller, gwXPB) == gwXPB(0));
5035 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5000));
5036 BEAST_EXPECT(env.balance(broker, gwXPB) == gwXPB(0));
5037 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-1000));
5038 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(0));
5039 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(0));
5040 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(0));
5041 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(0));
5042 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XPB"]) == gwXPB(0));
5043 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5000));
5044 BEAST_EXPECT(env.balance(gw, broker[
"XPB"]) == gwXPB(0));
5047 auto reinitializeTrustLineBalances = [&expectInitialState,
5056 if (
auto const difference = gwXAU(1000) - env.balance(buyer, gwXAU);
5057 difference > gwXAU(0))
5058 env(pay(gw, buyer, difference));
5059 if (env.balance(buyer, gwXPB) > gwXPB(0))
5060 env(pay(buyer, gw, env.balance(buyer, gwXPB)));
5061 if (env.balance(minter, gwXAU) > gwXAU(0))
5062 env(pay(minter, gw, env.balance(minter, gwXAU)));
5063 if (env.balance(minter, gwXPB) > gwXPB(0))
5064 env(pay(minter, gw, env.balance(minter, gwXPB)));
5065 if (env.balance(secondarySeller, gwXAU) > gwXAU(0))
5066 env(pay(secondarySeller, gw, env.balance(secondarySeller, gwXAU)));
5067 if (env.balance(secondarySeller, gwXPB) > gwXPB(0))
5068 env(pay(secondarySeller, gw, env.balance(secondarySeller, gwXPB)));
5069 auto brokerDiff = gwXAU(5000) - env.balance(broker, gwXAU);
5070 if (brokerDiff > gwXAU(0))
5072 env(pay(gw, broker, brokerDiff));
5074 else if (brokerDiff < gwXAU(0))
5076 brokerDiff.negate();
5077 env(pay(broker, gw, brokerDiff));
5079 if (env.balance(broker, gwXPB) > gwXPB(0))
5080 env(pay(broker, gw, env.balance(broker, gwXPB)));
5082 expectInitialState();
5085 auto mintNFT = [&env](
Account const& minter,
int transferFee = 0) {
5086 uint256 const nftID = token::getNextID(env, minter, 0, tfTransferable, transferFee);
5087 env(token::mint(minter), token::XferFee(transferFee), Txflags(tfTransferable));
5092 auto createBuyOffer = [&env](
5100 env(token::createOffer(offerer, nftID, amount),
5101 token::Owner(owner),
5102 terCode ? Ter(*terCode) : Ter(
static_cast<TER>(
tesSUCCESS)));
5107 auto createSellOffer = [&env](
5114 env(token::createOffer(offerer, nftID, amount),
5115 Txflags(tfSellNFToken),
5116 terCode ? Ter(*terCode) : Ter(
static_cast<TER>(
tesSUCCESS)));
5124 reinitializeTrustLineBalances();
5125 auto const nftID = mintNFT(minter);
5126 auto const offerID = createSellOffer(minter, nftID, gwXAU(1000));
5128 env(token::acceptSellOffer(buyer, offerID), Ter(sellTER));
5131 expectInitialState();
5136 reinitializeTrustLineBalances();
5137 auto const nftID = mintNFT(minter);
5138 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(1000));
5140 env(token::acceptBuyOffer(minter, offerID), Ter(sellTER));
5143 expectInitialState();
5149 reinitializeTrustLineBalances();
5150 auto const nftID = mintNFT(minter);
5151 auto const offerID = createSellOffer(minter, nftID, gwXAU(995));
5153 env(token::acceptSellOffer(buyer, offerID), Ter(sellTER));
5156 expectInitialState();
5162 reinitializeTrustLineBalances();
5163 auto const nftID = mintNFT(minter);
5164 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(995));
5166 env(token::acceptBuyOffer(minter, offerID), Ter(sellTER));
5169 expectInitialState();
5176 reinitializeTrustLineBalances();
5177 auto const nftID = mintNFT(minter);
5178 auto const offerID = createSellOffer(minter, nftID, gwXAU(900));
5179 env(token::acceptSellOffer(buyer, offerID));
5182 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
5183 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5184 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
5185 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5192 reinitializeTrustLineBalances();
5193 auto const nftID = mintNFT(minter);
5194 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(900));
5195 env(token::acceptBuyOffer(minter, offerID));
5198 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
5199 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5200 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
5201 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5208 reinitializeTrustLineBalances();
5211 env(pay(gw, buyer, gwXAU(20)));
5214 auto const nftID = mintNFT(minter);
5215 auto const offerID = createSellOffer(minter, nftID, gwXAU(1000));
5216 env(token::acceptSellOffer(buyer, offerID));
5219 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5220 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5221 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5222 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5229 reinitializeTrustLineBalances();
5232 env(pay(gw, buyer, gwXAU(20)));
5235 auto const nftID = mintNFT(minter);
5236 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(1000));
5237 env(token::acceptBuyOffer(minter, offerID));
5240 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5241 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5242 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5243 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5248 reinitializeTrustLineBalances();
5250 auto const nftID = mintNFT(minter);
5251 auto const offerID = createSellOffer(minter, nftID, gwXAU(1000));
5253 env(token::acceptSellOffer(gw, offerID), Ter(sellTER));
5256 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5257 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5262 reinitializeTrustLineBalances();
5264 auto const nftID = mintNFT(minter);
5266 auto const offerID = createBuyOffer(gw, minter, nftID, gwXAU(1000), {offerTER});
5268 env(token::acceptBuyOffer(minter, offerID), Ter(sellTER));
5271 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5272 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5277 reinitializeTrustLineBalances();
5278 auto const nftID = mintNFT(minter);
5279 auto const offerID = createSellOffer(minter, nftID, gwXAU(5000));
5281 env(token::acceptSellOffer(gw, offerID), Ter(sellTER));
5284 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5285 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5290 reinitializeTrustLineBalances();
5292 auto const nftID = mintNFT(minter);
5294 auto const offerID = createBuyOffer(gw, minter, nftID, gwXAU(5000), {offerTER});
5296 env(token::acceptBuyOffer(minter, offerID), Ter(sellTER));
5299 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5300 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5306 reinitializeTrustLineBalances();
5307 auto const nftID = mintNFT(gw);
5308 auto const offerID = createSellOffer(gw, nftID, gwXAU(1000));
5309 env(token::acceptSellOffer(buyer, offerID));
5312 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5313 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5319 reinitializeTrustLineBalances();
5321 auto const nftID = mintNFT(gw);
5322 auto const offerID = createBuyOffer(buyer, gw, nftID, gwXAU(1000));
5323 env(token::acceptBuyOffer(gw, offerID));
5326 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5327 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5333 reinitializeTrustLineBalances();
5334 auto const nftID = mintNFT(gw);
5335 auto const offerID = createSellOffer(gw, nftID, gwXAU(2000));
5336 env(token::acceptSellOffer(buyer, offerID),
5339 expectInitialState();
5345 reinitializeTrustLineBalances();
5346 auto const nftID = mintNFT(gw);
5347 auto const offerID = createBuyOffer(buyer, gw, nftID, gwXAU(2000));
5348 env(token::acceptBuyOffer(gw, offerID),
5351 expectInitialState();
5356 reinitializeTrustLineBalances();
5357 auto const nftID = mintNFT(minter);
5358 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5359 env(token::acceptSellOffer(buyer, offerID),
5362 expectInitialState();
5367 reinitializeTrustLineBalances();
5368 auto const nftID = mintNFT(minter);
5369 auto const offerID = createBuyOffer(
5371 env(token::acceptBuyOffer(minter, offerID),
5374 expectInitialState();
5380 reinitializeTrustLineBalances();
5381 env(pay(gw, buyer, gwXPB(100)));
5384 auto const nftID = mintNFT(minter);
5385 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5386 env(token::acceptSellOffer(buyer, offerID));
5389 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5390 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5391 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5392 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5398 reinitializeTrustLineBalances();
5399 env(pay(gw, buyer, gwXPB(100)));
5402 auto const nftID = mintNFT(minter);
5403 auto const offerID = createBuyOffer(buyer, minter, nftID, gwXPB(10));
5404 env(token::acceptBuyOffer(minter, offerID));
5407 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5408 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5409 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5410 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5415 reinitializeTrustLineBalances();
5419 auto const nftID = mintNFT(minter, 3000);
5420 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
5421 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5425 auto const offerID = createSellOffer(secondarySeller, nftID, gwXAU(1000));
5427 env(token::acceptSellOffer(buyer, offerID), Ter(sellTER));
5430 expectInitialState();
5435 reinitializeTrustLineBalances();
5439 auto const nftID = mintNFT(minter, 3000);
5440 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
5441 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5445 auto const offerID = createBuyOffer(buyer, secondarySeller, nftID, gwXAU(1000));
5447 env(token::acceptBuyOffer(secondarySeller, offerID), Ter(sellTER));
5450 expectInitialState();
5455 reinitializeTrustLineBalances();
5459 auto const nftID = mintNFT(minter, 3000);
5460 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
5461 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5465 auto const offerID = createSellOffer(secondarySeller, nftID, gwXAU(900));
5466 env(token::acceptSellOffer(buyer, offerID));
5469 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5470 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5471 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5472 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5473 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5474 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5479 reinitializeTrustLineBalances();
5483 auto const nftID = mintNFT(minter, 3000);
5484 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
5485 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5489 auto const offerID = createBuyOffer(buyer, secondarySeller, nftID, gwXAU(900));
5490 env(token::acceptBuyOffer(secondarySeller, offerID));
5494 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5496 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5498 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5499 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5500 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5501 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5519 reinitializeTrustLineBalances();
5521 auto const nftID = mintNFT(minter);
5522 auto const sellOffer = createSellOffer(minter, nftID, gwXAU(300));
5523 auto const buyOffer = createBuyOffer(buyer, minter, nftID, gwXAU(500));
5524 env(token::brokerOffers(broker, buyOffer, sellOffer), token::BrokerFee(gwXAU(100)));
5527 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(400));
5528 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5529 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5530 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-400));
5531 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5532 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5550 reinitializeTrustLineBalances();
5554 auto const nftID = mintNFT(minter, 3000);
5555 auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0));
5556 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5560 auto const sellOffer = createSellOffer(secondarySeller, nftID, gwXAU(300));
5561 auto const buyOffer = createBuyOffer(buyer, secondarySeller, nftID, gwXAU(500));
5562 env(token::brokerOffers(broker, buyOffer, sellOffer), token::BrokerFee(gwXAU(100)));
5565 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(12));
5566 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5567 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(388));
5568 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5569 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-12));
5570 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5571 BEAST_EXPECT(env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-388));
5572 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5675 auto openLedgerSeq = [](Env& env) {
return env.current()->seq(); };
5679 auto incLgrSeqForAcctDel = [&](Env& env,
Account const& acct) {
5680 int const delta = [&]() ->
int {
5681 if (env.seq(acct) + 255 > openLedgerSeq(env))
5682 return env.seq(acct) - openLedgerSeq(env) + 255;
5685 BEAST_EXPECT(delta >= 0);
5686 for (
int i = 0; i < delta; ++i)
5688 BEAST_EXPECT(openLedgerSeq(env) == env.seq(acct) + 255);
5693 auto incLgrSeqForFixNftRemint = [&](Env& env,
Account const& acct) {
5695 auto const deletableLgrSeq = (*env.le(acct))[~sfFirstNFTokenSequence].value_or(0) +
5696 (*env.le(acct))[sfMintedNFTokens] + 255;
5698 if (deletableLgrSeq > openLedgerSeq(env))
5699 delta = deletableLgrSeq - openLedgerSeq(env);
5701 BEAST_EXPECT(delta >= 0);
5702 for (
int i = 0; i < delta; ++i)
5704 BEAST_EXPECT(openLedgerSeq(env) == deletableLgrSeq);
5710 Env env{*
this, features};
5714 env.fund(XRP(10000), alice, becky);
5718 uint256 const prevNFTokenID = token::getNextID(env, alice, 0u);
5719 env(token::mint(alice));
5721 env(token::burn(alice, prevNFTokenID));
5725 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 1);
5728 incLgrSeqForAcctDel(env, alice);
5732 auto const acctDelFee{drops(env.current()->fees().increment)};
5733 env(acctdelete(alice, becky), Fee(acctDelFee));
5738 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5739 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5742 env.fund(XRP(10000), alice);
5746 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5747 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5748 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5751 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5752 env(token::mint(alice));
5756 env(token::burn(alice, remintNFTokenID));
5760 BEAST_EXPECT(remintNFTokenID != prevNFTokenID);
5766 Env env{*
this, features};
5769 Account const minter{
"minter"};
5771 env.fund(XRP(10000), alice, becky, minter);
5775 env(token::setMinter(alice, minter));
5781 for (
int i = 0; i < 500; i++)
5783 uint256 const nftokenID = token::getNextID(env, alice, 0u);
5785 env(token::mint(minter), token::Issuer(alice));
5790 for (
auto const nftokenID : nftIDs)
5792 env(token::burn(minter, nftokenID));
5796 incLgrSeqForAcctDel(env, alice);
5800 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5801 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5803 auto const acctDelFee{drops(env.current()->fees().increment)};
5812 env(acctdelete(alice, becky), Fee(acctDelFee), Ter(
tecTOO_SOON));
5816 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5821 incLgrSeqForFixNftRemint(env, alice);
5824 env(acctdelete(alice, becky), Fee(acctDelFee));
5829 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5830 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5833 env.fund(XRP(10000), alice);
5837 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5838 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5839 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5843 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5844 env(token::mint(alice));
5848 env(token::burn(alice, remintNFTokenID));
5859 Env env{*
this, features};
5863 env.fund(XRP(10000), alice, becky);
5870 env(ticket::create(alice, 100));
5879 for (
int i = 0; i < 50; i++)
5881 nftIDs.
push_back(token::getNextID(env, alice, 0u));
5882 env(token::mint(alice, 0u), ticket::Use(aliceTicketSeq++));
5887 for (
auto const nftokenID : nftIDs)
5889 env(token::burn(alice, nftokenID), ticket::Use(aliceTicketSeq++));
5895 incLgrSeqForAcctDel(env, alice);
5899 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5900 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5902 auto const acctDelFee{drops(env.current()->fees().increment)};
5911 env(acctdelete(alice, becky), Fee(acctDelFee), Ter(
tecTOO_SOON));
5915 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5920 incLgrSeqForFixNftRemint(env, alice);
5923 env(acctdelete(alice, becky), Fee(acctDelFee));
5928 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5929 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5932 env.fund(XRP(10000), alice);
5936 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5937 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5938 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5942 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5943 env(token::mint(alice));
5947 env(token::burn(alice, remintNFTokenID));
5959 Env env{*
this, features};
5962 Account const minter{
"minter"};
5964 env.fund(XRP(10000), alice, becky, minter);
5968 env(token::setMinter(alice, minter));
5973 env(ticket::create(minter, 100));
5977 BEAST_EXPECT(
ownerCount(env, minter) == 100);
5982 for (
int i = 0; i < 50; i++)
5984 uint256 const nftokenID = token::getNextID(env, alice, 0u);
5986 env(token::mint(minter), token::Issuer(alice), ticket::Use(minterTicketSeq++));
5991 for (
auto const nftokenID : nftIDs)
5993 env(token::burn(minter, nftokenID), ticket::Use(minterTicketSeq++));
5999 incLgrSeqForAcctDel(env, alice);
6003 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6004 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6013 auto const acctDelFee{drops(env.current()->fees().increment)};
6014 env(acctdelete(alice, becky), Fee(acctDelFee), Ter(
tecTOO_SOON));
6018 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6023 incLgrSeqForFixNftRemint(env, alice);
6026 env(acctdelete(alice, becky), Fee(acctDelFee));
6031 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
6032 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
6035 env.fund(XRP(10000), alice);
6039 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6040 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6041 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
6045 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
6046 env(token::mint(alice));
6050 env(token::burn(alice, remintNFTokenID));
6316 testcase(
"Test synthetic fields from JSON response");
6322 Account const broker{
"broker"};
6324 Env env{*
this, features};
6325 env.fund(XRP(10000), alice, bob, broker);
6331 auto verifyNFTokenID = [&](
uint256 const& actualNftID) {
6337 json::Value const meta = env.rpc(
"tx", txHash)[jss::result][jss::meta];
6340 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_id)))
6347 BEAST_EXPECT(nftID == actualNftID);
6358 json::Value const meta = env.rpc(
"tx", txHash)[jss::result][jss::meta];
6361 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_ids)))
6367 meta[jss::nftoken_ids].begin(),
6368 meta[jss::nftoken_ids].end(),
6372 BEAST_EXPECT(nftID.
parseHex(
id.asString()));
6381 BEAST_EXPECT(metaIDs.
size() == actualNftIDs.size());
6385 for (
size_t i = 0; i < metaIDs.
size(); ++i)
6386 BEAST_EXPECT(metaIDs[i] == actualNftIDs[i]);
6391 auto verifyNFTokenOfferID = [&](
uint256 const& offerID) {
6397 json::Value const meta = env.rpc(
"tx", txHash)[jss::result][jss::meta];
6400 if (!BEAST_EXPECT(meta.
isMember(jss::offer_id)))
6405 BEAST_EXPECT(metaOfferID == offerID);
6412 uint256 const nftId1{token::getNextID(env, alice, 0u, tfTransferable)};
6413 env(token::mint(alice, 0u), Txflags(tfTransferable));
6415 verifyNFTokenID(nftId1);
6417 uint256 const nftId2{token::getNextID(env, alice, 0u, tfTransferable)};
6418 env(token::mint(alice, 0u), Txflags(tfTransferable));
6420 verifyNFTokenID(nftId2);
6425 uint256 const aliceOfferIndex1 =
6427 env(token::createOffer(alice, nftId1, drops(1)), Txflags(tfSellNFToken));
6429 verifyNFTokenOfferID(aliceOfferIndex1);
6431 uint256 const aliceOfferIndex2 =
6433 env(token::createOffer(alice, nftId2, drops(1)), Txflags(tfSellNFToken));
6435 verifyNFTokenOfferID(aliceOfferIndex2);
6440 env(token::cancelOffer(alice, {aliceOfferIndex1, aliceOfferIndex2}));
6442 verifyNFTokenIDsInCancelOffer({nftId1, nftId2});
6446 auto const bobBuyOfferIndex =
6448 env(token::createOffer(bob, nftId1, drops(1)), token::Owner(alice));
6450 verifyNFTokenOfferID(bobBuyOfferIndex);
6454 env(token::acceptBuyOffer(alice, bobBuyOfferIndex));
6456 verifyNFTokenID(nftId1);
6462 uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)};
6463 env(token::mint(alice, 0u), Txflags(tfTransferable));
6465 verifyNFTokenID(nftId);
6468 uint256 const offerAliceToBroker =
6470 env(token::createOffer(alice, nftId, drops(1)),
6471 token::Destination(broker),
6472 Txflags(tfSellNFToken));
6474 verifyNFTokenOfferID(offerAliceToBroker);
6477 uint256 const offerBobToBroker =
6479 env(token::createOffer(bob, nftId, drops(1)), token::Owner(alice));
6481 verifyNFTokenOfferID(offerBobToBroker);
6484 env(token::brokerOffers(broker, offerBobToBroker, offerAliceToBroker));
6486 verifyNFTokenID(nftId);
6493 uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)};
6494 env(token::mint(alice, 0u), Txflags(tfTransferable));
6496 verifyNFTokenID(nftId);
6499 uint256 const aliceOfferIndex1 =
6501 env(token::createOffer(alice, nftId, drops(1)), Txflags(tfSellNFToken));
6503 verifyNFTokenOfferID(aliceOfferIndex1);
6505 uint256 const aliceOfferIndex2 =
6507 env(token::createOffer(alice, nftId, drops(1)), Txflags(tfSellNFToken));
6509 verifyNFTokenOfferID(aliceOfferIndex2);
6513 env(token::cancelOffer(alice, {aliceOfferIndex1, aliceOfferIndex2}));
6515 verifyNFTokenIDsInCancelOffer({nftId});
6518 if (features[featureNFTokenMintOffer])
6520 uint256 const aliceMintWithOfferIndex1 =
6522 env(token::mint(alice), token::Amount(XRP(0)));
6524 verifyNFTokenOfferID(aliceMintWithOfferIndex1);
6531 testcase(
"Test buyer reserve when accepting an offer");
6536 auto mintAndCreateSellOffer =
6539 uint256 const nftId{token::getNextID(env, acct, 0u, tfTransferable)};
6540 env(token::mint(acct, 0u), Txflags(tfTransferable));
6544 uint256 const sellOfferIndex =
6546 env(token::createOffer(acct, nftId, amt), Txflags(tfSellNFToken));
6549 return sellOfferIndex;
6559 Env env{*
this, features};
6560 auto const acctReserve = env.
current()->fees().reserve;
6561 auto const incReserve = env.current()->fees().increment;
6562 auto const baseFee = env.current()->fees().base;
6564 env.fund(XRP(10000), alice);
6568 env.fund(acctReserve, bob);
6572 auto const sellOfferIndex = mintAndCreateSellOffer(env, alice, XRP(0));
6597 env(pay(env.master, bob, incReserve + drops(baseFee)));
6607 env(pay(env.master, bob, drops(baseFee * 2)));
6611 env(token::acceptSellOffer(bob, sellOfferIndex));
6623 Env env{*
this, features};
6624 auto const acctReserve = env.
current()->fees().reserve;
6625 auto const incReserve = env.current()->fees().increment;
6627 env.fund(XRP(10000), alice);
6630 env.fund(acctReserve + XRP(1), bob);
6634 auto const sellOfferIndex1 = mintAndCreateSellOffer(env, alice, XRP(0));
6642 env(pay(env.master, bob, drops(incReserve)));
6648 env(token::acceptSellOffer(bob, sellOfferIndex1));
6655 for (
size_t i = 0; i < 31; i++)
6658 auto const sellOfferIndex = mintAndCreateSellOffer(env, alice, XRP(0));
6662 env(token::acceptSellOffer(bob, sellOfferIndex));
6670 auto const sellOfferIndex33 = mintAndCreateSellOffer(env, alice, XRP(0));
6678 env(pay(env.master, bob, drops(incReserve)));
6683 env(token::acceptSellOffer(bob, sellOfferIndex33));
6694 Env env{*
this, features};
6695 auto const acctReserve = env.
current()->fees().reserve;
6696 auto const incReserve = env.current()->fees().increment;
6697 auto const baseFee = env.current()->fees().base;
6699 env.fund(XRP(10000), alice);
6705 env.fund(acctReserve + incReserve + XRP(1), bob);
6709 uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)};
6710 env(token::mint(alice, 0u), Txflags(tfTransferable));
6714 auto const buyOfferIndex =
6716 env(token::createOffer(bob, nftId, XRP(1)), token::Owner(alice));
6726 env(pay(env.master, bob, drops(baseFee)));
6730 env(token::acceptBuyOffer(alice, buyOfferIndex));
6738 Account const broker{
"broker"};
6740 Env env{*
this, features};
6741 auto const acctReserve = env.
current()->fees().reserve;
6742 auto const incReserve = env.current()->fees().increment;
6743 auto const baseFee = env.current()->fees().base;
6745 env.fund(XRP(10000), alice, broker);
6750 env.fund(acctReserve + incReserve + XRP(1), bob);
6754 uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)};
6755 env(token::mint(alice, 0u), Txflags(tfTransferable));
6759 uint256 const offerAliceToBroker =
6761 env(token::createOffer(alice, nftId, XRP(1)),
6762 token::Destination(broker),
6763 Txflags(tfSellNFToken));
6767 uint256 const offerBobToBroker =
6769 env(token::createOffer(bob, nftId, XRP(1)), token::Owner(alice));
6776 env(token::brokerOffers(broker, offerBobToBroker, offerAliceToBroker),
6781 env(pay(env.master, bob, drops(baseFee)));
6785 env(token::brokerOffers(broker, offerBobToBroker, offerAliceToBroker));
7108 Account const issuer{
"issuer"};
7112 bool const modifyEnabled = features[featureDynamicNFT];
7116 Env env{*
this, features};
7117 env.fund(XRP(10000), issuer);
7121 env(token::mint(issuer, 0u), Txflags(tfMutable), Ter(expectedTer));
7125 Env env{*
this, features};
7126 env.fund(XRP(10000), issuer);
7130 uint256 const nftId{token::getNextID(env, issuer, 0u, tfMutable)};
7133 env(token::mint(issuer, 0u), Txflags(tfMutable));
7136 env(token::modify(issuer, nftId));
7141 env(token::mint(issuer, 0u));
7143 env(token::modify(issuer, nftId), Ter(
temDISABLED));
7151 Env env{*
this, features};
7152 env.fund(XRP(10000), issuer);
7155 uint256 const nftId{token::getNextID(env, issuer, 0u, tfMutable)};
7156 env(token::mint(issuer, 0u), Txflags(tfMutable));
7164 env(token::modify(issuer, nftId), Txflags(0x00000001), Ter(
temINVALID_FLAG));
7167 env(token::modify(issuer, nftId), token::Owner(issuer), Ter(
temMALFORMED));
7171 env(token::modify(issuer, nftId), token::Uri(
""), Ter(
temMALFORMED));
7175 env(token::modify(issuer, nftId),
7181 Env env{*
this, features};
7182 env.fund(XRP(10000), issuer, alice, bob);
7187 uint256 const nftIDNotExists{token::getNextID(env, issuer, 0u, tfMutable)};
7190 env(token::modify(issuer, nftIDNotExists), Ter(
tecNO_ENTRY));
7195 uint256 const nftIDNotModifiable{token::getNextID(env, issuer, 0u)};
7196 env(token::mint(issuer, 0u));
7204 uint256 const nftId{token::getNextID(env, issuer, 0u, tfMutable)};
7205 env(token::mint(issuer, 0u), Txflags(tfMutable));
7208 env(token::modify(bob, nftId), token::Owner(issuer), Ter(
tecNO_PERMISSION));
7211 env(token::setMinter(issuer, alice));
7214 env(token::modify(bob, nftId), token::Owner(issuer), Ter(
tecNO_PERMISSION));
7219 Env env{*
this, features};
7220 env.fund(XRP(10000), issuer, alice, bob);
7224 uint256 const nftId{token::getNextID(env, issuer, 0u, tfMutable)};
7225 env(token::mint(issuer, 0u), Txflags(tfMutable), token::Uri(
"uri"));
7232 Env env{*
this, features};
7233 env.fund(XRP(10000), issuer, alice, bob);
7237 auto accountNFTs = [&env](
Account const& acct) {
7239 params[jss::account] = acct.human();
7240 params[jss::type] =
"state";
7241 auto response = env.rpc(
"json",
"account_nfts",
to_string(params));
7242 return response[jss::result][jss::account_nfts];
7246 auto checkURI = [&accountNFTs,
this](
Account const& acct,
char const* uri,
int line) {
7247 auto const nfts = accountNFTs(acct);
7248 if (nfts.size() == 1)
7255 text <<
"checkURI: unexpected NFT count on line " << line;
7256 fail(text.
str(), __FILE__, line);
7262 if (!nfts[0u].isMember(sfURI.jsonName))
7269 text <<
"checkURI: unexpected URI present on line " << line;
7270 fail(text.
str(), __FILE__, line);
7282 text <<
"checkURI: unexpected URI contents on line " << line;
7283 fail(text.
str(), __FILE__, line);
7287 uint256 const nftId{token::getNextID(env, issuer, 0u, tfMutable)};
7290 env(token::mint(issuer, 0u), Txflags(tfMutable), token::Uri(
"uri"));
7292 checkURI(issuer,
"uri", __LINE__);
7295 env(token::modify(issuer, nftId), token::Uri(
"new_uri"));
7297 checkURI(issuer,
"new_uri", __LINE__);
7300 env(token::modify(issuer, nftId));
7302 checkURI(issuer,
nullptr, __LINE__);
7305 env(token::modify(issuer, nftId), token::Uri(
"uri"));
7307 checkURI(issuer,
"uri", __LINE__);
7312 env(token::createOffer(issuer, nftId, XRP(0)), Txflags(tfSellNFToken));
7314 env(token::acceptSellOffer(alice, offerID));
7318 checkURI(alice,
"uri", __LINE__);
7321 env(token::modify(alice, nftId), token::Uri(
"new_uri"), Ter(
tecNO_PERMISSION));
7325 checkURI(alice,
"uri", __LINE__);
7327 env(token::modify(issuer, nftId), token::Owner(alice), token::Uri(
"new_uri"));
7331 checkURI(alice,
"new_uri", __LINE__);
7333 env(token::modify(issuer, nftId), token::Owner(alice));
7335 checkURI(alice,
nullptr, __LINE__);
7337 env(token::modify(issuer, nftId), token::Owner(alice), token::Uri(
"uri"));
7339 checkURI(alice,
"uri", __LINE__);
7342 env(token::setMinter(issuer, bob));
7344 env(token::modify(bob, nftId), token::Owner(alice), token::Uri(
"new_uri"));
7346 checkURI(alice,
"new_uri", __LINE__);
7348 env(token::modify(bob, nftId), token::Owner(alice));
7350 checkURI(alice,
nullptr, __LINE__);
7352 env(token::modify(bob, nftId), token::Owner(alice), token::Uri(
"uri"));
7354 checkURI(alice,
"uri", __LINE__);