19#include <test/jtx/AMM.h>
20#include <test/jtx/CaptureLogs.h>
22#include <xrpld/app/misc/AMMUtils.h>
24#include <xrpl/protocol/Feature.h>
41 env.
fund(
XRP(100000), gw, alice);
49 auto const USD = gw[
"USD"];
50 env.
trust(USD(10000), alice);
51 env(
pay(gw, alice, USD(100)));
53 AMM amm(env, alice,
XRP(100), USD(100));
57 gw,
Account(
"unknown"), USD,
XRP, std::nullopt),
67 env.
fund(
XRP(100000), gw, alice);
76 auto const USD = gw[
"USD"];
77 env.
trust(USD(10000), alice);
78 env(
pay(gw, alice, USD(100)));
83 AMM amm(env, gw,
XRP(100), USD(100));
85 BEAST_EXPECT(!amm.ammExists());
100 env.
fund(
XRP(10000), gw, alice);
109 auto const USD = gw[
"USD"];
110 env.
trust(USD(1000), alice);
111 env(
pay(gw, alice, USD(100)));
130 env.
fund(
XRP(10000), gw, alice);
139 auto const USD = gw[
"USD"];
140 env.
trust(USD(1000), alice);
141 env(
pay(gw, alice, USD(100)));
162 env.
fund(
XRP(10000), gw, alice);
171 auto const USD = gw[
"USD"];
172 env.
trust(USD(1000), alice);
173 env(
pay(gw, alice, USD(100)));
195 env.
fund(
XRP(10000), gw, alice);
204 auto const USD = gw[
"USD"];
205 env.
trust(USD(1000), alice);
206 env(
pay(gw, alice, USD(100)));
236 env.
fund(
XRP(10000), gw, alice);
240 auto const USD = gw[
"USD"];
241 env.
trust(USD(1000), alice);
242 env(
pay(gw, alice, USD(100)));
261 env.
fund(
XRP(10000), gw, alice);
270 auto const USD = gw[
"USD"];
271 env.
trust(USD(1000), alice);
272 env(
pay(gw, alice, USD(100)));
289 env.
fund(
XRP(10000), gw, alice);
298 auto const USD = gw[
"USD"];
299 env.
trust(USD(1000), alice);
300 env(
pay(gw, alice, USD(100)));
320 env.
fund(
XRP(1000000), gw, alice);
329 auto const USD = gw[
"USD"];
330 env.
trust(USD(100000), alice);
331 env(
pay(gw, alice, USD(3000)));
347 testcase(
"test featureAMMClawback is not enabled.");
349 if (!features[featureAMMClawback])
351 Env env(*
this, features);
354 env.
fund(
XRP(1000000), gw, alice);
363 auto const USD = gw[
"USD"];
364 env.
trust(USD(100000), alice);
365 env(
pay(gw, alice, USD(3000)));
379 testcase(
"test AMMClawback specific amount");
385 Env env(*
this, features);
389 env.
fund(
XRP(1000000), gw, gw2, alice);
398 auto const USD = gw[
"USD"];
399 env.
trust(USD(100000), alice);
400 env(
pay(gw, alice, USD(3000)));
406 auto const EUR = gw2[
"EUR"];
407 env.
trust(EUR(100000), alice);
408 env(
pay(gw2, alice, EUR(3000)));
417 BEAST_EXPECT(amm.expectBalances(
418 USD(2000), EUR(1000),
IOUAmount{1414213562373095, -12}));
439 BEAST_EXPECT(amm.expectBalances(
440 USD(1000), EUR(500),
IOUAmount{7071067811865475, -13}));
444 amm.expectLPTokens(alice,
IOUAmount{7071067811865475, -13}));
463 BEAST_EXPECT(!amm.ammExists());
469 Env env(*
this, features);
472 env.
fund(
XRP(1000000), gw, alice);
481 auto const USD = gw[
"USD"];
482 env.
trust(USD(100000), alice);
483 env(
pay(gw, alice, USD(3000)));
492 BEAST_EXPECT(amm.expectBalances(
493 USD(2000),
XRP(1000),
IOUAmount{1414213562373095, -9}));
495 auto aliceXrpBalance = env.
balance(alice,
XRP);
515 BEAST_EXPECT(amm.expectBalances(
516 USD(1000),
XRP(500),
IOUAmount{7071067811865475, -10}));
520 amm.expectLPTokens(alice,
IOUAmount{7071067811865475, -10}));
538 BEAST_EXPECT(!amm.ammExists());
546 "test AMMClawback specific amount which exceeds the current "
555 Env env(*
this, features);
559 env.
fund(
XRP(1000000), gw, gw2, alice);
568 auto const USD = gw[
"USD"];
569 env.
trust(USD(100000), alice);
570 env(
pay(gw, alice, USD(6000)));
575 auto const EUR = gw2[
"EUR"];
576 env.
trust(EUR(100000), alice);
577 env(
pay(gw2, alice, EUR(6000)));
585 if (!features[fixAMMv1_3])
586 BEAST_EXPECT(amm.expectBalances(
587 USD(4000), EUR(5000),
IOUAmount{4472135954999580, -12}));
589 BEAST_EXPECT(amm.expectBalances(
590 USD(4000), EUR(5000),
IOUAmount{4472135954999579, -12}));
609 if (!features[fixAMMv1_3])
610 BEAST_EXPECT(amm.expectBalances(
611 USD(3000), EUR(3750),
IOUAmount{3354101966249685, -12}));
613 BEAST_EXPECT(amm.expectBalances(
614 USD(3000), EUR(3750),
IOUAmount{3354101966249684, -12}));
617 if (!features[fixAMMv1_3])
618 BEAST_EXPECT(amm.expectLPTokens(
619 alice,
IOUAmount{3354101966249685, -12}));
621 BEAST_EXPECT(amm.expectLPTokens(
622 alice,
IOUAmount{3354101966249684, -12}));
633 if (!features[fixAMMv1_3])
634 BEAST_EXPECT(amm.expectBalances(
635 STAmount{USD, UINT64_C(2500000000000001), -12},
636 STAmount{EUR, UINT64_C(3125000000000001), -12},
639 BEAST_EXPECT(amm.expectBalances(
640 USD(2500), EUR(3125),
IOUAmount{2795084971874737, -12}));
642 if (!features[fixAMMv1_3])
645 STAmount(EUR, UINT64_C(2874999999999999), -12));
647 BEAST_EXPECT(env.
balance(alice, EUR) == EUR(2875));
656 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
657 BEAST_EXPECT(amm.expectBalances(
658 STAmount{USD, UINT64_C(2499000000000002), -12},
659 STAmount{EUR, UINT64_C(3123750000000002), -12},
661 else if (!features[fixAMMClawbackRounding])
662 BEAST_EXPECT(amm.expectBalances(
663 USD(2499), EUR(3123.75),
IOUAmount{2793966937885987, -12}));
664 else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3])
665 BEAST_EXPECT(amm.expectBalances(
666 STAmount{USD, UINT64_C(2499000000000001), -12},
667 STAmount{EUR, UINT64_C(3123750000000001), -12},
670 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
673 STAmount(EUR, UINT64_C(2876'249999999998), -12));
674 else if (!features[fixAMMClawbackRounding])
675 BEAST_EXPECT(env.
balance(alice, EUR) == EUR(2876.25));
676 else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3])
679 STAmount(EUR, UINT64_C(2876'249999999999), -12));
692 STAmount(EUR, UINT64_C(6000000000000000), -12));
695 BEAST_EXPECT(!amm.ammExists());
704 Env env(*
this, features);
709 env.
fund(
XRP(1000000), gw, gw2, alice, bob);
723 auto const USD = gw[
"USD"];
724 env.
trust(USD(100000), alice);
725 env(
pay(gw, alice, USD(6000)));
726 env.
trust(USD(100000), bob);
727 env(
pay(gw, bob, USD(5000)));
731 auto const EUR = gw2[
"EUR"];
732 env.
trust(EUR(100000), alice);
733 env(
pay(gw2, alice, EUR(5000)));
734 env.
trust(EUR(100000), bob);
735 env(
pay(gw2, bob, EUR(4000)));
740 BEAST_EXPECT(amm.expectBalances(
741 USD(1000),
XRP(2000),
IOUAmount{1414213562373095, -9}));
742 amm.deposit(alice, USD(1000),
XRP(2000));
743 BEAST_EXPECT(amm.expectBalances(
744 USD(2000),
XRP(4000),
IOUAmount{2828427124746190, -9}));
745 amm.deposit(bob, USD(1000),
XRP(2000));
746 BEAST_EXPECT(amm.expectBalances(
747 USD(3000),
XRP(6000),
IOUAmount{4242640687119285, -9}));
752 if (!features[fixAMMv1_3])
754 EUR(1000),
XRP(3000),
IOUAmount{1732050807568878, -9}));
757 EUR(1000),
XRP(3000),
IOUAmount{1732050807568877, -9}));
760 if (!features[fixAMMv1_3])
762 EUR(2000),
XRP(6000),
IOUAmount{3464101615137756, -9}));
765 EUR(2000),
XRP(6000),
IOUAmount{3464101615137754, -9}));
768 if (!features[fixAMMv1_3])
770 EUR(3000),
XRP(9000),
IOUAmount{5196152422706634, -9}));
773 EUR(3000),
XRP(9000),
IOUAmount{5196152422706631, -9}));
776 auto aliceXrpBalance = env.
balance(alice,
XRP);
793 if (features[fixAMMClawbackRounding] && features[fixAMMv1_3])
795 env, alice, aliceXrpBalance +
XRP(1000) -
XRPAmount(1)));
798 env, alice, aliceXrpBalance +
XRP(1000)));
801 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
802 BEAST_EXPECT(amm.expectBalances(
803 USD(2500),
XRP(5000),
IOUAmount{3535533905932738, -9}));
804 else if (!features[fixAMMClawbackRounding])
805 BEAST_EXPECT(amm.expectBalances(
806 USD(2500),
XRP(5000),
IOUAmount{3535533905932737, -9}));
807 else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3])
808 BEAST_EXPECT(amm.expectBalances(
813 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
814 BEAST_EXPECT(amm.expectLPTokens(
815 alice,
IOUAmount{7071067811865480, -10}));
816 else if (!features[fixAMMClawbackRounding])
817 BEAST_EXPECT(amm.expectLPTokens(
818 alice,
IOUAmount{7071067811865474, -10}));
819 else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3])
821 amm.expectLPTokens(alice,
IOUAmount{707106781186548, -9}));
824 amm.expectLPTokens(bob,
IOUAmount{1414213562373095, -9}));
838 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
839 BEAST_EXPECT(amm.expectBalances(
840 STAmount{USD, UINT64_C(2490000000000001), -12},
843 else if (!features[fixAMMClawbackRounding])
844 BEAST_EXPECT(amm.expectBalances(
845 USD(2'490),
XRP(4980),
IOUAmount{3521391770309006, -9}));
846 else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3])
847 BEAST_EXPECT(amm.expectBalances(
848 STAmount{USD, UINT64_C(2490000000000001), -12},
852 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
853 BEAST_EXPECT(amm.expectLPTokens(
854 alice,
IOUAmount{7071067811865480, -10}));
855 else if (!features[fixAMMClawbackRounding])
856 BEAST_EXPECT(amm.expectLPTokens(
857 alice,
IOUAmount{7071067811865474, -10}));
858 else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3])
860 amm.expectLPTokens(alice,
IOUAmount{707106781186548, -9}));
862 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
864 amm.expectLPTokens(bob,
IOUAmount{1400071426749365, -9}));
865 else if (!features[fixAMMClawbackRounding])
867 amm.expectLPTokens(bob,
IOUAmount{1400071426749364, -9}));
868 else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3])
870 amm.expectLPTokens(bob,
IOUAmount{1400071426749365, -9}));
880 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
882 env, alice, aliceXrpBalance +
XRP(600)));
883 else if (!features[fixAMMClawbackRounding])
885 env, alice, aliceXrpBalance +
XRP(600)));
886 else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3])
888 env, alice, aliceXrpBalance +
XRP(600) -
XRPAmount{1}));
891 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
893 EUR(2800),
XRP(8400),
IOUAmount{4849742261192859, -9}));
894 else if (!features[fixAMMClawbackRounding])
896 EUR(2800),
XRP(8400),
IOUAmount{4849742261192856, -9}));
897 else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding])
903 if (!features[fixAMMv1_3])
905 alice,
IOUAmount{1385640646055103, -9}));
908 alice,
IOUAmount{1385640646055102, -9}));
909 if (!features[fixAMMv1_3])
927 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
929 env, alice, aliceXrpBalance +
XRP(1000)));
930 else if (!features[fixAMMClawbackRounding])
932 env, alice, aliceXrpBalance +
XRP(1000) -
XRPAmount{1}));
933 else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding])
935 env, alice, aliceXrpBalance +
XRP(1000)));
938 BEAST_EXPECT(amm.expectLPTokens(alice,
IOUAmount(0)));
939 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
941 amm.expectLPTokens(bob,
IOUAmount{1400071426749365, -9}));
942 else if (!features[fixAMMClawbackRounding])
944 amm.expectLPTokens(bob,
IOUAmount{1400071426749364, -9}));
945 else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3])
947 amm.expectLPTokens(bob,
IOUAmount{1400071426749365, -9}));
949 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
950 BEAST_EXPECT(amm.expectBalances(
951 STAmount{USD, UINT64_C(1990000000000001), -12},
954 else if (!features[fixAMMClawbackRounding])
955 BEAST_EXPECT(amm.expectBalances(
959 else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding])
960 BEAST_EXPECT(amm.expectBalances(
961 STAmount{USD, UINT64_C(1990000000000001), -12},
982 BEAST_EXPECT(amm.expectLPTokens(alice,
IOUAmount(0)));
983 BEAST_EXPECT(amm.expectLPTokens(bob,
IOUAmount(0)));
1006 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
1008 EUR(2000),
XRP(6000),
IOUAmount{3464101615137756, -9}));
1009 else if (!features[fixAMMClawbackRounding])
1011 EUR(2000),
XRP(6000),
IOUAmount{3464101615137754, -9}));
1012 else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding])
1040 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
1042 EUR(1000),
XRP(3000),
IOUAmount{1732050807568878, -9}));
1043 else if (!features[fixAMMClawbackRounding])
1045 EUR(1000),
XRP(3000),
IOUAmount{1732050807568877, -9}));
1046 else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding])
1057 testcase(
"test AMMClawback all the tokens in the AMM pool");
1058 using namespace jtx;
1063 Env env(*
this, features);
1069 env.
fund(
XRP(1000000), gw, gw2, alice, bob, carol);
1084 auto const USD = gw[
"USD"];
1085 env.
trust(USD(100000), alice);
1086 env(
pay(gw, alice, USD(6000)));
1087 env.
trust(USD(100000), bob);
1088 env(
pay(gw, bob, USD(5000)));
1089 env.
trust(USD(100000), carol);
1090 env(
pay(gw, carol, USD(4000)));
1095 auto const EUR = gw2[
"EUR"];
1096 env.
trust(EUR(100000), alice);
1097 env(
pay(gw2, alice, EUR(6000)));
1098 env.
trust(EUR(100000), bob);
1099 env(
pay(gw2, bob, EUR(5000)));
1100 env.
trust(EUR(100000), carol);
1101 env(
pay(gw2, carol, EUR(4000)));
1108 if (!features[fixAMMv1_3])
1109 BEAST_EXPECT(amm.expectBalances(
1110 USD(4000), EUR(5000),
IOUAmount{4472135954999580, -12}));
1112 BEAST_EXPECT(amm.expectBalances(
1113 USD(4000), EUR(5000),
IOUAmount{4472135954999579, -12}));
1114 amm.deposit(bob, USD(2000), EUR(2500));
1115 if (!features[fixAMMv1_3])
1116 BEAST_EXPECT(amm.expectBalances(
1117 USD(6000), EUR(7500),
IOUAmount{6708203932499370, -12}));
1119 BEAST_EXPECT(amm.expectBalances(
1120 USD(6000), EUR(7500),
IOUAmount{6708203932499368, -12}));
1121 amm.deposit(carol, USD(1000), EUR(1250));
1122 if (!features[fixAMMv1_3])
1123 BEAST_EXPECT(amm.expectBalances(
1124 USD(7000), EUR(8750),
IOUAmount{7826237921249265, -12}));
1126 BEAST_EXPECT(amm.expectBalances(
1127 USD(7000), EUR(8750),
IOUAmount{7826237921249262, -12}));
1129 if (!features[fixAMMv1_3])
1130 BEAST_EXPECT(amm.expectLPTokens(
1131 alice,
IOUAmount{4472135954999580, -12}));
1133 BEAST_EXPECT(amm.expectLPTokens(
1134 alice,
IOUAmount{4472135954999579, -12}));
1135 if (!features[fixAMMv1_3])
1137 amm.expectLPTokens(bob,
IOUAmount{2236067977499790, -12}));
1140 amm.expectLPTokens(bob,
IOUAmount{2236067977499789, -12}));
1141 if (!features[fixAMMv1_3])
1142 BEAST_EXPECT(amm.expectLPTokens(
1143 carol,
IOUAmount{1118033988749895, -12}));
1145 BEAST_EXPECT(amm.expectLPTokens(
1146 carol,
IOUAmount{1118033988749894, -12}));
1160 if (!features[fixAMMv1_3])
1161 BEAST_EXPECT(amm.expectBalances(
1162 STAmount{USD, UINT64_C(4999999999999999), -12},
1163 STAmount{EUR, UINT64_C(6249999999999999), -12},
1166 BEAST_EXPECT(amm.expectBalances(
1167 STAmount{USD, UINT64_C(5000000000000001), -12},
1168 STAmount{EUR, UINT64_C(6250000000000001), -12},
1171 if (!features[fixAMMv1_3])
1172 BEAST_EXPECT(amm.expectLPTokens(
1173 alice,
IOUAmount{4472135954999580, -12}));
1175 BEAST_EXPECT(amm.expectLPTokens(
1176 alice,
IOUAmount{4472135954999579, -12}));
1177 BEAST_EXPECT(amm.expectLPTokens(bob,
IOUAmount(0)));
1178 if (!features[fixAMMv1_3])
1179 BEAST_EXPECT(amm.expectLPTokens(
1180 carol,
IOUAmount{1118033988749895, -12}));
1182 BEAST_EXPECT(amm.expectLPTokens(
1183 carol,
IOUAmount{1118033988749894, -12}));
1190 STAmount(USD, UINT64_C(3000000000000000), -12));
1192 if (!features[fixAMMv1_3])
1195 STAmount(EUR, UINT64_C(5000000000000001), -12));
1199 STAmount(EUR, UINT64_C(4999999999999999), -12));
1207 if (!features[fixAMMv1_3])
1208 BEAST_EXPECT(amm.expectBalances(
1209 STAmount{USD, UINT64_C(3999999999999999), -12},
1210 STAmount{EUR, UINT64_C(4999999999999999), -12},
1213 BEAST_EXPECT(amm.expectBalances(
1214 STAmount{USD, UINT64_C(4000000000000001), -12},
1215 STAmount{EUR, UINT64_C(5000000000000002), -12},
1218 if (!features[fixAMMv1_3])
1219 BEAST_EXPECT(amm.expectLPTokens(
1220 alice,
IOUAmount{4472135954999580, -12}));
1222 BEAST_EXPECT(amm.expectLPTokens(
1223 alice,
IOUAmount{4472135954999579, -12}));
1224 BEAST_EXPECT(amm.expectLPTokens(bob,
IOUAmount(0)));
1225 BEAST_EXPECT(amm.expectLPTokens(carol,
IOUAmount(0)));
1234 BEAST_EXPECT(!amm.ammExists());
1240 Env env(*
this, features);
1244 env.
fund(
XRP(1000000), gw, alice, bob);
1253 auto const USD = gw[
"USD"];
1254 env.
trust(USD(1000000), alice);
1255 env(
pay(gw, alice, USD(600000)));
1256 env.
trust(USD(1000000), bob);
1257 env(
pay(gw, bob, USD(500000)));
1262 if (!features[fixAMMv1_3])
1263 BEAST_EXPECT(amm.expectBalances(
1264 USD(10000),
XRP(2000),
IOUAmount{4472135954999580, -9}));
1266 BEAST_EXPECT(amm.expectBalances(
1267 USD(10000),
XRP(2000),
IOUAmount{4472135954999579, -9}));
1268 amm.deposit(alice, USD(1000),
XRP(200));
1269 if (!features[fixAMMv1_3])
1270 BEAST_EXPECT(amm.expectBalances(
1271 USD(11000),
XRP(2200),
IOUAmount{4919349550499538, -9}));
1273 BEAST_EXPECT(amm.expectBalances(
1274 USD(11000),
XRP(2200),
IOUAmount{4919349550499536, -9}));
1275 amm.deposit(bob, USD(2000),
XRP(400));
1276 if (!features[fixAMMv1_3])
1277 BEAST_EXPECT(amm.expectBalances(
1278 USD(13000),
XRP(2600),
IOUAmount{5813776741499453, -9}));
1280 BEAST_EXPECT(amm.expectBalances(
1281 USD(13000),
XRP(2600),
IOUAmount{5813776741499451, -9}));
1284 auto aliceXrpBalance = env.
balance(alice,
XRP);
1291 if (!features[fixAMMv1_3])
1292 BEAST_EXPECT(amm.expectBalances(
1293 USD(12000),
XRP(2400),
IOUAmount{5366563145999495, -9}));
1295 BEAST_EXPECT(amm.expectBalances(
1299 if (!features[fixAMMv1_3])
1301 env, alice, aliceXrpBalance +
XRP(200)));
1304 env, alice, aliceXrpBalance +
XRP(200) -
XRPAmount{1}));
1305 BEAST_EXPECT(amm.expectLPTokens(alice,
IOUAmount(0)));
1311 if (!features[fixAMMv1_3])
1312 BEAST_EXPECT(amm.expectBalances(
1313 USD(10000),
XRP(2000),
IOUAmount{4472135954999580, -9}));
1315 BEAST_EXPECT(amm.expectBalances(
1321 BEAST_EXPECT(amm.expectLPTokens(alice,
IOUAmount(0)));
1322 BEAST_EXPECT(amm.expectLPTokens(bob,
IOUAmount(0)));
1330 "test AMMClawback from AMM pool with assets having the same "
1332 using namespace jtx;
1336 Env env(*
this, features);
1341 env.
fund(
XRP(1000000), gw, alice, bob, carol);
1349 auto const USD = gw[
"USD"];
1350 env.
trust(USD(100000), alice);
1351 env(
pay(gw, alice, USD(10000)));
1352 env.
trust(USD(100000), bob);
1353 env(
pay(gw, bob, USD(9000)));
1354 env.
trust(USD(100000), carol);
1355 env(
pay(gw, carol, USD(8000)));
1358 auto const EUR = gw[
"EUR"];
1359 env.
trust(EUR(100000), alice);
1360 env(
pay(gw, alice, EUR(10000)));
1361 env.
trust(EUR(100000), bob);
1362 env(
pay(gw, bob, EUR(9000)));
1363 env.
trust(EUR(100000), carol);
1364 env(
pay(gw, carol, EUR(8000)));
1370 BEAST_EXPECT(amm.expectBalances(USD(8000), EUR(2000),
IOUAmount(4000)));
1371 amm.deposit(bob, USD(4000), EUR(1000));
1373 amm.expectBalances(USD(12000), EUR(3000),
IOUAmount(6000)));
1374 if (!features[fixAMMv1_3])
1375 amm.deposit(carol, USD(2000), EUR(500));
1377 amm.deposit(carol, USD(2000.25), EUR(500));
1379 amm.expectBalances(USD(14000), EUR(3500),
IOUAmount(7000)));
1384 amm.expectBalances(USD(13000), EUR(3250),
IOUAmount(6500)));
1386 BEAST_EXPECT(amm.expectLPTokens(alice,
IOUAmount(4000)));
1387 BEAST_EXPECT(amm.expectLPTokens(bob,
IOUAmount(2000)));
1388 BEAST_EXPECT(amm.expectLPTokens(carol,
IOUAmount(500)));
1389 BEAST_EXPECT(env.
balance(alice, USD) == USD(2000));
1390 BEAST_EXPECT(env.
balance(alice, EUR) == EUR(8000));
1391 BEAST_EXPECT(env.
balance(bob, USD) == USD(5000));
1392 BEAST_EXPECT(env.
balance(bob, EUR) == EUR(8000));
1393 if (!features[fixAMMv1_3])
1394 BEAST_EXPECT(env.
balance(carol, USD) == USD(6000));
1398 STAmount(USD, UINT64_C(5999'999999999999), -12));
1400 BEAST_EXPECT(env.
balance(carol, EUR) == EUR(7750));
1410 amm.expectBalances(USD(12000), EUR(3000),
IOUAmount(6000)));
1412 BEAST_EXPECT(amm.expectLPTokens(alice,
IOUAmount(4000)));
1413 BEAST_EXPECT(amm.expectLPTokens(bob,
IOUAmount(1500)));
1414 BEAST_EXPECT(amm.expectLPTokens(carol,
IOUAmount(500)));
1415 BEAST_EXPECT(env.
balance(alice, USD) == USD(2000));
1416 BEAST_EXPECT(env.
balance(alice, EUR) == EUR(8000));
1417 BEAST_EXPECT(env.
balance(bob, USD) == USD(5000));
1419 BEAST_EXPECT(env.
balance(bob, EUR) == EUR(8000));
1420 if (!features[fixAMMv1_3])
1421 BEAST_EXPECT(env.
balance(carol, USD) == USD(6000));
1425 STAmount(USD, UINT64_C(5999'999999999999), -12));
1426 BEAST_EXPECT(env.
balance(carol, EUR) == EUR(7750));
1433 BEAST_EXPECT(amm.expectBalances(USD(4000), EUR(1000),
IOUAmount(2000)));
1435 BEAST_EXPECT(amm.expectLPTokens(alice,
IOUAmount(0)));
1436 BEAST_EXPECT(amm.expectLPTokens(bob,
IOUAmount(1500)));
1437 BEAST_EXPECT(amm.expectLPTokens(carol,
IOUAmount(500)));
1438 BEAST_EXPECT(env.
balance(alice, USD) == USD(2000));
1439 BEAST_EXPECT(env.
balance(alice, EUR) == EUR(8000));
1440 BEAST_EXPECT(env.
balance(bob, USD) == USD(5000));
1441 BEAST_EXPECT(env.
balance(bob, EUR) == EUR(8000));
1442 if (!features[fixAMMv1_3])
1443 BEAST_EXPECT(env.
balance(carol, USD) == USD(6000));
1447 STAmount(USD, UINT64_C(5999'999999999999), -12));
1448 BEAST_EXPECT(env.
balance(carol, EUR) == EUR(7750));
1455 "test AMMClawback from AMM pool with assets having the same "
1456 "currency, but from different issuer");
1457 using namespace jtx;
1461 Env env(*
this, features);
1466 env.
fund(
XRP(1000000), gw, gw2, alice, bob);
1479 env.
trust(gw[
"USD"](100000), alice);
1480 env(
pay(gw, alice, gw[
"USD"](8000)));
1481 env.
trust(gw[
"USD"](100000), bob);
1482 env(
pay(gw, bob, gw[
"USD"](7000)));
1484 env.
trust(gw2[
"USD"](100000), alice);
1485 env(
pay(gw2, alice, gw2[
"USD"](6000)));
1486 env.
trust(gw2[
"USD"](100000), bob);
1487 env(
pay(gw2, bob, gw2[
"USD"](5000)));
1493 BEAST_EXPECT(amm.expectBalances(
1497 amm.deposit(bob, gw[
"USD"](2000), gw2[
"USD"](3000));
1498 BEAST_EXPECT(amm.expectBalances(
1521 BEAST_EXPECT(amm.expectBalances(
1522 STAmount{gw[
"USD"], UINT64_C(2666666666666667), -12},
1527 amm.expectLPTokens(alice,
IOUAmount{8164965809277260, -13}));
1528 BEAST_EXPECT(amm.expectLPTokens(bob,
IOUAmount{2449489742783178, -12}));
1530 env.
balance(alice, gw[
"USD"]) ==
1531 STAmount(gw[
"USD"], UINT64_C(7333333333333333), -12));
1532 BEAST_EXPECT(env.
balance(alice, gw2[
"USD"]) == gw2[
"USD"](4500));
1533 BEAST_EXPECT(env.
balance(bob, gw[
"USD"]) == gw[
"USD"](5000));
1534 BEAST_EXPECT(env.
balance(bob, gw2[
"USD"]) == gw2[
"USD"](2000));
1540 BEAST_EXPECT(amm.expectBalances(
1541 STAmount{gw[
"USD"], UINT64_C(6666666666666670), -13},
1546 amm.expectLPTokens(alice,
IOUAmount{8164965809277260, -13}));
1547 BEAST_EXPECT(amm.expectLPTokens(bob,
IOUAmount(0)));
1549 env.
balance(alice, gw[
"USD"]) ==
1550 STAmount(gw[
"USD"], UINT64_C(7333333333333333), -12));
1551 BEAST_EXPECT(env.
balance(alice, gw2[
"USD"]) == gw2[
"USD"](4500));
1552 BEAST_EXPECT(env.
balance(bob, gw[
"USD"]) == gw[
"USD"](5000));
1554 BEAST_EXPECT(env.
balance(bob, gw2[
"USD"]) == gw2[
"USD"](5000));
1560 testcase(
"test AMMClawback when issuing token for each other");
1561 using namespace jtx;
1565 Env env(*
this, features);
1569 env.
fund(
XRP(1000000), gw, gw2, alice);
1582 auto const USD = gw[
"USD"];
1583 env.
trust(USD(100000), gw2);
1584 env(
pay(gw, gw2, USD(5000)));
1585 env.
trust(USD(100000), alice);
1586 env(
pay(gw, alice, USD(5000)));
1588 auto const EUR = gw2[
"EUR"];
1589 env.
trust(EUR(100000), gw);
1590 env(
pay(gw2, gw, EUR(6000)));
1591 env.
trust(EUR(100000), alice);
1592 env(
pay(gw2, alice, EUR(6000)));
1597 BEAST_EXPECT(amm.expectBalances(
1598 USD(1000), EUR(2000),
IOUAmount{1414213562373095, -12}));
1600 amm.deposit(gw2, USD(2000), EUR(4000));
1601 BEAST_EXPECT(amm.expectBalances(
1602 USD(3000), EUR(6000),
IOUAmount{4242640687119285, -12}));
1604 amm.deposit(alice, USD(3000), EUR(6000));
1605 BEAST_EXPECT(amm.expectBalances(
1606 USD(6000), EUR(12000),
IOUAmount{8485281374238570, -12}));
1608 BEAST_EXPECT(amm.expectLPTokens(gw,
IOUAmount{1414213562373095, -12}));
1609 BEAST_EXPECT(amm.expectLPTokens(gw2,
IOUAmount{2828427124746190, -12}));
1611 amm.expectLPTokens(alice,
IOUAmount{4242640687119285, -12}));
1616 if (!features[fixAMMv1_3] || !features[fixAMMClawbackRounding])
1617 BEAST_EXPECT(amm.expectBalances(
1618 USD(5000), EUR(10000),
IOUAmount{7071067811865475, -12}));
1620 BEAST_EXPECT(amm.expectBalances(
1621 USD(5000), EUR(10000),
IOUAmount{7071067811865474, -12}));
1623 BEAST_EXPECT(amm.expectLPTokens(gw,
IOUAmount{1414213562373095, -12}));
1624 if (!features[fixAMMv1_3] || !features[fixAMMClawbackRounding])
1626 amm.expectLPTokens(gw2,
IOUAmount{1414213562373095, -12}));
1629 amm.expectLPTokens(gw2,
IOUAmount{1414213562373094, -12}));
1631 amm.expectLPTokens(alice,
IOUAmount{4242640687119285, -12}));
1633 BEAST_EXPECT(env.
balance(alice, USD) == USD(2000));
1634 BEAST_EXPECT(env.
balance(alice, EUR) == EUR(0));
1635 BEAST_EXPECT(env.
balance(gw, EUR) == EUR(4000));
1636 BEAST_EXPECT(env.
balance(gw2, USD) == USD(3000));
1641 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
1642 BEAST_EXPECT(amm.expectBalances(
1644 STAmount(EUR, UINT64_C(9000000000000001), -12),
1646 else if (!features[fixAMMClawbackRounding])
1647 BEAST_EXPECT(amm.expectBalances(
1648 USD(4500), EUR(9000),
IOUAmount{6363961030678928, -12}));
1649 else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding])
1650 BEAST_EXPECT(amm.expectBalances(
1652 STAmount(EUR, UINT64_C(9000000000000001), -12),
1655 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
1657 amm.expectLPTokens(gw,
IOUAmount{7071067811865480, -13}));
1658 else if (!features[fixAMMClawbackRounding])
1660 amm.expectLPTokens(gw,
IOUAmount{7071067811865475, -13}));
1661 else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding])
1663 amm.expectLPTokens(gw,
IOUAmount{7071067811865480, -13}));
1665 if (!features[fixAMMv1_3] || !features[fixAMMClawbackRounding])
1667 amm.expectLPTokens(gw2,
IOUAmount{1414213562373095, -12}));
1670 amm.expectLPTokens(gw2,
IOUAmount{1414213562373094, -12}));
1673 amm.expectLPTokens(alice,
IOUAmount{4242640687119285, -12}));
1675 BEAST_EXPECT(env.
balance(alice, USD) == USD(2000));
1676 BEAST_EXPECT(env.
balance(alice, EUR) == EUR(0));
1677 BEAST_EXPECT(env.
balance(gw, EUR) == EUR(4000));
1678 BEAST_EXPECT(env.
balance(gw2, USD) == USD(3000));
1683 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
1684 BEAST_EXPECT(amm.expectBalances(
1686 STAmount(EUR, UINT64_C(5000000000000001), -12),
1688 else if (!features[fixAMMClawbackRounding])
1689 BEAST_EXPECT(amm.expectBalances(
1690 USD(2500), EUR(5000),
IOUAmount{3535533905932738, -12}));
1691 else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding])
1692 BEAST_EXPECT(amm.expectBalances(
1694 STAmount(EUR, UINT64_C(5000000000000001), -12),
1697 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
1699 amm.expectLPTokens(gw,
IOUAmount{7071067811865480, -13}));
1700 else if (!features[fixAMMClawbackRounding])
1702 amm.expectLPTokens(gw,
IOUAmount{7071067811865475, -13}));
1703 else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding])
1705 amm.expectLPTokens(gw,
IOUAmount{7071067811865480, -13}));
1707 if (!features[fixAMMv1_3] || !features[fixAMMClawbackRounding])
1709 amm.expectLPTokens(gw2,
IOUAmount{1414213562373095, -12}));
1712 amm.expectLPTokens(gw2,
IOUAmount{1414213562373094, -12}));
1714 amm.expectLPTokens(alice,
IOUAmount{1414213562373095, -12}));
1716 BEAST_EXPECT(env.
balance(alice, USD) == USD(4000));
1717 BEAST_EXPECT(env.
balance(alice, EUR) == EUR(0));
1718 BEAST_EXPECT(env.
balance(gw, EUR) == EUR(4000));
1719 BEAST_EXPECT(env.
balance(gw2, USD) == USD(3000));
1726 "test AMMClawback from account which does not own any lptoken in "
1728 using namespace jtx;
1730 Env env(*
this, features);
1733 env.
fund(
XRP(1000000), gw, alice);
1741 auto const USD = gw[
"USD"];
1742 env.
trust(USD(100000), alice);
1743 env(
pay(gw, alice, USD(5000)));
1758 using namespace jtx;
1762 Env env(*
this, features);
1766 env.
fund(
XRP(1000000), gw, gw2, alice);
1775 auto const USD = gw[
"USD"];
1776 env.
trust(USD(100000), alice);
1777 env(
pay(gw, alice, USD(3000)));
1782 auto const EUR = gw2[
"EUR"];
1783 env.
trust(EUR(100000), alice);
1784 env(
pay(gw2, alice, EUR(3000)));
1792 BEAST_EXPECT(amm.expectBalances(
1793 USD(2000), EUR(1000),
IOUAmount{1414213562373095, -12}));
1806 BEAST_EXPECT(amm.expectBalances(
1807 USD(1000), EUR(500),
IOUAmount{7071067811865475, -13}));
1811 amm.expectLPTokens(alice,
IOUAmount{7071067811865475, -13}));
1825 BEAST_EXPECT(!amm.ammExists());
1830 Env env(*
this, features);
1834 env.
fund(
XRP(1000000), gw, gw2, alice);
1843 auto const USD = gw[
"USD"];
1844 env.
trust(USD(100000), alice);
1845 env(
pay(gw, alice, USD(3000)));
1850 auto const EUR = gw2[
"EUR"];
1851 env.
trust(EUR(100000), alice);
1852 env(
pay(gw2, alice, EUR(3000)));
1860 BEAST_EXPECT(amm.expectBalances(
1861 USD(2000), EUR(1000),
IOUAmount{1414213562373095, -12}));
1875 BEAST_EXPECT(amm.expectBalances(
1876 USD(1000), EUR(500),
IOUAmount{7071067811865475, -13}));
1878 amm.expectLPTokens(alice,
IOUAmount{7071067811865475, -13}));
1883 Env env(*
this, features);
1887 env.
fund(
XRP(1000000), gw, gw2, alice);
1896 auto const USD = gw[
"USD"];
1897 env.
trust(USD(100000), alice);
1898 env(
pay(gw, alice, USD(3000)));
1903 auto const EUR = gw2[
"EUR"];
1904 env.
trust(EUR(100000), alice);
1905 env(
pay(gw2, alice, EUR(3000)));
1913 BEAST_EXPECT(amm.expectBalances(
1914 USD(2000), EUR(1000),
IOUAmount{1414213562373095, -12}));
1927 BEAST_EXPECT(amm.expectBalances(
1928 USD(1000), EUR(500),
IOUAmount{7071067811865475, -13}));
1930 amm.expectLPTokens(alice,
IOUAmount{7071067811865475, -13}));
1936 Env env(*
this, features);
1941 env.
fund(
XRP(1000000), gw, alice, bob, carol);
1949 auto const USD = gw[
"USD"];
1950 env.
trust(USD(100000), alice);
1951 env(
pay(gw, alice, USD(10000)));
1952 env.
trust(USD(100000), bob);
1953 env(
pay(gw, bob, USD(9000)));
1954 env.
trust(USD(100000), carol);
1955 env(
pay(gw, carol, USD(8000)));
1958 auto const EUR = gw[
"EUR"];
1959 env.
trust(EUR(100000), alice);
1960 env(
pay(gw, alice, EUR(10000)));
1961 env.
trust(EUR(100000), bob);
1962 env(
pay(gw, bob, EUR(9000)));
1963 env.
trust(EUR(100000), carol);
1964 env(
pay(gw, carol, EUR(8000)));
1971 amm.expectBalances(USD(8000), EUR(2000),
IOUAmount(4000)));
1972 amm.deposit(bob, USD(4000), EUR(1000));
1974 amm.expectBalances(USD(12000), EUR(3000),
IOUAmount(6000)));
1975 if (!features[fixAMMv1_3])
1976 amm.deposit(carol, USD(2000), EUR(500));
1978 amm.deposit(carol, USD(2000.25), EUR(500));
1980 amm.expectBalances(USD(14000), EUR(3500),
IOUAmount(7000)));
1991 amm.expectBalances(USD(13000), EUR(3250),
IOUAmount(6500)));
1993 BEAST_EXPECT(amm.expectLPTokens(alice,
IOUAmount(4000)));
1994 BEAST_EXPECT(amm.expectLPTokens(bob,
IOUAmount(2000)));
1995 BEAST_EXPECT(amm.expectLPTokens(carol,
IOUAmount(500)));
1996 BEAST_EXPECT(env.
balance(alice, USD) == USD(2000));
1997 BEAST_EXPECT(env.
balance(alice, EUR) == EUR(8000));
1998 BEAST_EXPECT(env.
balance(bob, USD) == USD(5000));
1999 BEAST_EXPECT(env.
balance(bob, EUR) == EUR(8000));
2000 if (!features[fixAMMv1_3])
2001 BEAST_EXPECT(env.
balance(carol, USD) == USD(6000));
2005 STAmount(USD, UINT64_C(5999'999999999999), -12));
2007 BEAST_EXPECT(env.
balance(carol, EUR) == EUR(7750));
2017 amm.expectBalances(USD(12000), EUR(3000),
IOUAmount(6000)));
2019 BEAST_EXPECT(amm.expectLPTokens(alice,
IOUAmount(4000)));
2020 BEAST_EXPECT(amm.expectLPTokens(bob,
IOUAmount(1500)));
2021 BEAST_EXPECT(amm.expectLPTokens(carol,
IOUAmount(500)));
2022 BEAST_EXPECT(env.
balance(alice, USD) == USD(2000));
2023 BEAST_EXPECT(env.
balance(alice, EUR) == EUR(8000));
2024 BEAST_EXPECT(env.
balance(bob, USD) == USD(5000));
2026 BEAST_EXPECT(env.
balance(bob, EUR) == EUR(8000));
2027 if (!features[fixAMMv1_3])
2028 BEAST_EXPECT(env.
balance(carol, USD) == USD(6000));
2032 STAmount(USD, UINT64_C(5999'999999999999), -12));
2033 BEAST_EXPECT(env.
balance(carol, EUR) == EUR(7750));
2041 amm.expectBalances(USD(4000), EUR(1000),
IOUAmount(2000)));
2043 BEAST_EXPECT(amm.expectLPTokens(alice,
IOUAmount(0)));
2044 BEAST_EXPECT(amm.expectLPTokens(bob,
IOUAmount(1500)));
2045 BEAST_EXPECT(amm.expectLPTokens(carol,
IOUAmount(500)));
2046 BEAST_EXPECT(env.
balance(alice, USD) == USD(2000));
2047 BEAST_EXPECT(env.
balance(alice, EUR) == EUR(8000));
2048 BEAST_EXPECT(env.
balance(bob, USD) == USD(5000));
2049 BEAST_EXPECT(env.
balance(bob, EUR) == EUR(8000));
2050 if (!features[fixAMMv1_3])
2051 BEAST_EXPECT(env.
balance(carol, USD) == USD(6000));
2055 STAmount(USD, UINT64_C(5999'999999999999), -12));
2056 BEAST_EXPECT(env.
balance(carol, EUR) == EUR(7750));
2063 testcase(
"test single depoit and clawback");
2064 using namespace jtx;
2069 Env env(*
this, features, std::make_unique<CaptureLogs>(&logs));
2072 env.
fund(
XRP(1000000000), gw, alice);
2081 auto const USD = gw[
"USD"];
2082 env.
trust(USD(100000), alice);
2083 env(
pay(gw, alice, USD(1000)));
2091 BEAST_EXPECT(amm.expectBalances(USD(400),
XRP(100),
IOUAmount(200000)));
2093 amm.deposit(alice, USD(400));
2096 BEAST_EXPECT(amm.expectBalances(
2097 USD(800),
XRP(100),
IOUAmount{2828427124746190, -10}));
2099 auto aliceXrpBalance = env.
balance(alice,
XRP);
2104 if (!features[fixAMMv1_3])
2105 BEAST_EXPECT(amm.expectBalances(
2106 STAmount(USD, UINT64_C(5656854249492380), -13),
2110 BEAST_EXPECT(amm.expectBalances(
2111 STAmount(USD, UINT64_C(565'685424949238), -12),
2114 BEAST_EXPECT(amm.expectLPTokens(alice,
IOUAmount(0)));
2115 if (!features[fixAMMv1_3])
2117 env, alice, aliceXrpBalance +
XRP(29.289322)));
2120 env, alice, aliceXrpBalance +
XRP(29.289321)));
2127 "test last holder's lptoken balance not equal to AMM's lptoken "
2128 "balance before clawback");
2129 using namespace jtx;
2132 auto setupAccounts =
2134 env.
fund(
XRP(100000), gw, alice, bob);
2139 auto const USD = gw[
"USD"];
2140 env.
trust(USD(100000), alice);
2141 env(
pay(gw, alice, USD(50000)));
2142 env.
trust(USD(100000), bob);
2143 env(
pay(gw, bob, USD(40000)));
2149 auto getLPTokenBalances =
2153 auto const lpToken =
2155 env, account, amm.lptIssue())[jss::lines][0u][jss::balance]
2157 auto const lpTokenBalance =
2158 amm.ammRpcInfo()[jss::amm][jss::lp_token][jss::value]
2160 return {lpToken, lpTokenBalance};
2165 Env env(*
this, features, std::make_unique<CaptureLogs>(&logs));
2166 Account gw{
"gateway"}, alice{
"alice"}, bob{
"bob"};
2167 auto const USD = setupAccounts(env, gw, alice, bob);
2169 AMM amm(env, alice,
XRP(2), USD(1));
2170 amm.deposit(alice,
IOUAmount{1'876123487565916, -15});
2172 amm.withdraw(alice,
IOUAmount{1'876123487565916, -15});
2173 amm.withdrawAll(bob);
2175 auto [lpToken, lpTokenBalance] =
2176 getLPTokenBalances(env, amm, alice);
2178 lpToken ==
"1414.21356237366" &&
2179 lpTokenBalance ==
"1414.213562374");
2183 BEAST_EXPECT(res && res.value());
2185 if (!features[fixAMMClawbackRounding] || !features[fixAMMv1_3])
2189 BEAST_EXPECT(amm.ammExists());
2193 auto const lpBalance =
IOUAmount{989, -12};
2195 BEAST_EXPECT(amm.expectBalances(
2196 STAmount(USD, UINT64_C(7000000000000000), -28),
2199 BEAST_EXPECT(amm.expectLPTokens(alice, lpBalance));
2205 Env env(*
this, features, std::make_unique<CaptureLogs>(&logs));
2206 Account gw{
"gateway"}, alice{
"alice"}, bob{
"bob"};
2207 auto const USD = setupAccounts(env, gw, alice, bob);
2209 AMM amm(env, alice,
XRP(2), USD(1));
2210 amm.deposit(alice,
IOUAmount{1'876123487565916, -15});
2212 amm.withdrawAll(bob);
2214 auto [lpToken, lpTokenBalance] =
2215 getLPTokenBalances(env, amm, alice);
2217 lpToken ==
"1416.08968586066" &&
2218 lpTokenBalance ==
"1416.089685861");
2222 BEAST_EXPECT(res && res.value());
2226 if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding])
2228 BEAST_EXPECT(amm.expectBalances(
2229 STAmount(USD, UINT64_C(5013266196406), -13),
2233 else if (!features[fixAMMClawbackRounding])
2235 BEAST_EXPECT(amm.expectBalances(
2236 STAmount(USD, UINT64_C(5013266196407), -13),
2240 else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding])
2242 auto const lpBalance =
IOUAmount{708'9829046743238, -13};
2243 BEAST_EXPECT(amm.expectBalances(
2244 STAmount(USD, UINT64_C(5013266196406999), -16),
2247 BEAST_EXPECT(amm.expectLPTokens(alice, lpBalance));
2253 Env env(*
this, features, std::make_unique<CaptureLogs>(&logs));
2254 Account gw{
"gateway"}, alice{
"alice"}, bob{
"bob"};
2255 auto const USD = setupAccounts(env, gw, alice, bob);
2257 AMM amm(env, alice,
XRP(2), USD(1));
2258 amm.deposit(alice,
IOUAmount{1'876123487565916, -15});
2260 amm.withdraw(alice,
IOUAmount{1'876123487565916, -15});
2261 amm.withdrawAll(bob);
2263 auto [lpToken, lpTokenBalance] =
2264 getLPTokenBalances(env, amm, alice);
2266 lpToken ==
"1414.21356237366" &&
2267 lpTokenBalance ==
"1414.213562374");
2271 BEAST_EXPECT(res && res.value());
2273 if (!features[fixAMMClawbackRounding] && !features[fixAMMv1_3])
2278 else if (!features[fixAMMClawbackRounding])
2281 BEAST_EXPECT(amm.expectBalances(
2282 STAmount(USD, UINT64_C(2410000000000000), -28),
2286 else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding])
2289 BEAST_EXPECT(!amm.ammExists());
2295 Env env(*
this, features, std::make_unique<CaptureLogs>(&logs));
2296 Account gw{
"gateway"}, alice{
"alice"}, bob{
"bob"};
2297 auto const USD = setupAccounts(env, gw, alice, bob);
2302 auto const EUR = gw2[
"EUR"];
2303 env.
trust(EUR(100000), alice);
2304 env(
pay(gw2, alice, EUR(50000)));
2305 env.
trust(EUR(100000), bob);
2306 env(
pay(gw2, bob, EUR(50000)));
2309 AMM amm(env, alice, USD(2), EUR(1));
2310 amm.deposit(alice,
IOUAmount{1'576123487565916, -15});
2312 amm.withdraw(alice,
IOUAmount{1'576123487565916, -15});
2313 amm.withdrawAll(bob);
2315 auto [lpToken, lpTokenBalance] =
2316 getLPTokenBalances(env, amm, alice);
2318 lpToken ==
"1.414213562374011" &&
2319 lpTokenBalance ==
"1.414213562374");
2323 BEAST_EXPECT(res && res.value());
2325 if (features[fixAMMv1_3] && features[fixAMMClawbackRounding])
2328 BEAST_EXPECT(!amm.ammExists());
2334 BEAST_EXPECT(amm.ammExists());
2340 Env env(*
this, features, std::make_unique<CaptureLogs>(&logs));
2341 Account gw{
"gateway"}, alice{
"alice"}, bob{
"bob"};
2342 auto const USD = setupAccounts(env, gw, alice, bob);
2344 auto const EUR = gw[
"EUR"];
2345 env.
trust(EUR(100000), alice);
2346 env(
pay(gw, alice, EUR(50000)));
2347 env.
trust(EUR(100000), bob);
2348 env(
pay(gw, bob, EUR(50000)));
2351 AMM amm(env, alice, USD(1), EUR(2));
2352 amm.deposit(alice,
IOUAmount{1'076123487565916, -15});
2354 amm.withdraw(alice,
IOUAmount{1'076123487565916, -15});
2355 amm.withdrawAll(bob);
2357 auto [lpToken, lpTokenBalance] =
2358 getLPTokenBalances(env, amm, alice);
2360 lpToken ==
"1.414213562374011" &&
2361 lpTokenBalance ==
"1.414213562374");
2365 BEAST_EXPECT(res && res.value());
2367 if (features[fixAMMClawbackRounding])
2371 BEAST_EXPECT(!amm.ammExists());
2378 BEAST_EXPECT(amm.ammExists());
2384 Env env(*
this, features, std::make_unique<CaptureLogs>(&logs));
2385 Account gw{
"gateway"}, alice{
"alice"}, bob{
"bob"};
2386 auto const USD = setupAccounts(env, gw, alice, bob);
2388 auto const EUR = gw[
"EUR"];
2389 env.
trust(EUR(1000000000), alice);
2390 env(
pay(gw, alice, EUR(500000000)));
2391 env.
trust(EUR(1000000000), bob);
2392 env(
pay(gw, bob, EUR(500000000)));
2395 AMM amm(env, alice, USD(1), EUR(2000000));
2396 amm.deposit(alice,
IOUAmount{1'076123487565916, -12});
2398 amm.withdraw(alice,
IOUAmount{1'076123487565916, -12});
2399 amm.withdrawAll(bob);
2401 auto [lpToken, lpTokenBalance] =
2402 getLPTokenBalances(env, amm, alice);
2405 lpToken ==
"1414.213562373101" &&
2406 lpTokenBalance ==
"1414.2135623731");
2410 BEAST_EXPECT(res && res.value());
2412 if (!features[fixAMMClawbackRounding] && !features[fixAMMv1_3])
2415 BEAST_EXPECT(amm.expectBalances(
2420 else if (!features[fixAMMClawbackRounding])
2426 BEAST_EXPECT(amm.ammExists());
2428 else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding])
2432 auto const lpBalance =
IOUAmount{5, -12};
2433 BEAST_EXPECT(amm.expectBalances(
2437 BEAST_EXPECT(amm.expectLPTokens(alice, lpBalance));
2450 for (
auto const& features :
2451 {
all - fixAMMv1_3 - fixAMMClawbackRounding,
2452 all - fixAMMClawbackRounding,
std::string asString() const
Returns the unquoted string value.
testcase_t testcase
Memberspace for declaring test cases.
Floating point representation of amounts with high dynamic range.
A currency issued by an account.
void testAMMClawbackSameCurrency(FeatureBitset features)
void testNotHoldingLptoken(FeatureBitset features)
void testSingleDepositAndClawback(FeatureBitset features)
void testAMMClawbackAll(FeatureBitset features)
void testAMMClawbackSpecificAmount(FeatureBitset features)
void testFeatureDisabled(FeatureBitset features)
void testAMMClawbackExceedBalance(FeatureBitset features)
void run() override
Runs the suite.
void testAssetFrozen(FeatureBitset features)
void testAMMClawbackSameIssuerAssets(FeatureBitset features)
void testAMMClawbackIssuesEachOther(FeatureBitset features)
void testInvalidRequest()
void testLastHolderLPTokenBalance(FeatureBitset features)
Convenience class to test AMM functionality.
bool expectBalances(STAmount const &asset1, STAmount const &asset2, IOUAmount const &lpt, std::optional< AccountID > const &account=std::nullopt) const
Verify the AMM balances.
IOUAmount deposit(std::optional< Account > const &account, LPToken tokens, std::optional< STAmount > const &asset1InDetails=std::nullopt, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< ter > const &ter=std::nullopt)
bool expectLPTokens(AccountID const &account, IOUAmount const &tokens) const
Immutable cryptographic account descriptor.
A transaction testing environment.
void require(Args const &... args)
Check a set of requirements.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Json::Value ammClawback(Account const &issuer, Account const &holder, Issue const &asset, Issue const &asset2, std::optional< STAmount > const &amount)
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Json::Value getAccountLines(Env &env, AccountID const &acctId)
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
bool expectLedgerEntryRoot(Env &env, Account const &acct, STAmount const &expectedValue)
XRP_t const XRP
Converts to XRP Issue or STAmount.
FeatureBitset supported_amendments()
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr std::uint32_t asfGlobalFreeze
constexpr std::uint32_t tfClawTwoAssets
Expected< bool, TER > isOnlyLiquidityProvider(ReadView const &view, Issue const &ammIssue, AccountID const &lpAccount)
Return true if the Liquidity Provider is the only AMM provider, false otherwise.
constexpr std::uint32_t tfTwoAssetIfEmpty
constexpr std::uint32_t asfAllowTrustLineClawback
constexpr std::uint32_t tfSetFreeze