136 using namespace test::jtx;
138 Env env{*
this, features};
139 Account
const alice{
"alice"};
140 Account
const minter{
"minter"};
144 auto const acctReserve = env.current()->fees().reserve;
145 auto const incReserve = env.current()->fees().increment;
146 auto const baseFee = env.current()->fees().base;
148 env.fund(acctReserve, alice, minter);
151 BEAST_EXPECT(env.balance(alice) == acctReserve);
152 BEAST_EXPECT(env.balance(minter) == acctReserve);
153 BEAST_EXPECT(ownerCount(env, alice) == 0);
154 BEAST_EXPECT(ownerCount(env, minter) == 0);
161 BEAST_EXPECT(ownerCount(env, alice) == 0);
166 env(pay(env.master, alice, incReserve + drops(baseFee - 1)));
171 auto checkAliceOwnerMintedBurned = [&env,
this, &alice](
184 ss <<
"Wrong " << type <<
" count. Found: " << found
185 <<
"; Expected: " << exp;
186 fail(ss.
str(), __FILE__, line);
189 oneCheck(
"owner", ownerCount(env, alice), owners);
190 oneCheck(
"minted",
mintedCount(env, alice), minted);
191 oneCheck(
"burned",
burnedCount(env, alice), burned);
199 checkAliceOwnerMintedBurned(0, 0, 0, __LINE__);
202 env(pay(env.master, alice, drops(baseFee + 1)));
206 env(token::mint(alice));
209 checkAliceOwnerMintedBurned(1, 1, 0, __LINE__);
213 for (
int i = 1; i < 32; ++i)
215 env(token::mint(alice));
216 checkAliceOwnerMintedBurned(1, i + 1, 0, __LINE__);
223 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
226 env(pay(env.master, alice, incReserve + drops(baseFee * 33 - 1)));
233 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
236 env(pay(env.master, alice, drops(baseFee + 1)));
240 env(token::mint(alice));
242 checkAliceOwnerMintedBurned(2, 33, 0, __LINE__);
249 env(token::burn(alice, token::getID(env, alice, 0, seq++)));
251 checkAliceOwnerMintedBurned((33 - seq) ? 1 : 0, 33, seq, __LINE__);
255 env(token::burn(alice, token::getID(env, alice, 197, 5)),
258 checkAliceOwnerMintedBurned(0, 33, 33, __LINE__);
263 env(token::setMinter(alice, minter));
266 env.le(alice)->getAccountID(sfNFTokenMinter) == minter.id());
270 auto checkMintersOwnerMintedBurned = [&env,
this, &alice, &minter](
278 auto oneCheck = [
this](
288 ss <<
"Wrong " << type <<
" count. Found: " << found
289 <<
"; Expected: " << exp;
290 fail(ss.
str(), __FILE__, line);
293 oneCheck(
"alice owner", ownerCount(env, alice), aliceOwners, line);
295 "alice minted",
mintedCount(env, alice), aliceMinted, line);
297 "alice burned",
burnedCount(env, alice), aliceBurned, line);
299 "minter owner", ownerCount(env, minter), minterOwners, line);
301 "minter minted",
mintedCount(env, minter), minterMinted, line);
303 "minter burned",
burnedCount(env, minter), minterBurned, line);
309 env(pay(env.master, minter, incReserve - drops(1)));
311 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
316 env(token::mint(minter),
317 token::issuer(alice),
321 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
324 env(pay(env.master, minter, drops(baseFee + 1)));
328 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
330 checkMintersOwnerMintedBurned(0, 34, nftSeq, 1, 0, 0, __LINE__);
334 for (
int i = 1; i < 32; ++i)
336 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
337 checkMintersOwnerMintedBurned(0, i + 34, nftSeq, 1, 0, 0, __LINE__);
342 env(pay(env.master, minter, incReserve + drops(baseFee * 32 - 1)));
347 env(token::mint(minter),
348 token::issuer(alice),
352 checkMintersOwnerMintedBurned(0, 65, nftSeq, 1, 0, 0, __LINE__);
355 env(pay(env.master, minter, drops(baseFee + 1)));
359 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
361 checkMintersOwnerMintedBurned(0, 66, nftSeq, 2, 0, 0, __LINE__);
366 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
368 checkMintersOwnerMintedBurned(
369 0, 66, nftSeq, (65 - seq) ? 1 : 0, 0, 0, __LINE__);
374 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
376 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
379 env(token::burn(minter, token::getID(env, alice, 2009, 3)),
382 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
585 testcase(
"Invalid NFT offer create");
587 using namespace test::jtx;
589 Env env{*
this, features};
590 Account
const alice{
"alice"};
591 Account
const buyer{
"buyer"};
592 Account
const gw(
"gw");
593 IOU
const gwAUD(gw[
"AUD"]);
598 env.fund(XRP(250), alice, buyer, gw);
600 BEAST_EXPECT(ownerCount(env, alice) == 0);
604 env(token::mint(alice, 0u),
608 BEAST_EXPECT(ownerCount(env, alice) == 1);
614 BEAST_EXPECT(ownerCount(env, alice) == 1);
616 uint256 nftNoXferID = token::getNextID(env, alice, 0);
617 env(token::mint(alice, 0));
619 BEAST_EXPECT(ownerCount(env, alice) == 1);
630 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
634 BEAST_EXPECT(ownerCount(env, buyer) == 0);
637 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
641 BEAST_EXPECT(ownerCount(env, buyer) == 0);
644 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
648 BEAST_EXPECT(ownerCount(env, buyer) == 0);
651 env(token::createOffer(buyer, nftXrpOnlyID, buyer[
"USD"](1)),
653 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](0)),
655 env(token::createOffer(buyer, nftXrpOnlyID, drops(0)),
658 BEAST_EXPECT(ownerCount(env, buyer) == 0);
661 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](1)),
662 token::expiration(0),
665 BEAST_EXPECT(ownerCount(env, buyer) == 0);
669 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
672 BEAST_EXPECT(ownerCount(env, buyer) == 0);
675 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
680 BEAST_EXPECT(ownerCount(env, alice) == 1);
683 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
687 BEAST_EXPECT(ownerCount(env, alice) == 1);
690 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
691 token::destination(alice),
695 BEAST_EXPECT(ownerCount(env, alice) == 1);
698 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
699 token::destination(Account(
"demon")),
703 BEAST_EXPECT(ownerCount(env, alice) == 1);
709 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
714 BEAST_EXPECT(ownerCount(env, buyer) == 0);
717 env(token::createOffer(
718 buyer, token::getID(env, alice, 0, 1), XRP(1000)),
722 BEAST_EXPECT(ownerCount(env, buyer) == 0);
725 env(token::createOffer(
726 alice, token::getID(env, alice, 0, 1), XRP(1000)),
730 BEAST_EXPECT(ownerCount(env, buyer) == 0);
733 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
737 BEAST_EXPECT(ownerCount(env, buyer) == 0);
739 env(trust(buyer, gwAUD(1000)));
741 BEAST_EXPECT(ownerCount(env, buyer) == 1);
745 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
749 BEAST_EXPECT(ownerCount(env, buyer) == 1);
757 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
761 BEAST_EXPECT(ownerCount(env, buyer) == 1);
768 env(token::createOffer(buyer, nftNoXferID, gwAUD(1000)),
772 BEAST_EXPECT(ownerCount(env, buyer) == 1);
778 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
782 BEAST_EXPECT(ownerCount(env, buyer) == 1);
787 env(trust(buyer, gwAUD(1000)));
790 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
794 BEAST_EXPECT(ownerCount(env, buyer) == 1);
800 env(pay(gw, buyer, gwAUD(999)));
805 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
809 BEAST_EXPECT(ownerCount(env, buyer) == 1);
812 auto const baseFee = env.current()->fees().base;
813 env(pay(env.master, buyer, XRP(50) + drops(baseFee * 12 - 1)));
816 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
820 BEAST_EXPECT(ownerCount(env, buyer) == 1);
823 env(pay(env.master, buyer, drops(baseFee + 1)));
828 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
832 BEAST_EXPECT(ownerCount(env, buyer) == 2);
958 testcase(
"Invalid NFT offer accept");
960 using namespace test::jtx;
962 Env env{*
this, features};
963 Account
const alice{
"alice"};
964 Account
const buyer{
"buyer"};
965 Account
const gw(
"gw");
966 IOU
const gwAUD(gw[
"AUD"]);
968 env.fund(XRP(1000), alice, buyer, gw);
970 BEAST_EXPECT(ownerCount(env, alice) == 0);
976 BEAST_EXPECT(ownerCount(env, alice) == 1);
982 BEAST_EXPECT(ownerCount(env, alice) == 1);
984 uint256 nftNoXferID = token::getNextID(env, alice, 0);
985 env(token::mint(alice, 0));
987 BEAST_EXPECT(ownerCount(env, alice) == 1);
990 uint256 const plainOfferIndex =
992 env(token::createOffer(alice, nftAlice0ID, XRP(10)),
995 BEAST_EXPECT(ownerCount(env, alice) == 2);
999 env(token::createOffer(alice, nftAlice0ID, gwAUD(30)),
1002 BEAST_EXPECT(ownerCount(env, alice) == 3);
1004 uint256 const xrpOnlyOfferIndex =
1006 env(token::createOffer(alice, nftXrpOnlyID, XRP(20)),
1009 BEAST_EXPECT(ownerCount(env, alice) == 4);
1011 uint256 const noXferOfferIndex =
1013 env(token::createOffer(alice, nftNoXferID, XRP(30)),
1016 BEAST_EXPECT(ownerCount(env, alice) == 5);
1019 uint256 const aliceExpOfferIndex =
1021 env(token::createOffer(alice, nftNoXferID, XRP(40)),
1025 BEAST_EXPECT(ownerCount(env, alice) == 6);
1031 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1035 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1038 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1039 txflags(0x00008000),
1042 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1046 Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1050 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1055 Json::Value jv = token::acceptBuyOffer(buyer, noXferOfferIndex);
1056 jv[sfNFTokenBrokerFee.jsonName] =
1060 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1065 Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1066 jv[sfNFTokenBrokerFee.jsonName] =
1070 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1074 env(token::brokerOffers(buyer, noXferOfferIndex, xrpOnlyOfferIndex),
1075 token::brokerFee(gwAUD(0)),
1078 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1084 env(token::acceptBuyOffer(buyer, beast::zero),
1087 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1091 env(token::acceptBuyOffer(buyer, missingOfferIndex),
1094 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1097 env(token::acceptBuyOffer(buyer, aliceExpOfferIndex), ter(
tecEXPIRED));
1099 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1102 env(token::acceptSellOffer(buyer, beast::zero),
1105 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1108 env(token::acceptSellOffer(buyer, missingOfferIndex),
1111 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1114 env(token::acceptSellOffer(buyer, aliceExpOfferIndex), ter(
tecEXPIRED));
1116 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1123 env(trust(alice, gwAUD(1000)));
1124 env(trust(buyer, gwAUD(1000)));
1126 env(pay(gw, buyer, gwAUD(30)));
1128 BEAST_EXPECT(ownerCount(env, alice) == 7);
1129 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1135 uint256 const buyerOfferIndex =
1137 env(token::createOffer(buyer, nftAlice0ID, gwAUD(29)),
1138 token::owner(alice));
1140 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1143 env(token::brokerOffers(gw, buyerOfferIndex, xrpOnlyOfferIndex),
1146 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1149 env(token::brokerOffers(gw, buyerOfferIndex, plainOfferIndex),
1152 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1156 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1159 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1162 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1164 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1168 uint256 const buyerOfferIndex =
1170 env(token::createOffer(buyer, nftAlice0ID, gwAUD(31)),
1171 token::owner(alice));
1173 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1177 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1178 token::brokerFee(XRP(40)),
1181 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1184 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1185 token::brokerFee(gwAUD(31)),
1188 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1192 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1193 token::brokerFee(gwAUD(1.5)),
1196 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1199 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1201 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1207 uint256 const buyerOfferIndex =
1209 env(token::createOffer(buyer, nftAlice0ID, gwAUD(30)),
1210 token::owner(alice));
1212 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1215 env(token::acceptBuyOffer(buyer, plainOfferIndex),
1218 BEAST_EXPECT(ownerCount(env, alice) == 7);
1221 env(token::acceptBuyOffer(buyer, buyerOfferIndex),
1224 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1227 env(pay(buyer, gw, gwAUD(30)));
1229 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1230 env(token::acceptBuyOffer(alice, buyerOfferIndex),
1233 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1239 env(token::createOffer(alice, nftAlice0ID, XRP(0)),
1242 env(token::acceptSellOffer(gw, offerIndex));
1244 BEAST_EXPECT(ownerCount(env, alice) == 7);
1246 env(pay(gw, buyer, gwAUD(30)));
1250 env(token::acceptBuyOffer(alice, buyerOfferIndex),
1253 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1256 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1258 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1264 uint256 const buyerOfferIndex =
1266 env(token::createOffer(buyer, nftXrpOnlyID, XRP(30)),
1267 token::owner(alice));
1269 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1272 env(token::acceptSellOffer(alice, buyerOfferIndex),
1275 BEAST_EXPECT(ownerCount(env, alice) == 7);
1278 env(token::acceptSellOffer(alice, plainOfferIndex),
1281 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1285 env(token::acceptSellOffer(buyer, plainOfferIndex),
1288 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1296 env(token::createOffer(gw, nftAlice0ID, XRP(0)),
1299 env(token::acceptSellOffer(alice, offerIndex));
1301 BEAST_EXPECT(ownerCount(env, alice) == 7);
1303 env(pay(buyer, gw, gwAUD(30)));
1305 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1306 env(token::acceptSellOffer(buyer, audOfferIndex),
1309 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1535 testcase(
"Mint flagCreateTrustLines");
1537 using namespace test::jtx;
1539 Account
const alice{
"alice"};
1540 Account
const becky{
"becky"};
1541 Account
const cheri{
"cheri"};
1542 Account
const gw(
"gw");
1543 IOU
const gwAUD(gw[
"AUD"]);
1544 IOU
const gwCAD(gw[
"CAD"]);
1545 IOU
const gwEUR(gw[
"EUR"]);
1550 for (
auto const& tweakedFeatures :
1551 {features - fixRemoveNFTokenAutoTrustLine,
1552 features | fixRemoveNFTokenAutoTrustLine})
1554 Env env{*
this, tweakedFeatures};
1555 env.fund(XRP(1000), alice, becky, cheri, gw);
1559 env(trust(becky, gwAUD(1000)));
1560 env(trust(cheri, gwAUD(1000)));
1561 env(trust(becky, gwCAD(1000)));
1562 env(trust(cheri, gwCAD(1000)));
1563 env(trust(becky, gwEUR(1000)));
1564 env(trust(cheri, gwEUR(1000)));
1566 env(pay(gw, becky, gwAUD(500)));
1567 env(pay(gw, becky, gwCAD(500)));
1568 env(pay(gw, becky, gwEUR(500)));
1569 env(pay(gw, cheri, gwAUD(500)));
1570 env(pay(gw, cheri, gwCAD(500)));
1577 uint256 const nftNoAutoTrustID{
1579 env(token::mint(alice, 0u),
1580 token::xferFee(xferFee),
1585 uint256 const beckyBuyOfferIndex =
1587 env(token::createOffer(becky, nftNoAutoTrustID, drops(1)),
1588 token::owner(alice));
1590 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1594 TER const createOfferTER =
1596 uint256 const beckyOfferIndex =
1598 env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)),
1600 ter(createOfferTER));
1604 uint256 const cheriOfferIndex =
1606 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
1607 token::owner(becky),
1608 ter(createOfferTER));
1612 env(token::cancelOffer(becky, {beckyOfferIndex}));
1613 env(token::cancelOffer(cheri, {cheriOfferIndex}));
1621 uint256 const nftAutoTrustID{token::getNextID(
1628 tweakedFeatures[fixRemoveNFTokenAutoTrustLine]
1632 env(token::mint(alice, 0u),
1633 token::xferFee(transferFee),
1640 if (tweakedFeatures[fixRemoveNFTokenAutoTrustLine])
1644 uint256 const beckyBuyOfferIndex =
1646 env(token::createOffer(becky, nftAutoTrustID, drops(1)),
1647 token::owner(alice));
1649 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1653 uint256 const beckySellOfferIndex =
1655 env(token::createOffer(becky, nftAutoTrustID, gwAUD(100)),
1658 env(token::acceptSellOffer(cheri, beckySellOfferIndex));
1662 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1665 uint256 const beckyBuyBackOfferIndex =
1667 env(token::createOffer(becky, nftAutoTrustID, gwCAD(50)),
1668 token::owner(cheri));
1670 env(token::acceptBuyOffer(cheri, beckyBuyBackOfferIndex));
1674 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
1675 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(5));
1681 uint256 const nftNoAutoTrustID{token::getNextID(
1683 env(token::mint(alice, 0u),
1684 token::xferFee(transferFee),
1689 uint256 const aliceSellOfferIndex =
1691 env(token::createOffer(alice, nftNoAutoTrustID, gwAUD(200)),
1694 env(token::acceptSellOffer(cheri, aliceSellOfferIndex));
1700 BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(210));
1703 env(token::createOffer(cheri, nftNoAutoTrustID, gwEUR(50)),
1707 uint256 const cheriSellOfferIndex =
1709 env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
1712 env(token::acceptSellOffer(becky, cheriSellOfferIndex));
1718 BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(10));
1729 using namespace test::jtx;
1731 Env env{*
this, features};
1733 Account
const alice{
"alice"};
1734 Account
const becky{
"becky"};
1735 Account
const minter{
"minter"};
1737 env.fund(XRP(1000), alice, becky, minter);
1742 BEAST_EXPECT(ownerCount(env, alice) == 0);
1743 uint256 const nftAliceNoTransferID{
1744 token::getNextID(env, alice, 0u)};
1745 env(token::mint(alice, 0u), token::xferFee(0));
1747 BEAST_EXPECT(ownerCount(env, alice) == 1);
1750 BEAST_EXPECT(ownerCount(env, becky) == 0);
1751 env(token::createOffer(becky, nftAliceNoTransferID, XRP(20)),
1752 token::owner(alice),
1756 uint256 const aliceSellOfferIndex =
1758 env(token::createOffer(alice, nftAliceNoTransferID, XRP(20)),
1761 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1763 BEAST_EXPECT(ownerCount(env, alice) == 0);
1764 BEAST_EXPECT(ownerCount(env, becky) == 1);
1767 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1771 BEAST_EXPECT(ownerCount(env, alice) == 0);
1772 BEAST_EXPECT(ownerCount(env, becky) == 1);
1776 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1778 token::destination(alice),
1781 BEAST_EXPECT(ownerCount(env, alice) == 0);
1782 BEAST_EXPECT(ownerCount(env, becky) == 1);
1786 uint256 const aliceBuyOfferIndex =
1788 env(token::createOffer(alice, nftAliceNoTransferID, XRP(22)),
1789 token::owner(becky));
1791 env(token::acceptBuyOffer(becky, aliceBuyOfferIndex));
1793 BEAST_EXPECT(ownerCount(env, alice) == 1);
1794 BEAST_EXPECT(ownerCount(env, becky) == 0);
1797 env(token::burn(alice, nftAliceNoTransferID));
1799 BEAST_EXPECT(ownerCount(env, alice) == 0);
1800 BEAST_EXPECT(ownerCount(env, becky) == 0);
1804 env(token::setMinter(alice, minter));
1807 BEAST_EXPECT(ownerCount(env, minter) == 0);
1808 uint256 const nftMinterNoTransferID{
1809 token::getNextID(env, alice, 0u)};
1810 env(token::mint(minter), token::issuer(alice));
1812 BEAST_EXPECT(ownerCount(env, minter) == 1);
1815 BEAST_EXPECT(ownerCount(env, becky) == 0);
1816 env(token::createOffer(becky, nftMinterNoTransferID, XRP(20)),
1817 token::owner(minter),
1820 BEAST_EXPECT(ownerCount(env, becky) == 0);
1823 env(token::clearMinter(alice));
1827 BEAST_EXPECT(ownerCount(env, minter) == 1);
1828 env(token::createOffer(minter, nftMinterNoTransferID, XRP(21)),
1832 BEAST_EXPECT(ownerCount(env, minter) == 1);
1836 for (
int i = 0; i < 10; ++i)
1839 env(token::setMinter(alice, minter));
1841 BEAST_EXPECT(ownerCount(env, minter) == 1);
1844 BEAST_EXPECT(ownerCount(env, minter) == 1);
1845 uint256 const minterSellOfferIndex =
1847 env(token::createOffer(minter, nftMinterNoTransferID, XRP(22)),
1850 BEAST_EXPECT(ownerCount(env, minter) == 2);
1854 env(token::clearMinter(alice));
1859 BEAST_EXPECT(ownerCount(env, becky) == 0);
1860 env(token::acceptSellOffer(becky, minterSellOfferIndex));
1862 BEAST_EXPECT(ownerCount(env, becky) == 1);
1863 BEAST_EXPECT(ownerCount(env, minter) == 0);
1866 env(token::createOffer(becky, nftMinterNoTransferID, XRP(23)),
1873 BEAST_EXPECT(ownerCount(env, minter) == 0);
1874 env(token::createOffer(minter, nftMinterNoTransferID, XRP(24)),
1875 token::owner(becky),
1878 BEAST_EXPECT(ownerCount(env, minter) == 0);
1881 BEAST_EXPECT(ownerCount(env, alice) == 0);
1882 uint256 const aliceBuyOfferIndex =
1884 env(token::createOffer(alice, nftMinterNoTransferID, XRP(25)),
1885 token::owner(becky));
1887 BEAST_EXPECT(ownerCount(env, alice) == 1);
1891 for (
int i = 0; i < 10; ++i)
1894 env(token::setMinter(alice, minter));
1898 BEAST_EXPECT(ownerCount(env, minter) == 0);
1899 uint256 const minterBuyOfferIndex =
1901 env(token::createOffer(minter, nftMinterNoTransferID, XRP(26)),
1902 token::owner(becky));
1904 BEAST_EXPECT(ownerCount(env, minter) == 1);
1908 env(token::clearMinter(alice));
1912 BEAST_EXPECT(ownerCount(env, minter) == 1);
1913 BEAST_EXPECT(ownerCount(env, becky) == 1);
1914 env(token::acceptBuyOffer(becky, minterBuyOfferIndex));
1916 BEAST_EXPECT(ownerCount(env, minter) == 1);
1917 BEAST_EXPECT(ownerCount(env, becky) == 0);
1918 BEAST_EXPECT(ownerCount(env, alice) == 1);
1922 env(token::burn(minter, nftMinterNoTransferID), ter(
tesSUCCESS));
1924 env(token::cancelOffer(alice, {aliceBuyOfferIndex}));
1926 BEAST_EXPECT(ownerCount(env, alice) == 0);
1927 BEAST_EXPECT(ownerCount(env, becky) == 0);
1928 BEAST_EXPECT(ownerCount(env, minter) == 0);
1933 BEAST_EXPECT(ownerCount(env, alice) == 0);
1938 BEAST_EXPECT(ownerCount(env, alice) == 1);
1941 uint256 const aliceSellOfferIndex =
1943 env(token::createOffer(alice, nftAliceID, XRP(20)),
1946 BEAST_EXPECT(ownerCount(env, alice) == 2);
1948 uint256 const beckyBuyOfferIndex =
1950 env(token::createOffer(becky, nftAliceID, XRP(21)),
1951 token::owner(alice));
1953 BEAST_EXPECT(ownerCount(env, alice) == 2);
1956 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1958 BEAST_EXPECT(ownerCount(env, alice) == 0);
1959 BEAST_EXPECT(ownerCount(env, becky) == 2);
1962 uint256 const beckySellOfferIndex =
1964 env(token::createOffer(becky, nftAliceID, XRP(22)),
1967 BEAST_EXPECT(ownerCount(env, alice) == 0);
1968 BEAST_EXPECT(ownerCount(env, becky) == 3);
1972 env(token::acceptSellOffer(minter, beckySellOfferIndex));
1974 BEAST_EXPECT(ownerCount(env, alice) == 0);
1975 BEAST_EXPECT(ownerCount(env, becky) == 1);
1976 BEAST_EXPECT(ownerCount(env, minter) == 1);
1979 uint256 const minterSellOfferIndex =
1981 env(token::createOffer(minter, nftAliceID, XRP(23)),
1984 BEAST_EXPECT(ownerCount(env, alice) == 0);
1985 BEAST_EXPECT(ownerCount(env, becky) == 1);
1986 BEAST_EXPECT(ownerCount(env, minter) == 2);
1989 env(token::acceptSellOffer(alice, minterSellOfferIndex));
1991 BEAST_EXPECT(ownerCount(env, alice) == 1);
1992 BEAST_EXPECT(ownerCount(env, becky) == 1);
1993 BEAST_EXPECT(ownerCount(env, minter) == 0);
1997 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
1999 BEAST_EXPECT(ownerCount(env, alice) == 0);
2000 BEAST_EXPECT(ownerCount(env, becky) == 1);
2001 BEAST_EXPECT(ownerCount(env, minter) == 0);
2005 env(token::burn(becky, nftAliceID));
2007 BEAST_EXPECT(ownerCount(env, alice) == 0);
2008 BEAST_EXPECT(ownerCount(env, becky) == 0);
2009 BEAST_EXPECT(ownerCount(env, minter) == 0);
2019 using namespace test::jtx;
2021 Env env{*
this, features};
2022 auto const baseFee = env.current()->fees().base;
2024 Account
const alice{
"alice"};
2025 Account
const becky{
"becky"};
2026 Account
const carol{
"carol"};
2027 Account
const minter{
"minter"};
2028 Account
const gw{
"gw"};
2029 IOU
const gwXAU(gw[
"XAU"]);
2031 env.fund(XRP(1000), alice, becky, carol, minter, gw);
2034 env(trust(alice, gwXAU(2000)));
2035 env(trust(becky, gwXAU(2000)));
2036 env(trust(carol, gwXAU(2000)));
2037 env(trust(minter, gwXAU(2000)));
2039 env(pay(gw, alice, gwXAU(1000)));
2040 env(pay(gw, becky, gwXAU(1000)));
2041 env(pay(gw, carol, gwXAU(1000)));
2042 env(pay(gw, minter, gwXAU(1000)));
2047 env(token::setMinter(alice, minter));
2053 BEAST_EXPECT(ownerCount(env, alice) == 1);
2054 BEAST_EXPECT(ownerCount(env, becky) == 1);
2055 BEAST_EXPECT(ownerCount(env, carol) == 1);
2056 BEAST_EXPECT(ownerCount(env, minter) == 1);
2064 uint256 const beckyBuyOfferIndex =
2066 env(token::createOffer(becky, nftID, gwXAU(10)),
2067 token::owner(alice));
2069 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2070 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2072 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2074 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2075 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2078 uint256 const beckySellOfferIndex =
2080 env(token::createOffer(becky, nftID, gwXAU(10)),
2083 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2085 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2086 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2087 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2090 uint256 const minterBuyOfferIndex =
2092 env(token::createOffer(minter, nftID, gwXAU(10)),
2093 token::owner(carol));
2095 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2097 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2098 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2099 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2100 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2104 uint256 const minterSellOfferIndex =
2106 env(token::createOffer(minter, nftID, gwXAU(10)),
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));
2119 BEAST_EXPECT(ownerCount(env, alice) == 1);
2120 BEAST_EXPECT(ownerCount(env, becky) == 1);
2121 BEAST_EXPECT(ownerCount(env, carol) == 1);
2122 BEAST_EXPECT(ownerCount(env, minter) == 1);
2130 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2134 uint256 const beckyBuyOfferIndex =
2136 env(token::createOffer(becky, nftID, gwXAU(10)),
2137 token::owner(alice));
2139 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2140 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2142 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2144 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2145 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2148 uint256 const beckySellOfferIndex =
2150 env(token::createOffer(becky, nftID, gwXAU(10)),
2153 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2156 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0001));
2157 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2158 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2161 uint256 const minterBuyOfferIndex =
2163 env(token::createOffer(minter, nftID, gwXAU(10)),
2164 token::owner(carol));
2166 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2169 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0002));
2170 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2171 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2172 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2176 uint256 const minterSellOfferIndex =
2178 env(token::createOffer(minter, nftID, gwXAU(10)),
2181 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2183 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000.0002));
2184 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2185 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2186 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2190 env(pay(alice, becky, gwXAU(0.0001)));
2191 env(pay(alice, carol, gwXAU(0.0001)));
2194 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2195 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2196 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2197 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2200 env(token::burn(alice, nftID));
2202 BEAST_EXPECT(ownerCount(env, alice) == 1);
2203 BEAST_EXPECT(ownerCount(env, becky) == 1);
2204 BEAST_EXPECT(ownerCount(env, carol) == 1);
2205 BEAST_EXPECT(ownerCount(env, minter) == 1);
2211 env(token::mint(alice),
2218 uint256 const nftID = token::getNextID(
2220 env(token::mint(alice),
2226 uint256 const beckyBuyOfferIndex =
2228 env(token::createOffer(becky, nftID, gwXAU(10)),
2229 token::owner(alice));
2231 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2232 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2234 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2236 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2237 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2240 uint256 const beckySellOfferIndex =
2242 env(token::createOffer(becky, nftID, gwXAU(100)),
2245 env(token::acceptSellOffer(minter, beckySellOfferIndex));
2248 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1060));
2249 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2250 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
2253 uint256 const carolBuyOfferIndex =
2255 env(token::createOffer(carol, nftID, gwXAU(10)),
2256 token::owner(minter));
2258 env(token::acceptBuyOffer(minter, carolBuyOfferIndex));
2261 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1065));
2262 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2263 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2264 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2268 uint256 const carolSellOfferIndex =
2270 env(token::createOffer(carol, nftID, gwXAU(10)),
2273 env(token::acceptSellOffer(alice, carolSellOfferIndex));
2276 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1055));
2277 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2278 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2279 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2282 env(pay(alice, minter, gwXAU(55)));
2283 env(pay(becky, minter, gwXAU(40)));
2285 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2286 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2287 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2288 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2291 env(token::burn(alice, nftID));
2293 BEAST_EXPECT(ownerCount(env, alice) == 1);
2294 BEAST_EXPECT(ownerCount(env, becky) == 1);
2295 BEAST_EXPECT(ownerCount(env, carol) == 1);
2296 BEAST_EXPECT(ownerCount(env, minter) == 1);
2301 for (
auto NumberSwitchOver : {
true})
2303 if (NumberSwitchOver)
2304 env.enableFeature(fixUniversalNumber);
2306 env.disableFeature(fixUniversalNumber);
2311 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2316 STAmount aliceBalance = env.balance(alice);
2317 STAmount minterBalance = env.balance(minter);
2318 uint256 const minterBuyOfferIndex =
2320 env(token::createOffer(minter, nftID, XRP(1)), token::owner(alice));
2322 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2324 aliceBalance += XRP(1) - baseFee;
2325 minterBalance -= XRP(1) + baseFee;
2326 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2327 BEAST_EXPECT(env.balance(minter) == minterBalance);
2331 auto pmt = NumberSwitchOver ? drops(50000) : drops(99999);
2332 STAmount carolBalance = env.balance(carol);
2333 uint256 const minterSellOfferIndex =
2335 env(token::createOffer(minter, nftID, pmt), txflags(
tfSellNFToken));
2337 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2339 minterBalance += pmt - baseFee;
2340 carolBalance -= pmt + baseFee;
2341 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2342 BEAST_EXPECT(env.balance(minter) == minterBalance);
2343 BEAST_EXPECT(env.balance(carol) == carolBalance);
2347 STAmount beckyBalance = env.balance(becky);
2348 uint256 const beckyBuyOfferIndex =
2350 pmt = NumberSwitchOver ? drops(50001) : drops(100000);
2351 env(token::createOffer(becky, nftID, pmt), token::owner(carol));
2353 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2355 carolBalance += pmt - drops(1) - baseFee;
2356 beckyBalance -= pmt + baseFee;
2357 aliceBalance += drops(1);
2359 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2360 BEAST_EXPECT(env.balance(minter) == minterBalance);
2361 BEAST_EXPECT(env.balance(carol) == carolBalance);
2362 BEAST_EXPECT(env.balance(becky) == beckyBalance);
2371 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2377 env(pay(alice, gw, env.balance(alice, gwXAU)));
2378 env(pay(minter, gw, env.balance(minter, gwXAU)));
2379 env(pay(becky, gw, env.balance(becky, gwXAU)));
2384 env(pay(gw, alice, startXAUBalance));
2385 env(pay(gw, minter, startXAUBalance));
2386 env(pay(gw, becky, startXAUBalance));
2395 STAmount aliceBalance = env.balance(alice, gwXAU);
2396 STAmount minterBalance = env.balance(minter, gwXAU);
2397 uint256 const minterBuyOfferIndex =
2399 env(token::createOffer(minter, nftID, tinyXAU),
2400 token::owner(alice));
2402 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2404 aliceBalance += tinyXAU;
2405 minterBalance -= tinyXAU;
2406 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2407 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2410 STAmount carolBalance = env.balance(carol, gwXAU);
2411 uint256 const minterSellOfferIndex =
2413 env(token::createOffer(minter, nftID, tinyXAU),
2416 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2419 minterBalance += tinyXAU;
2420 carolBalance -= tinyXAU;
2422 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2423 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2424 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2431 STAmount beckyBalance = env.balance(becky, gwXAU);
2432 uint256 const beckyBuyOfferIndex =
2434 env(token::createOffer(becky, nftID, cheapNFT),
2435 token::owner(carol));
2437 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2440 aliceBalance += tinyXAU;
2441 beckyBalance -= cheapNFT;
2442 carolBalance += cheapNFT - tinyXAU;
2443 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2444 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2445 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2446 BEAST_EXPECT(env.balance(becky, gwXAU) == beckyBalance);
2639 testcase(
"Create offer destination");
2641 using namespace test::jtx;
2643 Env env{*
this, features};
2645 Account
const issuer{
"issuer"};
2646 Account
const minter{
"minter"};
2647 Account
const buyer{
"buyer"};
2648 Account
const broker{
"broker"};
2650 env.fund(XRP(1000), issuer, minter, buyer, broker);
2654 env(token::setMinter(issuer, minter));
2659 env(token::mint(minter, 0),
2660 token::issuer(issuer),
2667 uint256 const offerMinterToIssuer =
2669 env(token::createOffer(minter, nftokenID, drops(1)),
2670 token::destination(issuer),
2673 uint256 const offerMinterToBuyer =
2675 env(token::createOffer(minter, nftokenID, drops(1)),
2676 token::destination(buyer),
2679 uint256 const offerIssuerToMinter =
2681 env(token::createOffer(issuer, nftokenID, drops(1)),
2682 token::owner(minter),
2683 token::destination(minter));
2685 uint256 const offerIssuerToBuyer =
2687 env(token::createOffer(issuer, nftokenID, drops(1)),
2688 token::owner(minter),
2689 token::destination(buyer));
2692 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2693 BEAST_EXPECT(ownerCount(env, minter) == 3);
2694 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2703 env(token::cancelOffer(issuer, {offerMinterToBuyer}),
2705 env(token::cancelOffer(buyer, {offerMinterToIssuer}),
2707 env(token::cancelOffer(buyer, {offerIssuerToMinter}),
2709 env(token::cancelOffer(minter, {offerIssuerToBuyer}),
2712 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2713 BEAST_EXPECT(ownerCount(env, minter) == 3);
2714 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2718 env(token::cancelOffer(buyer, {offerMinterToBuyer}));
2719 env(token::cancelOffer(minter, {offerMinterToIssuer}));
2720 env(token::cancelOffer(buyer, {offerIssuerToBuyer}));
2721 env(token::cancelOffer(issuer, {offerIssuerToMinter}));
2723 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2724 BEAST_EXPECT(ownerCount(env, minter) == 1);
2725 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2731 uint256 const offerMinterSellsToBuyer =
2733 env(token::createOffer(minter, nftokenID, drops(1)),
2734 token::destination(buyer),
2737 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2738 BEAST_EXPECT(ownerCount(env, minter) == 2);
2739 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2743 env(token::acceptSellOffer(issuer, offerMinterSellsToBuyer),
2746 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2747 BEAST_EXPECT(ownerCount(env, minter) == 2);
2748 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2751 env(token::acceptSellOffer(buyer, offerMinterSellsToBuyer));
2753 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2754 BEAST_EXPECT(ownerCount(env, minter) == 0);
2755 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2761 uint256 const offerMinterBuysFromBuyer =
2763 env(token::createOffer(minter, nftokenID, drops(1)),
2764 token::owner(buyer),
2765 token::destination(buyer));
2767 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2768 BEAST_EXPECT(ownerCount(env, minter) == 1);
2769 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2773 env(token::acceptBuyOffer(issuer, offerMinterBuysFromBuyer),
2776 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2777 BEAST_EXPECT(ownerCount(env, minter) == 1);
2778 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2781 env(token::acceptBuyOffer(buyer, offerMinterBuysFromBuyer));
2783 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2784 BEAST_EXPECT(ownerCount(env, minter) == 1);
2785 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2790 uint256 const offerBuyerBuysFromMinter =
2792 env(token::createOffer(buyer, nftokenID, drops(1)),
2793 token::owner(minter),
2794 token::destination(broker));
2796 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2797 BEAST_EXPECT(ownerCount(env, minter) == 1);
2798 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2800 env(token::acceptBuyOffer(minter, offerBuyerBuysFromMinter),
2805 env(token::cancelOffer(buyer, {offerBuyerBuysFromMinter}));
2807 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2808 BEAST_EXPECT(ownerCount(env, minter) == 1);
2809 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2815 uint256 const offerMinterToBroker =
2817 env(token::createOffer(minter, nftokenID, drops(1)),
2818 token::destination(broker),
2821 uint256 const offerBuyerToMinter =
2823 env(token::createOffer(buyer, nftokenID, drops(1)),
2824 token::owner(minter));
2827 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2828 BEAST_EXPECT(ownerCount(env, minter) == 2);
2829 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2834 env(token::brokerOffers(
2835 issuer, offerBuyerToMinter, offerMinterToBroker),
2838 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2839 BEAST_EXPECT(ownerCount(env, minter) == 2);
2840 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2845 env(token::brokerOffers(
2846 broker, offerBuyerToMinter, offerMinterToBroker));
2848 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2849 BEAST_EXPECT(ownerCount(env, minter) == 0);
2850 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2857 uint256 const offerBuyerToMinter =
2859 env(token::createOffer(buyer, nftokenID, drops(1)),
2860 token::destination(minter),
2863 uint256 const offerMinterToBuyer =
2865 env(token::createOffer(minter, nftokenID, drops(1)),
2866 token::owner(buyer));
2868 uint256 const offerIssuerToBuyer =
2870 env(token::createOffer(issuer, nftokenID, drops(1)),
2871 token::owner(buyer));
2874 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2875 BEAST_EXPECT(ownerCount(env, minter) == 1);
2876 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2881 env(token::brokerOffers(
2882 broker, offerIssuerToBuyer, offerBuyerToMinter),
2886 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2887 BEAST_EXPECT(ownerCount(env, minter) == 1);
2888 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2890 env(token::brokerOffers(
2891 broker, offerMinterToBuyer, offerBuyerToMinter),
2896 env(token::acceptBuyOffer(buyer, offerMinterToBuyer));
2900 env(token::cancelOffer(buyer, {offerBuyerToMinter}));
2903 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2904 BEAST_EXPECT(ownerCount(env, minter) == 1);
2905 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2908 env(token::cancelOffer(issuer, {offerIssuerToBuyer}));
2910 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2911 BEAST_EXPECT(ownerCount(env, minter) == 1);
2912 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2920 uint256 const offerMinterToBroker =
2922 env(token::createOffer(minter, nftokenID, drops(1)),
2923 token::destination(broker),
2926 uint256 const offerBuyerToBroker =
2928 env(token::createOffer(buyer, nftokenID, drops(1)),
2929 token::owner(minter),
2930 token::destination(broker));
2935 env(token::brokerOffers(
2936 issuer, offerBuyerToBroker, offerMinterToBroker),
2939 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2940 BEAST_EXPECT(ownerCount(env, minter) == 2);
2941 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2945 env(token::brokerOffers(
2946 broker, offerBuyerToBroker, offerMinterToBroker));
2948 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2949 BEAST_EXPECT(ownerCount(env, minter) == 0);
2950 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3095 testcase(
"Create offer expiration");
3097 using namespace test::jtx;
3099 Env env{*
this, features};
3101 Account
const issuer{
"issuer"};
3102 Account
const minter{
"minter"};
3103 Account
const buyer{
"buyer"};
3105 env.fund(XRP(1000), issuer, minter, buyer);
3109 env(token::setMinter(issuer, minter));
3114 env(token::mint(minter, 0),
3115 token::issuer(issuer),
3121 env(token::mint(minter, 0),
3122 token::issuer(issuer),
3131 uint256 const offerMinterToIssuer =
3133 env(token::createOffer(minter, nftokenID0, drops(1)),
3134 token::destination(issuer),
3135 token::expiration(expiration),
3138 uint256 const offerMinterToAnyone =
3140 env(token::createOffer(minter, nftokenID0, drops(1)),
3141 token::expiration(expiration),
3144 uint256 const offerIssuerToMinter =
3146 env(token::createOffer(issuer, nftokenID0, drops(1)),
3147 token::owner(minter),
3148 token::expiration(expiration));
3150 uint256 const offerBuyerToMinter =
3152 env(token::createOffer(buyer, nftokenID0, drops(1)),
3153 token::owner(minter),
3154 token::expiration(expiration));
3156 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3157 BEAST_EXPECT(ownerCount(env, minter) == 3);
3158 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3166 env(token::cancelOffer(issuer, {offerMinterToAnyone}),
3168 env(token::cancelOffer(buyer, {offerIssuerToMinter}),
3171 BEAST_EXPECT(
lastClose(env) < expiration);
3172 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3173 BEAST_EXPECT(ownerCount(env, minter) == 3);
3174 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3177 env(token::cancelOffer(minter, {offerMinterToAnyone}));
3181 env(token::cancelOffer(issuer, {offerMinterToIssuer}));
3187 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3188 BEAST_EXPECT(ownerCount(env, minter) == 1);
3189 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3192 env(token::cancelOffer(issuer, {offerBuyerToMinter}));
3193 env(token::cancelOffer(buyer, {offerIssuerToMinter}));
3195 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3196 BEAST_EXPECT(ownerCount(env, minter) == 1);
3197 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3208 env(token::createOffer(minter, nftokenID0, drops(1)),
3209 token::expiration(expiration),
3214 env(token::createOffer(minter, nftokenID1, drops(1)),
3215 token::expiration(expiration),
3218 BEAST_EXPECT(
lastClose(env) < expiration);
3219 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3220 BEAST_EXPECT(ownerCount(env, minter) == 3);
3221 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3224 env(token::acceptSellOffer(buyer, offer0));
3230 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3231 BEAST_EXPECT(ownerCount(env, minter) == 2);
3232 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3235 env(token::acceptSellOffer(buyer, offer1), ter(
tecEXPIRED));
3236 env(token::acceptSellOffer(issuer, offer1), ter(
tecEXPIRED));
3240 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3241 BEAST_EXPECT(ownerCount(env, minter) == 2);
3242 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3245 env(token::cancelOffer(issuer, {offer1}));
3247 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3248 BEAST_EXPECT(ownerCount(env, minter) == 1);
3249 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3255 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3257 token::destination(minter));
3259 env(token::acceptSellOffer(minter, offerSellBack));
3261 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3262 BEAST_EXPECT(ownerCount(env, minter) == 1);
3263 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3273 env(token::createOffer(buyer, nftokenID0, drops(1)),
3274 token::owner(minter),
3275 token::expiration(expiration));
3278 env(token::createOffer(buyer, nftokenID1, drops(1)),
3279 token::owner(minter),
3280 token::expiration(expiration));
3282 BEAST_EXPECT(
lastClose(env) < expiration);
3283 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3284 BEAST_EXPECT(ownerCount(env, minter) == 1);
3285 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3288 env(token::acceptBuyOffer(minter, offer0));
3294 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3295 BEAST_EXPECT(ownerCount(env, minter) == 1);
3296 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3299 env(token::acceptBuyOffer(minter, offer1), ter(
tecEXPIRED));
3300 env(token::acceptBuyOffer(issuer, offer1), ter(
tecEXPIRED));
3304 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3305 BEAST_EXPECT(ownerCount(env, minter) == 1);
3306 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3309 env(token::cancelOffer(issuer, {offer1}));
3311 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3312 BEAST_EXPECT(ownerCount(env, minter) == 1);
3313 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3319 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3321 token::destination(minter));
3323 env(token::acceptSellOffer(minter, offerSellBack));
3325 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3326 BEAST_EXPECT(ownerCount(env, minter) == 1);
3327 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3338 env(token::createOffer(minter, nftokenID0, drops(1)),
3339 token::expiration(expiration),
3344 env(token::createOffer(minter, nftokenID1, drops(1)),
3345 token::expiration(expiration),
3350 env(token::createOffer(buyer, nftokenID0, drops(1)),
3351 token::owner(minter));
3355 env(token::createOffer(buyer, nftokenID1, drops(1)),
3356 token::owner(minter));
3359 BEAST_EXPECT(
lastClose(env) < expiration);
3360 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3361 BEAST_EXPECT(ownerCount(env, minter) == 3);
3362 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3365 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3371 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3372 BEAST_EXPECT(ownerCount(env, minter) == 2);
3373 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3376 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3381 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3382 BEAST_EXPECT(ownerCount(env, minter) == 2);
3383 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3386 env(token::cancelOffer(buyer, {buyOffer1, sellOffer1}));
3388 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3389 BEAST_EXPECT(ownerCount(env, minter) == 1);
3390 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3396 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3398 token::destination(minter));
3400 env(token::acceptSellOffer(minter, offerSellBack));
3402 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3403 BEAST_EXPECT(ownerCount(env, minter) == 1);
3404 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3415 env(token::createOffer(minter, nftokenID0, drops(1)),
3420 env(token::createOffer(minter, nftokenID1, drops(1)),
3425 env(token::createOffer(buyer, nftokenID0, drops(1)),
3426 token::expiration(expiration),
3427 token::owner(minter));
3431 env(token::createOffer(buyer, nftokenID1, drops(1)),
3432 token::expiration(expiration),
3433 token::owner(minter));
3436 BEAST_EXPECT(
lastClose(env) < expiration);
3437 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3438 BEAST_EXPECT(ownerCount(env, minter) == 3);
3439 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3442 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3448 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3449 BEAST_EXPECT(ownerCount(env, minter) == 2);
3450 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3453 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3458 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3459 BEAST_EXPECT(ownerCount(env, minter) == 2);
3460 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3463 env(token::cancelOffer(minter, {buyOffer1, sellOffer1}));
3465 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3466 BEAST_EXPECT(ownerCount(env, minter) == 1);
3467 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3473 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3475 token::destination(minter));
3477 env(token::acceptSellOffer(minter, offerSellBack));
3479 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3480 BEAST_EXPECT(ownerCount(env, minter) == 1);
3481 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3493 env(token::createOffer(minter, nftokenID0, drops(1)),
3494 token::expiration(expiration),
3499 env(token::createOffer(minter, nftokenID1, drops(1)),
3500 token::expiration(expiration),
3505 env(token::createOffer(buyer, nftokenID0, drops(1)),
3506 token::expiration(expiration),
3507 token::owner(minter));
3511 env(token::createOffer(buyer, nftokenID1, drops(1)),
3512 token::expiration(expiration),
3513 token::owner(minter));
3516 BEAST_EXPECT(
lastClose(env) < expiration);
3517 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3518 BEAST_EXPECT(ownerCount(env, minter) == 3);
3519 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3522 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3528 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3529 BEAST_EXPECT(ownerCount(env, minter) == 2);
3530 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3533 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3538 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3539 BEAST_EXPECT(ownerCount(env, minter) == 2);
3540 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3543 env(token::cancelOffer(issuer, {buyOffer1, sellOffer1}));
3545 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3546 BEAST_EXPECT(ownerCount(env, minter) == 1);
3547 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3553 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3555 token::destination(minter));
3557 env(token::acceptSellOffer(minter, offerSellBack));
3559 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3560 BEAST_EXPECT(ownerCount(env, minter) == 1);
3561 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3802 testcase(
"Brokered NFT offer accept");
3804 using namespace test::jtx;
3807 Env env{*
this, features};
3808 auto const baseFee = env.current()->fees().base;
3816 Account
const issuer{
"issuer"};
3817 Account
const minter{
"minter"};
3818 Account
const buyer{
"buyer"};
3819 Account
const broker{
"broker"};
3820 Account
const gw{
"gw"};
3821 IOU
const gwXAU(gw[
"XAU"]);
3823 env.fund(XRP(1000), issuer, minter, buyer, broker, gw);
3826 env(trust(issuer, gwXAU(2000)));
3827 env(trust(minter, gwXAU(2000)));
3828 env(trust(buyer, gwXAU(2000)));
3829 env(trust(broker, gwXAU(2000)));
3832 env(token::setMinter(issuer, minter));
3836 auto checkOwnerCountIsOne =
3841 for (Account
const& acct : accounts)
3848 ss <<
"Account " << acct.human()
3849 <<
" expected ownerCount == 1. Got "
3851 fail(ss.
str(), __FILE__, line);
3857 auto mintNFT = [&env, &issuer, &minter](
std::uint16_t xferFee = 0) {
3860 env(token::mint(minter, 0),
3861 token::issuer(issuer),
3862 token::xferFee(xferFee),
3874 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3876 uint256 const nftID = mintNFT();
3879 uint256 const minterOfferIndex =
3881 env(token::createOffer(minter, nftID, XRP(0)),
3889 env(token::createOffer(buyer, nftID, XRP(1)),
3890 token::owner(minter));
3893 auto const minterBalance = env.balance(minter);
3894 auto const buyerBalance = env.balance(buyer);
3895 auto const brokerBalance = env.balance(broker);
3896 auto const issuerBalance = env.balance(issuer);
3899 env(token::brokerOffers(
3900 broker, buyOfferIndex, minterOfferIndex));
3905 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(1));
3906 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3907 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
3908 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
3911 env(token::burn(buyer, nftID));
3921 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3923 uint256 const nftID = mintNFT();
3926 uint256 const minterOfferIndex =
3928 env(token::createOffer(minter, nftID, XRP(0)),
3936 env(token::createOffer(buyer, nftID, XRP(1)),
3937 token::owner(minter));
3941 env(token::brokerOffers(
3942 broker, buyOfferIndex, minterOfferIndex),
3943 token::brokerFee(XRP(1.1)),
3947 auto const minterBalance = env.balance(minter);
3948 auto const buyerBalance = env.balance(buyer);
3949 auto const brokerBalance = env.balance(broker);
3950 auto const issuerBalance = env.balance(issuer);
3953 env(token::brokerOffers(
3954 broker, buyOfferIndex, minterOfferIndex),
3955 token::brokerFee(XRP(0.5)));
3960 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
3961 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
3963 env.balance(broker) == brokerBalance + XRP(0.5) - baseFee);
3964 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
3967 env(token::burn(buyer, nftID));
3977 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3982 uint256 const minterOfferIndex =
3984 env(token::createOffer(minter, nftID, XRP(0)),
3992 env(token::createOffer(buyer, nftID, XRP(1)),
3993 token::owner(minter));
3996 auto const minterBalance = env.balance(minter);
3997 auto const buyerBalance = env.balance(buyer);
3998 auto const brokerBalance = env.balance(broker);
3999 auto const issuerBalance = env.balance(issuer);
4002 env(token::brokerOffers(
4003 broker, buyOfferIndex, minterOfferIndex));
4008 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
4009 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4010 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
4011 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.5));
4014 env(token::burn(buyer, nftID));
4024 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4029 uint256 const minterOfferIndex =
4031 env(token::createOffer(minter, nftID, XRP(0)),
4039 env(token::createOffer(buyer, nftID, XRP(1)),
4040 token::owner(minter));
4043 auto const minterBalance = env.balance(minter);
4044 auto const buyerBalance = env.balance(buyer);
4045 auto const brokerBalance = env.balance(broker);
4046 auto const issuerBalance = env.balance(issuer);
4049 env(token::brokerOffers(
4050 broker, buyOfferIndex, minterOfferIndex),
4051 token::brokerFee(XRP(0.75)));
4057 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.125));
4058 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4060 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](
4076 for (Account
const& acct : accounts)
4078 auto const xauAmt = gwXAU(amount);
4079 auto const balance = env.balance(acct, gwXAU);
4080 if (balance < xauAmt)
4082 env(pay(gw, acct, xauAmt - balance));
4085 else if (balance > xauAmt)
4087 env(pay(acct, gw, balance - xauAmt));
4090 if (env.balance(acct, gwXAU) != xauAmt)
4093 ss <<
"Unable to set " << acct.human()
4094 <<
" account balance to gwXAU(" << amount <<
")";
4095 this->
fail(ss.
str(), __FILE__, line);
4103 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4104 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4106 uint256 const nftID = mintNFT();
4109 uint256 const minterOfferIndex =
4111 env(token::createOffer(minter, nftID, gwXAU(1000)),
4120 env(token::createOffer(buyer, nftID, gwXAU(1001)),
4121 token::owner(minter));
4125 env(token::brokerOffers(
4126 broker, buyOfferIndex, minterOfferIndex),
4132 env(token::cancelOffer(buyer, {buyOfferIndex}));
4140 env(token::createOffer(buyer, nftID, gwXAU(999)),
4141 token::owner(minter));
4145 env(token::brokerOffers(
4146 broker, buyOfferIndex, minterOfferIndex),
4152 env(token::cancelOffer(buyer, {buyOfferIndex}));
4159 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4160 token::owner(minter));
4164 env(token::brokerOffers(
4165 broker, buyOfferIndex, minterOfferIndex),
4166 token::brokerFee(gwXAU(0.1)),
4171 env(token::brokerOffers(
4172 broker, buyOfferIndex, minterOfferIndex));
4175 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4176 BEAST_EXPECT(ownerCount(env, minter) == 1);
4177 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4178 BEAST_EXPECT(ownerCount(env, broker) == 1);
4179 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1000));
4180 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(2000));
4181 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4182 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1000));
4185 env(token::burn(buyer, nftID));
4192 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4193 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4198 uint256 const minterOfferIndex =
4200 env(token::createOffer(minter, nftID, gwXAU(900)),
4208 env(token::createOffer(buyer, nftID, gwXAU(1001)),
4209 token::owner(minter));
4213 env(token::brokerOffers(
4214 broker, buyOfferIndex, minterOfferIndex),
4220 env(token::cancelOffer(buyer, {buyOfferIndex}));
4228 env(token::createOffer(buyer, nftID, gwXAU(899)),
4229 token::owner(minter));
4233 env(token::brokerOffers(
4234 broker, buyOfferIndex, minterOfferIndex),
4240 env(token::cancelOffer(buyer, {buyOfferIndex}));
4246 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4247 token::owner(minter));
4252 env(token::brokerOffers(
4253 broker, buyOfferIndex, minterOfferIndex),
4254 token::brokerFee(gwXAU(101)),
4260 env(token::brokerOffers(
4261 broker, buyOfferIndex, minterOfferIndex),
4262 token::brokerFee(gwXAU(100)));
4265 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4266 BEAST_EXPECT(ownerCount(env, minter) == 1);
4267 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4268 BEAST_EXPECT(ownerCount(env, broker) == 1);
4269 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1450));
4270 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1450));
4271 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4272 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1100));
4275 env(token::burn(buyer, nftID));
4282 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4283 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4288 uint256 const minterOfferIndex =
4290 env(token::createOffer(minter, nftID, gwXAU(900)),
4297 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4298 token::owner(minter));
4304 env(token::brokerOffers(
4305 broker, buyOfferIndex, minterOfferIndex),
4306 token::brokerFee(gwXAU(50)));
4309 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4310 BEAST_EXPECT(ownerCount(env, minter) == 1);
4311 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4312 BEAST_EXPECT(ownerCount(env, broker) == 1);
4313 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4314 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4315 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4316 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1050));
4319 env(token::burn(buyer, nftID));
4324 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4325 setXAUBalance({issuer, minter, buyer}, 1000, __LINE__);
4326 setXAUBalance({broker}, 500, __LINE__);
4330 uint256 const minterOfferIndex =
4332 env(token::createOffer(minter, nftID, gwXAU(900)),
4339 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4340 token::owner(minter));
4343 env(token::brokerOffers(
4344 broker, buyOfferIndex, minterOfferIndex),
4345 token::brokerFee(gwXAU(50)));
4347 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4348 BEAST_EXPECT(ownerCount(env, minter) == 1);
4349 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4350 BEAST_EXPECT(ownerCount(env, broker) == 1);
4351 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4352 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4353 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4354 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(550));
4357 env(token::burn(buyer, nftID));
4981 using namespace test::jtx;
4983 testcase(
"Payments with IOU transfer fees");
4986 Env env{*
this, features};
4988 Account
const minter{
"minter"};
4989 Account
const secondarySeller{
"seller"};
4990 Account
const buyer{
"buyer"};
4991 Account
const gw{
"gateway"};
4992 Account
const broker{
"broker"};
4993 IOU
const gwXAU(gw[
"XAU"]);
4994 IOU
const gwXPB(gw[
"XPB"]);
4996 env.fund(XRP(1000), gw, minter, secondarySeller, buyer, broker);
4999 env(trust(minter, gwXAU(2000)));
5000 env(trust(secondarySeller, gwXAU(2000)));
5001 env(trust(broker, gwXAU(10000)));
5002 env(trust(buyer, gwXAU(2000)));
5003 env(trust(buyer, gwXPB(2000)));
5007 env(rate(gw, 1.02));
5010 auto expectInitialState = [
this,
5023 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(1000));
5024 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(0));
5025 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(0));
5026 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(0));
5027 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(0));
5028 BEAST_EXPECT(env.balance(secondarySeller, gwXPB) == gwXPB(0));
5029 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5000));
5030 BEAST_EXPECT(env.balance(broker, gwXPB) == gwXPB(0));
5031 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-1000));
5032 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(0));
5033 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(0));
5034 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(0));
5036 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(0));
5038 env.balance(gw, secondarySeller[
"XPB"]) == gwXPB(0));
5039 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5000));
5040 BEAST_EXPECT(env.balance(gw, broker[
"XPB"]) == gwXPB(0));
5043 auto reinitializeTrustLineBalances = [&expectInitialState,
5052 if (
auto const difference =
5053 gwXAU(1000) - env.balance(buyer, gwXAU);
5054 difference > gwXAU(0))
5055 env(pay(gw, buyer, difference));
5056 if (env.balance(buyer, gwXPB) > gwXPB(0))
5057 env(pay(buyer, gw, env.balance(buyer, gwXPB)));
5058 if (env.balance(minter, gwXAU) > gwXAU(0))
5059 env(pay(minter, gw, env.balance(minter, gwXAU)));
5060 if (env.balance(minter, gwXPB) > gwXPB(0))
5061 env(pay(minter, gw, env.balance(minter, gwXPB)));
5062 if (env.balance(secondarySeller, gwXAU) > gwXAU(0))
5064 pay(secondarySeller,
5066 env.balance(secondarySeller, gwXAU)));
5067 if (env.balance(secondarySeller, gwXPB) > gwXPB(0))
5069 pay(secondarySeller,
5071 env.balance(secondarySeller, gwXPB)));
5072 auto brokerDiff = gwXAU(5000) - env.balance(broker, gwXAU);
5073 if (brokerDiff > gwXAU(0))
5074 env(pay(gw, broker, brokerDiff));
5075 else if (brokerDiff < gwXAU(0))
5077 brokerDiff.negate();
5078 env(pay(broker, gw, brokerDiff));
5080 if (env.balance(broker, gwXPB) > gwXPB(0))
5081 env(pay(broker, gw, env.balance(broker, gwXPB)));
5083 expectInitialState();
5086 auto mintNFT = [&env](Account
const& minter,
int transferFee = 0) {
5087 uint256 const nftID = token::getNextID(
5089 env(token::mint(minter),
5090 token::xferFee(transferFee),
5096 auto createBuyOffer =
5098 Account
const& offerer,
5099 Account
const& owner,
5105 env(token::createOffer(offerer, nftID, amount),
5106 token::owner(owner),
5107 terCode ? ter(*terCode)
5113 auto createSellOffer =
5115 Account
const& offerer,
5121 env(token::createOffer(offerer, nftID, amount),
5123 terCode ? ter(*terCode)
5132 reinitializeTrustLineBalances();
5133 auto const nftID = mintNFT(minter);
5134 auto const offerID =
5135 createSellOffer(minter, nftID, gwXAU(1000));
5137 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5140 expectInitialState();
5145 reinitializeTrustLineBalances();
5146 auto const nftID = mintNFT(minter);
5147 auto const offerID =
5148 createBuyOffer(buyer, minter, nftID, gwXAU(1000));
5150 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5153 expectInitialState();
5159 reinitializeTrustLineBalances();
5160 auto const nftID = mintNFT(minter);
5161 auto const offerID = createSellOffer(minter, nftID, gwXAU(995));
5163 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5166 expectInitialState();
5172 reinitializeTrustLineBalances();
5173 auto const nftID = mintNFT(minter);
5174 auto const offerID =
5175 createBuyOffer(buyer, minter, nftID, gwXAU(995));
5177 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5180 expectInitialState();
5187 reinitializeTrustLineBalances();
5188 auto const nftID = mintNFT(minter);
5189 auto const offerID = createSellOffer(minter, nftID, gwXAU(900));
5190 env(token::acceptSellOffer(buyer, offerID));
5193 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
5194 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5195 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
5196 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5203 reinitializeTrustLineBalances();
5204 auto const nftID = mintNFT(minter);
5205 auto const offerID =
5206 createBuyOffer(buyer, minter, nftID, gwXAU(900));
5207 env(token::acceptBuyOffer(minter, offerID));
5210 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
5211 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5212 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
5213 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5220 reinitializeTrustLineBalances();
5223 env(pay(gw, buyer, gwXAU(20)));
5226 auto const nftID = mintNFT(minter);
5227 auto const offerID =
5228 createSellOffer(minter, nftID, gwXAU(1000));
5229 env(token::acceptSellOffer(buyer, offerID));
5232 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5233 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5234 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5235 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5242 reinitializeTrustLineBalances();
5245 env(pay(gw, buyer, gwXAU(20)));
5248 auto const nftID = mintNFT(minter);
5249 auto const offerID =
5250 createBuyOffer(buyer, minter, nftID, gwXAU(1000));
5251 env(token::acceptBuyOffer(minter, offerID));
5254 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5255 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5256 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5257 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5262 reinitializeTrustLineBalances();
5264 auto const nftID = mintNFT(minter);
5265 auto const offerID =
5266 createSellOffer(minter, nftID, gwXAU(1000));
5268 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
5271 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5272 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5277 reinitializeTrustLineBalances();
5279 auto const nftID = mintNFT(minter);
5281 auto const offerID =
5282 createBuyOffer(gw, minter, nftID, gwXAU(1000), {offerTER});
5284 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5287 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5288 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5293 reinitializeTrustLineBalances();
5294 auto const nftID = mintNFT(minter);
5295 auto const offerID =
5296 createSellOffer(minter, nftID, gwXAU(5000));
5298 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
5301 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5302 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5307 reinitializeTrustLineBalances();
5309 auto const nftID = mintNFT(minter);
5311 auto const offerID =
5312 createBuyOffer(gw, minter, nftID, gwXAU(5000), {offerTER});
5314 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5317 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5318 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5324 reinitializeTrustLineBalances();
5325 auto const nftID = mintNFT(gw);
5326 auto const offerID = createSellOffer(gw, nftID, gwXAU(1000));
5327 env(token::acceptSellOffer(buyer, offerID));
5330 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5331 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5337 reinitializeTrustLineBalances();
5339 auto const nftID = mintNFT(gw);
5340 auto const offerID =
5341 createBuyOffer(buyer, gw, nftID, gwXAU(1000));
5342 env(token::acceptBuyOffer(gw, offerID));
5345 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5346 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5352 reinitializeTrustLineBalances();
5353 auto const nftID = mintNFT(gw);
5354 auto const offerID = createSellOffer(gw, nftID, gwXAU(2000));
5355 env(token::acceptSellOffer(buyer, offerID),
5358 expectInitialState();
5364 reinitializeTrustLineBalances();
5365 auto const nftID = mintNFT(gw);
5366 auto const offerID =
5367 createBuyOffer(buyer, gw, nftID, gwXAU(2000));
5368 env(token::acceptBuyOffer(gw, offerID),
5371 expectInitialState();
5376 reinitializeTrustLineBalances();
5377 auto const nftID = mintNFT(minter);
5378 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5379 env(token::acceptSellOffer(buyer, offerID),
5382 expectInitialState();
5387 reinitializeTrustLineBalances();
5388 auto const nftID = mintNFT(minter);
5389 auto const offerID = createBuyOffer(
5395 env(token::acceptBuyOffer(minter, offerID),
5398 expectInitialState();
5404 reinitializeTrustLineBalances();
5405 env(pay(gw, buyer, gwXPB(100)));
5408 auto const nftID = mintNFT(minter);
5409 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5410 env(token::acceptSellOffer(buyer, offerID));
5413 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5414 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5415 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5416 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5422 reinitializeTrustLineBalances();
5423 env(pay(gw, buyer, gwXPB(100)));
5426 auto const nftID = mintNFT(minter);
5427 auto const offerID =
5428 createBuyOffer(buyer, minter, nftID, gwXPB(10));
5429 env(token::acceptBuyOffer(minter, offerID));
5432 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5433 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5434 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5435 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5440 reinitializeTrustLineBalances();
5444 auto const nftID = mintNFT(minter, 3000);
5445 auto const primaryOfferID =
5446 createSellOffer(minter, nftID, XRP(0));
5447 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5451 auto const offerID =
5452 createSellOffer(secondarySeller, nftID, gwXAU(1000));
5454 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5457 expectInitialState();
5462 reinitializeTrustLineBalances();
5466 auto const nftID = mintNFT(minter, 3000);
5467 auto const primaryOfferID =
5468 createSellOffer(minter, nftID, XRP(0));
5469 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5473 auto const offerID =
5474 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(1000));
5476 env(token::acceptBuyOffer(secondarySeller, offerID),
5480 expectInitialState();
5485 reinitializeTrustLineBalances();
5489 auto const nftID = mintNFT(minter, 3000);
5490 auto const primaryOfferID =
5491 createSellOffer(minter, nftID, XRP(0));
5492 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5496 auto const offerID =
5497 createSellOffer(secondarySeller, nftID, gwXAU(900));
5498 env(token::acceptSellOffer(buyer, offerID));
5501 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5502 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5503 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5504 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5506 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5507 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5512 reinitializeTrustLineBalances();
5516 auto const nftID = mintNFT(minter, 3000);
5517 auto const primaryOfferID =
5518 createSellOffer(minter, nftID, XRP(0));
5519 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5523 auto const offerID =
5524 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(900));
5525 env(token::acceptBuyOffer(secondarySeller, offerID));
5529 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5531 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5533 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5534 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5536 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5537 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5555 reinitializeTrustLineBalances();
5557 auto const nftID = mintNFT(minter);
5558 auto const sellOffer =
5559 createSellOffer(minter, nftID, gwXAU(300));
5560 auto const buyOffer =
5561 createBuyOffer(buyer, minter, nftID, gwXAU(500));
5562 env(token::brokerOffers(broker, buyOffer, sellOffer),
5563 token::brokerFee(gwXAU(100)));
5566 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(400));
5567 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5568 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5569 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-400));
5570 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5571 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5589 reinitializeTrustLineBalances();
5593 auto const nftID = mintNFT(minter, 3000);
5594 auto const primaryOfferID =
5595 createSellOffer(minter, nftID, XRP(0));
5596 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5600 auto const sellOffer =
5601 createSellOffer(secondarySeller, nftID, gwXAU(300));
5602 auto const buyOffer =
5603 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(500));
5604 env(token::brokerOffers(broker, buyOffer, sellOffer),
5605 token::brokerFee(gwXAU(100)));
5608 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(12));
5609 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5610 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(388));
5611 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5612 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-12));
5613 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5615 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-388));
5616 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5714 using namespace test::jtx;
5719 auto openLedgerSeq = [](Env& env) {
return env.current()->seq(); };
5724 auto incLgrSeqForAcctDel = [&](Env& env, Account
const& acct) {
5725 int const delta = [&]() ->
int {
5726 if (env.seq(acct) + 255 > openLedgerSeq(env))
5727 return env.seq(acct) - openLedgerSeq(env) + 255;
5730 BEAST_EXPECT(delta >= 0);
5731 for (
int i = 0; i < delta; ++i)
5733 BEAST_EXPECT(openLedgerSeq(env) == env.seq(acct) + 255);
5738 auto incLgrSeqForFixNftRemint = [&](Env& env, Account
const& acct) {
5740 auto const deletableLgrSeq =
5741 (*env.le(acct))[~sfFirstNFTokenSequence].value_or(0) +
5742 (*env.le(acct))[sfMintedNFTokens] + 255;
5744 if (deletableLgrSeq > openLedgerSeq(env))
5745 delta = deletableLgrSeq - openLedgerSeq(env);
5747 BEAST_EXPECT(delta >= 0);
5748 for (
int i = 0; i < delta; ++i)
5750 BEAST_EXPECT(openLedgerSeq(env) == deletableLgrSeq);
5756 Env env{*
this, features};
5757 Account
const alice(
"alice");
5758 Account
const becky(
"becky");
5760 env.fund(XRP(10000), alice, becky);
5764 uint256 const prevNFTokenID = token::getNextID(env, alice, 0u);
5765 env(token::mint(alice));
5767 env(token::burn(alice, prevNFTokenID));
5771 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 1);
5774 incLgrSeqForAcctDel(env, alice);
5778 auto const acctDelFee{drops(env.current()->fees().increment)};
5779 env(acctdelete(alice, becky), fee(acctDelFee));
5784 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5785 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5788 env.fund(XRP(10000), alice);
5792 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5793 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5794 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5797 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5798 env(token::mint(alice));
5802 env(token::burn(alice, remintNFTokenID));
5806 BEAST_EXPECT(remintNFTokenID != prevNFTokenID);
5812 Env env{*
this, features};
5813 Account
const alice(
"alice");
5814 Account
const becky(
"becky");
5815 Account
const minter{
"minter"};
5817 env.fund(XRP(10000), alice, becky, minter);
5821 env(token::setMinter(alice, minter));
5827 for (
int i = 0; i < 500; i++)
5829 uint256 const nftokenID = token::getNextID(env, alice, 0u);
5831 env(token::mint(minter), token::issuer(alice));
5836 for (
auto const nftokenID : nftIDs)
5838 env(token::burn(minter, nftokenID));
5844 incLgrSeqForAcctDel(env, alice);
5848 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5849 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5851 auto const acctDelFee{drops(env.current()->fees().increment)};
5860 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
5864 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5869 incLgrSeqForFixNftRemint(env, alice);
5872 env(acctdelete(alice, becky), fee(acctDelFee));
5877 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5878 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5881 env.fund(XRP(10000), alice);
5885 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5886 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5887 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5891 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5892 env(token::mint(alice));
5896 env(token::burn(alice, remintNFTokenID));
5909 Env env{*
this, features};
5911 Account
const alice{
"alice"};
5912 Account
const becky{
"becky"};
5913 env.fund(XRP(10000), alice, becky);
5920 env(ticket::create(alice, 100));
5924 BEAST_EXPECT(ownerCount(env, alice) == 100);
5929 for (
int i = 0; i < 50; i++)
5931 nftIDs.
push_back(token::getNextID(env, alice, 0u));
5932 env(token::mint(alice, 0u), ticket::use(aliceTicketSeq++));
5937 for (
auto const nftokenID : nftIDs)
5939 env(token::burn(alice, nftokenID),
5940 ticket::use(aliceTicketSeq++));
5948 incLgrSeqForAcctDel(env, alice);
5952 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5953 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5955 auto const acctDelFee{drops(env.current()->fees().increment)};
5964 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
5968 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5973 incLgrSeqForFixNftRemint(env, alice);
5976 env(acctdelete(alice, becky), fee(acctDelFee));
5981 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
5982 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
5985 env.fund(XRP(10000), alice);
5989 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
5990 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
5991 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
5995 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
5996 env(token::mint(alice));
6000 env(token::burn(alice, remintNFTokenID));
6014 Env env{*
this, features};
6015 Account
const alice(
"alice");
6016 Account
const becky(
"becky");
6017 Account
const minter{
"minter"};
6019 env.fund(XRP(10000), alice, becky, minter);
6023 env(token::setMinter(alice, minter));
6028 env(ticket::create(minter, 100));
6032 BEAST_EXPECT(ownerCount(env, minter) == 100);
6037 for (
int i = 0; i < 50; i++)
6039 uint256 const nftokenID = token::getNextID(env, alice, 0u);
6041 env(token::mint(minter),
6042 token::issuer(alice),
6043 ticket::use(minterTicketSeq++));
6048 for (
auto const nftokenID : nftIDs)
6050 env(token::burn(minter, nftokenID), ticket::use(minterTicketSeq++));
6058 incLgrSeqForAcctDel(env, alice);
6062 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6063 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6072 auto const acctDelFee{drops(env.current()->fees().increment)};
6073 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
6077 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6082 incLgrSeqForFixNftRemint(env, alice);
6085 env(acctdelete(alice, becky), fee(acctDelFee));
6090 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
6091 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
6094 env.fund(XRP(10000), alice);
6098 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6099 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6100 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
6104 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
6105 env(token::mint(alice));
6109 env(token::burn(alice, remintNFTokenID));
6122 testcase(
"NFTokenMint with Create NFTokenOffer");
6124 using namespace test::jtx;
6126 if (!features[featureNFTokenMintOffer])
6128 Env env{*
this, features};
6129 Account
const alice(
"alice");
6130 Account
const buyer(
"buyer");
6132 env.fund(XRP(10000), alice, buyer);
6135 env(token::mint(alice),
6136 token::amount(XRP(10000)),
6140 env(token::mint(alice),
6141 token::destination(
"buyer"),
6145 env(token::mint(alice),
6155 Env env{*
this, features};
6156 auto const baseFee = env.current()->fees().base;
6157 Account
const alice(
"alice");
6158 Account
const buyer{
"buyer"};
6159 Account
const gw(
"gw");
6160 Account
const issuer(
"issuer");
6161 Account
const minter(
"minter");
6162 Account
const bob(
"bob");
6163 IOU
const gwAUD(gw[
"AUD"]);
6165 env.fund(XRP(10000), alice, buyer, gw, issuer, minter);
6170 env(token::mint(alice),
6171 token::destination(buyer),
6174 BEAST_EXPECT(ownerCount(env, alice) == 0);
6177 env(token::mint(alice),
6181 BEAST_EXPECT(ownerCount(env, buyer) == 0);
6187 env(token::mint(alice),
6188 token::amount(XRP(1000)),
6189 token::destination(alice),
6192 BEAST_EXPECT(ownerCount(env, alice) == 0);
6196 env(token::mint(alice),
6197 token::amount(XRP(1000)),
6198 token::destination(Account(
"demon")),
6201 BEAST_EXPECT(ownerCount(env, alice) == 0);
6206 env(token::mint(alice),
6207 token::amount(XRP(1000)),
6208 token::expiration(0),
6211 BEAST_EXPECT(ownerCount(env, alice) == 0);
6214 env(token::mint(alice),
6215 token::amount(XRP(1000)),
6219 BEAST_EXPECT(ownerCount(env, alice) == 0);
6224 env(token::mint(alice),
6225 token::amount(buyer[
"USD"](1)),
6228 env(token::mint(alice),
6229 token::amount(buyer[
"USD"](0)),
6232 BEAST_EXPECT(ownerCount(env, alice) == 0);
6235 env(token::mint(alice),
6236 token::amount(gwAUD(1000)),
6241 BEAST_EXPECT(ownerCount(env, alice) == 0);
6246 env(token::mint(gw),
6247 token::amount(gwAUD(1000)),
6249 token::xferFee(10));
6258 env(token::mint(alice),
6259 token::amount(gwAUD(1000)),
6264 BEAST_EXPECT(ownerCount(env, alice) == 0);
6267 env(token::mint(alice),
6268 token::amount(gwAUD(1000)),
6271 BEAST_EXPECT(ownerCount(env, alice) == 0);
6280 auto const acctReserve = env.current()->fees().reserve;
6281 auto const incReserve = env.current()->fees().increment;
6283 env.fund(acctReserve + incReserve, bob);
6287 env(token::mint(bob),
6288 token::amount(XRP(0)),
6293 env(pay(env.master, bob, incReserve + drops(baseFee)));
6295 env(token::mint(bob), token::amount(XRP(0)));
6299 env(pay(env.master, bob, drops(baseFee)));
6301 env(token::mint(bob),
6302 token::amount(XRP(0)),
6307 env(pay(env.master, bob, incReserve + drops(baseFee)));
6309 env(token::mint(bob), token::amount(XRP(0)));
6314 BEAST_EXPECT(ownerCount(env, alice) == 0);
6315 env(token::mint(alice), token::amount(XRP(10)));
6316 BEAST_EXPECT(ownerCount(env, alice) == 2);
6320 env(token::mint(alice),
6321 token::amount(XRP(10)),
6322 token::destination(buyer),
6323 token::expiration(
lastClose(env) + 25));
6327 env(trust(alice, gwAUD(1000)));
6329 env(token::mint(alice),
6330 token::amount(gwAUD(1)),
6331 token::destination(buyer),
6334 token::xferFee(10));
6338 env(token::mint(alice),
6339 token::amount(XRP(10)),
6340 token::destination(buyer),
6341 token::expiration(
lastClose(env) + 25));
6342 uint256 const offerAliceSellsToBuyer =
6344 env(token::cancelOffer(alice, {offerAliceSellsToBuyer}));
6348 env(token::mint(buyer),
6349 token::amount(XRP(10)),
6350 token::destination(alice),
6351 token::expiration(
lastClose(env) + 25));
6352 uint256 const offerBuyerSellsToAlice =
6354 env(token::cancelOffer(alice, {offerBuyerSellsToAlice}));
6357 env(token::setMinter(issuer, minter));
6361 BEAST_EXPECT(ownerCount(env, minter) == 0);
6362 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6363 env(token::mint(minter),
6364 token::issuer(issuer),
6365 token::amount(drops(1)));
6367 BEAST_EXPECT(ownerCount(env, minter) == 2);
6368 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6371 Env env{*
this, features};
6372 Account
const alice(
"alice");
6374 env.fund(XRP(1000000), alice);
6379 env(token::mint(alice), token::amount(XRP(-2)), ter(offerCreateTER));
6397 testcase(
"Test synthetic fields from JSON response");
6399 using namespace test::jtx;
6401 Account
const alice{
"alice"};
6402 Account
const bob{
"bob"};
6403 Account
const broker{
"broker"};
6405 Env env{*
this, features};
6406 env.fund(XRP(10000), alice, bob, broker);
6412 auto verifyNFTokenID = [&](
uint256 const& actualNftID) {
6419 env.rpc(
"tx", txHash)[jss::result][jss::meta];
6422 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_id)))
6429 BEAST_EXPECT(nftID == actualNftID);
6434 auto verifyNFTokenIDsInCancelOffer =
6442 env.rpc(
"tx", txHash)[jss::result][jss::meta];
6445 if (!BEAST_EXPECT(meta.
isMember(jss::nftoken_ids)))
6451 meta[jss::nftoken_ids].begin(),
6452 meta[jss::nftoken_ids].end(),
6456 BEAST_EXPECT(nftID.
parseHex(
id.asString()));
6462 std::sort(actualNftIDs.begin(), actualNftIDs.end());
6465 BEAST_EXPECT(metaIDs.
size() == actualNftIDs.size());
6469 for (
size_t i = 0; i < metaIDs.
size(); ++i)
6470 BEAST_EXPECT(metaIDs[i] == actualNftIDs[i]);
6475 auto verifyNFTokenOfferID = [&](
uint256 const& offerID) {
6482 env.rpc(
"tx", txHash)[jss::result][jss::meta];
6485 if (!BEAST_EXPECT(meta.
isMember(jss::offer_id)))
6490 BEAST_EXPECT(metaOfferID == offerID);
6501 verifyNFTokenID(nftId1);
6507 verifyNFTokenID(nftId2);
6512 uint256 const aliceOfferIndex1 =
6514 env(token::createOffer(alice, nftId1, drops(1)),
6517 verifyNFTokenOfferID(aliceOfferIndex1);
6519 uint256 const aliceOfferIndex2 =
6521 env(token::createOffer(alice, nftId2, drops(1)),
6524 verifyNFTokenOfferID(aliceOfferIndex2);
6529 env(token::cancelOffer(
6530 alice, {aliceOfferIndex1, aliceOfferIndex2}));
6532 verifyNFTokenIDsInCancelOffer({nftId1, nftId2});
6536 auto const bobBuyOfferIndex =
6538 env(token::createOffer(bob, nftId1, drops(1)), token::owner(alice));
6540 verifyNFTokenOfferID(bobBuyOfferIndex);
6544 env(token::acceptBuyOffer(alice, bobBuyOfferIndex));
6546 verifyNFTokenID(nftId1);
6556 verifyNFTokenID(nftId);
6559 uint256 const offerAliceToBroker =
6561 env(token::createOffer(alice, nftId, drops(1)),
6562 token::destination(broker),
6565 verifyNFTokenOfferID(offerAliceToBroker);
6568 uint256 const offerBobToBroker =
6570 env(token::createOffer(bob, nftId, drops(1)), token::owner(alice));
6572 verifyNFTokenOfferID(offerBobToBroker);
6575 env(token::brokerOffers(
6576 broker, offerBobToBroker, offerAliceToBroker));
6578 verifyNFTokenID(nftId);
6589 verifyNFTokenID(nftId);
6592 uint256 const aliceOfferIndex1 =
6594 env(token::createOffer(alice, nftId, drops(1)),
6597 verifyNFTokenOfferID(aliceOfferIndex1);
6599 uint256 const aliceOfferIndex2 =
6601 env(token::createOffer(alice, nftId, drops(1)),
6604 verifyNFTokenOfferID(aliceOfferIndex2);
6608 env(token::cancelOffer(
6609 alice, {aliceOfferIndex1, aliceOfferIndex2}));
6611 verifyNFTokenIDsInCancelOffer({nftId});
6614 if (features[featureNFTokenMintOffer])
6616 uint256 const aliceMintWithOfferIndex1 =
6618 env(token::mint(alice), token::amount(XRP(0)));
6620 verifyNFTokenOfferID(aliceMintWithOfferIndex1);
6627 testcase(
"Test buyer reserve when accepting an offer");
6629 using namespace test::jtx;
6642 uint256 const sellOfferIndex =
6644 env(token::createOffer(acct, nftId, amt), txflags(
tfSellNFToken));
6647 return sellOfferIndex;
6654 Account
const alice{
"alice"};
6655 Account
const bob{
"bob"};
6657 Env env{*
this, features};
6658 auto const acctReserve = env.
current()->fees().reserve;
6659 auto const incReserve = env.
current()->fees().increment;
6660 auto const baseFee = env.
current()->fees().base;
6662 env.
fund(XRP(10000), alice);
6666 env.
fund(acctReserve, bob);
6670 auto const sellOfferIndex =
6671 mintAndCreateSellOffer(env, alice, XRP(0));
6674 BEAST_EXPECT(ownerCount(env, bob) == 0);
6678 if (!features[fixNFTokenReserve])
6681 env(token::acceptSellOffer(bob, sellOfferIndex));
6685 BEAST_EXPECT(ownerCount(env, bob) == 1);
6700 env(token::acceptSellOffer(bob, sellOfferIndex),
6707 BEAST_EXPECT(ownerCount(env, bob) == 0);
6712 env(pay(env.
master, bob, incReserve + drops(baseFee)));
6717 env(token::acceptSellOffer(bob, sellOfferIndex),
6723 env(pay(env.
master, bob, drops(baseFee * 2)));
6727 env(token::acceptSellOffer(bob, sellOfferIndex));
6730 BEAST_EXPECT(ownerCount(env, bob) == 1);
6737 Account
const alice{
"alice"};
6738 Account
const bob{
"bob"};
6740 Env env{*
this, features};
6741 auto const acctReserve = env.
current()->fees().reserve;
6742 auto const incReserve = env.
current()->fees().increment;
6744 env.
fund(XRP(10000), alice);
6747 env.
fund(acctReserve + XRP(1), bob);
6750 if (!features[fixNFTokenReserve])
6753 for (
size_t i = 0; i < 200; i++)
6756 auto const sellOfferIndex =
6757 mintAndCreateSellOffer(env, alice, XRP(0));
6760 env(token::acceptSellOffer(bob, sellOfferIndex));
6767 auto const sellOfferIndex1 =
6768 mintAndCreateSellOffer(env, alice, XRP(0));
6772 env(token::acceptSellOffer(bob, sellOfferIndex1),
6777 env(pay(env.
master, bob, drops(incReserve)));
6780 BEAST_EXPECT(ownerCount(env, bob) == 0);
6783 env(token::acceptSellOffer(bob, sellOfferIndex1));
6786 BEAST_EXPECT(ownerCount(env, bob) == 1);
6790 for (
size_t i = 0; i < 31; i++)
6793 auto const sellOfferIndex =
6794 mintAndCreateSellOffer(env, alice, XRP(0));
6798 env(token::acceptSellOffer(bob, sellOfferIndex));
6802 BEAST_EXPECT(ownerCount(env, bob) == 1);
6806 auto const sellOfferIndex33 =
6807 mintAndCreateSellOffer(env, alice, XRP(0));
6811 env(token::acceptSellOffer(bob, sellOfferIndex33),
6816 env(pay(env.
master, bob, drops(incReserve)));
6821 env(token::acceptSellOffer(bob, sellOfferIndex33));
6824 BEAST_EXPECT(ownerCount(env, bob) == 2);
6834 Account
const alice{
"alice"};
6835 Account
const bob{
"bob"};
6837 Env env{*
this, features};
6838 auto const acctReserve = env.
current()->fees().reserve;
6839 auto const incReserve = env.
current()->fees().increment;
6840 auto const baseFee = env.
current()->fees().base;
6842 env.
fund(XRP(10000), alice);
6848 env.
fund(acctReserve + incReserve + XRP(1), bob);
6859 env(token::createOffer(bob, nftId, XRP(1)), token::owner(alice));
6865 env(token::acceptBuyOffer(alice, buyOfferIndex),
6870 env(pay(env.
master, bob, drops(baseFee)));
6874 env(token::acceptBuyOffer(alice, buyOfferIndex));
6884 Account
const alice{
"alice"};
6885 Account
const bob{
"bob"};
6886 Account
const broker{
"broker"};
6888 Env env{*
this, features};
6889 auto const acctReserve = env.
current()->fees().reserve;
6890 auto const incReserve = env.
current()->fees().increment;
6891 auto const baseFee = env.
current()->fees().base;
6893 env.
fund(XRP(10000), alice, broker);
6898 env.
fund(acctReserve + incReserve + XRP(1), bob);
6908 uint256 const offerAliceToBroker =
6910 env(token::createOffer(alice, nftId, XRP(1)),
6911 token::destination(broker),
6916 uint256 const offerBobToBroker =
6918 env(token::createOffer(bob, nftId, XRP(1)), token::owner(alice));
6925 env(token::brokerOffers(
6926 broker, offerBobToBroker, offerAliceToBroker),
6931 env(pay(env.
master, bob, drops(baseFee)));
6935 env(token::brokerOffers(
6936 broker, offerBobToBroker, offerAliceToBroker));
7274 using namespace test::jtx;
7276 Account
const issuer{
"issuer"};
7277 Account
const alice(
"alice");
7278 Account
const bob(
"bob");
7280 bool const modifyEnabled = features[featureDynamicNFT];
7284 Env env{*
this, features};
7285 env.fund(XRP(10000), issuer);
7288 auto const expectedTer =
7290 env(token::mint(issuer, 0u), txflags(
tfMutable), ter(expectedTer));
7294 Env env{*
this, features};
7295 env.fund(XRP(10000), issuer);
7302 env(token::mint(issuer, 0u), txflags(
tfMutable));
7304 BEAST_EXPECT(ownerCount(env, issuer) == 1);
7305 env(token::modify(issuer, nftId));
7306 BEAST_EXPECT(ownerCount(env, issuer) == 1);
7310 env(token::mint(issuer, 0u));
7312 env(token::modify(issuer, nftId), ter(
temDISABLED));
7320 Env env{*
this, features};
7321 env.fund(XRP(10000), issuer);
7325 env(token::mint(issuer, 0u), txflags(
tfMutable));
7329 env(token::modify(issuer, nftId),
7335 env(token::modify(issuer, nftId),
7336 txflags(0x00000001),
7340 env(token::modify(issuer, nftId),
7341 token::owner(issuer),
7346 env(token::modify(issuer, nftId),
7352 env(token::modify(issuer, nftId),
7358 Env env{*
this, features};
7359 env.fund(XRP(10000), issuer, alice, bob);
7365 token::getNextID(env, issuer, 0u,
tfMutable)};
7368 env(token::modify(issuer, nftIDNotExists), ter(
tecNO_ENTRY));
7373 uint256 const nftIDNotModifiable{
7374 token::getNextID(env, issuer, 0u)};
7375 env(token::mint(issuer, 0u));
7378 env(token::modify(issuer, nftIDNotModifiable),
7385 token::getNextID(env, issuer, 0u,
tfMutable)};
7386 env(token::mint(issuer, 0u), txflags(
tfMutable));
7389 env(token::modify(bob, nftId),
7390 token::owner(issuer),
7394 env(token::setMinter(issuer, alice));
7397 env(token::modify(bob, nftId),
7398 token::owner(issuer),
7404 Env env{*
this, features};
7405 env.fund(XRP(10000), issuer, alice, bob);
7410 env(token::mint(issuer, 0u), txflags(
tfMutable), token::uri(
"uri"));
7417 Env env{*
this, features};
7418 env.fund(XRP(10000), issuer, alice, bob);
7422 auto accountNFTs = [&env](Account
const& acct) {
7424 params[jss::account] = acct.human();
7425 params[jss::type] =
"state";
7427 env.rpc(
"json",
"account_nfts",
to_string(params));
7428 return response[jss::result][jss::account_nfts];
7432 auto checkURI = [&accountNFTs,
this](
7433 Account
const& acct,
7436 auto const nfts = accountNFTs(acct);
7437 if (nfts.size() == 1)
7442 text <<
"checkURI: unexpected NFT count on line " << line;
7443 fail(text.
str(), __FILE__, line);
7449 if (!nfts[0u].isMember(sfURI.jsonName))
7454 text <<
"checkURI: unexpected URI present on line "
7456 fail(text.
str(), __FILE__, line);
7466 text <<
"checkURI: unexpected URI contents on line "
7468 fail(text.
str(), __FILE__, line);
7475 env(token::mint(issuer, 0u), txflags(
tfMutable), token::uri(
"uri"));
7477 checkURI(issuer,
"uri", __LINE__);
7480 env(token::modify(issuer, nftId), token::uri(
"new_uri"));
7482 checkURI(issuer,
"new_uri", __LINE__);
7485 env(token::modify(issuer, nftId));
7487 checkURI(issuer,
nullptr, __LINE__);
7490 env(token::modify(issuer, nftId), token::uri(
"uri"));
7492 checkURI(issuer,
"uri", __LINE__);
7497 env(token::createOffer(issuer, nftId, XRP(0)),
7500 env(token::acceptSellOffer(alice, offerID));
7502 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7503 BEAST_EXPECT(ownerCount(env, alice) == 1);
7504 checkURI(alice,
"uri", __LINE__);
7507 env(token::modify(alice, nftId),
7508 token::uri(
"new_uri"),
7511 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7512 BEAST_EXPECT(ownerCount(env, alice) == 1);
7513 checkURI(alice,
"uri", __LINE__);
7515 env(token::modify(issuer, nftId),
7516 token::owner(alice),
7517 token::uri(
"new_uri"));
7519 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7520 BEAST_EXPECT(ownerCount(env, alice) == 1);
7521 checkURI(alice,
"new_uri", __LINE__);
7523 env(token::modify(issuer, nftId), token::owner(alice));
7525 checkURI(alice,
nullptr, __LINE__);
7527 env(token::modify(issuer, nftId),
7528 token::owner(alice),
7531 checkURI(alice,
"uri", __LINE__);
7534 env(token::setMinter(issuer, bob));
7536 env(token::modify(bob, nftId),
7537 token::owner(alice),
7538 token::uri(
"new_uri"));
7540 checkURI(alice,
"new_uri", __LINE__);
7542 env(token::modify(bob, nftId), token::owner(alice));
7544 checkURI(alice,
nullptr, __LINE__);
7546 env(token::modify(bob, nftId),
7547 token::owner(alice),
7550 checkURI(alice,
"uri", __LINE__);