203 using namespace test::jtx;
205 Env env{*
this, features};
206 Account
const alice{
"alice"};
207 Account
const minter{
"minter"};
211 auto const acctReserve = env.current()->fees().accountReserve(0);
212 auto const incReserve = env.current()->fees().increment;
213 auto const baseFee = env.current()->fees().base;
215 env.fund(acctReserve, alice, minter);
218 BEAST_EXPECT(env.balance(alice) == acctReserve);
219 BEAST_EXPECT(env.balance(minter) == acctReserve);
220 BEAST_EXPECT(ownerCount(env, alice) == 0);
221 BEAST_EXPECT(ownerCount(env, minter) == 0);
228 BEAST_EXPECT(ownerCount(env, alice) == 0);
233 env(pay(env.master, alice, incReserve + drops(baseFee - 1)));
238 auto checkAliceOwnerMintedBurned = [&env,
this, &alice](
251 ss <<
"Wrong " << type <<
" count. Found: " << found
252 <<
"; Expected: " << exp;
253 fail(ss.
str(), __FILE__, line);
256 oneCheck(
"owner", ownerCount(env, alice), owners);
257 oneCheck(
"minted",
mintedCount(env, alice), minted);
258 oneCheck(
"burned",
burnedCount(env, alice), burned);
266 checkAliceOwnerMintedBurned(0, 0, 0, __LINE__);
269 env(pay(env.master, alice, drops(baseFee + 1)));
273 env(token::mint(alice));
276 checkAliceOwnerMintedBurned(1, 1, 0, __LINE__);
280 for (
int i = 1; i < 32; ++i)
282 env(token::mint(alice));
283 checkAliceOwnerMintedBurned(1, i + 1, 0, __LINE__);
290 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
293 env(pay(env.master, alice, incReserve + drops(baseFee * 33 - 1)));
300 checkAliceOwnerMintedBurned(1, 32, 0, __LINE__);
303 env(pay(env.master, alice, drops(baseFee + 1)));
307 env(token::mint(alice));
309 checkAliceOwnerMintedBurned(2, 33, 0, __LINE__);
316 env(token::burn(alice, token::getID(env, alice, 0, seq++)));
318 checkAliceOwnerMintedBurned((33 - seq) ? 1 : 0, 33, seq, __LINE__);
322 env(token::burn(alice, token::getID(env, alice, 197, 5)),
325 checkAliceOwnerMintedBurned(0, 33, 33, __LINE__);
330 env(token::setMinter(alice, minter));
333 env.le(alice)->getAccountID(sfNFTokenMinter) == minter.id());
337 auto checkMintersOwnerMintedBurned = [&env,
this, &alice, &minter](
345 auto oneCheck = [
this](
355 ss <<
"Wrong " << type <<
" count. Found: " << found
356 <<
"; Expected: " << exp;
357 fail(ss.
str(), __FILE__, line);
360 oneCheck(
"alice owner", ownerCount(env, alice), aliceOwners, line);
362 "alice minted",
mintedCount(env, alice), aliceMinted, line);
364 "alice burned",
burnedCount(env, alice), aliceBurned, line);
366 "minter owner", ownerCount(env, minter), minterOwners, line);
368 "minter minted",
mintedCount(env, minter), minterMinted, line);
370 "minter burned",
burnedCount(env, minter), minterBurned, line);
376 env(pay(env.master, minter, incReserve - drops(1)));
378 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
383 env(token::mint(minter),
384 token::issuer(alice),
388 checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__);
391 env(pay(env.master, minter, drops(baseFee + 1)));
395 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
397 checkMintersOwnerMintedBurned(0, 34, nftSeq, 1, 0, 0, __LINE__);
401 for (
int i = 1; i < 32; ++i)
403 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
404 checkMintersOwnerMintedBurned(0, i + 34, nftSeq, 1, 0, 0, __LINE__);
409 env(pay(env.master, minter, incReserve + drops(baseFee * 32 - 1)));
414 env(token::mint(minter),
415 token::issuer(alice),
419 checkMintersOwnerMintedBurned(0, 65, nftSeq, 1, 0, 0, __LINE__);
422 env(pay(env.master, minter, drops(baseFee + 1)));
426 env(token::mint(minter), token::issuer(alice), token::uri(
"uri"));
428 checkMintersOwnerMintedBurned(0, 66, nftSeq, 2, 0, 0, __LINE__);
433 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
435 checkMintersOwnerMintedBurned(
436 0, 66, nftSeq, (65 - seq) ? 1 : 0, 0, 0, __LINE__);
441 env(token::burn(minter, token::getID(env, alice, 0, nftSeq++)));
443 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
446 env(token::burn(minter, token::getID(env, alice, 2009, 3)),
449 checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__);
662 testcase(
"Invalid NFT offer create");
664 using namespace test::jtx;
666 Env env{*
this, features};
667 Account
const alice{
"alice"};
668 Account
const buyer{
"buyer"};
669 Account
const gw(
"gw");
670 IOU
const gwAUD(gw[
"AUD"]);
675 env.fund(XRP(250), alice, buyer, gw);
677 BEAST_EXPECT(ownerCount(env, alice) == 0);
681 env(token::mint(alice, 0u),
685 BEAST_EXPECT(ownerCount(env, alice) == 1);
691 BEAST_EXPECT(ownerCount(env, alice) == 1);
693 uint256 nftNoXferID = token::getNextID(env, alice, 0);
694 env(token::mint(alice, 0));
696 BEAST_EXPECT(ownerCount(env, alice) == 1);
707 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
711 BEAST_EXPECT(ownerCount(env, buyer) == 0);
714 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
718 BEAST_EXPECT(ownerCount(env, buyer) == 0);
721 env(token::createOffer(buyer, nftAlice0ID, XRP(1000)),
725 BEAST_EXPECT(ownerCount(env, buyer) == 0);
728 env(token::createOffer(buyer, nftXrpOnlyID, buyer[
"USD"](1)),
730 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](0)),
732 env(token::createOffer(buyer, nftXrpOnlyID, drops(0)),
735 BEAST_EXPECT(ownerCount(env, buyer) == 0);
738 env(token::createOffer(buyer, nftAlice0ID, buyer[
"USD"](1)),
739 token::expiration(0),
742 BEAST_EXPECT(ownerCount(env, buyer) == 0);
746 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
749 BEAST_EXPECT(ownerCount(env, buyer) == 0);
752 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
757 BEAST_EXPECT(ownerCount(env, alice) == 1);
760 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
764 BEAST_EXPECT(ownerCount(env, alice) == 1);
767 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
768 token::destination(alice),
772 BEAST_EXPECT(ownerCount(env, alice) == 1);
775 env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)),
776 token::destination(Account(
"demon")),
780 BEAST_EXPECT(ownerCount(env, alice) == 1);
786 env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)),
791 BEAST_EXPECT(ownerCount(env, buyer) == 0);
794 env(token::createOffer(
795 buyer, token::getID(env, alice, 0, 1), XRP(1000)),
799 BEAST_EXPECT(ownerCount(env, buyer) == 0);
802 env(token::createOffer(
803 alice, token::getID(env, alice, 0, 1), XRP(1000)),
807 BEAST_EXPECT(ownerCount(env, buyer) == 0);
810 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
814 BEAST_EXPECT(ownerCount(env, buyer) == 0);
816 env(trust(buyer, gwAUD(1000)));
818 BEAST_EXPECT(ownerCount(env, buyer) == 1);
822 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
826 BEAST_EXPECT(ownerCount(env, buyer) == 1);
834 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
838 BEAST_EXPECT(ownerCount(env, buyer) == 1);
845 env(token::createOffer(buyer, nftNoXferID, gwAUD(1000)),
849 BEAST_EXPECT(ownerCount(env, buyer) == 1);
855 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
859 BEAST_EXPECT(ownerCount(env, buyer) == 1);
864 env(trust(buyer, gwAUD(1000)));
867 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
871 BEAST_EXPECT(ownerCount(env, buyer) == 1);
877 env(pay(gw, buyer, gwAUD(999)));
882 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
886 BEAST_EXPECT(ownerCount(env, buyer) == 1);
889 auto const baseFee = env.current()->fees().base;
890 env(pay(env.master, buyer, XRP(50) + drops(baseFee * 12 - 1)));
893 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
897 BEAST_EXPECT(ownerCount(env, buyer) == 1);
900 env(pay(env.master, buyer, drops(baseFee + 1)));
905 env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)),
909 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1035 testcase(
"Invalid NFT offer accept");
1037 using namespace test::jtx;
1039 Env env{*
this, features};
1040 Account
const alice{
"alice"};
1041 Account
const buyer{
"buyer"};
1042 Account
const gw(
"gw");
1043 IOU
const gwAUD(gw[
"AUD"]);
1045 env.fund(XRP(1000), alice, buyer, gw);
1047 BEAST_EXPECT(ownerCount(env, alice) == 0);
1053 BEAST_EXPECT(ownerCount(env, alice) == 1);
1059 BEAST_EXPECT(ownerCount(env, alice) == 1);
1061 uint256 nftNoXferID = token::getNextID(env, alice, 0);
1062 env(token::mint(alice, 0));
1064 BEAST_EXPECT(ownerCount(env, alice) == 1);
1067 uint256 const plainOfferIndex =
1069 env(token::createOffer(alice, nftAlice0ID, XRP(10)),
1072 BEAST_EXPECT(ownerCount(env, alice) == 2);
1076 env(token::createOffer(alice, nftAlice0ID, gwAUD(30)),
1079 BEAST_EXPECT(ownerCount(env, alice) == 3);
1081 uint256 const xrpOnlyOfferIndex =
1083 env(token::createOffer(alice, nftXrpOnlyID, XRP(20)),
1086 BEAST_EXPECT(ownerCount(env, alice) == 4);
1088 uint256 const noXferOfferIndex =
1090 env(token::createOffer(alice, nftNoXferID, XRP(30)),
1093 BEAST_EXPECT(ownerCount(env, alice) == 5);
1096 uint256 const aliceExpOfferIndex =
1098 env(token::createOffer(alice, nftNoXferID, XRP(40)),
1102 BEAST_EXPECT(ownerCount(env, alice) == 6);
1108 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1112 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1115 env(token::acceptSellOffer(buyer, noXferOfferIndex),
1116 txflags(0x00008000),
1119 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1123 Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1127 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1132 Json::Value jv = token::acceptBuyOffer(buyer, noXferOfferIndex);
1133 jv[sfNFTokenBrokerFee.jsonName] =
1137 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1142 Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex);
1143 jv[sfNFTokenBrokerFee.jsonName] =
1147 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1151 env(token::brokerOffers(buyer, noXferOfferIndex, xrpOnlyOfferIndex),
1152 token::brokerFee(gwAUD(0)),
1155 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1161 env(token::acceptBuyOffer(buyer, beast::zero),
1164 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1168 env(token::acceptBuyOffer(buyer, missingOfferIndex),
1171 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1174 env(token::acceptBuyOffer(buyer, aliceExpOfferIndex), ter(
tecEXPIRED));
1176 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1179 env(token::acceptSellOffer(buyer, beast::zero),
1182 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1185 env(token::acceptSellOffer(buyer, missingOfferIndex),
1188 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1191 env(token::acceptSellOffer(buyer, aliceExpOfferIndex), ter(
tecEXPIRED));
1193 BEAST_EXPECT(ownerCount(env, buyer) == 0);
1200 env(trust(alice, gwAUD(1000)));
1201 env(trust(buyer, gwAUD(1000)));
1203 env(pay(gw, buyer, gwAUD(30)));
1205 BEAST_EXPECT(ownerCount(env, alice) == 7);
1206 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1212 uint256 const buyerOfferIndex =
1214 env(token::createOffer(buyer, nftAlice0ID, gwAUD(29)),
1215 token::owner(alice));
1217 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1220 env(token::brokerOffers(gw, buyerOfferIndex, xrpOnlyOfferIndex),
1223 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1226 env(token::brokerOffers(gw, buyerOfferIndex, plainOfferIndex),
1229 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1233 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1236 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1239 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1241 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1245 uint256 const buyerOfferIndex =
1247 env(token::createOffer(buyer, nftAlice0ID, gwAUD(31)),
1248 token::owner(alice));
1250 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1254 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1255 token::brokerFee(XRP(40)),
1258 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1261 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1262 token::brokerFee(gwAUD(31)),
1265 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1269 env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex),
1270 token::brokerFee(gwAUD(1.5)),
1273 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1276 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1278 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1284 uint256 const buyerOfferIndex =
1286 env(token::createOffer(buyer, nftAlice0ID, gwAUD(30)),
1287 token::owner(alice));
1289 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1292 env(token::acceptBuyOffer(buyer, plainOfferIndex),
1295 BEAST_EXPECT(ownerCount(env, alice) == 7);
1298 env(token::acceptBuyOffer(buyer, buyerOfferIndex),
1301 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1304 env(pay(buyer, gw, gwAUD(30)));
1306 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1307 env(token::acceptBuyOffer(alice, buyerOfferIndex),
1310 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1316 env(token::createOffer(alice, nftAlice0ID, XRP(0)),
1319 env(token::acceptSellOffer(gw, offerIndex));
1321 BEAST_EXPECT(ownerCount(env, alice) == 7);
1323 env(pay(gw, buyer, gwAUD(30)));
1327 env(token::acceptBuyOffer(alice, buyerOfferIndex),
1330 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1333 env(token::cancelOffer(buyer, {buyerOfferIndex}));
1335 BEAST_EXPECT(ownerCount(env, buyer) == 1);
1341 uint256 const buyerOfferIndex =
1343 env(token::createOffer(buyer, nftXrpOnlyID, XRP(30)),
1344 token::owner(alice));
1346 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1349 env(token::acceptSellOffer(alice, buyerOfferIndex),
1352 BEAST_EXPECT(ownerCount(env, alice) == 7);
1355 env(token::acceptSellOffer(alice, plainOfferIndex),
1358 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1362 env(token::acceptSellOffer(buyer, plainOfferIndex),
1365 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1373 env(token::createOffer(gw, nftAlice0ID, XRP(0)),
1376 env(token::acceptSellOffer(alice, offerIndex));
1378 BEAST_EXPECT(ownerCount(env, alice) == 7);
1380 env(pay(buyer, gw, gwAUD(30)));
1382 BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0));
1383 env(token::acceptSellOffer(buyer, audOfferIndex),
1386 BEAST_EXPECT(ownerCount(env, buyer) == 2);
1806 using namespace test::jtx;
1808 Env env{*
this, features};
1810 Account
const alice{
"alice"};
1811 Account
const becky{
"becky"};
1812 Account
const minter{
"minter"};
1814 env.fund(XRP(1000), alice, becky, minter);
1819 BEAST_EXPECT(ownerCount(env, alice) == 0);
1820 uint256 const nftAliceNoTransferID{
1821 token::getNextID(env, alice, 0u)};
1822 env(token::mint(alice, 0u), token::xferFee(0));
1824 BEAST_EXPECT(ownerCount(env, alice) == 1);
1827 BEAST_EXPECT(ownerCount(env, becky) == 0);
1828 env(token::createOffer(becky, nftAliceNoTransferID, XRP(20)),
1829 token::owner(alice),
1833 uint256 const aliceSellOfferIndex =
1835 env(token::createOffer(alice, nftAliceNoTransferID, XRP(20)),
1838 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
1840 BEAST_EXPECT(ownerCount(env, alice) == 0);
1841 BEAST_EXPECT(ownerCount(env, becky) == 1);
1844 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1848 BEAST_EXPECT(ownerCount(env, alice) == 0);
1849 BEAST_EXPECT(ownerCount(env, becky) == 1);
1853 env(token::createOffer(becky, nftAliceNoTransferID, XRP(21)),
1855 token::destination(alice),
1858 BEAST_EXPECT(ownerCount(env, alice) == 0);
1859 BEAST_EXPECT(ownerCount(env, becky) == 1);
1863 uint256 const aliceBuyOfferIndex =
1865 env(token::createOffer(alice, nftAliceNoTransferID, XRP(22)),
1866 token::owner(becky));
1868 env(token::acceptBuyOffer(becky, aliceBuyOfferIndex));
1870 BEAST_EXPECT(ownerCount(env, alice) == 1);
1871 BEAST_EXPECT(ownerCount(env, becky) == 0);
1874 env(token::burn(alice, nftAliceNoTransferID));
1876 BEAST_EXPECT(ownerCount(env, alice) == 0);
1877 BEAST_EXPECT(ownerCount(env, becky) == 0);
1881 env(token::setMinter(alice, minter));
1884 BEAST_EXPECT(ownerCount(env, minter) == 0);
1885 uint256 const nftMinterNoTransferID{
1886 token::getNextID(env, alice, 0u)};
1887 env(token::mint(minter), token::issuer(alice));
1889 BEAST_EXPECT(ownerCount(env, minter) == 1);
1892 BEAST_EXPECT(ownerCount(env, becky) == 0);
1893 env(token::createOffer(becky, nftMinterNoTransferID, XRP(20)),
1894 token::owner(minter),
1897 BEAST_EXPECT(ownerCount(env, becky) == 0);
1900 env(token::clearMinter(alice));
1904 BEAST_EXPECT(ownerCount(env, minter) == 1);
1905 env(token::createOffer(minter, nftMinterNoTransferID, XRP(21)),
1909 BEAST_EXPECT(ownerCount(env, minter) == 1);
1913 for (
int i = 0; i < 10; ++i)
1916 env(token::setMinter(alice, minter));
1918 BEAST_EXPECT(ownerCount(env, minter) == 1);
1921 BEAST_EXPECT(ownerCount(env, minter) == 1);
1922 uint256 const minterSellOfferIndex =
1924 env(token::createOffer(minter, nftMinterNoTransferID, XRP(22)),
1927 BEAST_EXPECT(ownerCount(env, minter) == 2);
1931 env(token::clearMinter(alice));
1936 BEAST_EXPECT(ownerCount(env, becky) == 0);
1937 env(token::acceptSellOffer(becky, minterSellOfferIndex));
1939 BEAST_EXPECT(ownerCount(env, becky) == 1);
1940 BEAST_EXPECT(ownerCount(env, minter) == 0);
1943 env(token::createOffer(becky, nftMinterNoTransferID, XRP(23)),
1950 BEAST_EXPECT(ownerCount(env, minter) == 0);
1951 env(token::createOffer(minter, nftMinterNoTransferID, XRP(24)),
1952 token::owner(becky),
1955 BEAST_EXPECT(ownerCount(env, minter) == 0);
1958 BEAST_EXPECT(ownerCount(env, alice) == 0);
1959 uint256 const aliceBuyOfferIndex =
1961 env(token::createOffer(alice, nftMinterNoTransferID, XRP(25)),
1962 token::owner(becky));
1964 BEAST_EXPECT(ownerCount(env, alice) == 1);
1968 for (
int i = 0; i < 10; ++i)
1971 env(token::setMinter(alice, minter));
1975 BEAST_EXPECT(ownerCount(env, minter) == 0);
1976 uint256 const minterBuyOfferIndex =
1978 env(token::createOffer(minter, nftMinterNoTransferID, XRP(26)),
1979 token::owner(becky));
1981 BEAST_EXPECT(ownerCount(env, minter) == 1);
1985 env(token::clearMinter(alice));
1989 BEAST_EXPECT(ownerCount(env, minter) == 1);
1990 BEAST_EXPECT(ownerCount(env, becky) == 1);
1991 env(token::acceptBuyOffer(becky, minterBuyOfferIndex));
1993 BEAST_EXPECT(ownerCount(env, minter) == 1);
1994 BEAST_EXPECT(ownerCount(env, becky) == 0);
1995 BEAST_EXPECT(ownerCount(env, alice) == 1);
1999 env(token::burn(minter, nftMinterNoTransferID), ter(
tesSUCCESS));
2001 env(token::cancelOffer(alice, {aliceBuyOfferIndex}));
2003 BEAST_EXPECT(ownerCount(env, alice) == 0);
2004 BEAST_EXPECT(ownerCount(env, becky) == 0);
2005 BEAST_EXPECT(ownerCount(env, minter) == 0);
2010 BEAST_EXPECT(ownerCount(env, alice) == 0);
2015 BEAST_EXPECT(ownerCount(env, alice) == 1);
2018 uint256 const aliceSellOfferIndex =
2020 env(token::createOffer(alice, nftAliceID, XRP(20)),
2023 BEAST_EXPECT(ownerCount(env, alice) == 2);
2025 uint256 const beckyBuyOfferIndex =
2027 env(token::createOffer(becky, nftAliceID, XRP(21)),
2028 token::owner(alice));
2030 BEAST_EXPECT(ownerCount(env, alice) == 2);
2033 env(token::acceptSellOffer(becky, aliceSellOfferIndex));
2035 BEAST_EXPECT(ownerCount(env, alice) == 0);
2036 BEAST_EXPECT(ownerCount(env, becky) == 2);
2039 uint256 const beckySellOfferIndex =
2041 env(token::createOffer(becky, nftAliceID, XRP(22)),
2044 BEAST_EXPECT(ownerCount(env, alice) == 0);
2045 BEAST_EXPECT(ownerCount(env, becky) == 3);
2049 env(token::acceptSellOffer(minter, beckySellOfferIndex));
2051 BEAST_EXPECT(ownerCount(env, alice) == 0);
2052 BEAST_EXPECT(ownerCount(env, becky) == 1);
2053 BEAST_EXPECT(ownerCount(env, minter) == 1);
2056 uint256 const minterSellOfferIndex =
2058 env(token::createOffer(minter, nftAliceID, XRP(23)),
2061 BEAST_EXPECT(ownerCount(env, alice) == 0);
2062 BEAST_EXPECT(ownerCount(env, becky) == 1);
2063 BEAST_EXPECT(ownerCount(env, minter) == 2);
2066 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2068 BEAST_EXPECT(ownerCount(env, alice) == 1);
2069 BEAST_EXPECT(ownerCount(env, becky) == 1);
2070 BEAST_EXPECT(ownerCount(env, minter) == 0);
2074 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2076 BEAST_EXPECT(ownerCount(env, alice) == 0);
2077 BEAST_EXPECT(ownerCount(env, becky) == 1);
2078 BEAST_EXPECT(ownerCount(env, minter) == 0);
2082 env(token::burn(becky, nftAliceID));
2084 BEAST_EXPECT(ownerCount(env, alice) == 0);
2085 BEAST_EXPECT(ownerCount(env, becky) == 0);
2086 BEAST_EXPECT(ownerCount(env, minter) == 0);
2096 using namespace test::jtx;
2098 Env env{*
this, features};
2099 auto const baseFee = env.current()->fees().base;
2101 Account
const alice{
"alice"};
2102 Account
const becky{
"becky"};
2103 Account
const carol{
"carol"};
2104 Account
const minter{
"minter"};
2105 Account
const gw{
"gw"};
2106 IOU
const gwXAU(gw[
"XAU"]);
2108 env.fund(XRP(1000), alice, becky, carol, minter, gw);
2111 env(trust(alice, gwXAU(2000)));
2112 env(trust(becky, gwXAU(2000)));
2113 env(trust(carol, gwXAU(2000)));
2114 env(trust(minter, gwXAU(2000)));
2116 env(pay(gw, alice, gwXAU(1000)));
2117 env(pay(gw, becky, gwXAU(1000)));
2118 env(pay(gw, carol, gwXAU(1000)));
2119 env(pay(gw, minter, gwXAU(1000)));
2124 env(token::setMinter(alice, minter));
2130 BEAST_EXPECT(ownerCount(env, alice) == 1);
2131 BEAST_EXPECT(ownerCount(env, becky) == 1);
2132 BEAST_EXPECT(ownerCount(env, carol) == 1);
2133 BEAST_EXPECT(ownerCount(env, minter) == 1);
2141 uint256 const beckyBuyOfferIndex =
2143 env(token::createOffer(becky, nftID, gwXAU(10)),
2144 token::owner(alice));
2146 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2147 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2149 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2151 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2152 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2155 uint256 const beckySellOfferIndex =
2157 env(token::createOffer(becky, nftID, gwXAU(10)),
2160 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2162 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2163 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2164 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2167 uint256 const minterBuyOfferIndex =
2169 env(token::createOffer(minter, nftID, gwXAU(10)),
2170 token::owner(carol));
2172 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2174 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2175 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2176 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2177 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2181 uint256 const minterSellOfferIndex =
2183 env(token::createOffer(minter, nftID, gwXAU(10)),
2186 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2188 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2189 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2190 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2191 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2194 env(token::burn(alice, nftID));
2196 BEAST_EXPECT(ownerCount(env, alice) == 1);
2197 BEAST_EXPECT(ownerCount(env, becky) == 1);
2198 BEAST_EXPECT(ownerCount(env, carol) == 1);
2199 BEAST_EXPECT(ownerCount(env, minter) == 1);
2207 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2211 uint256 const beckyBuyOfferIndex =
2213 env(token::createOffer(becky, nftID, gwXAU(10)),
2214 token::owner(alice));
2216 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2217 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2219 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2221 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2222 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2225 uint256 const beckySellOfferIndex =
2227 env(token::createOffer(becky, nftID, gwXAU(10)),
2230 env(token::acceptSellOffer(carol, beckySellOfferIndex));
2233 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0001));
2234 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2235 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2238 uint256 const minterBuyOfferIndex =
2240 env(token::createOffer(minter, nftID, gwXAU(10)),
2241 token::owner(carol));
2243 env(token::acceptBuyOffer(carol, minterBuyOfferIndex));
2246 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010.0002));
2247 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2248 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2249 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(990));
2253 uint256 const minterSellOfferIndex =
2255 env(token::createOffer(minter, nftID, gwXAU(10)),
2258 env(token::acceptSellOffer(alice, minterSellOfferIndex));
2260 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000.0002));
2261 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(999.9999));
2262 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(999.9999));
2263 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2267 env(pay(alice, becky, gwXAU(0.0001)));
2268 env(pay(alice, carol, gwXAU(0.0001)));
2271 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2272 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2273 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2274 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2277 env(token::burn(alice, nftID));
2279 BEAST_EXPECT(ownerCount(env, alice) == 1);
2280 BEAST_EXPECT(ownerCount(env, becky) == 1);
2281 BEAST_EXPECT(ownerCount(env, carol) == 1);
2282 BEAST_EXPECT(ownerCount(env, minter) == 1);
2288 env(token::mint(alice),
2295 uint256 const nftID = token::getNextID(
2297 env(token::mint(alice),
2303 uint256 const beckyBuyOfferIndex =
2305 env(token::createOffer(becky, nftID, gwXAU(10)),
2306 token::owner(alice));
2308 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2309 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2311 env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
2313 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1010));
2314 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990));
2317 uint256 const beckySellOfferIndex =
2319 env(token::createOffer(becky, nftID, gwXAU(100)),
2322 env(token::acceptSellOffer(minter, beckySellOfferIndex));
2325 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1060));
2326 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2327 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
2330 uint256 const carolBuyOfferIndex =
2332 env(token::createOffer(carol, nftID, gwXAU(10)),
2333 token::owner(minter));
2335 env(token::acceptBuyOffer(minter, carolBuyOfferIndex));
2338 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1065));
2339 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2340 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2341 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990));
2345 uint256 const carolSellOfferIndex =
2347 env(token::createOffer(carol, nftID, gwXAU(10)),
2350 env(token::acceptSellOffer(alice, carolSellOfferIndex));
2353 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1055));
2354 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1040));
2355 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(905));
2356 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2359 env(pay(alice, minter, gwXAU(55)));
2360 env(pay(becky, minter, gwXAU(40)));
2362 BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000));
2363 BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000));
2364 BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(1000));
2365 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
2368 env(token::burn(alice, nftID));
2370 BEAST_EXPECT(ownerCount(env, alice) == 1);
2371 BEAST_EXPECT(ownerCount(env, becky) == 1);
2372 BEAST_EXPECT(ownerCount(env, carol) == 1);
2373 BEAST_EXPECT(ownerCount(env, minter) == 1);
2378 for (
auto NumberSwitchOver : {
true})
2380 if (NumberSwitchOver)
2381 env.enableFeature(fixUniversalNumber);
2383 env.disableFeature(fixUniversalNumber);
2388 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2393 STAmount aliceBalance = env.balance(alice);
2394 STAmount minterBalance = env.balance(minter);
2395 uint256 const minterBuyOfferIndex =
2397 env(token::createOffer(minter, nftID, XRP(1)), token::owner(alice));
2399 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2401 aliceBalance += XRP(1) - baseFee;
2402 minterBalance -= XRP(1) + baseFee;
2403 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2404 BEAST_EXPECT(env.balance(minter) == minterBalance);
2408 auto pmt = NumberSwitchOver ? drops(50000) : drops(99999);
2409 STAmount carolBalance = env.balance(carol);
2410 uint256 const minterSellOfferIndex =
2412 env(token::createOffer(minter, nftID, pmt), txflags(
tfSellNFToken));
2414 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2416 minterBalance += pmt - baseFee;
2417 carolBalance -= pmt + baseFee;
2418 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2419 BEAST_EXPECT(env.balance(minter) == minterBalance);
2420 BEAST_EXPECT(env.balance(carol) == carolBalance);
2424 STAmount beckyBalance = env.balance(becky);
2425 uint256 const beckyBuyOfferIndex =
2427 pmt = NumberSwitchOver ? drops(50001) : drops(100000);
2428 env(token::createOffer(becky, nftID, pmt), token::owner(carol));
2430 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2432 carolBalance += pmt - drops(1) - baseFee;
2433 beckyBalance -= pmt + baseFee;
2434 aliceBalance += drops(1);
2436 BEAST_EXPECT(env.balance(alice) == aliceBalance);
2437 BEAST_EXPECT(env.balance(minter) == minterBalance);
2438 BEAST_EXPECT(env.balance(carol) == carolBalance);
2439 BEAST_EXPECT(env.balance(becky) == beckyBalance);
2448 env(token::mint(alice), txflags(
tfTransferable), token::xferFee(1));
2454 env(pay(alice, gw, env.balance(alice, gwXAU)));
2455 env(pay(minter, gw, env.balance(minter, gwXAU)));
2456 env(pay(becky, gw, env.balance(becky, gwXAU)));
2461 env(pay(gw, alice, startXAUBalance));
2462 env(pay(gw, minter, startXAUBalance));
2463 env(pay(gw, becky, startXAUBalance));
2472 STAmount aliceBalance = env.balance(alice, gwXAU);
2473 STAmount minterBalance = env.balance(minter, gwXAU);
2474 uint256 const minterBuyOfferIndex =
2476 env(token::createOffer(minter, nftID, tinyXAU),
2477 token::owner(alice));
2479 env(token::acceptBuyOffer(alice, minterBuyOfferIndex));
2481 aliceBalance += tinyXAU;
2482 minterBalance -= tinyXAU;
2483 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2484 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2487 STAmount carolBalance = env.balance(carol, gwXAU);
2488 uint256 const minterSellOfferIndex =
2490 env(token::createOffer(minter, nftID, tinyXAU),
2493 env(token::acceptSellOffer(carol, minterSellOfferIndex));
2496 minterBalance += tinyXAU;
2497 carolBalance -= tinyXAU;
2499 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2500 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2501 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2508 STAmount beckyBalance = env.balance(becky, gwXAU);
2509 uint256 const beckyBuyOfferIndex =
2511 env(token::createOffer(becky, nftID, cheapNFT),
2512 token::owner(carol));
2514 env(token::acceptBuyOffer(carol, beckyBuyOfferIndex));
2517 aliceBalance += tinyXAU;
2518 beckyBalance -= cheapNFT;
2519 carolBalance += cheapNFT - tinyXAU;
2520 BEAST_EXPECT(env.balance(alice, gwXAU) == aliceBalance);
2521 BEAST_EXPECT(env.balance(minter, gwXAU) == minterBalance);
2522 BEAST_EXPECT(env.balance(carol, gwXAU) == carolBalance);
2523 BEAST_EXPECT(env.balance(becky, gwXAU) == beckyBalance);
2716 testcase(
"Create offer destination");
2718 using namespace test::jtx;
2720 Env env{*
this, features};
2722 Account
const issuer{
"issuer"};
2723 Account
const minter{
"minter"};
2724 Account
const buyer{
"buyer"};
2725 Account
const broker{
"broker"};
2727 env.fund(XRP(1000), issuer, minter, buyer, broker);
2731 env(token::setMinter(issuer, minter));
2736 env(token::mint(minter, 0),
2737 token::issuer(issuer),
2744 uint256 const offerMinterToIssuer =
2746 env(token::createOffer(minter, nftokenID, drops(1)),
2747 token::destination(issuer),
2750 uint256 const offerMinterToBuyer =
2752 env(token::createOffer(minter, nftokenID, drops(1)),
2753 token::destination(buyer),
2756 uint256 const offerIssuerToMinter =
2758 env(token::createOffer(issuer, nftokenID, drops(1)),
2759 token::owner(minter),
2760 token::destination(minter));
2762 uint256 const offerIssuerToBuyer =
2764 env(token::createOffer(issuer, nftokenID, drops(1)),
2765 token::owner(minter),
2766 token::destination(buyer));
2769 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2770 BEAST_EXPECT(ownerCount(env, minter) == 3);
2771 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2780 env(token::cancelOffer(issuer, {offerMinterToBuyer}),
2782 env(token::cancelOffer(buyer, {offerMinterToIssuer}),
2784 env(token::cancelOffer(buyer, {offerIssuerToMinter}),
2786 env(token::cancelOffer(minter, {offerIssuerToBuyer}),
2789 BEAST_EXPECT(ownerCount(env, issuer) == 2);
2790 BEAST_EXPECT(ownerCount(env, minter) == 3);
2791 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2795 env(token::cancelOffer(buyer, {offerMinterToBuyer}));
2796 env(token::cancelOffer(minter, {offerMinterToIssuer}));
2797 env(token::cancelOffer(buyer, {offerIssuerToBuyer}));
2798 env(token::cancelOffer(issuer, {offerIssuerToMinter}));
2800 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2801 BEAST_EXPECT(ownerCount(env, minter) == 1);
2802 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2808 uint256 const offerMinterSellsToBuyer =
2810 env(token::createOffer(minter, nftokenID, drops(1)),
2811 token::destination(buyer),
2814 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2815 BEAST_EXPECT(ownerCount(env, minter) == 2);
2816 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2820 env(token::acceptSellOffer(issuer, offerMinterSellsToBuyer),
2823 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2824 BEAST_EXPECT(ownerCount(env, minter) == 2);
2825 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2828 env(token::acceptSellOffer(buyer, offerMinterSellsToBuyer));
2830 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2831 BEAST_EXPECT(ownerCount(env, minter) == 0);
2832 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2838 uint256 const offerMinterBuysFromBuyer =
2840 env(token::createOffer(minter, nftokenID, drops(1)),
2841 token::owner(buyer),
2842 token::destination(buyer));
2844 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2845 BEAST_EXPECT(ownerCount(env, minter) == 1);
2846 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2850 env(token::acceptBuyOffer(issuer, offerMinterBuysFromBuyer),
2853 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2854 BEAST_EXPECT(ownerCount(env, minter) == 1);
2855 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2858 env(token::acceptBuyOffer(buyer, offerMinterBuysFromBuyer));
2860 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2861 BEAST_EXPECT(ownerCount(env, minter) == 1);
2862 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2867 uint256 const offerBuyerBuysFromMinter =
2869 env(token::createOffer(buyer, nftokenID, drops(1)),
2870 token::owner(minter),
2871 token::destination(broker));
2873 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2874 BEAST_EXPECT(ownerCount(env, minter) == 1);
2875 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2877 env(token::acceptBuyOffer(minter, offerBuyerBuysFromMinter),
2882 env(token::cancelOffer(buyer, {offerBuyerBuysFromMinter}));
2884 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2885 BEAST_EXPECT(ownerCount(env, minter) == 1);
2886 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2892 uint256 const offerMinterToBroker =
2894 env(token::createOffer(minter, nftokenID, drops(1)),
2895 token::destination(broker),
2898 uint256 const offerBuyerToMinter =
2900 env(token::createOffer(buyer, nftokenID, drops(1)),
2901 token::owner(minter));
2904 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2905 BEAST_EXPECT(ownerCount(env, minter) == 2);
2906 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2911 TER const expectTer = features[fixNonFungibleTokensV1_2]
2914 env(token::brokerOffers(
2915 issuer, offerBuyerToMinter, offerMinterToBroker),
2918 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2919 BEAST_EXPECT(ownerCount(env, minter) == 2);
2920 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2925 env(token::brokerOffers(
2926 broker, offerBuyerToMinter, offerMinterToBroker));
2928 BEAST_EXPECT(ownerCount(env, issuer) == 0);
2929 BEAST_EXPECT(ownerCount(env, minter) == 0);
2930 BEAST_EXPECT(ownerCount(env, buyer) == 1);
2937 uint256 const offerBuyerToMinter =
2939 env(token::createOffer(buyer, nftokenID, drops(1)),
2940 token::destination(minter),
2943 uint256 const offerMinterToBuyer =
2945 env(token::createOffer(minter, nftokenID, drops(1)),
2946 token::owner(buyer));
2948 uint256 const offerIssuerToBuyer =
2950 env(token::createOffer(issuer, nftokenID, drops(1)),
2951 token::owner(buyer));
2954 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2955 BEAST_EXPECT(ownerCount(env, minter) == 1);
2956 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2961 TER const expectTer = features[fixNonFungibleTokensV1_2]
2964 env(token::brokerOffers(
2965 broker, offerIssuerToBuyer, offerBuyerToMinter),
2969 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2970 BEAST_EXPECT(ownerCount(env, minter) == 1);
2971 BEAST_EXPECT(ownerCount(env, buyer) == 2);
2975 TER const eexpectTer = features[fixNonFungibleTokensV1_2]
2978 env(token::brokerOffers(
2979 broker, offerMinterToBuyer, offerBuyerToMinter),
2983 if (features[fixNonFungibleTokensV1_2])
2985 env(token::acceptBuyOffer(buyer, offerMinterToBuyer));
2989 env(token::cancelOffer(buyer, {offerBuyerToMinter}));
2992 BEAST_EXPECT(ownerCount(env, issuer) == 1);
2993 BEAST_EXPECT(ownerCount(env, minter) == 1);
2994 BEAST_EXPECT(ownerCount(env, buyer) == 0);
2997 env(token::cancelOffer(issuer, {offerIssuerToBuyer}));
2999 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3000 BEAST_EXPECT(ownerCount(env, minter) == 1);
3001 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3009 uint256 const offerMinterToBroker =
3011 env(token::createOffer(minter, nftokenID, drops(1)),
3012 token::destination(broker),
3015 uint256 const offerBuyerToBroker =
3017 env(token::createOffer(buyer, nftokenID, drops(1)),
3018 token::owner(minter),
3019 token::destination(broker));
3024 TER const expectTer = features[fixNonFungibleTokensV1_2]
3027 env(token::brokerOffers(
3028 issuer, offerBuyerToBroker, offerMinterToBroker),
3031 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3032 BEAST_EXPECT(ownerCount(env, minter) == 2);
3033 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3037 env(token::brokerOffers(
3038 broker, offerBuyerToBroker, offerMinterToBroker));
3040 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3041 BEAST_EXPECT(ownerCount(env, minter) == 0);
3042 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3199 testcase(
"Create offer expiration");
3201 using namespace test::jtx;
3203 Env env{*
this, features};
3205 Account
const issuer{
"issuer"};
3206 Account
const minter{
"minter"};
3207 Account
const buyer{
"buyer"};
3209 env.fund(XRP(1000), issuer, minter, buyer);
3213 env(token::setMinter(issuer, minter));
3218 env(token::mint(minter, 0),
3219 token::issuer(issuer),
3225 env(token::mint(minter, 0),
3226 token::issuer(issuer),
3235 uint256 const offerMinterToIssuer =
3237 env(token::createOffer(minter, nftokenID0, drops(1)),
3238 token::destination(issuer),
3239 token::expiration(expiration),
3242 uint256 const offerMinterToAnyone =
3244 env(token::createOffer(minter, nftokenID0, drops(1)),
3245 token::expiration(expiration),
3248 uint256 const offerIssuerToMinter =
3250 env(token::createOffer(issuer, nftokenID0, drops(1)),
3251 token::owner(minter),
3252 token::expiration(expiration));
3254 uint256 const offerBuyerToMinter =
3256 env(token::createOffer(buyer, nftokenID0, drops(1)),
3257 token::owner(minter),
3258 token::expiration(expiration));
3260 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3261 BEAST_EXPECT(ownerCount(env, minter) == 3);
3262 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3270 env(token::cancelOffer(issuer, {offerMinterToAnyone}),
3272 env(token::cancelOffer(buyer, {offerIssuerToMinter}),
3275 BEAST_EXPECT(
lastClose(env) < expiration);
3276 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3277 BEAST_EXPECT(ownerCount(env, minter) == 3);
3278 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3281 env(token::cancelOffer(minter, {offerMinterToAnyone}));
3285 env(token::cancelOffer(issuer, {offerMinterToIssuer}));
3291 BEAST_EXPECT(ownerCount(env, issuer) == 1);
3292 BEAST_EXPECT(ownerCount(env, minter) == 1);
3293 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3296 env(token::cancelOffer(issuer, {offerBuyerToMinter}));
3297 env(token::cancelOffer(buyer, {offerIssuerToMinter}));
3299 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3300 BEAST_EXPECT(ownerCount(env, minter) == 1);
3301 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3312 env(token::createOffer(minter, nftokenID0, drops(1)),
3313 token::expiration(expiration),
3318 env(token::createOffer(minter, nftokenID1, drops(1)),
3319 token::expiration(expiration),
3322 BEAST_EXPECT(
lastClose(env) < expiration);
3323 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3324 BEAST_EXPECT(ownerCount(env, minter) == 3);
3325 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3328 env(token::acceptSellOffer(buyer, offer0));
3334 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3335 BEAST_EXPECT(ownerCount(env, minter) == 2);
3336 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3339 env(token::acceptSellOffer(buyer, offer1), ter(
tecEXPIRED));
3340 env(token::acceptSellOffer(issuer, offer1), ter(
tecEXPIRED));
3344 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3345 BEAST_EXPECT(ownerCount(env, minter) == 2);
3346 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3349 env(token::cancelOffer(issuer, {offer1}));
3351 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3352 BEAST_EXPECT(ownerCount(env, minter) == 1);
3353 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3359 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3361 token::destination(minter));
3363 env(token::acceptSellOffer(minter, offerSellBack));
3365 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3366 BEAST_EXPECT(ownerCount(env, minter) == 1);
3367 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3377 env(token::createOffer(buyer, nftokenID0, drops(1)),
3378 token::owner(minter),
3379 token::expiration(expiration));
3382 env(token::createOffer(buyer, nftokenID1, drops(1)),
3383 token::owner(minter),
3384 token::expiration(expiration));
3386 BEAST_EXPECT(
lastClose(env) < expiration);
3387 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3388 BEAST_EXPECT(ownerCount(env, minter) == 1);
3389 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3392 env(token::acceptBuyOffer(minter, offer0));
3398 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3399 BEAST_EXPECT(ownerCount(env, minter) == 1);
3400 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3403 env(token::acceptBuyOffer(minter, offer1), ter(
tecEXPIRED));
3404 env(token::acceptBuyOffer(issuer, offer1), ter(
tecEXPIRED));
3408 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3409 BEAST_EXPECT(ownerCount(env, minter) == 1);
3410 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3413 env(token::cancelOffer(issuer, {offer1}));
3415 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3416 BEAST_EXPECT(ownerCount(env, minter) == 1);
3417 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3423 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3425 token::destination(minter));
3427 env(token::acceptSellOffer(minter, offerSellBack));
3429 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3430 BEAST_EXPECT(ownerCount(env, minter) == 1);
3431 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3442 env(token::createOffer(minter, nftokenID0, drops(1)),
3443 token::expiration(expiration),
3448 env(token::createOffer(minter, nftokenID1, drops(1)),
3449 token::expiration(expiration),
3454 env(token::createOffer(buyer, nftokenID0, drops(1)),
3455 token::owner(minter));
3459 env(token::createOffer(buyer, nftokenID1, drops(1)),
3460 token::owner(minter));
3463 BEAST_EXPECT(
lastClose(env) < expiration);
3464 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3465 BEAST_EXPECT(ownerCount(env, minter) == 3);
3466 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3469 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3475 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3476 BEAST_EXPECT(ownerCount(env, minter) == 2);
3477 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3480 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3485 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3486 BEAST_EXPECT(ownerCount(env, minter) == 2);
3487 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3490 env(token::cancelOffer(buyer, {buyOffer1, sellOffer1}));
3492 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3493 BEAST_EXPECT(ownerCount(env, minter) == 1);
3494 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3500 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3502 token::destination(minter));
3504 env(token::acceptSellOffer(minter, offerSellBack));
3506 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3507 BEAST_EXPECT(ownerCount(env, minter) == 1);
3508 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3519 env(token::createOffer(minter, nftokenID0, drops(1)),
3524 env(token::createOffer(minter, nftokenID1, drops(1)),
3529 env(token::createOffer(buyer, nftokenID0, drops(1)),
3530 token::expiration(expiration),
3531 token::owner(minter));
3535 env(token::createOffer(buyer, nftokenID1, drops(1)),
3536 token::expiration(expiration),
3537 token::owner(minter));
3540 BEAST_EXPECT(
lastClose(env) < expiration);
3541 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3542 BEAST_EXPECT(ownerCount(env, minter) == 3);
3543 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3546 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3552 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3553 BEAST_EXPECT(ownerCount(env, minter) == 2);
3554 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3557 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3562 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3563 BEAST_EXPECT(ownerCount(env, minter) == 2);
3564 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3567 env(token::cancelOffer(minter, {buyOffer1, sellOffer1}));
3569 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3570 BEAST_EXPECT(ownerCount(env, minter) == 1);
3571 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3577 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3579 token::destination(minter));
3581 env(token::acceptSellOffer(minter, offerSellBack));
3583 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3584 BEAST_EXPECT(ownerCount(env, minter) == 1);
3585 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3597 env(token::createOffer(minter, nftokenID0, drops(1)),
3598 token::expiration(expiration),
3603 env(token::createOffer(minter, nftokenID1, drops(1)),
3604 token::expiration(expiration),
3609 env(token::createOffer(buyer, nftokenID0, drops(1)),
3610 token::expiration(expiration),
3611 token::owner(minter));
3615 env(token::createOffer(buyer, nftokenID1, drops(1)),
3616 token::expiration(expiration),
3617 token::owner(minter));
3620 BEAST_EXPECT(
lastClose(env) < expiration);
3621 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3622 BEAST_EXPECT(ownerCount(env, minter) == 3);
3623 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3626 env(token::brokerOffers(issuer, buyOffer0, sellOffer0));
3632 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3633 BEAST_EXPECT(ownerCount(env, minter) == 2);
3634 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3637 env(token::brokerOffers(issuer, buyOffer1, sellOffer1),
3642 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3643 BEAST_EXPECT(ownerCount(env, minter) == 2);
3644 BEAST_EXPECT(ownerCount(env, buyer) == 2);
3647 env(token::cancelOffer(issuer, {buyOffer1, sellOffer1}));
3649 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3650 BEAST_EXPECT(ownerCount(env, minter) == 1);
3651 BEAST_EXPECT(ownerCount(env, buyer) == 1);
3657 env(token::createOffer(buyer, nftokenID0, XRP(0)),
3659 token::destination(minter));
3661 env(token::acceptSellOffer(minter, offerSellBack));
3663 BEAST_EXPECT(ownerCount(env, issuer) == 0);
3664 BEAST_EXPECT(ownerCount(env, minter) == 1);
3665 BEAST_EXPECT(ownerCount(env, buyer) == 0);
3906 testcase(
"Brokered NFT offer accept");
3908 using namespace test::jtx;
3910 for (
auto const& tweakedFeatures :
3911 {features - fixNonFungibleTokensV1_2,
3912 features | fixNonFungibleTokensV1_2})
3914 Env env{*
this, tweakedFeatures};
3915 auto const baseFee = env.current()->fees().base;
3923 Account
const issuer{
"issuer"};
3924 Account
const minter{
"minter"};
3925 Account
const buyer{
"buyer"};
3926 Account
const broker{
"broker"};
3927 Account
const gw{
"gw"};
3928 IOU
const gwXAU(gw[
"XAU"]);
3930 env.fund(XRP(1000), issuer, minter, buyer, broker, gw);
3933 env(trust(issuer, gwXAU(2000)));
3934 env(trust(minter, gwXAU(2000)));
3935 env(trust(buyer, gwXAU(2000)));
3936 env(trust(broker, gwXAU(2000)));
3939 env(token::setMinter(issuer, minter));
3943 auto checkOwnerCountIsOne =
3948 for (Account
const& acct : accounts)
3955 ss <<
"Account " << acct.human()
3956 <<
" expected ownerCount == 1. Got "
3958 fail(ss.
str(), __FILE__, line);
3964 auto mintNFT = [&env, &issuer, &minter](
std::uint16_t xferFee = 0) {
3967 env(token::mint(minter, 0),
3968 token::issuer(issuer),
3969 token::xferFee(xferFee),
3981 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
3983 uint256 const nftID = mintNFT();
3986 uint256 const minterOfferIndex =
3988 env(token::createOffer(minter, nftID, XRP(0)),
3996 env(token::createOffer(buyer, nftID, XRP(1)),
3997 token::owner(minter));
4000 auto const minterBalance = env.balance(minter);
4001 auto const buyerBalance = env.balance(buyer);
4002 auto const brokerBalance = env.balance(broker);
4003 auto const issuerBalance = env.balance(issuer);
4006 env(token::brokerOffers(
4007 broker, buyOfferIndex, minterOfferIndex));
4012 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(1));
4013 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4014 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
4015 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
4018 env(token::burn(buyer, nftID));
4028 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4030 uint256 const nftID = mintNFT();
4033 uint256 const minterOfferIndex =
4035 env(token::createOffer(minter, nftID, XRP(0)),
4043 env(token::createOffer(buyer, nftID, XRP(1)),
4044 token::owner(minter));
4048 env(token::brokerOffers(
4049 broker, buyOfferIndex, minterOfferIndex),
4050 token::brokerFee(XRP(1.1)),
4054 auto const minterBalance = env.balance(minter);
4055 auto const buyerBalance = env.balance(buyer);
4056 auto const brokerBalance = env.balance(broker);
4057 auto const issuerBalance = env.balance(issuer);
4060 env(token::brokerOffers(
4061 broker, buyOfferIndex, minterOfferIndex),
4062 token::brokerFee(XRP(0.5)));
4067 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
4068 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4070 env.balance(broker) == brokerBalance + XRP(0.5) - baseFee);
4071 BEAST_EXPECT(env.balance(issuer) == issuerBalance);
4074 env(token::burn(buyer, nftID));
4084 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4089 uint256 const minterOfferIndex =
4091 env(token::createOffer(minter, nftID, XRP(0)),
4099 env(token::createOffer(buyer, nftID, XRP(1)),
4100 token::owner(minter));
4103 auto const minterBalance = env.balance(minter);
4104 auto const buyerBalance = env.balance(buyer);
4105 auto const brokerBalance = env.balance(broker);
4106 auto const issuerBalance = env.balance(issuer);
4109 env(token::brokerOffers(
4110 broker, buyOfferIndex, minterOfferIndex));
4115 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5));
4116 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4117 BEAST_EXPECT(env.balance(broker) == brokerBalance - baseFee);
4118 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.5));
4121 env(token::burn(buyer, nftID));
4131 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4136 uint256 const minterOfferIndex =
4138 env(token::createOffer(minter, nftID, XRP(0)),
4146 env(token::createOffer(buyer, nftID, XRP(1)),
4147 token::owner(minter));
4150 auto const minterBalance = env.balance(minter);
4151 auto const buyerBalance = env.balance(buyer);
4152 auto const brokerBalance = env.balance(broker);
4153 auto const issuerBalance = env.balance(issuer);
4156 env(token::brokerOffers(
4157 broker, buyOfferIndex, minterOfferIndex),
4158 token::brokerFee(XRP(0.75)));
4164 BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.125));
4165 BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1));
4167 env.balance(broker) == brokerBalance + XRP(0.75) - baseFee);
4168 BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.125));
4171 env(token::burn(buyer, nftID));
4177 auto setXAUBalance =
4178 [
this, &gw, &gwXAU, &env](
4183 for (Account
const& acct : accounts)
4185 auto const xauAmt = gwXAU(amount);
4186 auto const balance = env.balance(acct, gwXAU);
4187 if (balance < xauAmt)
4189 env(pay(gw, acct, xauAmt - balance));
4192 else if (balance > xauAmt)
4194 env(pay(acct, gw, balance - xauAmt));
4197 if (env.balance(acct, gwXAU) != xauAmt)
4200 ss <<
"Unable to set " << acct.human()
4201 <<
" account balance to gwXAU(" << amount <<
")";
4202 this->
fail(ss.
str(), __FILE__, line);
4210 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4211 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4213 uint256 const nftID = mintNFT();
4216 uint256 const minterOfferIndex =
4218 env(token::createOffer(minter, nftID, gwXAU(1000)),
4227 env(token::createOffer(buyer, nftID, gwXAU(1001)),
4228 token::owner(minter));
4232 env(token::brokerOffers(
4233 broker, buyOfferIndex, minterOfferIndex),
4239 env(token::cancelOffer(buyer, {buyOfferIndex}));
4247 env(token::createOffer(buyer, nftID, gwXAU(999)),
4248 token::owner(minter));
4252 env(token::brokerOffers(
4253 broker, buyOfferIndex, minterOfferIndex),
4259 env(token::cancelOffer(buyer, {buyOfferIndex}));
4266 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4267 token::owner(minter));
4271 env(token::brokerOffers(
4272 broker, buyOfferIndex, minterOfferIndex),
4273 token::brokerFee(gwXAU(0.1)),
4278 env(token::brokerOffers(
4279 broker, buyOfferIndex, minterOfferIndex));
4282 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4283 BEAST_EXPECT(ownerCount(env, minter) == 1);
4284 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4285 BEAST_EXPECT(ownerCount(env, broker) == 1);
4286 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1000));
4287 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(2000));
4288 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4289 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1000));
4292 env(token::burn(buyer, nftID));
4299 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4300 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4305 uint256 const minterOfferIndex =
4307 env(token::createOffer(minter, nftID, gwXAU(900)),
4315 env(token::createOffer(buyer, nftID, gwXAU(1001)),
4316 token::owner(minter));
4320 env(token::brokerOffers(
4321 broker, buyOfferIndex, minterOfferIndex),
4327 env(token::cancelOffer(buyer, {buyOfferIndex}));
4335 env(token::createOffer(buyer, nftID, gwXAU(899)),
4336 token::owner(minter));
4340 env(token::brokerOffers(
4341 broker, buyOfferIndex, minterOfferIndex),
4347 env(token::cancelOffer(buyer, {buyOfferIndex}));
4353 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4354 token::owner(minter));
4359 env(token::brokerOffers(
4360 broker, buyOfferIndex, minterOfferIndex),
4361 token::brokerFee(gwXAU(101)),
4367 env(token::brokerOffers(
4368 broker, buyOfferIndex, minterOfferIndex),
4369 token::brokerFee(gwXAU(100)));
4372 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4373 BEAST_EXPECT(ownerCount(env, minter) == 1);
4374 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4375 BEAST_EXPECT(ownerCount(env, broker) == 1);
4376 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1450));
4377 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1450));
4378 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4379 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1100));
4382 env(token::burn(buyer, nftID));
4389 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4390 setXAUBalance({issuer, minter, buyer, broker}, 1000, __LINE__);
4395 uint256 const minterOfferIndex =
4397 env(token::createOffer(minter, nftID, gwXAU(900)),
4404 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4405 token::owner(minter));
4411 env(token::brokerOffers(
4412 broker, buyOfferIndex, minterOfferIndex),
4413 token::brokerFee(gwXAU(50)));
4416 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4417 BEAST_EXPECT(ownerCount(env, minter) == 1);
4418 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4419 BEAST_EXPECT(ownerCount(env, broker) == 1);
4420 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4421 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4422 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4423 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(1050));
4426 env(token::burn(buyer, nftID));
4431 checkOwnerCountIsOne({issuer, minter, buyer, broker}, __LINE__);
4432 setXAUBalance({issuer, minter, buyer}, 1000, __LINE__);
4433 setXAUBalance({broker}, 500, __LINE__);
4437 uint256 const minterOfferIndex =
4439 env(token::createOffer(minter, nftID, gwXAU(900)),
4446 env(token::createOffer(buyer, nftID, gwXAU(1000)),
4447 token::owner(minter));
4450 if (tweakedFeatures[fixNonFungibleTokensV1_2])
4452 env(token::brokerOffers(
4453 broker, buyOfferIndex, minterOfferIndex),
4454 token::brokerFee(gwXAU(50)));
4456 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4457 BEAST_EXPECT(ownerCount(env, minter) == 1);
4458 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4459 BEAST_EXPECT(ownerCount(env, broker) == 1);
4460 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1237.5));
4461 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1712.5));
4462 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
4463 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(550));
4466 env(token::burn(buyer, nftID));
4471 env(token::brokerOffers(
4472 broker, buyOfferIndex, minterOfferIndex),
4473 token::brokerFee(gwXAU(50)),
4476 BEAST_EXPECT(ownerCount(env, issuer) == 1);
4477 BEAST_EXPECT(ownerCount(env, minter) == 3);
4478 BEAST_EXPECT(ownerCount(env, buyer) == 2);
4479 BEAST_EXPECT(ownerCount(env, broker) == 1);
4480 BEAST_EXPECT(env.balance(issuer, gwXAU) == gwXAU(1000));
4481 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
4482 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(1000));
4483 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(500));
4486 env(token::burn(minter, nftID));
4986 using namespace test::jtx;
4990 Account
const issuer{
"issuer"};
4991 Account
const buyer{
"buyer"};
4992 Account
const gw{
"gw"};
4993 IOU
const gwXAU(gw[
"XAU"]);
4999 for (
auto const& tweakedFeatures :
5000 {features - fixNFTokenNegOffer - featureNonFungibleTokensV1_1 -
5001 fixNonFungibleTokensV1_2,
5002 features - fixNFTokenNegOffer - featureNonFungibleTokensV1_1,
5003 features | fixNFTokenNegOffer})
5008 Env env{*
this, tweakedFeatures};
5010 env.fund(XRP(1000000), issuer, buyer, gw);
5013 env(trust(issuer, gwXAU(2000)));
5014 env(trust(buyer, gwXAU(2000)));
5017 env(pay(gw, issuer, gwXAU(1000)));
5018 env(pay(gw, buyer, gwXAU(1000)));
5033 TER const offerCreateTER = tweakedFeatures[fixNFTokenNegOffer]
5038 uint256 const sellNegXrpOfferIndex =
5040 env(token::createOffer(issuer, nftID0, XRP(-2)),
5042 ter(offerCreateTER));
5045 uint256 const sellNegIouOfferIndex =
5047 env(token::createOffer(issuer, nftID1, gwXAU(-2)),
5049 ter(offerCreateTER));
5052 uint256 const buyNegXrpOfferIndex =
5054 env(token::createOffer(buyer, nftID0, XRP(-1)),
5055 token::owner(issuer),
5056 ter(offerCreateTER));
5059 uint256 const buyNegIouOfferIndex =
5061 env(token::createOffer(buyer, nftID1, gwXAU(-1)),
5062 token::owner(issuer),
5063 ter(offerCreateTER));
5070 TER const offerAcceptTER = tweakedFeatures[fixNFTokenNegOffer]
5075 env(token::acceptSellOffer(buyer, sellNegXrpOfferIndex),
5076 ter(offerAcceptTER));
5078 env(token::acceptSellOffer(buyer, sellNegIouOfferIndex),
5079 ter(offerAcceptTER));
5083 env(token::acceptBuyOffer(issuer, buyNegXrpOfferIndex),
5084 ter(offerAcceptTER));
5086 env(token::acceptBuyOffer(issuer, buyNegIouOfferIndex),
5087 ter(offerAcceptTER));
5095 TER const offerAcceptTER = tweakedFeatures[fixNFTokenNegOffer]
5100 env(token::brokerOffers(
5101 gw, buyNegXrpOfferIndex, sellNegXrpOfferIndex),
5102 ter(offerAcceptTER));
5104 env(token::brokerOffers(
5105 gw, buyNegIouOfferIndex, sellNegIouOfferIndex),
5106 ter(offerAcceptTER));
5116 features - fixNFTokenNegOffer - featureNonFungibleTokensV1_1};
5118 env.fund(XRP(1000000), issuer, buyer, gw);
5121 env(trust(issuer, gwXAU(2000)));
5122 env(trust(buyer, gwXAU(2000)));
5125 env(pay(gw, issuer, gwXAU(1000)));
5126 env(pay(gw, buyer, gwXAU(1000)));
5142 uint256 const sellNegXrpOfferIndex =
5144 env(token::createOffer(issuer, nftID0, XRP(-2)),
5148 uint256 const sellNegIouOfferIndex =
5150 env(token::createOffer(issuer, nftID1, gwXAU(-2)),
5154 uint256 const buyNegXrpOfferIndex =
5156 env(token::createOffer(buyer, nftID0, XRP(-1)),
5157 token::owner(issuer));
5160 uint256 const buyNegIouOfferIndex =
5162 env(token::createOffer(buyer, nftID1, gwXAU(-1)),
5163 token::owner(issuer));
5167 env.enableFeature(fixNFTokenNegOffer);
5172 env(token::acceptSellOffer(buyer, sellNegXrpOfferIndex),
5175 env(token::acceptSellOffer(buyer, sellNegIouOfferIndex),
5180 env(token::acceptBuyOffer(issuer, buyNegXrpOfferIndex),
5183 env(token::acceptBuyOffer(issuer, buyNegIouOfferIndex),
5188 env(token::brokerOffers(
5189 gw, buyNegXrpOfferIndex, sellNegXrpOfferIndex),
5192 env(token::brokerOffers(
5193 gw, buyNegIouOfferIndex, sellNegIouOfferIndex),
5200 for (
auto const& tweakedFeatures :
5201 {features - fixNFTokenNegOffer - featureNonFungibleTokensV1_1,
5202 features | fixNFTokenNegOffer})
5204 Env env{*
this, tweakedFeatures};
5206 env.fund(XRP(1000000), issuer, buyer);
5214 TER const offerCreateTER = tweakedFeatures[fixNFTokenNegOffer]
5218 env(token::createOffer(buyer, nftID, drops(1)),
5219 token::owner(issuer),
5220 token::destination(issuer),
5221 ter(offerCreateTER));
5229 using namespace test::jtx;
5231 testcase(
"Payments with IOU transfer fees");
5233 for (
auto const& tweakedFeatures :
5234 {features - fixNonFungibleTokensV1_2,
5235 features | fixNonFungibleTokensV1_2})
5237 Env env{*
this, tweakedFeatures};
5239 Account
const minter{
"minter"};
5240 Account
const secondarySeller{
"seller"};
5241 Account
const buyer{
"buyer"};
5242 Account
const gw{
"gateway"};
5243 Account
const broker{
"broker"};
5244 IOU
const gwXAU(gw[
"XAU"]);
5245 IOU
const gwXPB(gw[
"XPB"]);
5247 env.fund(XRP(1000), gw, minter, secondarySeller, buyer, broker);
5250 env(trust(minter, gwXAU(2000)));
5251 env(trust(secondarySeller, gwXAU(2000)));
5252 env(trust(broker, gwXAU(10000)));
5253 env(trust(buyer, gwXAU(2000)));
5254 env(trust(buyer, gwXPB(2000)));
5258 env(rate(gw, 1.02));
5261 auto expectInitialState = [
this,
5274 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(1000));
5275 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(0));
5276 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(0));
5277 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(0));
5278 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(0));
5279 BEAST_EXPECT(env.balance(secondarySeller, gwXPB) == gwXPB(0));
5280 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5000));
5281 BEAST_EXPECT(env.balance(broker, gwXPB) == gwXPB(0));
5282 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-1000));
5283 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(0));
5284 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(0));
5285 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(0));
5287 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(0));
5289 env.balance(gw, secondarySeller[
"XPB"]) == gwXPB(0));
5290 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5000));
5291 BEAST_EXPECT(env.balance(gw, broker[
"XPB"]) == gwXPB(0));
5294 auto reinitializeTrustLineBalances = [&expectInitialState,
5303 if (
auto const difference =
5304 gwXAU(1000) - env.balance(buyer, gwXAU);
5305 difference > gwXAU(0))
5306 env(pay(gw, buyer, difference));
5307 if (env.balance(buyer, gwXPB) > gwXPB(0))
5308 env(pay(buyer, gw, env.balance(buyer, gwXPB)));
5309 if (env.balance(minter, gwXAU) > gwXAU(0))
5310 env(pay(minter, gw, env.balance(minter, gwXAU)));
5311 if (env.balance(minter, gwXPB) > gwXPB(0))
5312 env(pay(minter, gw, env.balance(minter, gwXPB)));
5313 if (env.balance(secondarySeller, gwXAU) > gwXAU(0))
5315 pay(secondarySeller,
5317 env.balance(secondarySeller, gwXAU)));
5318 if (env.balance(secondarySeller, gwXPB) > gwXPB(0))
5320 pay(secondarySeller,
5322 env.balance(secondarySeller, gwXPB)));
5323 auto brokerDiff = gwXAU(5000) - env.balance(broker, gwXAU);
5324 if (brokerDiff > gwXAU(0))
5325 env(pay(gw, broker, brokerDiff));
5326 else if (brokerDiff < gwXAU(0))
5328 brokerDiff.negate();
5329 env(pay(broker, gw, brokerDiff));
5331 if (env.balance(broker, gwXPB) > gwXPB(0))
5332 env(pay(broker, gw, env.balance(broker, gwXPB)));
5334 expectInitialState();
5337 auto mintNFT = [&env](Account
const& minter,
int transferFee = 0) {
5338 uint256 const nftID = token::getNextID(
5340 env(token::mint(minter),
5341 token::xferFee(transferFee),
5347 auto createBuyOffer =
5349 Account
const& offerer,
5350 Account
const& owner,
5356 env(token::createOffer(offerer, nftID, amount),
5357 token::owner(owner),
5358 terCode ? ter(*terCode)
5364 auto createSellOffer =
5366 Account
const& offerer,
5372 env(token::createOffer(offerer, nftID, amount),
5374 terCode ? ter(*terCode)
5383 reinitializeTrustLineBalances();
5384 auto const nftID = mintNFT(minter);
5385 auto const offerID =
5386 createSellOffer(minter, nftID, gwXAU(1000));
5387 auto const sellTER = tweakedFeatures[fixNonFungibleTokensV1_2]
5390 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5393 if (tweakedFeatures[fixNonFungibleTokensV1_2])
5394 expectInitialState();
5397 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5398 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(-20));
5400 env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5401 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(20));
5407 reinitializeTrustLineBalances();
5408 auto const nftID = mintNFT(minter);
5409 auto const offerID =
5410 createBuyOffer(buyer, minter, nftID, gwXAU(1000));
5411 auto const sellTER = tweakedFeatures[fixNonFungibleTokensV1_2]
5414 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5417 if (tweakedFeatures[fixNonFungibleTokensV1_2])
5418 expectInitialState();
5421 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5422 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(-20));
5424 env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5425 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(20));
5432 reinitializeTrustLineBalances();
5433 auto const nftID = mintNFT(minter);
5434 auto const offerID = createSellOffer(minter, nftID, gwXAU(995));
5435 auto const sellTER = tweakedFeatures[fixNonFungibleTokensV1_2]
5438 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5441 if (tweakedFeatures[fixNonFungibleTokensV1_2])
5442 expectInitialState();
5445 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(995));
5446 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(-14.9));
5447 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-995));
5448 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(14.9));
5455 reinitializeTrustLineBalances();
5456 auto const nftID = mintNFT(minter);
5457 auto const offerID =
5458 createBuyOffer(buyer, minter, nftID, gwXAU(995));
5459 auto const sellTER = tweakedFeatures[fixNonFungibleTokensV1_2]
5462 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5465 if (tweakedFeatures[fixNonFungibleTokensV1_2])
5466 expectInitialState();
5469 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(995));
5470 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(-14.9));
5471 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-995));
5472 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(14.9));
5480 reinitializeTrustLineBalances();
5481 auto const nftID = mintNFT(minter);
5482 auto const offerID = createSellOffer(minter, nftID, gwXAU(900));
5483 env(token::acceptSellOffer(buyer, offerID));
5486 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
5487 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5488 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
5489 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5496 reinitializeTrustLineBalances();
5497 auto const nftID = mintNFT(minter);
5498 auto const offerID =
5499 createBuyOffer(buyer, minter, nftID, gwXAU(900));
5500 env(token::acceptBuyOffer(minter, offerID));
5503 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900));
5504 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5505 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-900));
5506 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5513 reinitializeTrustLineBalances();
5516 env(pay(gw, buyer, gwXAU(20)));
5519 auto const nftID = mintNFT(minter);
5520 auto const offerID =
5521 createSellOffer(minter, nftID, gwXAU(1000));
5522 env(token::acceptSellOffer(buyer, offerID));
5525 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5526 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5527 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5528 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5535 reinitializeTrustLineBalances();
5538 env(pay(gw, buyer, gwXAU(20)));
5541 auto const nftID = mintNFT(minter);
5542 auto const offerID =
5543 createBuyOffer(buyer, minter, nftID, gwXAU(1000));
5544 env(token::acceptBuyOffer(minter, offerID));
5547 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5548 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5549 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5550 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5555 reinitializeTrustLineBalances();
5557 auto const nftID = mintNFT(minter);
5558 auto const offerID =
5559 createSellOffer(minter, nftID, gwXAU(1000));
5560 auto const sellTER = tweakedFeatures[fixNonFungibleTokensV1_2]
5563 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
5566 if (tweakedFeatures[fixNonFungibleTokensV1_2])
5568 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5570 env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5573 expectInitialState();
5578 reinitializeTrustLineBalances();
5580 auto const nftID = mintNFT(minter);
5581 auto const offerTER = tweakedFeatures[fixNonFungibleTokensV1_2]
5584 auto const offerID =
5585 createBuyOffer(gw, minter, nftID, gwXAU(1000), {offerTER});
5586 auto const sellTER = tweakedFeatures[fixNonFungibleTokensV1_2]
5589 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5592 if (tweakedFeatures[fixNonFungibleTokensV1_2])
5594 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(1000));
5596 env.balance(gw, minter[
"XAU"]) == gwXAU(-1000));
5599 expectInitialState();
5604 reinitializeTrustLineBalances();
5605 auto const nftID = mintNFT(minter);
5606 auto const offerID =
5607 createSellOffer(minter, nftID, gwXAU(5000));
5608 auto const sellTER = tweakedFeatures[fixNonFungibleTokensV1_2]
5611 env(token::acceptSellOffer(gw, offerID), ter(sellTER));
5614 if (tweakedFeatures[fixNonFungibleTokensV1_2])
5616 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5618 env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5621 expectInitialState();
5626 reinitializeTrustLineBalances();
5628 auto const nftID = mintNFT(minter);
5629 auto const offerTER = tweakedFeatures[fixNonFungibleTokensV1_2]
5632 auto const offerID =
5633 createBuyOffer(gw, minter, nftID, gwXAU(5000), {offerTER});
5634 auto const sellTER = tweakedFeatures[fixNonFungibleTokensV1_2]
5637 env(token::acceptBuyOffer(minter, offerID), ter(sellTER));
5640 if (tweakedFeatures[fixNonFungibleTokensV1_2])
5642 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(5000));
5644 env.balance(gw, minter[
"XAU"]) == gwXAU(-5000));
5647 expectInitialState();
5653 reinitializeTrustLineBalances();
5654 auto const nftID = mintNFT(gw);
5655 auto const offerID = createSellOffer(gw, nftID, gwXAU(1000));
5656 env(token::acceptSellOffer(buyer, offerID));
5659 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5660 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5666 reinitializeTrustLineBalances();
5668 auto const nftID = mintNFT(gw);
5669 auto const offerID =
5670 createBuyOffer(buyer, gw, nftID, gwXAU(1000));
5671 env(token::acceptBuyOffer(gw, offerID));
5674 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(0));
5675 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(0));
5681 reinitializeTrustLineBalances();
5682 auto const nftID = mintNFT(gw);
5683 auto const offerID = createSellOffer(gw, nftID, gwXAU(2000));
5684 env(token::acceptSellOffer(buyer, offerID),
5687 expectInitialState();
5693 reinitializeTrustLineBalances();
5694 auto const nftID = mintNFT(gw);
5695 auto const offerID =
5696 createBuyOffer(buyer, gw, nftID, gwXAU(2000));
5697 env(token::acceptBuyOffer(gw, offerID),
5700 expectInitialState();
5705 reinitializeTrustLineBalances();
5706 auto const nftID = mintNFT(minter);
5707 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5708 env(token::acceptSellOffer(buyer, offerID),
5711 expectInitialState();
5716 reinitializeTrustLineBalances();
5717 auto const nftID = mintNFT(minter);
5718 auto const offerID = createBuyOffer(
5724 env(token::acceptBuyOffer(minter, offerID),
5727 expectInitialState();
5733 reinitializeTrustLineBalances();
5734 env(pay(gw, buyer, gwXPB(100)));
5737 auto const nftID = mintNFT(minter);
5738 auto const offerID = createSellOffer(minter, nftID, gwXPB(10));
5739 env(token::acceptSellOffer(buyer, offerID));
5742 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5743 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5744 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5745 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5751 reinitializeTrustLineBalances();
5752 env(pay(gw, buyer, gwXPB(100)));
5755 auto const nftID = mintNFT(minter);
5756 auto const offerID =
5757 createBuyOffer(buyer, minter, nftID, gwXPB(10));
5758 env(token::acceptBuyOffer(minter, offerID));
5761 BEAST_EXPECT(env.balance(minter, gwXPB) == gwXPB(10));
5762 BEAST_EXPECT(env.balance(buyer, gwXPB) == gwXPB(89.8));
5763 BEAST_EXPECT(env.balance(gw, minter[
"XPB"]) == gwXPB(-10));
5764 BEAST_EXPECT(env.balance(gw, buyer[
"XPB"]) == gwXPB(-89.8));
5769 reinitializeTrustLineBalances();
5773 auto const nftID = mintNFT(minter, 3000);
5774 auto const primaryOfferID =
5775 createSellOffer(minter, nftID, XRP(0));
5776 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5780 auto const offerID =
5781 createSellOffer(secondarySeller, nftID, gwXAU(1000));
5782 auto const sellTER = tweakedFeatures[fixNonFungibleTokensV1_2]
5785 env(token::acceptSellOffer(buyer, offerID), ter(sellTER));
5788 if (tweakedFeatures[fixNonFungibleTokensV1_2])
5789 expectInitialState();
5792 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(30));
5794 env.balance(secondarySeller, gwXAU) == gwXAU(970));
5795 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(-20));
5796 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-30));
5798 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-970));
5799 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(20));
5805 reinitializeTrustLineBalances();
5809 auto const nftID = mintNFT(minter, 3000);
5810 auto const primaryOfferID =
5811 createSellOffer(minter, nftID, XRP(0));
5812 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5816 auto const offerID =
5817 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(1000));
5818 auto const sellTER = tweakedFeatures[fixNonFungibleTokensV1_2]
5821 env(token::acceptBuyOffer(secondarySeller, offerID),
5825 if (tweakedFeatures[fixNonFungibleTokensV1_2])
5826 expectInitialState();
5829 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(30));
5831 env.balance(secondarySeller, gwXAU) == gwXAU(970));
5832 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(-20));
5833 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-30));
5835 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-970));
5836 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(20));
5842 reinitializeTrustLineBalances();
5846 auto const nftID = mintNFT(minter, 3000);
5847 auto const primaryOfferID =
5848 createSellOffer(minter, nftID, XRP(0));
5849 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5853 auto const offerID =
5854 createSellOffer(secondarySeller, nftID, gwXAU(900));
5855 env(token::acceptSellOffer(buyer, offerID));
5858 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5859 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5860 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5861 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5863 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5864 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5869 reinitializeTrustLineBalances();
5873 auto const nftID = mintNFT(minter, 3000);
5874 auto const primaryOfferID =
5875 createSellOffer(minter, nftID, XRP(0));
5876 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5880 auto const offerID =
5881 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(900));
5882 env(token::acceptBuyOffer(secondarySeller, offerID));
5886 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(27));
5888 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873));
5890 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82));
5891 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-27));
5893 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-873));
5894 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-82));
5912 reinitializeTrustLineBalances();
5914 auto const nftID = mintNFT(minter);
5915 auto const sellOffer =
5916 createSellOffer(minter, nftID, gwXAU(300));
5917 auto const buyOffer =
5918 createBuyOffer(buyer, minter, nftID, gwXAU(500));
5919 env(token::brokerOffers(broker, buyOffer, sellOffer),
5920 token::brokerFee(gwXAU(100)));
5923 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(400));
5924 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5925 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5926 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-400));
5927 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5928 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
5946 reinitializeTrustLineBalances();
5950 auto const nftID = mintNFT(minter, 3000);
5951 auto const primaryOfferID =
5952 createSellOffer(minter, nftID, XRP(0));
5953 env(token::acceptSellOffer(secondarySeller, primaryOfferID));
5957 auto const sellOffer =
5958 createSellOffer(secondarySeller, nftID, gwXAU(300));
5959 auto const buyOffer =
5960 createBuyOffer(buyer, secondarySeller, nftID, gwXAU(500));
5961 env(token::brokerOffers(broker, buyOffer, sellOffer),
5962 token::brokerFee(gwXAU(100)));
5965 BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(12));
5966 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(490));
5967 BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(388));
5968 BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100));
5969 BEAST_EXPECT(env.balance(gw, minter[
"XAU"]) == gwXAU(-12));
5970 BEAST_EXPECT(env.balance(gw, buyer[
"XAU"]) == gwXAU(-490));
5972 env.balance(gw, secondarySeller[
"XAU"]) == gwXAU(-388));
5973 BEAST_EXPECT(env.balance(gw, broker[
"XAU"]) == gwXAU(-5100));
6089 using namespace test::jtx;
6094 auto openLedgerSeq = [](Env& env) {
return env.current()->seq(); };
6099 auto incLgrSeqForAcctDel = [&](Env& env, Account
const& acct) {
6100 int const delta = [&]() ->
int {
6101 if (env.seq(acct) + 255 > openLedgerSeq(env))
6102 return env.seq(acct) - openLedgerSeq(env) + 255;
6105 BEAST_EXPECT(delta >= 0);
6106 for (
int i = 0; i < delta; ++i)
6108 BEAST_EXPECT(openLedgerSeq(env) == env.seq(acct) + 255);
6114 auto incLgrSeqForFixNftRemint = [&](Env& env, Account
const& acct) {
6116 auto const deletableLgrSeq =
6117 (*env.le(acct))[~sfFirstNFTokenSequence].value_or(0) +
6118 (*env.le(acct))[sfMintedNFTokens] + 255;
6120 if (deletableLgrSeq > openLedgerSeq(env))
6121 delta = deletableLgrSeq - openLedgerSeq(env);
6123 BEAST_EXPECT(delta >= 0);
6124 for (
int i = 0; i < delta; ++i)
6126 BEAST_EXPECT(openLedgerSeq(env) == deletableLgrSeq);
6132 Env env{*
this, features};
6133 Account
const alice(
"alice");
6134 Account
const becky(
"becky");
6136 env.fund(XRP(10000), alice, becky);
6140 uint256 const prevNFTokenID = token::getNextID(env, alice, 0u);
6141 env(token::mint(alice));
6143 env(token::burn(alice, prevNFTokenID));
6147 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 1);
6150 incLgrSeqForAcctDel(env, alice);
6154 auto const acctDelFee{drops(env.current()->fees().increment)};
6155 env(acctdelete(alice, becky), fee(acctDelFee));
6160 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
6161 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
6164 env.fund(XRP(10000), alice);
6168 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6169 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6170 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
6173 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
6174 env(token::mint(alice));
6178 env(token::burn(alice, remintNFTokenID));
6181 if (features[fixNFTokenRemint])
6183 BEAST_EXPECT(remintNFTokenID != prevNFTokenID);
6186 BEAST_EXPECT(remintNFTokenID == prevNFTokenID);
6192 Env env{*
this, features};
6193 Account
const alice(
"alice");
6194 Account
const becky(
"becky");
6195 Account
const minter{
"minter"};
6197 env.fund(XRP(10000), alice, becky, minter);
6201 env(token::setMinter(alice, minter));
6207 for (
int i = 0; i < 500; i++)
6209 uint256 const nftokenID = token::getNextID(env, alice, 0u);
6211 env(token::mint(minter), token::issuer(alice));
6216 for (
auto const nftokenID : nftIDs)
6218 env(token::burn(minter, nftokenID));
6224 incLgrSeqForAcctDel(env, alice);
6228 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6229 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6231 auto const acctDelFee{drops(env.current()->fees().increment)};
6233 if (!features[fixNFTokenRemint])
6236 env(acctdelete(alice, becky), fee(acctDelFee));
6238 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
6241 env.fund(XRP(10000), alice);
6245 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6246 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6247 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
6251 uint256 const remintNFTokenID =
6252 token::getNextID(env, alice, 0u);
6253 env(token::mint(alice));
6257 env(token::burn(alice, remintNFTokenID));
6266 else if (features[fixNFTokenRemint])
6275 env(acctdelete(alice, becky),
6281 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6286 incLgrSeqForFixNftRemint(env, alice);
6289 env(acctdelete(alice, becky), fee(acctDelFee));
6294 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
6295 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
6298 env.fund(XRP(10000), alice);
6302 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6303 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6304 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
6308 uint256 const remintNFTokenID =
6309 token::getNextID(env, alice, 0u);
6310 env(token::mint(alice));
6314 env(token::burn(alice, remintNFTokenID));
6328 Env env{*
this, features};
6330 Account
const alice{
"alice"};
6331 Account
const becky{
"becky"};
6332 env.fund(XRP(10000), alice, becky);
6339 env(ticket::create(alice, 100));
6343 BEAST_EXPECT(ownerCount(env, alice) == 100);
6348 for (
int i = 0; i < 50; i++)
6350 nftIDs.
push_back(token::getNextID(env, alice, 0u));
6351 env(token::mint(alice, 0u), ticket::use(aliceTicketSeq++));
6356 for (
auto const nftokenID : nftIDs)
6358 env(token::burn(alice, nftokenID),
6359 ticket::use(aliceTicketSeq++));
6367 incLgrSeqForAcctDel(env, alice);
6371 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6372 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6374 auto const acctDelFee{drops(env.current()->fees().increment)};
6376 if (!features[fixNFTokenRemint])
6379 env(acctdelete(alice, becky), fee(acctDelFee));
6384 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
6385 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
6388 env.fund(XRP(10000), alice);
6392 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6393 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6394 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
6398 uint256 const remintNFTokenID =
6399 token::getNextID(env, alice, 0u);
6400 env(token::mint(alice));
6404 env(token::burn(alice, remintNFTokenID));
6413 else if (features[fixNFTokenRemint])
6422 env(acctdelete(alice, becky),
6428 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6433 incLgrSeqForFixNftRemint(env, alice);
6436 env(acctdelete(alice, becky), fee(acctDelFee));
6441 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
6442 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
6445 env.fund(XRP(10000), alice);
6449 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6450 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6451 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
6455 uint256 const remintNFTokenID =
6456 token::getNextID(env, alice, 0u);
6457 env(token::mint(alice));
6461 env(token::burn(alice, remintNFTokenID));
6477 if (features[fixNFTokenRemint])
6479 Env env{*
this, features};
6480 Account
const alice(
"alice");
6481 Account
const becky(
"becky");
6482 Account
const minter{
"minter"};
6484 env.fund(XRP(10000), alice, becky, minter);
6488 env(token::setMinter(alice, minter));
6493 env(ticket::create(minter, 100));
6497 BEAST_EXPECT(ownerCount(env, minter) == 100);
6502 for (
int i = 0; i < 50; i++)
6504 uint256 const nftokenID = token::getNextID(env, alice, 0u);
6506 env(token::mint(minter),
6507 token::issuer(alice),
6508 ticket::use(minterTicketSeq++));
6513 for (
auto const nftokenID : nftIDs)
6515 env(token::burn(minter, nftokenID),
6516 ticket::use(minterTicketSeq++));
6524 incLgrSeqForAcctDel(env, alice);
6528 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6529 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6538 auto const acctDelFee{drops(env.current()->fees().increment)};
6539 env(acctdelete(alice, becky), fee(acctDelFee), ter(
tecTOO_SOON));
6543 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6548 incLgrSeqForFixNftRemint(env, alice);
6551 env(acctdelete(alice, becky), fee(acctDelFee));
6556 BEAST_EXPECT(!env.closed()->exists(aliceAcctKey));
6557 BEAST_EXPECT(!env.current()->exists(aliceAcctKey));
6560 env.fund(XRP(10000), alice);
6564 BEAST_EXPECT(env.closed()->exists(aliceAcctKey));
6565 BEAST_EXPECT(env.current()->exists(aliceAcctKey));
6566 BEAST_EXPECT((*env.le(alice))[sfMintedNFTokens] == 0);
6570 uint256 const remintNFTokenID = token::getNextID(env, alice, 0u);
6571 env(token::mint(alice));
6575 env(token::burn(alice, remintNFTokenID));
6589 testcase(
"NFTokenMint with Create NFTokenOffer");
6591 using namespace test::jtx;
6593 if (!features[featureNFTokenMintOffer])
6595 Env env{*
this, features};
6596 Account
const alice(
"alice");
6597 Account
const buyer(
"buyer");
6599 env.fund(XRP(10000), alice, buyer);
6602 env(token::mint(alice),
6603 token::amount(XRP(10000)),
6607 env(token::mint(alice),
6608 token::destination(
"buyer"),
6612 env(token::mint(alice),
6622 Env env{*
this, features};
6623 auto const baseFee = env.current()->fees().base;
6624 Account
const alice(
"alice");
6625 Account
const buyer{
"buyer"};
6626 Account
const gw(
"gw");
6627 Account
const issuer(
"issuer");
6628 Account
const minter(
"minter");
6629 Account
const bob(
"bob");
6630 IOU
const gwAUD(gw[
"AUD"]);
6632 env.fund(XRP(10000), alice, buyer, gw, issuer, minter);
6637 env(token::mint(alice),
6638 token::destination(buyer),
6641 BEAST_EXPECT(ownerCount(env, alice) == 0);
6644 env(token::mint(alice),
6648 BEAST_EXPECT(ownerCount(env, buyer) == 0);
6654 env(token::mint(alice),
6655 token::amount(XRP(1000)),
6656 token::destination(alice),
6659 BEAST_EXPECT(ownerCount(env, alice) == 0);
6663 env(token::mint(alice),
6664 token::amount(XRP(1000)),
6665 token::destination(Account(
"demon")),
6668 BEAST_EXPECT(ownerCount(env, alice) == 0);
6673 env(token::mint(alice),
6674 token::amount(XRP(1000)),
6675 token::expiration(0),
6678 BEAST_EXPECT(ownerCount(env, alice) == 0);
6681 env(token::mint(alice),
6682 token::amount(XRP(1000)),
6686 BEAST_EXPECT(ownerCount(env, alice) == 0);
6691 env(token::mint(alice),
6692 token::amount(buyer[
"USD"](1)),
6695 env(token::mint(alice),
6696 token::amount(buyer[
"USD"](0)),
6699 BEAST_EXPECT(ownerCount(env, alice) == 0);
6702 env(token::mint(alice),
6703 token::amount(gwAUD(1000)),
6708 BEAST_EXPECT(ownerCount(env, alice) == 0);
6713 env(token::mint(gw),
6714 token::amount(gwAUD(1000)),
6716 token::xferFee(10));
6725 env(token::mint(alice),
6726 token::amount(gwAUD(1000)),
6731 BEAST_EXPECT(ownerCount(env, alice) == 0);
6734 env(token::mint(alice),
6735 token::amount(gwAUD(1000)),
6738 BEAST_EXPECT(ownerCount(env, alice) == 0);
6747 auto const acctReserve =
6748 env.current()->fees().accountReserve(0);
6749 auto const incReserve = env.current()->fees().increment;
6751 env.fund(acctReserve + incReserve, bob);
6755 env(token::mint(bob),
6756 token::amount(XRP(0)),
6761 env(pay(env.master, bob, incReserve + drops(baseFee)));
6763 env(token::mint(bob), token::amount(XRP(0)));
6767 env(pay(env.master, bob, drops(baseFee)));
6769 env(token::mint(bob),
6770 token::amount(XRP(0)),
6775 env(pay(env.master, bob, incReserve + drops(baseFee)));
6777 env(token::mint(bob), token::amount(XRP(0)));
6782 BEAST_EXPECT(ownerCount(env, alice) == 0);
6783 env(token::mint(alice), token::amount(XRP(10)));
6784 BEAST_EXPECT(ownerCount(env, alice) == 2);
6788 env(token::mint(alice),
6789 token::amount(XRP(10)),
6790 token::destination(buyer),
6791 token::expiration(
lastClose(env) + 25));
6795 env(trust(alice, gwAUD(1000)));
6797 env(token::mint(alice),
6798 token::amount(gwAUD(1)),
6799 token::destination(buyer),
6802 token::xferFee(10));
6806 env(token::mint(alice),
6807 token::amount(XRP(10)),
6808 token::destination(buyer),
6809 token::expiration(
lastClose(env) + 25));
6810 uint256 const offerAliceSellsToBuyer =
6812 env(token::cancelOffer(alice, {offerAliceSellsToBuyer}));
6816 env(token::mint(buyer),
6817 token::amount(XRP(10)),
6818 token::destination(alice),
6819 token::expiration(
lastClose(env) + 25));
6820 uint256 const offerBuyerSellsToAlice =
6822 env(token::cancelOffer(alice, {offerBuyerSellsToAlice}));
6825 env(token::setMinter(issuer, minter));
6829 BEAST_EXPECT(ownerCount(env, minter) == 0);
6830 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6831 env(token::mint(minter),
6832 token::issuer(issuer),
6833 token::amount(drops(1)));
6835 BEAST_EXPECT(ownerCount(env, minter) == 2);
6836 BEAST_EXPECT(ownerCount(env, issuer) == 0);
6841 for (
auto const& tweakedFeatures :
6842 {features - fixNFTokenNegOffer - featureNonFungibleTokensV1_1,
6843 features | fixNFTokenNegOffer})
6845 Env env{*
this, tweakedFeatures};
6846 Account
const alice(
"alice");
6848 env.fund(XRP(1000000), alice);
6850 TER const offerCreateTER = tweakedFeatures[fixNFTokenNegOffer]
6855 env(token::mint(alice),
6856 token::amount(XRP(-2)),
6857 ter(offerCreateTER));
7106 testcase(
"Test buyer reserve when accepting an offer");
7108 using namespace test::jtx;
7121 uint256 const sellOfferIndex =
7123 env(token::createOffer(acct, nftId, amt), txflags(
tfSellNFToken));
7126 return sellOfferIndex;
7133 Account
const alice{
"alice"};
7134 Account
const bob{
"bob"};
7136 Env env{*
this, features};
7137 auto const acctReserve = env.
current()->fees().accountReserve(0);
7138 auto const incReserve = env.
current()->fees().increment;
7139 auto const baseFee = env.
current()->fees().base;
7141 env.
fund(XRP(10000), alice);
7145 env.
fund(acctReserve, bob);
7149 auto const sellOfferIndex =
7150 mintAndCreateSellOffer(env, alice, XRP(0));
7153 BEAST_EXPECT(ownerCount(env, bob) == 0);
7157 if (!features[fixNFTokenReserve])
7160 env(token::acceptSellOffer(bob, sellOfferIndex));
7164 BEAST_EXPECT(ownerCount(env, bob) == 1);
7179 env(token::acceptSellOffer(bob, sellOfferIndex),
7186 BEAST_EXPECT(ownerCount(env, bob) == 0);
7191 env(pay(env.
master, bob, incReserve + drops(baseFee)));
7196 env(token::acceptSellOffer(bob, sellOfferIndex),
7202 env(pay(env.
master, bob, drops(baseFee * 2)));
7206 env(token::acceptSellOffer(bob, sellOfferIndex));
7209 BEAST_EXPECT(ownerCount(env, bob) == 1);
7216 Account
const alice{
"alice"};
7217 Account
const bob{
"bob"};
7219 Env env{*
this, features};
7220 auto const acctReserve = env.
current()->fees().accountReserve(0);
7221 auto const incReserve = env.
current()->fees().increment;
7223 env.
fund(XRP(10000), alice);
7226 env.
fund(acctReserve + XRP(1), bob);
7229 if (!features[fixNFTokenReserve])
7232 for (
size_t i = 0; i < 200; i++)
7235 auto const sellOfferIndex =
7236 mintAndCreateSellOffer(env, alice, XRP(0));
7239 env(token::acceptSellOffer(bob, sellOfferIndex));
7246 auto const sellOfferIndex1 =
7247 mintAndCreateSellOffer(env, alice, XRP(0));
7251 env(token::acceptSellOffer(bob, sellOfferIndex1),
7256 env(pay(env.
master, bob, drops(incReserve)));
7259 BEAST_EXPECT(ownerCount(env, bob) == 0);
7262 env(token::acceptSellOffer(bob, sellOfferIndex1));
7265 BEAST_EXPECT(ownerCount(env, bob) == 1);
7269 for (
size_t i = 0; i < 31; i++)
7272 auto const sellOfferIndex =
7273 mintAndCreateSellOffer(env, alice, XRP(0));
7277 env(token::acceptSellOffer(bob, sellOfferIndex));
7281 BEAST_EXPECT(ownerCount(env, bob) == 1);
7285 auto const sellOfferIndex33 =
7286 mintAndCreateSellOffer(env, alice, XRP(0));
7290 env(token::acceptSellOffer(bob, sellOfferIndex33),
7295 env(pay(env.
master, bob, drops(incReserve)));
7300 env(token::acceptSellOffer(bob, sellOfferIndex33));
7303 BEAST_EXPECT(ownerCount(env, bob) == 2);
7313 Account
const alice{
"alice"};
7314 Account
const bob{
"bob"};
7316 Env env{*
this, features};
7317 auto const acctReserve = env.
current()->fees().accountReserve(0);
7318 auto const incReserve = env.
current()->fees().increment;
7319 auto const baseFee = env.
current()->fees().base;
7321 env.
fund(XRP(10000), alice);
7327 env.
fund(acctReserve + incReserve + XRP(1), bob);
7338 env(token::createOffer(bob, nftId, XRP(1)), token::owner(alice));
7344 env(token::acceptBuyOffer(alice, buyOfferIndex),
7349 env(pay(env.
master, bob, drops(baseFee)));
7353 env(token::acceptBuyOffer(alice, buyOfferIndex));
7363 Account
const alice{
"alice"};
7364 Account
const bob{
"bob"};
7365 Account
const broker{
"broker"};
7367 Env env{*
this, features};
7368 auto const acctReserve = env.
current()->fees().accountReserve(0);
7369 auto const incReserve = env.
current()->fees().increment;
7370 auto const baseFee = env.
current()->fees().base;
7372 env.
fund(XRP(10000), alice, broker);
7377 env.
fund(acctReserve + incReserve + XRP(1), bob);
7387 uint256 const offerAliceToBroker =
7389 env(token::createOffer(alice, nftId, XRP(1)),
7390 token::destination(broker),
7395 uint256 const offerBobToBroker =
7397 env(token::createOffer(bob, nftId, XRP(1)), token::owner(alice));
7404 env(token::brokerOffers(
7405 broker, offerBobToBroker, offerAliceToBroker),
7410 env(pay(env.
master, bob, drops(baseFee)));
7414 env(token::brokerOffers(
7415 broker, offerBobToBroker, offerAliceToBroker));
7753 using namespace test::jtx;
7755 Account
const issuer{
"issuer"};
7756 Account
const alice(
"alice");
7757 Account
const bob(
"bob");
7759 bool const modifyEnabled = features[featureDynamicNFT];
7763 Env env{*
this, features};
7764 env.fund(XRP(10000), issuer);
7767 auto const expectedTer =
7769 env(token::mint(issuer, 0u), txflags(
tfMutable), ter(expectedTer));
7773 Env env{*
this, features};
7774 env.fund(XRP(10000), issuer);
7781 env(token::mint(issuer, 0u), txflags(
tfMutable));
7783 BEAST_EXPECT(ownerCount(env, issuer) == 1);
7784 env(token::modify(issuer, nftId));
7785 BEAST_EXPECT(ownerCount(env, issuer) == 1);
7789 env(token::mint(issuer, 0u));
7791 env(token::modify(issuer, nftId), ter(
temDISABLED));
7799 Env env{*
this, features};
7800 env.fund(XRP(10000), issuer);
7804 env(token::mint(issuer, 0u), txflags(
tfMutable));
7808 env(token::modify(issuer, nftId),
7814 env(token::modify(issuer, nftId),
7815 txflags(0x00000001),
7819 env(token::modify(issuer, nftId),
7820 token::owner(issuer),
7825 env(token::modify(issuer, nftId),
7831 env(token::modify(issuer, nftId),
7837 Env env{*
this, features};
7838 env.fund(XRP(10000), issuer, alice, bob);
7844 token::getNextID(env, issuer, 0u,
tfMutable)};
7847 env(token::modify(issuer, nftIDNotExists), ter(
tecNO_ENTRY));
7852 uint256 const nftIDNotModifiable{
7853 token::getNextID(env, issuer, 0u)};
7854 env(token::mint(issuer, 0u));
7857 env(token::modify(issuer, nftIDNotModifiable),
7864 token::getNextID(env, issuer, 0u,
tfMutable)};
7865 env(token::mint(issuer, 0u), txflags(
tfMutable));
7868 env(token::modify(bob, nftId),
7869 token::owner(issuer),
7873 env(token::setMinter(issuer, alice));
7876 env(token::modify(bob, nftId),
7877 token::owner(issuer),
7883 Env env{*
this, features};
7884 env.fund(XRP(10000), issuer, alice, bob);
7889 env(token::mint(issuer, 0u), txflags(
tfMutable), token::uri(
"uri"));
7896 Env env{*
this, features};
7897 env.fund(XRP(10000), issuer, alice, bob);
7901 auto accountNFTs = [&env](Account
const& acct) {
7903 params[jss::account] = acct.human();
7904 params[jss::type] =
"state";
7906 env.rpc(
"json",
"account_nfts",
to_string(params));
7907 return response[jss::result][jss::account_nfts];
7911 auto checkURI = [&accountNFTs,
this](
7912 Account
const& acct,
7915 auto const nfts = accountNFTs(acct);
7916 if (nfts.size() == 1)
7921 text <<
"checkURI: unexpected NFT count on line " << line;
7922 fail(text.
str(), __FILE__, line);
7928 if (!nfts[0u].isMember(sfURI.jsonName))
7933 text <<
"checkURI: unexpected URI present on line "
7935 fail(text.
str(), __FILE__, line);
7945 text <<
"checkURI: unexpected URI contents on line "
7947 fail(text.
str(), __FILE__, line);
7954 env(token::mint(issuer, 0u), txflags(
tfMutable), token::uri(
"uri"));
7956 checkURI(issuer,
"uri", __LINE__);
7959 env(token::modify(issuer, nftId), token::uri(
"new_uri"));
7961 checkURI(issuer,
"new_uri", __LINE__);
7964 env(token::modify(issuer, nftId));
7966 checkURI(issuer,
nullptr, __LINE__);
7969 env(token::modify(issuer, nftId), token::uri(
"uri"));
7971 checkURI(issuer,
"uri", __LINE__);
7976 env(token::createOffer(issuer, nftId, XRP(0)),
7979 env(token::acceptSellOffer(alice, offerID));
7981 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7982 BEAST_EXPECT(ownerCount(env, alice) == 1);
7983 checkURI(alice,
"uri", __LINE__);
7986 env(token::modify(alice, nftId),
7987 token::uri(
"new_uri"),
7990 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7991 BEAST_EXPECT(ownerCount(env, alice) == 1);
7992 checkURI(alice,
"uri", __LINE__);
7994 env(token::modify(issuer, nftId),
7995 token::owner(alice),
7996 token::uri(
"new_uri"));
7998 BEAST_EXPECT(ownerCount(env, issuer) == 0);
7999 BEAST_EXPECT(ownerCount(env, alice) == 1);
8000 checkURI(alice,
"new_uri", __LINE__);
8002 env(token::modify(issuer, nftId), token::owner(alice));
8004 checkURI(alice,
nullptr, __LINE__);
8006 env(token::modify(issuer, nftId),
8007 token::owner(alice),
8010 checkURI(alice,
"uri", __LINE__);
8013 env(token::setMinter(issuer, bob));
8015 env(token::modify(bob, nftId),
8016 token::owner(alice),
8017 token::uri(
"new_uri"));
8019 checkURI(alice,
"new_uri", __LINE__);
8021 env(token::modify(bob, nftId), token::owner(alice));
8023 checkURI(alice,
nullptr, __LINE__);
8025 env(token::modify(bob, nftId),
8026 token::owner(alice),
8029 checkURI(alice,
"uri", __LINE__);