From 1846538a8030c688878923fa979b31c4b8aec216 Mon Sep 17 00:00:00 2001 From: ximinez Date: Mon, 29 Sep 2025 14:34:39 -0700 Subject: [PATCH] deploy: d67dcfe3c41218d6e09ce7dc73121c908ecc9cca --- AMMBid_8cpp_source.html | 731 ++-- AMMBid_8h_source.html | 38 +- AMMClawback_8cpp_source.html | 651 ++- AMMClawback_8h_source.html | 75 +- AMMCreate_8cpp_source.html | 662 ++-- AMMCreate_8h_source.html | 46 +- AMMDelete_8cpp_source.html | 123 +- AMMDelete_8h_source.html | 38 +- AMMDeposit_8cpp_source.html | 1906 ++++----- AMMDeposit_8h_source.html | 222 +- AMMVote_8cpp_source.html | 449 +-- AMMVote_8h_source.html | 38 +- AMMWithdraw_8cpp_source.html | 2097 +++++----- AMMWithdraw_8h_source.html | 298 +- AMM__test_8cpp_source.html | 6 +- AccountObjects__test_8cpp_source.html | 2 +- AccountSet__test_8cpp_source.html | 1237 +++--- ApplyContext_8cpp_source.html | 2 +- Batch_8cpp_source.html | 565 +-- CancelCheck_8cpp_source.html | 199 +- CancelCheck_8h_source.html | 10 +- CancelOffer_8cpp_source.html | 138 +- CancelOffer_8h_source.html | 10 +- CashCheck_8cpp_source.html | 951 +++-- CashCheck_8h_source.html | 10 +- Change_8cpp_source.html | 1002 +++-- Change_8h_source.html | 93 +- Clawback_8cpp_source.html | 454 ++- Clawback_8h_source.html | 39 +- CreateCheck_8cpp_source.html | 441 +-- CreateCheck_8h_source.html | 10 +- CreateOffer_8cpp_source.html | 1791 ++++----- CreateOffer_8h_source.html | 129 +- CreateTicket_8cpp_source.html | 242 +- CreateTicket_8h_source.html | 10 +- Credentials_8cpp_source.html | 722 ++-- Credentials_8h_source.html | 157 +- DID_8cpp_source.html | 384 +- DID_8h_source.html | 16 +- DelegateSet_8cpp_source.html | 302 +- DelegateSet_8h_source.html | 14 +- DeleteAccount_8cpp_source.html | 63 +- DeleteAccount_8h_source.html | 44 +- DeleteOracle_8cpp_source.html | 183 +- DeleteOracle_8h_source.html | 14 +- DepositPreauth_8cpp_source.html | 600 ++- DepositPreauth_8h_source.html | 54 +- Escrow_8cpp_source.html | 2697 ++++++------- Escrow_8h_source.html | 173 +- LedgerStateFix_8cpp_source.html | 149 +- LedgerStateFix_8h_source.html | 14 +- MPTokenAuthorize_8cpp_source.html | 337 +- MPTokenAuthorize_8h_source.html | 54 +- MPTokenIssuanceCreate_8cpp_source.html | 314 +- MPTokenIssuanceCreate_8h_source.html | 44 +- MPTokenIssuanceDestroy_8cpp_source.html | 136 +- MPTokenIssuanceDestroy_8h_source.html | 39 +- MPTokenIssuanceSet_8cpp_source.html | 133 +- MPTokenIssuanceSet_8h_source.html | 45 +- NFTokenAcceptOffer_8cpp_source.html | 1177 +++--- NFTokenAcceptOffer_8h_source.html | 45 +- NFTokenBurn_8cpp_source.html | 235 +- NFTokenBurn_8h_source.html | 10 +- NFTokenCancelOffer_8cpp_source.html | 190 +- NFTokenCancelOffer_8h_source.html | 39 +- NFTokenCreateOffer_8cpp_source.html | 173 +- NFTokenCreateOffer_8h_source.html | 39 +- NFTokenMint_8cpp_source.html | 664 ++-- NFTokenMint_8h_source.html | 62 +- NFTokenModify_8cpp_source.html | 145 +- NFTokenModify_8h_source.html | 38 +- PayChan_8cpp_source.html | 917 ++--- Payment_8cpp_source.html | 1289 +++--- Payment_8h_source.html | 51 +- PermissionedDomainDelete_8cpp_source.html | 143 +- PermissionedDomainDelete_8h_source.html | 10 +- PermissionedDomainSet_8cpp_source.html | 258 +- PermissionedDomainSet_8h_source.html | 38 +- Permissions_8cpp_source.html | 122 +- Permissions_8h_source.html | 42 +- SetAccount_8cpp_source.html | 1243 +++--- SetAccount_8h_source.html | 49 +- SetOracle_8cpp_source.html | 595 ++- SetOracle_8h_source.html | 10 +- SetRegularKey_8cpp_source.html | 115 +- SetRegularKey_8h_source.html | 10 +- SetSignerList_8cpp_source.html | 792 ++-- SetSignerList_8h_source.html | 120 +- SetTrust_8cpp_source.html | 1332 ++++--- SetTrust_8h_source.html | 49 +- TER_8h_source.html | 63 +- TER__test_8cpp_source.html | 2 +- Transactor_8cpp_source.html | 2563 ++++++------ Transactor_8h_source.html | 517 ++- VaultClawback_8cpp_source.html | 613 ++- VaultClawback_8h_source.html | 10 +- VaultCreate_8cpp_source.html | 518 ++- VaultCreate_8h_source.html | 51 +- VaultDelete_8cpp_source.html | 343 +- VaultDelete_8h_source.html | 10 +- VaultDeposit_8cpp_source.html | 595 ++- VaultDeposit_8h_source.html | 10 +- VaultSet_8cpp_source.html | 348 +- VaultSet_8h_source.html | 38 +- VaultWithdraw_8cpp_source.html | 639 ++- VaultWithdraw_8h_source.html | 10 +- XChainBridge_8cpp_source.html | 2205 +++++------ XChainBridge_8h_source.html | 495 +-- applySteps_8cpp_source.html | 10 +- applySteps_8h_source.html | 2 +- apply_8cpp_source.html | 2 +- classripple_1_1AMMBid-members.html | 26 +- classripple_1_1AMMBid.html | 504 ++- classripple_1_1AMMClawback-members.html | 26 +- classripple_1_1AMMClawback.html | 508 ++- classripple_1_1AMMCreate-members.html | 26 +- classripple_1_1AMMCreate.html | 504 ++- classripple_1_1AMMDelete-members.html | 26 +- classripple_1_1AMMDelete.html | 504 ++- classripple_1_1AMMDeposit-members.html | 32 +- classripple_1_1AMMDeposit.html | 520 ++- classripple_1_1AMMVote-members.html | 26 +- classripple_1_1AMMVote.html | 504 ++- classripple_1_1AMMWithdraw-members.html | 32 +- classripple_1_1AMMWithdraw.html | 526 ++- classripple_1_1AccountSet__test-members.html | 39 +- classripple_1_1AccountSet__test.html | 51 +- classripple_1_1Batch-members.html | 26 +- classripple_1_1Batch.html | 502 ++- classripple_1_1BridgeModify-members.html | 26 +- classripple_1_1BridgeModify.html | 504 ++- classripple_1_1CancelCheck-members.html | 28 +- classripple_1_1CancelCheck.html | 502 ++- classripple_1_1CancelOffer-members.html | 28 +- classripple_1_1CancelOffer.html | 502 ++- classripple_1_1CashCheck-members.html | 28 +- classripple_1_1CashCheck.html | 502 ++- classripple_1_1Change-members.html | 23 +- classripple_1_1Change.html | 540 ++- classripple_1_1Clawback-members.html | 26 +- classripple_1_1Clawback.html | 504 ++- classripple_1_1CreateCheck-members.html | 26 +- classripple_1_1CreateCheck.html | 502 ++- classripple_1_1CreateOffer-members.html | 28 +- classripple_1_1CreateOffer.html | 514 ++- classripple_1_1CreateTicket-members.html | 26 +- classripple_1_1CreateTicket.html | 502 ++- classripple_1_1CredentialAccept-members.html | 26 +- classripple_1_1CredentialAccept.html | 510 ++- classripple_1_1CredentialCreate-members.html | 26 +- classripple_1_1CredentialCreate.html | 504 ++- classripple_1_1CredentialDelete-members.html | 26 +- classripple_1_1CredentialDelete.html | 510 ++- classripple_1_1DIDDelete-members.html | 26 +- classripple_1_1DIDDelete.html | 508 ++- classripple_1_1DIDSet-members.html | 26 +- classripple_1_1DIDSet.html | 502 ++- classripple_1_1DelegateSet-members.html | 26 +- classripple_1_1DelegateSet.html | 504 ++- classripple_1_1DeleteAccount-members.html | 26 +- classripple_1_1DeleteAccount.html | 498 ++- classripple_1_1DeleteOracle-members.html | 26 +- classripple_1_1DeleteOracle.html | 504 ++- classripple_1_1DepositPreauth-members.html | 28 +- classripple_1_1DepositPreauth.html | 506 ++- classripple_1_1EscrowCancel-members.html | 26 +- classripple_1_1EscrowCancel.html | 510 ++- classripple_1_1EscrowCreate-members.html | 26 +- classripple_1_1EscrowCreate.html | 504 ++- classripple_1_1EscrowFinish-members.html | 26 +- classripple_1_1EscrowFinish.html | 510 ++- classripple_1_1LedgerStateFix-members.html | 26 +- classripple_1_1LedgerStateFix.html | 502 ++- classripple_1_1MPTokenAuthorize-members.html | 26 +- classripple_1_1MPTokenAuthorize.html | 506 ++- ...pple_1_1MPTokenIssuanceCreate-members.html | 26 +- classripple_1_1MPTokenIssuanceCreate.html | 506 ++- ...ple_1_1MPTokenIssuanceDestroy-members.html | 26 +- classripple_1_1MPTokenIssuanceDestroy.html | 504 ++- ...sripple_1_1MPTokenIssuanceSet-members.html | 26 +- classripple_1_1MPTokenIssuanceSet.html | 498 ++- ...sripple_1_1NFTokenAcceptOffer-members.html | 28 +- classripple_1_1NFTokenAcceptOffer.html | 510 ++- classripple_1_1NFTokenBurn-members.html | 26 +- classripple_1_1NFTokenBurn.html | 502 ++- ...sripple_1_1NFTokenCancelOffer-members.html | 26 +- classripple_1_1NFTokenCancelOffer.html | 504 ++- ...sripple_1_1NFTokenCreateOffer-members.html | 26 +- classripple_1_1NFTokenCreateOffer.html | 504 ++- classripple_1_1NFTokenMint-members.html | 26 +- classripple_1_1NFTokenMint.html | 506 ++- classripple_1_1NFTokenModify-members.html | 26 +- classripple_1_1NFTokenModify.html | 504 ++- classripple_1_1PayChanClaim-members.html | 26 +- classripple_1_1PayChanClaim.html | 510 ++- classripple_1_1PayChanCreate-members.html | 26 +- classripple_1_1PayChanCreate.html | 504 ++- classripple_1_1PayChanFund-members.html | 26 +- classripple_1_1PayChanFund.html | 512 ++- classripple_1_1Payment-members.html | 26 +- classripple_1_1Payment.html | 504 ++- classripple_1_1Permission-members.html | 21 +- classripple_1_1Permission.html | 28 +- ...e_1_1PermissionedDomainDelete-members.html | 26 +- classripple_1_1PermissionedDomainDelete.html | 502 ++- ...pple_1_1PermissionedDomainSet-members.html | 26 +- classripple_1_1PermissionedDomainSet.html | 504 ++- classripple_1_1SetAccount-members.html | 28 +- classripple_1_1SetAccount.html | 504 ++- classripple_1_1SetOracle-members.html | 28 +- classripple_1_1SetOracle.html | 502 ++- classripple_1_1SetRegularKey-members.html | 28 +- classripple_1_1SetRegularKey.html | 500 ++- classripple_1_1SetSignerList-members.html | 42 +- classripple_1_1SetSignerList.html | 514 ++- classripple_1_1SetTrust-members.html | 28 +- classripple_1_1SetTrust.html | 504 ++- classripple_1_1Transactor-members.html | 26 +- classripple_1_1Transactor.html | 504 ++- classripple_1_1VaultClawback-members.html | 26 +- classripple_1_1VaultClawback.html | 502 ++- classripple_1_1VaultCreate-members.html | 26 +- classripple_1_1VaultCreate.html | 504 ++- classripple_1_1VaultDelete-members.html | 26 +- classripple_1_1VaultDelete.html | 502 ++- classripple_1_1VaultDeposit-members.html | 26 +- classripple_1_1VaultDeposit.html | 502 ++- classripple_1_1VaultSet-members.html | 26 +- classripple_1_1VaultSet.html | 504 ++- classripple_1_1VaultWithdraw-members.html | 26 +- classripple_1_1VaultWithdraw.html | 502 ++- ...inAddAccountCreateAttestation-members.html | 26 +- ..._1_1XChainAddAccountCreateAttestation.html | 510 ++- ..._1_1XChainAddClaimAttestation-members.html | 26 +- classripple_1_1XChainAddClaimAttestation.html | 510 ++- classripple_1_1XChainClaim-members.html | 26 +- classripple_1_1XChainClaim.html | 510 ++- classripple_1_1XChainCommit-members.html | 26 +- classripple_1_1XChainCommit.html | 512 ++- ..._1_1XChainCreateAccountCommit-members.html | 26 +- classripple_1_1XChainCreateAccountCommit.html | 510 ++- ...sripple_1_1XChainCreateBridge-members.html | 26 +- classripple_1_1XChainCreateBridge.html | 504 ++- ...ripple_1_1XChainCreateClaimID-members.html | 26 +- classripple_1_1XChainCreateClaimID.html | 510 ++- functions_a.html | 14 +- functions_b.html | 2 +- functions_c.html | 38 +- functions_d.html | 14 +- functions_f.html | 6 +- functions_func.html | 2 +- functions_func_b.html | 2 +- functions_func_c.html | 42 +- functions_func_e.html | 4 +- functions_func_f.html | 6 +- functions_func_g.html | 10 +- functions_func_i.html | 7 +- functions_func_j.html | 6 +- functions_func_l.html | 8 +- functions_func_m.html | 4 +- functions_func_n.html | 2 +- functions_func_o.html | 10 +- functions_func_p.html | 31 +- functions_func_r.html | 2 +- functions_func_s.html | 26 +- functions_func_t.html | 3 +- functions_func_v.html | 16 +- functions_g.html | 19 +- functions_h.html | 2 +- functions_i.html | 11 +- functions_j.html | 6 +- functions_l.html | 6 +- functions_m.html | 4 +- functions_n.html | 13 +- functions_o.html | 4 +- functions_p.html | 24 +- functions_r.html | 8 +- functions_s.html | 16 +- functions_t.html | 39 +- functions_u.html | 4 +- functions_v.html | 18 +- functions_w.html | 4 +- namespacemembers_e.html | 2 +- namespacemembers_func_h.html | 1 + namespacemembers_func_p.html | 6 +- namespacemembers_h.html | 1 + namespacemembers_i.html | 2 +- namespacemembers_p.html | 6 +- namespacemembers_s.html | 2 +- namespacemembers_t.html | 2 +- namespaceripple.html | 193 +- namespaceripple_1_1detail.html | 79 + search/all_10.js | 1155 +++--- search/all_11.js | 4 +- search/all_12.js | 2 +- search/all_13.js | 10 +- search/all_14.js | 10 +- search/all_15.js | 16 +- search/all_16.js | 14 +- search/all_17.js | 527 +-- search/all_19.js | 14 +- search/all_1a.js | 26 +- search/all_1b.js | 3525 +++++++++-------- search/all_1c.js | 2 +- search/all_1d.js | 476 +-- search/all_1e.js | 2 +- search/all_20.js | 2 +- search/all_21.js | 2 +- search/all_22.js | 2 +- search/all_8.js | 14 +- search/all_9.js | 12 +- search/all_a.js | 1928 ++++----- search/all_b.js | 8 +- search/all_c.js | 8 +- search/all_d.js | 14 +- search/all_e.js | 964 ++--- search/all_f.js | 267 +- search/enums_2.js | 2 +- search/enumvalues_19.js | 2 +- search/enumvalues_2.js | 2 +- search/enumvalues_3.js | 4 +- search/enumvalues_6.js | 2 +- search/enumvalues_9.js | 2 +- search/enumvalues_e.js | 4 +- search/enumvalues_f.js | 2 +- search/functions_1.js | 8 +- search/functions_10.js | 307 +- search/functions_12.js | 8 +- search/functions_13.js | 18 +- search/functions_14.js | 2639 ++++++------ search/functions_15.js | 2 +- search/functions_16.js | 164 +- search/functions_17.js | 2 +- search/functions_1a.js | 2 +- search/functions_1b.js | 2 +- search/functions_2.js | 8 +- search/functions_3.js | 1022 ++--- search/functions_4.js | 6 +- search/functions_5.js | 4 +- search/functions_6.js | 8 +- search/functions_7.js | 868 ++-- search/functions_8.js | 103 +- search/functions_9.js | 623 +-- search/functions_a.js | 4 +- search/functions_c.js | 4 +- search/functions_d.js | 6 +- search/functions_e.js | 4 +- search/functions_f.js | 2 +- search/variables_13.js | 4 +- search/variables_d.js | 4 +- ...pld_2app_2tx_2detail_2Batch_8h_source.html | 43 +- ...d_2app_2tx_2detail_2PayChan_8h_source.html | 175 +- structripple_1_1MPTMutabilityFlags.html | 8 +- token_8cpp_source.html | 2 +- 354 files changed, 60408 insertions(+), 30622 deletions(-) diff --git a/AMMBid_8cpp_source.html b/AMMBid_8cpp_source.html index abb6c62884..dd4f340449 100644 --- a/AMMBid_8cpp_source.html +++ b/AMMBid_8cpp_source.html @@ -113,376 +113,373 @@ $(document).ready(function() { init_codefold(0); });
30
31namespace ripple {
32
-
33NotTEC
+
33bool
- +
35{
-
36 if (!ammEnabled(ctx.rules))
-
37 return temDISABLED;
-
38
-
39 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
-
40 return ret;
-
41
-
42 if (ctx.tx.getFlags() & tfUniversalMask)
-
43 {
-
44 JLOG(ctx.j.debug()) << "AMM Bid: invalid flags.";
-
45 return temINVALID_FLAG;
-
46 }
-
47
-
48 if (auto const res = invalidAMMAssetPair(
-
49 ctx.tx[sfAsset].get<Issue>(), ctx.tx[sfAsset2].get<Issue>()))
-
50 {
-
51 JLOG(ctx.j.debug()) << "AMM Bid: Invalid asset pair.";
-
52 return res;
-
53 }
-
54
-
55 if (auto const bidMin = ctx.tx[~sfBidMin])
-
56 {
-
57 if (auto const res = invalidAMMAmount(*bidMin))
-
58 {
-
59 JLOG(ctx.j.debug()) << "AMM Bid: invalid min slot price.";
-
60 return res;
-
61 }
-
62 }
-
63
-
64 if (auto const bidMax = ctx.tx[~sfBidMax])
-
65 {
-
66 if (auto const res = invalidAMMAmount(*bidMax))
-
67 {
-
68 JLOG(ctx.j.debug()) << "AMM Bid: invalid max slot price.";
-
69 return res;
-
70 }
-
71 }
-
72
-
73 if (ctx.tx.isFieldPresent(sfAuthAccounts))
-
74 {
-
75 if (auto const authAccounts = ctx.tx.getFieldArray(sfAuthAccounts);
-
76 authAccounts.size() > AUCTION_SLOT_MAX_AUTH_ACCOUNTS)
-
77 {
-
78 JLOG(ctx.j.debug()) << "AMM Bid: Invalid number of AuthAccounts.";
-
79 return temMALFORMED;
-
80 }
-
81 else if (ctx.rules.enabled(fixAMMv1_3))
-
82 {
-
83 AccountID account = ctx.tx[sfAccount];
- -
85 for (auto const& obj : authAccounts)
-
86 {
-
87 auto authAccount = obj[sfAccount];
-
88 if (authAccount == account || unique.contains(authAccount))
-
89 {
-
90 JLOG(ctx.j.debug()) << "AMM Bid: Invalid auth.account.";
-
91 return temMALFORMED;
-
92 }
-
93 unique.insert(authAccount);
-
94 }
-
95 }
-
96 }
-
97
-
98 return preflight2(ctx);
-
99}
+
36 return ammEnabled(ctx.rules);
+
37}
-
100
-
101TER
-
- -
103{
-
104 auto const ammSle =
-
105 ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
-
106 if (!ammSle)
-
107 {
-
108 JLOG(ctx.j.debug()) << "AMM Bid: Invalid asset pair.";
-
109 return terNO_AMM;
-
110 }
-
111
-
112 auto const lpTokensBalance = (*ammSle)[sfLPTokenBalance];
-
113 if (lpTokensBalance == beast::zero)
-
114 return tecAMM_EMPTY;
-
115
-
116 if (ctx.tx.isFieldPresent(sfAuthAccounts))
-
117 {
-
118 for (auto const& account : ctx.tx.getFieldArray(sfAuthAccounts))
-
119 {
-
120 if (!ctx.view.read(keylet::account(account[sfAccount])))
-
121 {
-
122 JLOG(ctx.j.debug()) << "AMM Bid: Invalid Account.";
-
123 return terNO_ACCOUNT;
-
124 }
-
125 }
-
126 }
-
127
-
128 auto const lpTokens =
-
129 ammLPHolds(ctx.view, *ammSle, ctx.tx[sfAccount], ctx.j);
-
130 // Not LP
-
131 if (lpTokens == beast::zero)
-
132 {
-
133 JLOG(ctx.j.debug()) << "AMM Bid: account is not LP.";
- -
135 }
-
136
-
137 auto const bidMin = ctx.tx[~sfBidMin];
-
138
-
139 if (bidMin)
-
140 {
-
141 if (bidMin->issue() != lpTokens.issue())
-
142 {
-
143 JLOG(ctx.j.debug()) << "AMM Bid: Invalid LPToken.";
-
144 return temBAD_AMM_TOKENS;
-
145 }
-
146 if (*bidMin > lpTokens || *bidMin >= lpTokensBalance)
-
147 {
-
148 JLOG(ctx.j.debug()) << "AMM Bid: Invalid Tokens.";
- -
150 }
-
151 }
-
152
-
153 auto const bidMax = ctx.tx[~sfBidMax];
-
154 if (bidMax)
-
155 {
-
156 if (bidMax->issue() != lpTokens.issue())
-
157 {
-
158 JLOG(ctx.j.debug()) << "AMM Bid: Invalid LPToken.";
-
159 return temBAD_AMM_TOKENS;
-
160 }
-
161 if (*bidMax > lpTokens || *bidMax >= lpTokensBalance)
-
162 {
-
163 JLOG(ctx.j.debug()) << "AMM Bid: Invalid Tokens.";
- -
165 }
+
38
+ +
+ +
41{
+
42 if (auto const res = invalidAMMAssetPair(
+
43 ctx.tx[sfAsset].get<Issue>(), ctx.tx[sfAsset2].get<Issue>()))
+
44 {
+
45 JLOG(ctx.j.debug()) << "AMM Bid: Invalid asset pair.";
+
46 return res;
+
47 }
+
48
+
49 if (auto const bidMin = ctx.tx[~sfBidMin])
+
50 {
+
51 if (auto const res = invalidAMMAmount(*bidMin))
+
52 {
+
53 JLOG(ctx.j.debug()) << "AMM Bid: invalid min slot price.";
+
54 return res;
+
55 }
+
56 }
+
57
+
58 if (auto const bidMax = ctx.tx[~sfBidMax])
+
59 {
+
60 if (auto const res = invalidAMMAmount(*bidMax))
+
61 {
+
62 JLOG(ctx.j.debug()) << "AMM Bid: invalid max slot price.";
+
63 return res;
+
64 }
+
65 }
+
66
+
67 if (ctx.tx.isFieldPresent(sfAuthAccounts))
+
68 {
+
69 if (auto const authAccounts = ctx.tx.getFieldArray(sfAuthAccounts);
+
70 authAccounts.size() > AUCTION_SLOT_MAX_AUTH_ACCOUNTS)
+
71 {
+
72 JLOG(ctx.j.debug()) << "AMM Bid: Invalid number of AuthAccounts.";
+
73 return temMALFORMED;
+
74 }
+
75 else if (ctx.rules.enabled(fixAMMv1_3))
+
76 {
+
77 AccountID account = ctx.tx[sfAccount];
+ +
79 for (auto const& obj : authAccounts)
+
80 {
+
81 auto authAccount = obj[sfAccount];
+
82 if (authAccount == account || unique.contains(authAccount))
+
83 {
+
84 JLOG(ctx.j.debug()) << "AMM Bid: Invalid auth.account.";
+
85 return temMALFORMED;
+
86 }
+
87 unique.insert(authAccount);
+
88 }
+
89 }
+
90 }
+
91
+
92 return tesSUCCESS;
+
93}
+
+
94
+
95TER
+
+ +
97{
+
98 auto const ammSle =
+
99 ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
+
100 if (!ammSle)
+
101 {
+
102 JLOG(ctx.j.debug()) << "AMM Bid: Invalid asset pair.";
+
103 return terNO_AMM;
+
104 }
+
105
+
106 auto const lpTokensBalance = (*ammSle)[sfLPTokenBalance];
+
107 if (lpTokensBalance == beast::zero)
+
108 return tecAMM_EMPTY;
+
109
+
110 if (ctx.tx.isFieldPresent(sfAuthAccounts))
+
111 {
+
112 for (auto const& account : ctx.tx.getFieldArray(sfAuthAccounts))
+
113 {
+
114 if (!ctx.view.read(keylet::account(account[sfAccount])))
+
115 {
+
116 JLOG(ctx.j.debug()) << "AMM Bid: Invalid Account.";
+
117 return terNO_ACCOUNT;
+
118 }
+
119 }
+
120 }
+
121
+
122 auto const lpTokens =
+
123 ammLPHolds(ctx.view, *ammSle, ctx.tx[sfAccount], ctx.j);
+
124 // Not LP
+
125 if (lpTokens == beast::zero)
+
126 {
+
127 JLOG(ctx.j.debug()) << "AMM Bid: account is not LP.";
+ +
129 }
+
130
+
131 auto const bidMin = ctx.tx[~sfBidMin];
+
132
+
133 if (bidMin)
+
134 {
+
135 if (bidMin->issue() != lpTokens.issue())
+
136 {
+
137 JLOG(ctx.j.debug()) << "AMM Bid: Invalid LPToken.";
+
138 return temBAD_AMM_TOKENS;
+
139 }
+
140 if (*bidMin > lpTokens || *bidMin >= lpTokensBalance)
+
141 {
+
142 JLOG(ctx.j.debug()) << "AMM Bid: Invalid Tokens.";
+ +
144 }
+
145 }
+
146
+
147 auto const bidMax = ctx.tx[~sfBidMax];
+
148 if (bidMax)
+
149 {
+
150 if (bidMax->issue() != lpTokens.issue())
+
151 {
+
152 JLOG(ctx.j.debug()) << "AMM Bid: Invalid LPToken.";
+
153 return temBAD_AMM_TOKENS;
+
154 }
+
155 if (*bidMax > lpTokens || *bidMax >= lpTokensBalance)
+
156 {
+
157 JLOG(ctx.j.debug()) << "AMM Bid: Invalid Tokens.";
+ +
159 }
+
160 }
+
161
+
162 if (bidMin && bidMax && bidMin > bidMax)
+
163 {
+
164 JLOG(ctx.j.debug()) << "AMM Bid: Invalid Max/MinSlotPrice.";
+
166 }
167
-
168 if (bidMin && bidMax && bidMin > bidMax)
-
169 {
-
170 JLOG(ctx.j.debug()) << "AMM Bid: Invalid Max/MinSlotPrice.";
- -
172 }
-
173
-
174 return tesSUCCESS;
-
175}
+
168 return tesSUCCESS;
+
169}
-
176
- -
- -
179 ApplyContext& ctx_,
-
180 Sandbox& sb,
-
181 AccountID const& account_,
- -
183{
-
184 using namespace std::chrono;
-
185 auto const ammSle =
-
186 sb.peek(keylet::amm(ctx_.tx[sfAsset], ctx_.tx[sfAsset2]));
-
187 if (!ammSle)
-
188 return {tecINTERNAL, false};
-
189 STAmount const lptAMMBalance = (*ammSle)[sfLPTokenBalance];
-
190 auto const lpTokens = ammLPHolds(sb, *ammSle, account_, ctx_.journal);
-
191 auto const& rules = ctx_.view().rules();
-
192 if (!rules.enabled(fixInnerObjTemplate))
-
193 {
-
194 if (!ammSle->isFieldPresent(sfAuctionSlot))
-
195 ammSle->makeFieldPresent(sfAuctionSlot);
-
196 }
-
197 else
-
198 {
-
199 XRPL_ASSERT(
-
200 ammSle->isFieldPresent(sfAuctionSlot),
-
201 "ripple::applyBid : has auction slot");
-
202 if (!ammSle->isFieldPresent(sfAuctionSlot))
-
203 return {tecINTERNAL, false};
-
204 }
-
205 auto& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);
-
206 auto const current =
-
207 duration_cast<seconds>(
- -
209 .count();
-
210 // Auction slot discounted fee
-
211 auto const discountedFee =
-
212 (*ammSle)[sfTradingFee] / AUCTION_SLOT_DISCOUNTED_FEE_FRACTION;
-
213 auto const tradingFee = getFee((*ammSle)[sfTradingFee]);
-
214 // Min price
-
215 auto const minSlotPrice =
-
216 lptAMMBalance * tradingFee / AUCTION_SLOT_MIN_FEE_FRACTION;
+
170
+ +
+ +
173 ApplyContext& ctx_,
+
174 Sandbox& sb,
+
175 AccountID const& account_,
+ +
177{
+
178 using namespace std::chrono;
+
179 auto const ammSle =
+
180 sb.peek(keylet::amm(ctx_.tx[sfAsset], ctx_.tx[sfAsset2]));
+
181 if (!ammSle)
+
182 return {tecINTERNAL, false};
+
183 STAmount const lptAMMBalance = (*ammSle)[sfLPTokenBalance];
+
184 auto const lpTokens = ammLPHolds(sb, *ammSle, account_, ctx_.journal);
+
185 auto const& rules = ctx_.view().rules();
+
186 if (!rules.enabled(fixInnerObjTemplate))
+
187 {
+
188 if (!ammSle->isFieldPresent(sfAuctionSlot))
+
189 ammSle->makeFieldPresent(sfAuctionSlot);
+
190 }
+
191 else
+
192 {
+
193 XRPL_ASSERT(
+
194 ammSle->isFieldPresent(sfAuctionSlot),
+
195 "ripple::applyBid : has auction slot");
+
196 if (!ammSle->isFieldPresent(sfAuctionSlot))
+
197 return {tecINTERNAL, false};
+
198 }
+
199 auto& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);
+
200 auto const current =
+
201 duration_cast<seconds>(
+ +
203 .count();
+
204 // Auction slot discounted fee
+
205 auto const discountedFee =
+
206 (*ammSle)[sfTradingFee] / AUCTION_SLOT_DISCOUNTED_FEE_FRACTION;
+
207 auto const tradingFee = getFee((*ammSle)[sfTradingFee]);
+
208 // Min price
+
209 auto const minSlotPrice =
+
210 lptAMMBalance * tradingFee / AUCTION_SLOT_MIN_FEE_FRACTION;
+
211
+
212 std::uint32_t constexpr tailingSlot = AUCTION_SLOT_TIME_INTERVALS - 1;
+
213
+
214 // If seated then it is the current slot-holder time slot, otherwise
+
215 // the auction slot is not owned. Slot range is in {0-19}
+
216 auto const timeSlot = ammAuctionTimeSlot(current, auctionSlot);
217
-
218 std::uint32_t constexpr tailingSlot = AUCTION_SLOT_TIME_INTERVALS - 1;
-
219
-
220 // If seated then it is the current slot-holder time slot, otherwise
-
221 // the auction slot is not owned. Slot range is in {0-19}
-
222 auto const timeSlot = ammAuctionTimeSlot(current, auctionSlot);
-
223
-
224 // Account must exist and the slot not expired.
-
225 auto validOwner = [&](AccountID const& account) {
-
226 // Valid range is 0-19 but the tailing slot pays MinSlotPrice
-
227 // and doesn't refund so the check is < instead of <= to optimize.
-
228 return timeSlot && *timeSlot < tailingSlot &&
-
229 sb.read(keylet::account(account));
-
230 };
-
231
-
232 auto updateSlot = [&](std::uint32_t fee,
-
233 Number const& minPrice,
-
234 Number const& burn) -> TER {
-
235 auctionSlot.setAccountID(sfAccount, account_);
-
236 auctionSlot.setFieldU32(sfExpiration, current + TOTAL_TIME_SLOT_SECS);
-
237 if (fee != 0)
-
238 auctionSlot.setFieldU16(sfDiscountedFee, fee);
-
239 else if (auctionSlot.isFieldPresent(sfDiscountedFee))
-
240 auctionSlot.makeFieldAbsent(sfDiscountedFee);
-
241 auctionSlot.setFieldAmount(
-
242 sfPrice, toSTAmount(lpTokens.issue(), minPrice));
-
243 if (ctx_.tx.isFieldPresent(sfAuthAccounts))
-
244 auctionSlot.setFieldArray(
-
245 sfAuthAccounts, ctx_.tx.getFieldArray(sfAuthAccounts));
-
246 else
-
247 auctionSlot.makeFieldAbsent(sfAuthAccounts);
-
248 // Burn the remaining bid amount
-
249 auto const saBurn = adjustLPTokens(
-
250 lptAMMBalance,
-
251 toSTAmount(lptAMMBalance.issue(), burn),
- -
253 if (saBurn >= lptAMMBalance)
-
254 {
-
255 // This error case should never occur.
-
256 JLOG(ctx_.journal.fatal())
-
257 << "AMM Bid: LP Token burn exceeds AMM balance " << burn << " "
-
258 << lptAMMBalance;
-
259 return tecINTERNAL;
-
260 }
-
261 auto res =
-
262 redeemIOU(sb, account_, saBurn, lpTokens.issue(), ctx_.journal);
-
263 if (res != tesSUCCESS)
-
264 {
-
265 JLOG(ctx_.journal.debug()) << "AMM Bid: failed to redeem.";
-
266 return res;
-
267 }
-
268 ammSle->setFieldAmount(sfLPTokenBalance, lptAMMBalance - saBurn);
-
269 sb.update(ammSle);
-
270 return tesSUCCESS;
-
271 };
-
272
-
273 TER res = tesSUCCESS;
-
274
-
275 auto const bidMin = ctx_.tx[~sfBidMin];
-
276 auto const bidMax = ctx_.tx[~sfBidMax];
-
277
-
278 auto getPayPrice =
-
279 [&](Number const& computedPrice) -> Expected<Number, TER> {
-
280 auto const payPrice = [&]() -> std::optional<Number> {
-
281 // Both min/max bid price are defined
-
282 if (bidMin && bidMax)
-
283 {
-
284 if (computedPrice <= *bidMax)
-
285 return std::max(computedPrice, Number(*bidMin));
-
286 JLOG(ctx_.journal.debug())
-
287 << "AMM Bid: not in range " << computedPrice << " "
-
288 << *bidMin << " " << *bidMax;
-
289 return std::nullopt;
-
290 }
-
291 // Bidder pays max(bidPrice, computedPrice)
-
292 if (bidMin)
-
293 {
-
294 return std::max(computedPrice, Number(*bidMin));
-
295 }
-
296 else if (bidMax)
-
297 {
-
298 if (computedPrice <= *bidMax)
-
299 return computedPrice;
-
300 JLOG(ctx_.journal.debug()) << "AMM Bid: not in range "
-
301 << computedPrice << " " << *bidMax;
-
302 return std::nullopt;
-
303 }
-
304 else
-
305 return computedPrice;
-
306 }();
-
307 if (!payPrice)
- -
309 else if (payPrice > lpTokens)
- -
311 return *payPrice;
-
312 };
-
313
-
314 // No one owns the slot or expired slot.
-
315 if (auto const acct = auctionSlot[~sfAccount]; !acct || !validOwner(*acct))
-
316 {
-
317 if (auto const payPrice = getPayPrice(minSlotPrice); !payPrice)
-
318 return {payPrice.error(), false};
-
319 else
-
320 res = updateSlot(discountedFee, *payPrice, *payPrice);
-
321 }
-
322 else
-
323 {
-
324 // Price the slot was purchased at.
-
325 STAmount const pricePurchased = auctionSlot[sfPrice];
-
326 XRPL_ASSERT(timeSlot, "ripple::applyBid : timeSlot is set");
-
327 auto const fractionUsed =
-
328 (Number(*timeSlot) + 1) / AUCTION_SLOT_TIME_INTERVALS;
-
329 auto const fractionRemaining = Number(1) - fractionUsed;
-
330 auto const computedPrice = [&]() -> Number {
-
331 auto const p1_05 = Number(105, -2);
-
332 // First interval slot price
-
333 if (*timeSlot == 0)
-
334 return pricePurchased * p1_05 + minSlotPrice;
-
335 // Other intervals slot price
-
336 return pricePurchased * p1_05 * (1 - power(fractionUsed, 60)) +
-
337 minSlotPrice;
-
338 }();
-
339
-
340 auto const payPrice = getPayPrice(computedPrice);
-
341
-
342 if (!payPrice)
-
343 return {payPrice.error(), false};
-
344
-
345 // Refund the previous owner. If the time slot is 0 then
-
346 // the owner is refunded 95% of the amount.
-
347 auto const refund = fractionRemaining * pricePurchased;
-
348 if (refund > *payPrice)
-
349 {
-
350 // This error case should never occur.
-
351 JLOG(ctx_.journal.fatal()) << "AMM Bid: refund exceeds payPrice "
-
352 << refund << " " << *payPrice;
-
353 return {tecINTERNAL, false};
-
354 }
-
355 res = accountSend(
-
356 sb,
-
357 account_,
-
358 auctionSlot[sfAccount],
-
359 toSTAmount(lpTokens.issue(), refund),
-
360 ctx_.journal);
-
361 if (res != tesSUCCESS)
-
362 {
-
363 JLOG(ctx_.journal.debug()) << "AMM Bid: failed to refund.";
-
364 return {res, false};
-
365 }
-
366
-
367 auto const burn = *payPrice - refund;
-
368 res = updateSlot(discountedFee, *payPrice, burn);
-
369 }
-
370
-
371 return {res, res == tesSUCCESS};
-
372}
+
218 // Account must exist and the slot not expired.
+
219 auto validOwner = [&](AccountID const& account) {
+
220 // Valid range is 0-19 but the tailing slot pays MinSlotPrice
+
221 // and doesn't refund so the check is < instead of <= to optimize.
+
222 return timeSlot && *timeSlot < tailingSlot &&
+
223 sb.read(keylet::account(account));
+
224 };
+
225
+
226 auto updateSlot = [&](std::uint32_t fee,
+
227 Number const& minPrice,
+
228 Number const& burn) -> TER {
+
229 auctionSlot.setAccountID(sfAccount, account_);
+
230 auctionSlot.setFieldU32(sfExpiration, current + TOTAL_TIME_SLOT_SECS);
+
231 if (fee != 0)
+
232 auctionSlot.setFieldU16(sfDiscountedFee, fee);
+
233 else if (auctionSlot.isFieldPresent(sfDiscountedFee))
+
234 auctionSlot.makeFieldAbsent(sfDiscountedFee);
+
235 auctionSlot.setFieldAmount(
+
236 sfPrice, toSTAmount(lpTokens.issue(), minPrice));
+
237 if (ctx_.tx.isFieldPresent(sfAuthAccounts))
+
238 auctionSlot.setFieldArray(
+
239 sfAuthAccounts, ctx_.tx.getFieldArray(sfAuthAccounts));
+
240 else
+
241 auctionSlot.makeFieldAbsent(sfAuthAccounts);
+
242 // Burn the remaining bid amount
+
243 auto const saBurn = adjustLPTokens(
+
244 lptAMMBalance,
+
245 toSTAmount(lptAMMBalance.issue(), burn),
+ +
247 if (saBurn >= lptAMMBalance)
+
248 {
+
249 // This error case should never occur.
+
250 JLOG(ctx_.journal.fatal())
+
251 << "AMM Bid: LP Token burn exceeds AMM balance " << burn << " "
+
252 << lptAMMBalance;
+
253 return tecINTERNAL;
+
254 }
+
255 auto res =
+
256 redeemIOU(sb, account_, saBurn, lpTokens.issue(), ctx_.journal);
+
257 if (res != tesSUCCESS)
+
258 {
+
259 JLOG(ctx_.journal.debug()) << "AMM Bid: failed to redeem.";
+
260 return res;
+
261 }
+
262 ammSle->setFieldAmount(sfLPTokenBalance, lptAMMBalance - saBurn);
+
263 sb.update(ammSle);
+
264 return tesSUCCESS;
+
265 };
+
266
+
267 TER res = tesSUCCESS;
+
268
+
269 auto const bidMin = ctx_.tx[~sfBidMin];
+
270 auto const bidMax = ctx_.tx[~sfBidMax];
+
271
+
272 auto getPayPrice =
+
273 [&](Number const& computedPrice) -> Expected<Number, TER> {
+
274 auto const payPrice = [&]() -> std::optional<Number> {
+
275 // Both min/max bid price are defined
+
276 if (bidMin && bidMax)
+
277 {
+
278 if (computedPrice <= *bidMax)
+
279 return std::max(computedPrice, Number(*bidMin));
+
280 JLOG(ctx_.journal.debug())
+
281 << "AMM Bid: not in range " << computedPrice << " "
+
282 << *bidMin << " " << *bidMax;
+
283 return std::nullopt;
+
284 }
+
285 // Bidder pays max(bidPrice, computedPrice)
+
286 if (bidMin)
+
287 {
+
288 return std::max(computedPrice, Number(*bidMin));
+
289 }
+
290 else if (bidMax)
+
291 {
+
292 if (computedPrice <= *bidMax)
+
293 return computedPrice;
+
294 JLOG(ctx_.journal.debug()) << "AMM Bid: not in range "
+
295 << computedPrice << " " << *bidMax;
+
296 return std::nullopt;
+
297 }
+
298 else
+
299 return computedPrice;
+
300 }();
+
301 if (!payPrice)
+ +
303 else if (payPrice > lpTokens)
+ +
305 return *payPrice;
+
306 };
+
307
+
308 // No one owns the slot or expired slot.
+
309 if (auto const acct = auctionSlot[~sfAccount]; !acct || !validOwner(*acct))
+
310 {
+
311 if (auto const payPrice = getPayPrice(minSlotPrice); !payPrice)
+
312 return {payPrice.error(), false};
+
313 else
+
314 res = updateSlot(discountedFee, *payPrice, *payPrice);
+
315 }
+
316 else
+
317 {
+
318 // Price the slot was purchased at.
+
319 STAmount const pricePurchased = auctionSlot[sfPrice];
+
320 XRPL_ASSERT(timeSlot, "ripple::applyBid : timeSlot is set");
+
321 auto const fractionUsed =
+
322 (Number(*timeSlot) + 1) / AUCTION_SLOT_TIME_INTERVALS;
+
323 auto const fractionRemaining = Number(1) - fractionUsed;
+
324 auto const computedPrice = [&]() -> Number {
+
325 auto const p1_05 = Number(105, -2);
+
326 // First interval slot price
+
327 if (*timeSlot == 0)
+
328 return pricePurchased * p1_05 + minSlotPrice;
+
329 // Other intervals slot price
+
330 return pricePurchased * p1_05 * (1 - power(fractionUsed, 60)) +
+
331 minSlotPrice;
+
332 }();
+
333
+
334 auto const payPrice = getPayPrice(computedPrice);
+
335
+
336 if (!payPrice)
+
337 return {payPrice.error(), false};
+
338
+
339 // Refund the previous owner. If the time slot is 0 then
+
340 // the owner is refunded 95% of the amount.
+
341 auto const refund = fractionRemaining * pricePurchased;
+
342 if (refund > *payPrice)
+
343 {
+
344 // This error case should never occur.
+
345 JLOG(ctx_.journal.fatal()) << "AMM Bid: refund exceeds payPrice "
+
346 << refund << " " << *payPrice;
+
347 return {tecINTERNAL, false};
+
348 }
+
349 res = accountSend(
+
350 sb,
+
351 account_,
+
352 auctionSlot[sfAccount],
+
353 toSTAmount(lpTokens.issue(), refund),
+
354 ctx_.journal);
+
355 if (res != tesSUCCESS)
+
356 {
+
357 JLOG(ctx_.journal.debug()) << "AMM Bid: failed to refund.";
+
358 return {res, false};
+
359 }
+
360
+
361 auto const burn = *payPrice - refund;
+
362 res = updateSlot(discountedFee, *payPrice, burn);
+
363 }
+
364
+
365 return {res, res == tesSUCCESS};
+
366}
-
373
-
374TER
-
- -
376{
-
377 // This is the ledger view that we work against. Transactions are applied
-
378 // as we go on processing transactions.
-
379 Sandbox sb(&ctx_.view());
-
380
-
381 auto const result = applyBid(ctx_, sb, account_, j_);
-
382 if (result.second)
-
383 sb.apply(ctx_.rawView());
-
384
-
385 return result.first;
-
386}
+
367
+
368TER
+
+ +
370{
+
371 // This is the ledger view that we work against. Transactions are applied
+
372 // as we go on processing transactions.
+
373 Sandbox sb(&ctx_.view());
+
374
+
375 auto const result = applyBid(ctx_, sb, account_, j_);
+
376 if (result.second)
+
377 sb.apply(ctx_.rawView());
+
378
+
379 return result.first;
+
380}
-
387
-
388} // namespace ripple
+
381
+
382} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:60
Stream fatal() const
Definition Journal.h:352
Stream debug() const
Definition Journal.h:328
-
TER doApply() override
Definition AMMBid.cpp:375
-
static TER preclaim(PreclaimContext const &ctx)
Definition AMMBid.cpp:102
-
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMBid.cpp:34
+
TER doApply() override
Definition AMMBid.cpp:369
+
static TER preclaim(PreclaimContext const &ctx)
Definition AMMBid.cpp:96
+
static bool checkExtraFeatures(PreflightContext const &ctx)
Definition AMMBid.cpp:34
+
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMBid.cpp:40
State information when applying a tx.
ApplyView & view()
@@ -499,13 +496,12 @@ $(document).ready(function() { init_codefold(0); });
Issue const & issue() const
Definition STAmount.h:496
STArray const & getFieldArray(SField const &field) const
Definition STObject.cpp:692
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:484
-
std::uint32_t getFlags() const
Definition STObject.cpp:537
Discardable, editable view to a ledger.
Definition Sandbox.h:35
void apply(RawView &to)
Definition Sandbox.h:55
- -
AccountID const account_
Definition Transactor.h:145
-
beast::Journal const j_
Definition Transactor.h:143
-
ApplyContext & ctx_
Definition Transactor.h:141
+ +
AccountID const account_
Definition Transactor.h:147
+
beast::Journal const j_
Definition Transactor.h:145
+
ApplyContext & ctx_
Definition Transactor.h:143
void update(std::shared_ptr< SLE > const &sle) override
Indicate changes to a peeked SLE.
@@ -524,13 +520,11 @@ $(document).ready(function() { init_codefold(0); });
TER redeemIOU(ApplyView &view, AccountID const &account, STAmount const &amount, Issue const &issue, beast::Journal j)
Definition View.cpp:2348
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
bool ammEnabled(Rules const &)
Return true if required AMM amendments are enabled.
Definition AMMCore.cpp:129
-
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
@ current
This was a new validation and was added.
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No)
Calls static accountSendIOU if saAmount represents Issue.
Definition View.cpp:2174
std::uint32_t constexpr AUCTION_SLOT_MIN_FEE_FRACTION
Definition AMMCore.h:39
STAmount adjustLPTokens(STAmount const &lptAMMBalance, STAmount const &lpTokens, IsDeposit isDeposit)
Adjust LP tokens to deposit/withdraw.
STAmount ammLPHolds(ReadView const &view, Currency const &cur1, Currency const &cur2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
Definition AMMUtils.cpp:113
-
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
@ tecAMM_EMPTY
Definition TER.h:332
@ tecINTERNAL
Definition TER.h:310
@ tecAMM_FAILED
Definition TER.h:330
@@ -540,19 +534,14 @@ $(document).ready(function() { init_codefold(0); });
@ tesSUCCESS
Definition TER.h:244
NotTEC invalidAMMAssetPair(Issue const &issue1, Issue const &issue2, std::optional< std::pair< Issue, Issue > > const &pair=std::nullopt)
Definition AMMCore.cpp:80
-
bool isTesSuccess(TER x) noexcept
Definition TER.h:674
-
constexpr std::uint32_t tfUniversalMask
Definition TxFlags.h:63
-
static std::pair< TER, bool > applyBid(ApplyContext &ctx_, Sandbox &sb, AccountID const &account_, beast::Journal j_)
Definition AMMBid.cpp:178
+
static std::pair< TER, bool > applyBid(ApplyContext &ctx_, Sandbox &sb, AccountID const &account_, beast::Journal j_)
Definition AMMBid.cpp:172
@ terNO_ACCOUNT
Definition TER.h:217
@ terNO_AMM
Definition TER.h:227
TERSubset< CanCvtToTER > TER
Definition TER.h:645
std::uint16_t constexpr AUCTION_SLOT_MAX_AUTH_ACCOUNTS
Definition AMMCore.h:36
-
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:605
std::uint32_t constexpr AUCTION_SLOT_DISCOUNTED_FEE_FRACTION
Definition AMMCore.h:38
@ temMALFORMED
Definition TER.h:87
@ temBAD_AMM_TOKENS
Definition TER.h:129
-
@ temINVALID_FLAG
Definition TER.h:111
-
@ temDISABLED
Definition TER.h:114
diff --git a/AMMBid_8h_source.html b/AMMBid_8h_source.html index 9c6c95ccc1..8e80cf56f5 100644 --- a/AMMBid_8h_source.html +++ b/AMMBid_8h_source.html @@ -119,31 +119,35 @@ $(document).ready(function() { init_codefold(0); });
72 }
73
-
74 static NotTEC
-
75 preflight(PreflightContext const& ctx);
+
74 static bool
+
76
-
77 static TER
-
78 preclaim(PreclaimContext const& ctx);
+
77 static NotTEC
+
78 preflight(PreflightContext const& ctx);
79
-
80 TER
-
81 doApply() override;
-
82};
+
80 static TER
+
81 preclaim(PreclaimContext const& ctx);
+
82
+
83 TER
+
84 doApply() override;
+
85};
-
83
-
84} // namespace ripple
-
85
-
86#endif // RIPPLE_TX_AMMBID_H_INCLUDED
+
86
+
87} // namespace ripple
+
88
+
89#endif // RIPPLE_TX_AMMBID_H_INCLUDED
AMMBid implements AMM bid Transactor.
Definition AMMBid.h:66
static constexpr ConsequencesFactoryType ConsequencesFactory
Definition AMMBid.h:68
-
TER doApply() override
Definition AMMBid.cpp:375
-
static TER preclaim(PreclaimContext const &ctx)
Definition AMMBid.cpp:102
-
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMBid.cpp:34
+
TER doApply() override
Definition AMMBid.cpp:369
+
static TER preclaim(PreclaimContext const &ctx)
Definition AMMBid.cpp:96
+
static bool checkExtraFeatures(PreflightContext const &ctx)
Definition AMMBid.cpp:34
+
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMBid.cpp:40
AMMBid(ApplyContext &ctx)
Definition AMMBid.h:70
State information when applying a tx.
- - - + + +
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:80
State information when preflighting a tx.
Definition Transactor.h:35
diff --git a/AMMClawback_8cpp_source.html b/AMMClawback_8cpp_source.html index 67f052a7d9..815ad5a861 100644 --- a/AMMClawback_8cpp_source.html +++ b/AMMClawback_8cpp_source.html @@ -116,336 +116,337 @@ $(document).ready(function() { init_codefold(0); });
33
34namespace ripple {
35
- +
- +
38{
-
39 if (!ctx.rules.enabled(featureAMMClawback))
-
40 return temDISABLED;
+
39 return tfAMMClawbackMask;
+
40}
+
41
-
42 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
-
43 return ret; // LCOV_EXCL_LINE
-
44
-
45 auto const flags = ctx.tx.getFlags();
-
46 if (flags & tfAMMClawbackMask)
-
47 return temINVALID_FLAG;
-
48
-
49 AccountID const issuer = ctx.tx[sfAccount];
-
50 AccountID const holder = ctx.tx[sfHolder];
-
51
-
52 if (issuer == holder)
-
53 {
-
54 JLOG(ctx.j.trace())
-
55 << "AMMClawback: holder cannot be the same as issuer.";
-
56 return temMALFORMED;
-
57 }
+ +
+ +
44{
+
45 AccountID const issuer = ctx.tx[sfAccount];
+
46 AccountID const holder = ctx.tx[sfHolder];
+
47
+
48 if (issuer == holder)
+
49 {
+
50 JLOG(ctx.j.trace())
+
51 << "AMMClawback: holder cannot be the same as issuer.";
+
52 return temMALFORMED;
+
53 }
+
54
+
55 std::optional<STAmount> const clawAmount = ctx.tx[~sfAmount];
+
56 auto const asset = ctx.tx[sfAsset].get<Issue>();
+
57 auto const asset2 = ctx.tx[sfAsset2].get<Issue>();
58
-
59 std::optional<STAmount> const clawAmount = ctx.tx[~sfAmount];
-
60 auto const asset = ctx.tx[sfAsset].get<Issue>();
-
61 auto const asset2 = ctx.tx[sfAsset2].get<Issue>();
-
62
-
63 if (isXRP(asset))
-
64 return temMALFORMED;
-
65
-
66 if (flags & tfClawTwoAssets && asset.account != asset2.account)
-
67 {
-
68 JLOG(ctx.j.trace())
-
69 << "AMMClawback: tfClawTwoAssets can only be enabled when two "
-
70 "assets in the AMM pool are both issued by the issuer";
-
71 return temINVALID_FLAG;
-
72 }
-
73
-
74 if (asset.account != issuer)
-
75 {
-
76 JLOG(ctx.j.trace()) << "AMMClawback: Asset's account does not "
-
77 "match Account field.";
-
78 return temMALFORMED;
-
79 }
-
80
-
81 if (clawAmount && clawAmount->get<Issue>() != asset)
-
82 {
-
83 JLOG(ctx.j.trace()) << "AMMClawback: Amount's issuer/currency subfield "
-
84 "does not match Asset field";
-
85 return temBAD_AMOUNT;
-
86 }
-
87
-
88 if (clawAmount && *clawAmount <= beast::zero)
-
89 return temBAD_AMOUNT;
-
90
-
91 return preflight2(ctx);
-
92}
+
59 if (isXRP(asset))
+
60 return temMALFORMED;
+
61
+
62 auto const flags = ctx.tx.getFlags();
+
63
+
64 if (flags & tfClawTwoAssets && asset.account != asset2.account)
+
65 {
+
66 JLOG(ctx.j.trace())
+
67 << "AMMClawback: tfClawTwoAssets can only be enabled when two "
+
68 "assets in the AMM pool are both issued by the issuer";
+
69 return temINVALID_FLAG;
+
70 }
+
71
+
72 if (asset.account != issuer)
+
73 {
+
74 JLOG(ctx.j.trace()) << "AMMClawback: Asset's account does not "
+
75 "match Account field.";
+
76 return temMALFORMED;
+
77 }
+
78
+
79 if (clawAmount && clawAmount->get<Issue>() != asset)
+
80 {
+
81 JLOG(ctx.j.trace()) << "AMMClawback: Amount's issuer/currency subfield "
+
82 "does not match Asset field";
+
83 return temBAD_AMOUNT;
+
84 }
+
85
+
86 if (clawAmount && *clawAmount <= beast::zero)
+
87 return temBAD_AMOUNT;
+
88
+
89 return tesSUCCESS;
+
90}
-
93
-
94TER
-
- -
96{
-
97 auto const asset = ctx.tx[sfAsset].get<Issue>();
-
98 auto const asset2 = ctx.tx[sfAsset2].get<Issue>();
-
99 auto const sleIssuer = ctx.view.read(keylet::account(ctx.tx[sfAccount]));
-
100 if (!sleIssuer)
-
101 return terNO_ACCOUNT; // LCOV_EXCL_LINE
-
102
-
103 if (!ctx.view.read(keylet::account(ctx.tx[sfHolder])))
-
104 return terNO_ACCOUNT;
-
105
-
106 auto const ammSle = ctx.view.read(keylet::amm(asset, asset2));
-
107 if (!ammSle)
-
108 {
-
109 JLOG(ctx.j.debug()) << "AMM Clawback: Invalid asset pair.";
-
110 return terNO_AMM;
-
111 }
+
91
+
92TER
+
+ +
94{
+
95 auto const asset = ctx.tx[sfAsset].get<Issue>();
+
96 auto const asset2 = ctx.tx[sfAsset2].get<Issue>();
+
97 auto const sleIssuer = ctx.view.read(keylet::account(ctx.tx[sfAccount]));
+
98 if (!sleIssuer)
+
99 return terNO_ACCOUNT; // LCOV_EXCL_LINE
+
100
+
101 if (!ctx.view.read(keylet::account(ctx.tx[sfHolder])))
+
102 return terNO_ACCOUNT;
+
103
+
104 auto const ammSle = ctx.view.read(keylet::amm(asset, asset2));
+
105 if (!ammSle)
+
106 {
+
107 JLOG(ctx.j.debug()) << "AMM Clawback: Invalid asset pair.";
+
108 return terNO_AMM;
+
109 }
+
110
+
111 std::uint32_t const issuerFlagsIn = sleIssuer->getFieldU32(sfFlags);
112
-
113 std::uint32_t const issuerFlagsIn = sleIssuer->getFieldU32(sfFlags);
-
114
-
115 // If AllowTrustLineClawback is not set or NoFreeze is set, return no
-
116 // permission
-
117 if (!(issuerFlagsIn & lsfAllowTrustLineClawback) ||
-
118 (issuerFlagsIn & lsfNoFreeze))
-
119 return tecNO_PERMISSION;
-
120
-
121 return tesSUCCESS;
-
122}
+
113 // If AllowTrustLineClawback is not set or NoFreeze is set, return no
+
114 // permission
+
115 if (!(issuerFlagsIn & lsfAllowTrustLineClawback) ||
+
116 (issuerFlagsIn & lsfNoFreeze))
+
117 return tecNO_PERMISSION;
+
118
+
119 return tesSUCCESS;
+
120}
-
123
-
124TER
-
- -
126{
-
127 Sandbox sb(&ctx_.view());
-
128
-
129 auto const ter = applyGuts(sb);
-
130 if (ter == tesSUCCESS)
-
131 sb.apply(ctx_.rawView());
-
132
-
133 return ter;
-
134}
+
121
+
122TER
+
+ +
124{
+
125 Sandbox sb(&ctx_.view());
+
126
+
127 auto const ter = applyGuts(sb);
+
128 if (ter == tesSUCCESS)
+
129 sb.apply(ctx_.rawView());
+
130
+
131 return ter;
+
132}
-
135
-
136TER
-
- -
138{
-
139 std::optional<STAmount> const clawAmount = ctx_.tx[~sfAmount];
-
140 AccountID const issuer = ctx_.tx[sfAccount];
-
141 AccountID const holder = ctx_.tx[sfHolder];
-
142 Issue const asset = ctx_.tx[sfAsset].get<Issue>();
-
143 Issue const asset2 = ctx_.tx[sfAsset2].get<Issue>();
-
144
-
145 auto ammSle = sb.peek(keylet::amm(asset, asset2));
-
146 if (!ammSle)
-
147 return tecINTERNAL; // LCOV_EXCL_LINE
-
148
-
149 auto const ammAccount = (*ammSle)[sfAccount];
-
150 auto const accountSle = sb.read(keylet::account(ammAccount));
-
151 if (!accountSle)
-
152 return tecINTERNAL; // LCOV_EXCL_LINE
-
153
-
154 if (sb.rules().enabled(fixAMMClawbackRounding))
-
155 {
-
156 // retrieve LP token balance inside the amendment gate to avoid
-
157 // inconsistent error behavior
-
158 auto const lpTokenBalance = ammLPHolds(sb, *ammSle, holder, j_);
-
159 if (lpTokenBalance == beast::zero)
-
160 return tecAMM_BALANCE;
-
161
-
162 if (auto const res = verifyAndAdjustLPTokenBalance(
-
163 sb, lpTokenBalance, ammSle, holder);
-
164 !res)
-
165 return res.error(); // LCOV_EXCL_LINE
-
166 }
-
167
-
168 auto const expected = ammHolds(
-
169 sb,
-
170 *ammSle,
-
171 asset,
-
172 asset2,
- -
174 ctx_.journal);
-
175
-
176 if (!expected)
-
177 return expected.error(); // LCOV_EXCL_LINE
-
178 auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected;
-
179
-
180 TER result;
-
181 STAmount newLPTokenBalance;
-
182 STAmount amountWithdraw;
-
183 std::optional<STAmount> amount2Withdraw;
-
184
-
185 auto const holdLPtokens = ammLPHolds(sb, *ammSle, holder, j_);
-
186 if (holdLPtokens == beast::zero)
-
187 return tecAMM_BALANCE;
-
188
-
189 if (!clawAmount)
-
190 // Because we are doing a two-asset withdrawal,
-
191 // tfee is actually not used, so pass tfee as 0.
-
192 std::tie(result, newLPTokenBalance, amountWithdraw, amount2Withdraw) =
- -
194 sb,
-
195 *ammSle,
-
196 holder,
-
197 ammAccount,
-
198 amountBalance,
-
199 amount2Balance,
-
200 lptAMMBalance,
-
201 holdLPtokens,
-
202 holdLPtokens,
-
203 0,
- - - -
207 ctx_.journal);
-
208 else
-
209 std::tie(result, newLPTokenBalance, amountWithdraw, amount2Withdraw) =
- -
211 sb,
-
212 *ammSle,
-
213 holder,
-
214 ammAccount,
-
215 amountBalance,
-
216 amount2Balance,
-
217 lptAMMBalance,
-
218 holdLPtokens,
-
219 *clawAmount);
-
220
-
221 if (result != tesSUCCESS)
-
222 return result; // LCOV_EXCL_LINE
-
223
- -
225 sb, ammSle, newLPTokenBalance, asset, asset2, j_);
-
226 if (!res.second)
-
227 return res.first; // LCOV_EXCL_LINE
-
228
-
229 JLOG(ctx_.journal.trace())
-
230 << "AMM Withdraw during AMMClawback: lptoken new balance: "
-
231 << to_string(newLPTokenBalance.iou())
-
232 << " old balance: " << to_string(lptAMMBalance.iou());
-
233
-
234 auto const ter = rippleCredit(sb, holder, issuer, amountWithdraw, true, j_);
-
235 if (ter != tesSUCCESS)
-
236 return ter; // LCOV_EXCL_LINE
-
237
-
238 // if the issuer issues both assets and sets flag tfClawTwoAssets, we
-
239 // will claw the paired asset as well. We already checked if
-
240 // tfClawTwoAssets is enabled, the two assets have to be issued by the
-
241 // same issuer.
-
242 if (!amount2Withdraw)
-
243 return tecINTERNAL; // LCOV_EXCL_LINE
-
244
-
245 auto const flags = ctx_.tx.getFlags();
-
246 if (flags & tfClawTwoAssets)
-
247 return rippleCredit(sb, holder, issuer, *amount2Withdraw, true, j_);
-
248
-
249 return tesSUCCESS;
-
250}
+
133
+
134TER
+
+ +
136{
+
137 std::optional<STAmount> const clawAmount = ctx_.tx[~sfAmount];
+
138 AccountID const issuer = ctx_.tx[sfAccount];
+
139 AccountID const holder = ctx_.tx[sfHolder];
+
140 Issue const asset = ctx_.tx[sfAsset].get<Issue>();
+
141 Issue const asset2 = ctx_.tx[sfAsset2].get<Issue>();
+
142
+
143 auto ammSle = sb.peek(keylet::amm(asset, asset2));
+
144 if (!ammSle)
+
145 return tecINTERNAL; // LCOV_EXCL_LINE
+
146
+
147 auto const ammAccount = (*ammSle)[sfAccount];
+
148 auto const accountSle = sb.read(keylet::account(ammAccount));
+
149 if (!accountSle)
+
150 return tecINTERNAL; // LCOV_EXCL_LINE
+
151
+
152 if (sb.rules().enabled(fixAMMClawbackRounding))
+
153 {
+
154 // retrieve LP token balance inside the amendment gate to avoid
+
155 // inconsistent error behavior
+
156 auto const lpTokenBalance = ammLPHolds(sb, *ammSle, holder, j_);
+
157 if (lpTokenBalance == beast::zero)
+
158 return tecAMM_BALANCE;
+
159
+
160 if (auto const res = verifyAndAdjustLPTokenBalance(
+
161 sb, lpTokenBalance, ammSle, holder);
+
162 !res)
+
163 return res.error(); // LCOV_EXCL_LINE
+
164 }
+
165
+
166 auto const expected = ammHolds(
+
167 sb,
+
168 *ammSle,
+
169 asset,
+
170 asset2,
+ +
172 ctx_.journal);
+
173
+
174 if (!expected)
+
175 return expected.error(); // LCOV_EXCL_LINE
+
176 auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected;
+
177
+
178 TER result;
+
179 STAmount newLPTokenBalance;
+
180 STAmount amountWithdraw;
+
181 std::optional<STAmount> amount2Withdraw;
+
182
+
183 auto const holdLPtokens = ammLPHolds(sb, *ammSle, holder, j_);
+
184 if (holdLPtokens == beast::zero)
+
185 return tecAMM_BALANCE;
+
186
+
187 if (!clawAmount)
+
188 // Because we are doing a two-asset withdrawal,
+
189 // tfee is actually not used, so pass tfee as 0.
+
190 std::tie(result, newLPTokenBalance, amountWithdraw, amount2Withdraw) =
+ +
192 sb,
+
193 *ammSle,
+
194 holder,
+
195 ammAccount,
+
196 amountBalance,
+
197 amount2Balance,
+
198 lptAMMBalance,
+
199 holdLPtokens,
+
200 holdLPtokens,
+
201 0,
+ + + +
205 ctx_.journal);
+
206 else
+
207 std::tie(result, newLPTokenBalance, amountWithdraw, amount2Withdraw) =
+ +
209 sb,
+
210 *ammSle,
+
211 holder,
+
212 ammAccount,
+
213 amountBalance,
+
214 amount2Balance,
+
215 lptAMMBalance,
+
216 holdLPtokens,
+
217 *clawAmount);
+
218
+
219 if (result != tesSUCCESS)
+
220 return result; // LCOV_EXCL_LINE
+
221
+ +
223 sb, ammSle, newLPTokenBalance, asset, asset2, j_);
+
224 if (!res.second)
+
225 return res.first; // LCOV_EXCL_LINE
+
226
+
227 JLOG(ctx_.journal.trace())
+
228 << "AMM Withdraw during AMMClawback: lptoken new balance: "
+
229 << to_string(newLPTokenBalance.iou())
+
230 << " old balance: " << to_string(lptAMMBalance.iou());
+
231
+
232 auto const ter = rippleCredit(sb, holder, issuer, amountWithdraw, true, j_);
+
233 if (ter != tesSUCCESS)
+
234 return ter; // LCOV_EXCL_LINE
+
235
+
236 // if the issuer issues both assets and sets flag tfClawTwoAssets, we
+
237 // will claw the paired asset as well. We already checked if
+
238 // tfClawTwoAssets is enabled, the two assets have to be issued by the
+
239 // same issuer.
+
240 if (!amount2Withdraw)
+
241 return tecINTERNAL; // LCOV_EXCL_LINE
+
242
+
243 auto const flags = ctx_.tx.getFlags();
+
244 if (flags & tfClawTwoAssets)
+
245 return rippleCredit(sb, holder, issuer, *amount2Withdraw, true, j_);
+
246
+
247 return tesSUCCESS;
+
248}
-
251
- -
- -
254 Sandbox& sb,
-
255 SLE const& ammSle,
-
256 AccountID const& holder,
-
257 AccountID const& ammAccount,
-
258 STAmount const& amountBalance,
-
259 STAmount const& amount2Balance,
-
260 STAmount const& lptAMMBalance,
-
261 STAmount const& holdLPtokens,
-
262 STAmount const& amount)
-
263{
-
264 auto frac = Number{amount} / amountBalance;
-
265 auto amount2Withdraw = amount2Balance * frac;
-
266
-
267 auto const lpTokensWithdraw =
-
268 toSTAmount(lptAMMBalance.issue(), lptAMMBalance * frac);
-
269
-
270 if (lpTokensWithdraw > holdLPtokens)
-
271 // if lptoken balance less than what the issuer intended to clawback,
-
272 // clawback all the tokens. Because we are doing a two-asset withdrawal,
-
273 // tfee is actually not used, so pass tfee as 0.
- -
275 sb,
-
276 ammSle,
-
277 holder,
-
278 ammAccount,
-
279 amountBalance,
-
280 amount2Balance,
-
281 lptAMMBalance,
-
282 holdLPtokens,
-
283 holdLPtokens,
-
284 0,
- - - -
288 ctx_.journal);
-
289
-
290 auto const& rules = sb.rules();
-
291 if (rules.enabled(fixAMMClawbackRounding))
-
292 {
-
293 auto tokensAdj =
-
294 getRoundedLPTokens(rules, lptAMMBalance, frac, IsDeposit::No);
-
295
-
296 // LCOV_EXCL_START
-
297 if (tokensAdj == beast::zero)
-
298 return {
- -
300 // LCOV_EXCL_STOP
-
301
-
302 frac = adjustFracByTokens(rules, lptAMMBalance, tokensAdj, frac);
-
303 auto amount2Rounded =
-
304 getRoundedAsset(rules, amount2Balance, frac, IsDeposit::No);
-
305
-
306 auto amountRounded =
-
307 getRoundedAsset(rules, amountBalance, frac, IsDeposit::No);
-
308
- -
310 sb,
-
311 ammSle,
-
312 ammAccount,
-
313 holder,
-
314 amountBalance,
-
315 amountRounded,
-
316 amount2Rounded,
-
317 lptAMMBalance,
-
318 tokensAdj,
-
319 0,
- - - -
323 ctx_.journal);
-
324 }
-
325
-
326 // Because we are doing a two-asset withdrawal,
-
327 // tfee is actually not used, so pass tfee as 0.
- -
329 sb,
-
330 ammSle,
-
331 ammAccount,
-
332 holder,
-
333 amountBalance,
-
334 amount,
-
335 toSTAmount(amount2Balance.issue(), amount2Withdraw),
-
336 lptAMMBalance,
-
337 toSTAmount(lptAMMBalance.issue(), lptAMMBalance * frac),
-
338 0,
- - - -
342 ctx_.journal);
-
343}
+
249
+ +
+ +
252 Sandbox& sb,
+
253 SLE const& ammSle,
+
254 AccountID const& holder,
+
255 AccountID const& ammAccount,
+
256 STAmount const& amountBalance,
+
257 STAmount const& amount2Balance,
+
258 STAmount const& lptAMMBalance,
+
259 STAmount const& holdLPtokens,
+
260 STAmount const& amount)
+
261{
+
262 auto frac = Number{amount} / amountBalance;
+
263 auto amount2Withdraw = amount2Balance * frac;
+
264
+
265 auto const lpTokensWithdraw =
+
266 toSTAmount(lptAMMBalance.issue(), lptAMMBalance * frac);
+
267
+
268 if (lpTokensWithdraw > holdLPtokens)
+
269 // if lptoken balance less than what the issuer intended to clawback,
+
270 // clawback all the tokens. Because we are doing a two-asset withdrawal,
+
271 // tfee is actually not used, so pass tfee as 0.
+ +
273 sb,
+
274 ammSle,
+
275 holder,
+
276 ammAccount,
+
277 amountBalance,
+
278 amount2Balance,
+
279 lptAMMBalance,
+
280 holdLPtokens,
+
281 holdLPtokens,
+
282 0,
+ + + +
286 ctx_.journal);
+
287
+
288 auto const& rules = sb.rules();
+
289 if (rules.enabled(fixAMMClawbackRounding))
+
290 {
+
291 auto tokensAdj =
+
292 getRoundedLPTokens(rules, lptAMMBalance, frac, IsDeposit::No);
+
293
+
294 // LCOV_EXCL_START
+
295 if (tokensAdj == beast::zero)
+
296 return {
+ +
298 // LCOV_EXCL_STOP
+
299
+
300 frac = adjustFracByTokens(rules, lptAMMBalance, tokensAdj, frac);
+
301 auto amount2Rounded =
+
302 getRoundedAsset(rules, amount2Balance, frac, IsDeposit::No);
+
303
+
304 auto amountRounded =
+
305 getRoundedAsset(rules, amountBalance, frac, IsDeposit::No);
+
306
+ +
308 sb,
+
309 ammSle,
+
310 ammAccount,
+
311 holder,
+
312 amountBalance,
+
313 amountRounded,
+
314 amount2Rounded,
+
315 lptAMMBalance,
+
316 tokensAdj,
+
317 0,
+ + + +
321 ctx_.journal);
+
322 }
+
323
+
324 // Because we are doing a two-asset withdrawal,
+
325 // tfee is actually not used, so pass tfee as 0.
+ +
327 sb,
+
328 ammSle,
+
329 ammAccount,
+
330 holder,
+
331 amountBalance,
+
332 amount,
+
333 toSTAmount(amount2Balance.issue(), amount2Withdraw),
+
334 lptAMMBalance,
+
335 toSTAmount(lptAMMBalance.issue(), lptAMMBalance * frac),
+
336 0,
+ + + +
340 ctx_.journal);
+
341}
-
344
-
345} // namespace ripple
+
342
+
343} // namespace ripple
Stream debug() const
Definition Journal.h:328
Stream trace() const
Severity stream access functions.
Definition Journal.h:322
-
TER doApply() override
-
TER applyGuts(Sandbox &view)
-
static NotTEC preflight(PreflightContext const &ctx)
-
static TER preclaim(PreclaimContext const &ctx)
-
std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > equalWithdrawMatchingOneAmount(Sandbox &view, SLE const &ammSle, AccountID const &holder, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &holdLPtokens, STAmount const &amount)
Withdraw both assets by providing maximum amount of asset1, asset2's amount will be calculated accord...
-
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > equalWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const account, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokens, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHanding, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Equal-asset withdrawal (LPTokens) of some AMM instance pools shares represented by the number of LPTo...
-
static std::pair< TER, bool > deleteAMMAccountIfEmpty(Sandbox &sb, std::shared_ptr< SLE > const ammSle, STAmount const &lpTokenBalance, Issue const &issue1, Issue const &issue2, beast::Journal const &journal)
-
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > withdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, AccountID const &account, STAmount const &amountBalance, STAmount const &amountWithdraw, std::optional< STAmount > const &amount2Withdraw, STAmount const &lpTokensAMMBalance, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHandling, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Withdraw requested assets and token from AMM into LP account.
+
TER doApply() override
+
TER applyGuts(Sandbox &view)
+
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
+
static NotTEC preflight(PreflightContext const &ctx)
+
static TER preclaim(PreclaimContext const &ctx)
+
std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > equalWithdrawMatchingOneAmount(Sandbox &view, SLE const &ammSle, AccountID const &holder, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &holdLPtokens, STAmount const &amount)
Withdraw both assets by providing maximum amount of asset1, asset2's amount will be calculated accord...
+
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > equalWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const account, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokens, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHanding, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Equal-asset withdrawal (LPTokens) of some AMM instance pools shares represented by the number of LPTo...
+
static std::pair< TER, bool > deleteAMMAccountIfEmpty(Sandbox &sb, std::shared_ptr< SLE > const ammSle, STAmount const &lpTokenBalance, Issue const &issue1, Issue const &issue2, beast::Journal const &journal)
+
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > withdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, AccountID const &account, STAmount const &amountBalance, STAmount const &amountWithdraw, std::optional< STAmount > const &amount2Withdraw, STAmount const &lpTokensAMMBalance, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHandling, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Withdraw requested assets and token from AMM into LP account.
ApplyView & view()
beast::Journal const journal
@@ -462,10 +463,10 @@ $(document).ready(function() { init_codefold(0); });
std::uint32_t getFlags() const
Definition STObject.cpp:537
Discardable, editable view to a ledger.
Definition Sandbox.h:35
void apply(RawView &to)
Definition Sandbox.h:55
- -
beast::Journal const j_
Definition Transactor.h:143
-
XRPAmount mPriorBalance
Definition Transactor.h:146
-
ApplyContext & ctx_
Definition Transactor.h:141
+ +
beast::Journal const j_
Definition Transactor.h:145
+
XRPAmount mPriorBalance
Definition Transactor.h:148
+
ApplyContext & ctx_
Definition Transactor.h:143
std::shared_ptr< SLE const > read(Keylet const &k) const override
Return the state item associated with a key.
Rules const & rules() const override
Returns the tx processing rules.
@@ -483,12 +484,10 @@ $(document).ready(function() { init_codefold(0); });
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
constexpr std::uint32_t tfClawTwoAssets
Definition TxFlags.h:262
-
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
STAmount getRoundedLPTokens(Rules const &rules, STAmount const &balance, Number const &frac, IsDeposit isDeposit)
Round AMM deposit/withdrawal LPToken amount.
Expected< bool, TER > verifyAndAdjustLPTokenBalance(Sandbox &sb, STAmount const &lpTokens, std::shared_ptr< SLE > &ammSle, AccountID const &account)
Due to rounding, the LPTokenBalance of the last LP might not match the LP's trustline balance.
Definition AMMUtils.cpp:469
constexpr std::uint32_t tfAMMClawbackMask
Definition TxFlags.h:263
STAmount ammLPHolds(ReadView const &view, Currency const &cur1, Currency const &cur2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
Definition AMMUtils.cpp:113
-
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
@ tecINTERNAL
Definition TER.h:310
@ tecNO_PERMISSION
Definition TER.h:305
@ tecAMM_INVALID_TOKENS
Definition TER.h:331
@@ -496,25 +495,21 @@ $(document).ready(function() { init_codefold(0); });
TER rippleCredit(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, bool bCheckIssuer, beast::Journal j)
Calls static rippleCreditIOU if saAmount represents Issue.
Definition View.cpp:2829
@ tesSUCCESS
Definition TER.h:244
-
bool isTesSuccess(TER x) noexcept
Definition TER.h:674
Expected< std::tuple< STAmount, STAmount, STAmount >, TER > ammHolds(ReadView const &view, SLE const &ammSle, std::optional< Issue > const &optIssue1, std::optional< Issue > const &optIssue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool and LP token balances.
Definition AMMUtils.cpp:47
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
@ terNO_ACCOUNT
Definition TER.h:217
@ terNO_AMM
Definition TER.h:227
STAmount getRoundedAsset(Rules const &rules, STAmount const &balance, A const &frac, IsDeposit isDeposit)
Round AMM equal deposit/withdrawal amount.
Definition AMMHelpers.h:678
Number adjustFracByTokens(Rules const &rules, STAmount const &lptAMMBalance, STAmount const &tokens, Number const &frac)
Find a fraction of tokens after the tokens are adjusted.
-
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:605
@ temBAD_AMOUNT
Definition TER.h:89
@ temMALFORMED
Definition TER.h:87
@ temINVALID_FLAG
Definition TER.h:111
-
@ temDISABLED
Definition TER.h:114
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:80
ReadView const & view
Definition Transactor.h:83
beast::Journal const j
Definition Transactor.h:88
State information when preflighting a tx.
Definition Transactor.h:35
-
beast::Journal const j
Definition Transactor.h:42
T tie(T... args)
diff --git a/AMMClawback_8h_source.html b/AMMClawback_8h_source.html index 7d586f99ca..55d941c088 100644 --- a/AMMClawback_8h_source.html +++ b/AMMClawback_8h_source.html @@ -119,54 +119,59 @@ $(document).ready(function() { init_codefold(0); });
34 }
35
-
36 static NotTEC
-
37 preflight(PreflightContext const& ctx);
+
36 static std::uint32_t
+
38
-
39 static TER
-
40 preclaim(PreclaimContext const& ctx);
+
39 static NotTEC
+
40 preflight(PreflightContext const& ctx);
41
-
42 TER
-
43 doApply() override;
+
42 static TER
+
43 preclaim(PreclaimContext const& ctx);
44
-
45private:
-
46 TER
- -
48
- - - -
63 SLE const& ammSle,
-
64 AccountID const& holder,
-
65 AccountID const& ammAccount,
-
66 STAmount const& amountBalance,
-
67 STAmount const& amount2Balance,
-
68 STAmount const& lptAMMBalance,
-
69 STAmount const& holdLPtokens,
-
70 STAmount const& amount);
-
71};
+
45 TER
+
46 doApply() override;
+
47
+
48private:
+
49 TER
+ +
51
+ + + +
66 SLE const& ammSle,
+
67 AccountID const& holder,
+
68 AccountID const& ammAccount,
+
69 STAmount const& amountBalance,
+
70 STAmount const& amount2Balance,
+
71 STAmount const& lptAMMBalance,
+
72 STAmount const& holdLPtokens,
+
73 STAmount const& amount);
+
74};
-
72
-
73} // namespace ripple
-
74
-
75#endif
+
75
+
76} // namespace ripple
+
77
+
78#endif
static constexpr ConsequencesFactoryType ConsequencesFactory
Definition AMMClawback.h:30
-
TER doApply() override
-
TER applyGuts(Sandbox &view)
+
TER doApply() override
+
TER applyGuts(Sandbox &view)
+
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
AMMClawback(ApplyContext &ctx)
Definition AMMClawback.h:32
-
static NotTEC preflight(PreflightContext const &ctx)
-
static TER preclaim(PreclaimContext const &ctx)
-
std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > equalWithdrawMatchingOneAmount(Sandbox &view, SLE const &ammSle, AccountID const &holder, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &holdLPtokens, STAmount const &amount)
Withdraw both assets by providing maximum amount of asset1, asset2's amount will be calculated accord...
+
static NotTEC preflight(PreflightContext const &ctx)
+
static TER preclaim(PreclaimContext const &ctx)
+
std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > equalWithdrawMatchingOneAmount(Sandbox &view, SLE const &ammSle, AccountID const &holder, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &holdLPtokens, STAmount const &amount)
Withdraw both assets by providing maximum amount of asset1, asset2's amount will be calculated accord...
State information when applying a tx.
Discardable, editable view to a ledger.
Definition Sandbox.h:35
- - - -
ApplyView & view()
Definition Transactor.h:161
+ + + +
ApplyView & view()
Definition Transactor.h:163
+
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:80
State information when preflighting a tx.
Definition Transactor.h:35
diff --git a/AMMCreate_8cpp_source.html b/AMMCreate_8cpp_source.html index dcf5b3c8c2..d2aeaa97fa 100644 --- a/AMMCreate_8cpp_source.html +++ b/AMMCreate_8cpp_source.html @@ -114,348 +114,345 @@ $(document).ready(function() { init_codefold(0); });
31
32namespace ripple {
33
- +
34bool
- +
36{
-
37 if (!ammEnabled(ctx.rules))
-
38 return temDISABLED;
+
37 return ammEnabled(ctx.rules);
+
38}
+
39
-
40 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
-
41 return ret;
-
42
-
43 if (ctx.tx.getFlags() & tfUniversalMask)
-
44 {
-
45 JLOG(ctx.j.debug()) << "AMM Instance: invalid flags.";
-
46 return temINVALID_FLAG;
-
47 }
-
48
-
49 auto const amount = ctx.tx[sfAmount];
-
50 auto const amount2 = ctx.tx[sfAmount2];
-
51
-
52 if (amount.issue() == amount2.issue())
-
53 {
-
54 JLOG(ctx.j.debug())
-
55 << "AMM Instance: tokens can not have the same currency/issuer.";
-
56 return temBAD_AMM_TOKENS;
+ +
+ +
42{
+
43 auto const amount = ctx.tx[sfAmount];
+
44 auto const amount2 = ctx.tx[sfAmount2];
+
45
+
46 if (amount.issue() == amount2.issue())
+
47 {
+
48 JLOG(ctx.j.debug())
+
49 << "AMM Instance: tokens can not have the same currency/issuer.";
+
50 return temBAD_AMM_TOKENS;
+
51 }
+
52
+
53 if (auto const err = invalidAMMAmount(amount))
+
54 {
+
55 JLOG(ctx.j.debug()) << "AMM Instance: invalid asset1 amount.";
+
56 return err;
57 }
58
-
59 if (auto const err = invalidAMMAmount(amount))
+
59 if (auto const err = invalidAMMAmount(amount2))
60 {
-
61 JLOG(ctx.j.debug()) << "AMM Instance: invalid asset1 amount.";
+
61 JLOG(ctx.j.debug()) << "AMM Instance: invalid asset2 amount.";
62 return err;
63 }
64
-
65 if (auto const err = invalidAMMAmount(amount2))
+
65 if (ctx.tx[sfTradingFee] > TRADING_FEE_THRESHOLD)
66 {
-
67 JLOG(ctx.j.debug()) << "AMM Instance: invalid asset2 amount.";
-
68 return err;
+
67 JLOG(ctx.j.debug()) << "AMM Instance: invalid trading fee.";
+
68 return temBAD_FEE;
69 }
70
-
71 if (ctx.tx[sfTradingFee] > TRADING_FEE_THRESHOLD)
-
72 {
-
73 JLOG(ctx.j.debug()) << "AMM Instance: invalid trading fee.";
-
74 return temBAD_FEE;
-
75 }
-
76
-
77 return preflight2(ctx);
-
78}
+
71 return tesSUCCESS;
+
72}
-
79
- -
- -
82{
-
83 // The fee required for AMMCreate is one owner reserve.
-
84 return view.fees().increment;
-
85}
+
73
+ +
+ +
76{
+
77 // The fee required for AMMCreate is one owner reserve.
+ +
79}
-
86
-
87TER
-
- -
89{
-
90 auto const accountID = ctx.tx[sfAccount];
-
91 auto const amount = ctx.tx[sfAmount];
-
92 auto const amount2 = ctx.tx[sfAmount2];
-
93
-
94 // Check if AMM already exists for the token pair
-
95 if (auto const ammKeylet = keylet::amm(amount.issue(), amount2.issue());
-
96 ctx.view.read(ammKeylet))
-
97 {
-
98 JLOG(ctx.j.debug()) << "AMM Instance: ltAMM already exists.";
-
99 return tecDUPLICATE;
-
100 }
-
101
-
102 if (auto const ter = requireAuth(ctx.view, amount.issue(), accountID);
-
103 ter != tesSUCCESS)
-
104 {
-
105 JLOG(ctx.j.debug())
-
106 << "AMM Instance: account is not authorized, " << amount.issue();
-
107 return ter;
-
108 }
-
109
-
110 if (auto const ter = requireAuth(ctx.view, amount2.issue(), accountID);
-
111 ter != tesSUCCESS)
-
112 {
-
113 JLOG(ctx.j.debug())
-
114 << "AMM Instance: account is not authorized, " << amount2.issue();
-
115 return ter;
-
116 }
-
117
-
118 // Globally or individually frozen
-
119 if (isFrozen(ctx.view, accountID, amount.issue()) ||
-
120 isFrozen(ctx.view, accountID, amount2.issue()))
-
121 {
-
122 JLOG(ctx.j.debug()) << "AMM Instance: involves frozen asset.";
-
123 return tecFROZEN;
-
124 }
-
125
-
126 auto noDefaultRipple = [](ReadView const& view, Issue const& issue) {
-
127 if (isXRP(issue))
-
128 return false;
-
129
-
130 if (auto const issuerAccount =
-
131 view.read(keylet::account(issue.account)))
-
132 return (issuerAccount->getFlags() & lsfDefaultRipple) == 0;
-
133
-
134 return false;
-
135 };
-
136
-
137 if (noDefaultRipple(ctx.view, amount.issue()) ||
-
138 noDefaultRipple(ctx.view, amount2.issue()))
-
139 {
-
140 JLOG(ctx.j.debug()) << "AMM Instance: DefaultRipple not set";
-
141 return terNO_RIPPLE;
-
142 }
-
143
-
144 // Check the reserve for LPToken trustline
-
145 STAmount const xrpBalance = xrpLiquid(ctx.view, accountID, 1, ctx.j);
-
146 // Insufficient reserve
-
147 if (xrpBalance <= beast::zero)
-
148 {
-
149 JLOG(ctx.j.debug()) << "AMM Instance: insufficient reserves";
- -
151 }
-
152
-
153 auto insufficientBalance = [&](STAmount const& asset) {
-
154 if (isXRP(asset))
-
155 return xrpBalance < asset;
-
156 return accountID != asset.issue().account &&
- -
158 ctx.view,
-
159 accountID,
-
160 asset.issue(),
- -
162 ctx.j) < asset;
-
163 };
-
164
-
165 if (insufficientBalance(amount) || insufficientBalance(amount2))
-
166 {
-
167 JLOG(ctx.j.debug())
-
168 << "AMM Instance: insufficient funds, " << amount << " " << amount2;
-
169 return tecUNFUNDED_AMM;
-
170 }
-
171
-
172 auto isLPToken = [&](STAmount const& amount) -> bool {
-
173 if (auto const sle =
-
174 ctx.view.read(keylet::account(amount.issue().account)))
-
175 return sle->isFieldPresent(sfAMMID);
-
176 return false;
-
177 };
-
178
-
179 if (isLPToken(amount) || isLPToken(amount2))
-
180 {
-
181 JLOG(ctx.j.debug()) << "AMM Instance: can't create with LPTokens "
-
182 << amount << " " << amount2;
- -
184 }
-
185
-
186 if (ctx.view.rules().enabled(featureSingleAssetVault))
-
187 {
-
188 if (auto const accountId = pseudoAccountAddress(
-
189 ctx.view, keylet::amm(amount.issue(), amount2.issue()).key);
-
190 accountId == beast::zero)
- -
192 }
-
193
-
194 // If featureAMMClawback is enabled, allow AMMCreate without checking
-
195 // if the issuer has clawback enabled
-
196 if (ctx.view.rules().enabled(featureAMMClawback))
-
197 return tesSUCCESS;
-
198
-
199 // Disallow AMM if the issuer has clawback enabled when featureAMMClawback
-
200 // is not enabled
-
201 auto clawbackDisabled = [&](Issue const& issue) -> TER {
-
202 if (isXRP(issue))
-
203 return tesSUCCESS;
-
204 if (auto const sle = ctx.view.read(keylet::account(issue.account));
-
205 !sle)
-
206 return tecINTERNAL;
-
207 else if (sle->getFlags() & lsfAllowTrustLineClawback)
-
208 return tecNO_PERMISSION;
-
209 return tesSUCCESS;
-
210 };
-
211
-
212 if (auto const ter = clawbackDisabled(amount.issue()); ter != tesSUCCESS)
-
213 return ter;
-
214 return clawbackDisabled(amount2.issue());
-
215}
+
80
+
81TER
+
+ +
83{
+
84 auto const accountID = ctx.tx[sfAccount];
+
85 auto const amount = ctx.tx[sfAmount];
+
86 auto const amount2 = ctx.tx[sfAmount2];
+
87
+
88 // Check if AMM already exists for the token pair
+
89 if (auto const ammKeylet = keylet::amm(amount.issue(), amount2.issue());
+
90 ctx.view.read(ammKeylet))
+
91 {
+
92 JLOG(ctx.j.debug()) << "AMM Instance: ltAMM already exists.";
+
93 return tecDUPLICATE;
+
94 }
+
95
+
96 if (auto const ter = requireAuth(ctx.view, amount.issue(), accountID);
+
97 ter != tesSUCCESS)
+
98 {
+
99 JLOG(ctx.j.debug())
+
100 << "AMM Instance: account is not authorized, " << amount.issue();
+
101 return ter;
+
102 }
+
103
+
104 if (auto const ter = requireAuth(ctx.view, amount2.issue(), accountID);
+
105 ter != tesSUCCESS)
+
106 {
+
107 JLOG(ctx.j.debug())
+
108 << "AMM Instance: account is not authorized, " << amount2.issue();
+
109 return ter;
+
110 }
+
111
+
112 // Globally or individually frozen
+
113 if (isFrozen(ctx.view, accountID, amount.issue()) ||
+
114 isFrozen(ctx.view, accountID, amount2.issue()))
+
115 {
+
116 JLOG(ctx.j.debug()) << "AMM Instance: involves frozen asset.";
+
117 return tecFROZEN;
+
118 }
+
119
+
120 auto noDefaultRipple = [](ReadView const& view, Issue const& issue) {
+
121 if (isXRP(issue))
+
122 return false;
+
123
+
124 if (auto const issuerAccount =
+
125 view.read(keylet::account(issue.account)))
+
126 return (issuerAccount->getFlags() & lsfDefaultRipple) == 0;
+
127
+
128 return false;
+
129 };
+
130
+
131 if (noDefaultRipple(ctx.view, amount.issue()) ||
+
132 noDefaultRipple(ctx.view, amount2.issue()))
+
133 {
+
134 JLOG(ctx.j.debug()) << "AMM Instance: DefaultRipple not set";
+
135 return terNO_RIPPLE;
+
136 }
+
137
+
138 // Check the reserve for LPToken trustline
+
139 STAmount const xrpBalance = xrpLiquid(ctx.view, accountID, 1, ctx.j);
+
140 // Insufficient reserve
+
141 if (xrpBalance <= beast::zero)
+
142 {
+
143 JLOG(ctx.j.debug()) << "AMM Instance: insufficient reserves";
+ +
145 }
+
146
+
147 auto insufficientBalance = [&](STAmount const& asset) {
+
148 if (isXRP(asset))
+
149 return xrpBalance < asset;
+
150 return accountID != asset.issue().account &&
+ +
152 ctx.view,
+
153 accountID,
+
154 asset.issue(),
+ +
156 ctx.j) < asset;
+
157 };
+
158
+
159 if (insufficientBalance(amount) || insufficientBalance(amount2))
+
160 {
+
161 JLOG(ctx.j.debug())
+
162 << "AMM Instance: insufficient funds, " << amount << " " << amount2;
+
163 return tecUNFUNDED_AMM;
+
164 }
+
165
+
166 auto isLPToken = [&](STAmount const& amount) -> bool {
+
167 if (auto const sle =
+
168 ctx.view.read(keylet::account(amount.issue().account)))
+
169 return sle->isFieldPresent(sfAMMID);
+
170 return false;
+
171 };
+
172
+
173 if (isLPToken(amount) || isLPToken(amount2))
+
174 {
+
175 JLOG(ctx.j.debug()) << "AMM Instance: can't create with LPTokens "
+
176 << amount << " " << amount2;
+ +
178 }
+
179
+
180 if (ctx.view.rules().enabled(featureSingleAssetVault))
+
181 {
+
182 if (auto const accountId = pseudoAccountAddress(
+
183 ctx.view, keylet::amm(amount.issue(), amount2.issue()).key);
+
184 accountId == beast::zero)
+ +
186 }
+
187
+
188 // If featureAMMClawback is enabled, allow AMMCreate without checking
+
189 // if the issuer has clawback enabled
+
190 if (ctx.view.rules().enabled(featureAMMClawback))
+
191 return tesSUCCESS;
+
192
+
193 // Disallow AMM if the issuer has clawback enabled when featureAMMClawback
+
194 // is not enabled
+
195 auto clawbackDisabled = [&](Issue const& issue) -> TER {
+
196 if (isXRP(issue))
+
197 return tesSUCCESS;
+
198 if (auto const sle = ctx.view.read(keylet::account(issue.account));
+
199 !sle)
+
200 return tecINTERNAL;
+
201 else if (sle->getFlags() & lsfAllowTrustLineClawback)
+
202 return tecNO_PERMISSION;
+
203 return tesSUCCESS;
+
204 };
+
205
+
206 if (auto const ter = clawbackDisabled(amount.issue()); ter != tesSUCCESS)
+
207 return ter;
+
208 return clawbackDisabled(amount2.issue());
+
209}
-
216
- -
- -
219 ApplyContext& ctx_,
-
220 Sandbox& sb,
-
221 AccountID const& account_,
- -
223{
-
224 auto const amount = ctx_.tx[sfAmount];
-
225 auto const amount2 = ctx_.tx[sfAmount2];
-
226
-
227 auto const ammKeylet = keylet::amm(amount.issue(), amount2.issue());
-
228
-
229 // Mitigate same account exists possibility
-
230 auto const maybeAccount = createPseudoAccount(sb, ammKeylet.key, sfAMMID);
-
231 // AMM account already exists (should not happen)
-
232 if (!maybeAccount)
-
233 {
-
234 JLOG(j_.error()) << "AMM Instance: failed to create pseudo account.";
-
235 return {maybeAccount.error(), false};
-
236 }
-
237 auto& account = *maybeAccount;
-
238 auto const accountId = (*account)[sfAccount];
-
239
-
240 // LP Token already exists. (should not happen)
-
241 auto const lptIss = ammLPTIssue(
-
242 amount.issue().currency, amount2.issue().currency, accountId);
-
243 if (sb.read(keylet::line(accountId, lptIss)))
-
244 {
-
245 JLOG(j_.error()) << "AMM Instance: LP Token already exists.";
-
246 return {tecDUPLICATE, false};
-
247 }
+
210
+ +
+ +
213 ApplyContext& ctx_,
+
214 Sandbox& sb,
+
215 AccountID const& account_,
+ +
217{
+
218 auto const amount = ctx_.tx[sfAmount];
+
219 auto const amount2 = ctx_.tx[sfAmount2];
+
220
+
221 auto const ammKeylet = keylet::amm(amount.issue(), amount2.issue());
+
222
+
223 // Mitigate same account exists possibility
+
224 auto const maybeAccount = createPseudoAccount(sb, ammKeylet.key, sfAMMID);
+
225 // AMM account already exists (should not happen)
+
226 if (!maybeAccount)
+
227 {
+
228 JLOG(j_.error()) << "AMM Instance: failed to create pseudo account.";
+
229 return {maybeAccount.error(), false};
+
230 }
+
231 auto& account = *maybeAccount;
+
232 auto const accountId = (*account)[sfAccount];
+
233
+
234 // LP Token already exists. (should not happen)
+
235 auto const lptIss = ammLPTIssue(
+
236 amount.issue().currency, amount2.issue().currency, accountId);
+
237 if (sb.read(keylet::line(accountId, lptIss)))
+
238 {
+
239 JLOG(j_.error()) << "AMM Instance: LP Token already exists.";
+
240 return {tecDUPLICATE, false};
+
241 }
+
242
+
243 // Note, that the trustlines created by AMM have 0 credit limit.
+
244 // This prevents shifting the balance between accounts via AMM,
+
245 // or sending unsolicited LPTokens. This is a desired behavior.
+
246 // A user can only receive LPTokens through affirmative action -
+
247 // either an AMMDeposit, TrustSet, crossing an offer, etc.
248
-
249 // Note, that the trustlines created by AMM have 0 credit limit.
-
250 // This prevents shifting the balance between accounts via AMM,
-
251 // or sending unsolicited LPTokens. This is a desired behavior.
-
252 // A user can only receive LPTokens through affirmative action -
-
253 // either an AMMDeposit, TrustSet, crossing an offer, etc.
-
254
-
255 // Calculate initial LPT balance.
-
256 auto const lpTokens = ammLPTokens(amount, amount2, lptIss);
-
257
-
258 // Create ltAMM
-
259 auto ammSle = std::make_shared<SLE>(ammKeylet);
-
260 ammSle->setAccountID(sfAccount, accountId);
-
261 ammSle->setFieldAmount(sfLPTokenBalance, lpTokens);
-
262 auto const& [issue1, issue2] = std::minmax(amount.issue(), amount2.issue());
-
263 ammSle->setFieldIssue(sfAsset, STIssue{sfAsset, issue1});
-
264 ammSle->setFieldIssue(sfAsset2, STIssue{sfAsset2, issue2});
-
265 // AMM creator gets the auction slot and the voting slot.
- -
267 ctx_.view(), ammSle, account_, lptIss, ctx_.tx[sfTradingFee]);
-
268
-
269 // Add owner directory to link the root account and AMM object.
-
270 if (auto ter = dirLink(sb, accountId, ammSle); ter)
-
271 {
-
272 JLOG(j_.debug()) << "AMM Instance: failed to insert owner dir";
-
273 return {ter, false};
-
274 }
-
275 sb.insert(ammSle);
-
276
-
277 // Send LPT to LP.
-
278 auto res = accountSend(sb, accountId, account_, lpTokens, ctx_.journal);
-
279 if (res != tesSUCCESS)
-
280 {
-
281 JLOG(j_.debug()) << "AMM Instance: failed to send LPT " << lpTokens;
-
282 return {res, false};
-
283 }
-
284
-
285 auto sendAndTrustSet = [&](STAmount const& amount) -> TER {
-
286 if (auto const res = accountSend(
-
287 sb,
-
288 account_,
-
289 accountId,
-
290 amount,
-
291 ctx_.journal,
- -
293 return res;
-
294 // Set AMM flag on AMM trustline
-
295 if (!isXRP(amount))
-
296 {
-
297 if (SLE::pointer sleRippleState =
-
298 sb.peek(keylet::line(accountId, amount.issue()));
-
299 !sleRippleState)
-
300 return tecINTERNAL;
-
301 else
-
302 {
-
303 auto const flags = sleRippleState->getFlags();
-
304 sleRippleState->setFieldU32(sfFlags, flags | lsfAMMNode);
-
305 sb.update(sleRippleState);
-
306 }
-
307 }
-
308 return tesSUCCESS;
-
309 };
-
310
-
311 // Send asset1.
-
312 res = sendAndTrustSet(amount);
-
313 if (res != tesSUCCESS)
-
314 {
-
315 JLOG(j_.debug()) << "AMM Instance: failed to send " << amount;
-
316 return {res, false};
-
317 }
-
318
-
319 // Send asset2.
-
320 res = sendAndTrustSet(amount2);
-
321 if (res != tesSUCCESS)
-
322 {
-
323 JLOG(j_.debug()) << "AMM Instance: failed to send " << amount2;
-
324 return {res, false};
-
325 }
-
326
-
327 JLOG(j_.debug()) << "AMM Instance: success " << accountId << " "
-
328 << ammKeylet.key << " " << lpTokens << " " << amount << " "
-
329 << amount2;
-
330 auto addOrderBook =
-
331 [&](Issue const& issueIn, Issue const& issueOut, std::uint64_t uRate) {
-
332 Book const book{issueIn, issueOut, std::nullopt};
-
333 auto const dir = keylet::quality(keylet::book(book), uRate);
-
334 if (auto const bookExisted = static_cast<bool>(sb.read(dir));
-
335 !bookExisted)
-
336 ctx_.app.getOrderBookDB().addOrderBook(book);
-
337 };
-
338 addOrderBook(amount.issue(), amount2.issue(), getRate(amount2, amount));
-
339 addOrderBook(amount2.issue(), amount.issue(), getRate(amount, amount2));
-
340
-
341 return {res, res == tesSUCCESS};
-
342}
+
249 // Calculate initial LPT balance.
+
250 auto const lpTokens = ammLPTokens(amount, amount2, lptIss);
+
251
+
252 // Create ltAMM
+
253 auto ammSle = std::make_shared<SLE>(ammKeylet);
+
254 ammSle->setAccountID(sfAccount, accountId);
+
255 ammSle->setFieldAmount(sfLPTokenBalance, lpTokens);
+
256 auto const& [issue1, issue2] = std::minmax(amount.issue(), amount2.issue());
+
257 ammSle->setFieldIssue(sfAsset, STIssue{sfAsset, issue1});
+
258 ammSle->setFieldIssue(sfAsset2, STIssue{sfAsset2, issue2});
+
259 // AMM creator gets the auction slot and the voting slot.
+ +
261 ctx_.view(), ammSle, account_, lptIss, ctx_.tx[sfTradingFee]);
+
262
+
263 // Add owner directory to link the root account and AMM object.
+
264 if (auto ter = dirLink(sb, accountId, ammSle); ter)
+
265 {
+
266 JLOG(j_.debug()) << "AMM Instance: failed to insert owner dir";
+
267 return {ter, false};
+
268 }
+
269 sb.insert(ammSle);
+
270
+
271 // Send LPT to LP.
+
272 auto res = accountSend(sb, accountId, account_, lpTokens, ctx_.journal);
+
273 if (res != tesSUCCESS)
+
274 {
+
275 JLOG(j_.debug()) << "AMM Instance: failed to send LPT " << lpTokens;
+
276 return {res, false};
+
277 }
+
278
+
279 auto sendAndTrustSet = [&](STAmount const& amount) -> TER {
+
280 if (auto const res = accountSend(
+
281 sb,
+
282 account_,
+
283 accountId,
+
284 amount,
+
285 ctx_.journal,
+ +
287 return res;
+
288 // Set AMM flag on AMM trustline
+
289 if (!isXRP(amount))
+
290 {
+
291 if (SLE::pointer sleRippleState =
+
292 sb.peek(keylet::line(accountId, amount.issue()));
+
293 !sleRippleState)
+
294 return tecINTERNAL;
+
295 else
+
296 {
+
297 auto const flags = sleRippleState->getFlags();
+
298 sleRippleState->setFieldU32(sfFlags, flags | lsfAMMNode);
+
299 sb.update(sleRippleState);
+
300 }
+
301 }
+
302 return tesSUCCESS;
+
303 };
+
304
+
305 // Send asset1.
+
306 res = sendAndTrustSet(amount);
+
307 if (res != tesSUCCESS)
+
308 {
+
309 JLOG(j_.debug()) << "AMM Instance: failed to send " << amount;
+
310 return {res, false};
+
311 }
+
312
+
313 // Send asset2.
+
314 res = sendAndTrustSet(amount2);
+
315 if (res != tesSUCCESS)
+
316 {
+
317 JLOG(j_.debug()) << "AMM Instance: failed to send " << amount2;
+
318 return {res, false};
+
319 }
+
320
+
321 JLOG(j_.debug()) << "AMM Instance: success " << accountId << " "
+
322 << ammKeylet.key << " " << lpTokens << " " << amount << " "
+
323 << amount2;
+
324 auto addOrderBook =
+
325 [&](Issue const& issueIn, Issue const& issueOut, std::uint64_t uRate) {
+
326 Book const book{issueIn, issueOut, std::nullopt};
+
327 auto const dir = keylet::quality(keylet::book(book), uRate);
+
328 if (auto const bookExisted = static_cast<bool>(sb.read(dir));
+
329 !bookExisted)
+
330 ctx_.app.getOrderBookDB().addOrderBook(book);
+
331 };
+
332 addOrderBook(amount.issue(), amount2.issue(), getRate(amount2, amount));
+
333 addOrderBook(amount2.issue(), amount.issue(), getRate(amount, amount2));
+
334
+
335 return {res, res == tesSUCCESS};
+
336}
-
343
-
344TER
-
- -
346{
-
347 // This is the ledger view that we work against. Transactions are applied
-
348 // as we go on processing transactions.
-
349 Sandbox sb(&ctx_.view());
-
350
-
351 auto const result = applyCreate(ctx_, sb, account_, j_);
-
352 if (result.second)
-
353 sb.apply(ctx_.rawView());
-
354
-
355 return result.first;
-
356}
+
337
+
338TER
+
+ +
340{
+
341 // This is the ledger view that we work against. Transactions are applied
+
342 // as we go on processing transactions.
+
343 Sandbox sb(&ctx_.view());
+
344
+
345 auto const result = applyCreate(ctx_, sb, account_, j_);
+
346 if (result.second)
+
347 sb.apply(ctx_.rawView());
+
348
+
349 return result.first;
+
350}
-
357
-
358} // namespace ripple
+
351
+
352} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:60
Stream error() const
Definition Journal.h:346
Stream debug() const
Definition Journal.h:328
-
static TER preclaim(PreclaimContext const &ctx)
Definition AMMCreate.cpp:88
-
TER doApply() override
Attempt to create the AMM instance.
-
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMCreate.cpp:35
-
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Definition AMMCreate.cpp:81
+
static TER preclaim(PreclaimContext const &ctx)
Definition AMMCreate.cpp:82
+
static bool checkExtraFeatures(PreflightContext const &ctx)
Definition AMMCreate.cpp:35
+
TER doApply() override
Attempt to create the AMM instance.
+
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMCreate.cpp:41
+
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Definition AMMCreate.cpp:75
virtual OrderBookDB & getOrderBookDB()=0
State information when applying a tx.
@@ -469,21 +466,20 @@ $(document).ready(function() { init_codefold(0); });
void addOrderBook(Book const &)
A view into a ledger.
Definition ReadView.h:51
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
-
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:130
Issue const & issue() const
Definition STAmount.h:496
-
std::uint32_t getFlags() const
Definition STObject.cpp:537
Discardable, editable view to a ledger.
Definition Sandbox.h:35
void apply(RawView &to)
Definition Sandbox.h:55
- -
AccountID const account_
Definition Transactor.h:145
-
ApplyView & view()
Definition Transactor.h:161
-
beast::Journal const j_
Definition Transactor.h:143
-
ApplyContext & ctx_
Definition Transactor.h:141
+ +
AccountID const account_
Definition Transactor.h:147
+
ApplyView & view()
Definition Transactor.h:163
+
static XRPAmount calculateOwnerReserveFee(ReadView const &view, STTx const &tx)
+
beast::Journal const j_
Definition Transactor.h:145
+
ApplyContext & ctx_
Definition Transactor.h:143
void update(std::shared_ptr< SLE > const &sle) override
Indicate changes to a peeked SLE.
@@ -506,15 +502,13 @@ $(document).ready(function() { init_codefold(0); });
@ lsfAllowTrustLineClawback
bool ammEnabled(Rules const &)
Return true if required AMM amendments are enabled.
Definition AMMCore.cpp:129
-
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
Issue ammLPTIssue(Currency const &cur1, Currency const &cur2, AccountID const &ammAccountID)
Calculate LPT Issue from AMM asset pair.
Definition AMMCore.cpp:57
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No)
Calls static accountSendIOU if saAmount represents Issue.
Definition View.cpp:2174
bool isFrozen(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer)
Definition View.cpp:247
std::uint64_t getRate(STAmount const &offerOut, STAmount const &offerIn)
Definition STAmount.cpp:486
TER requireAuth(ReadView const &view, Issue const &issue, AccountID const &account, AuthType authType=AuthType::Legacy)
Check if the account lacks required authorization.
Definition View.cpp:2464
void initializeFeeAuctionVote(ApplyView &view, std::shared_ptr< SLE > &ammSle, AccountID const &account, Issue const &lptIssue, std::uint16_t tfee)
Initialize Auction and Voting slots and set the trading/discounted fee.
Definition AMMUtils.cpp:340
-
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
-
static std::pair< TER, bool > applyCreate(ApplyContext &ctx_, Sandbox &sb, AccountID const &account_, beast::Journal j_)
+
static std::pair< TER, bool > applyCreate(ApplyContext &ctx_, Sandbox &sb, AccountID const &account_, beast::Journal j_)
Expected< std::shared_ptr< SLE >, TER > createPseudoAccount(ApplyView &view, uint256 const &pseudoOwnerKey, SField const &ownerField)
Create pseudo-account, storing pseudoOwnerKey into ownerField.
Definition View.cpp:1129
@ tecINSUF_RESERVE_LINE
Definition TER.h:288
@@ -527,23 +521,17 @@ $(document).ready(function() { init_codefold(0); });
@ tesSUCCESS
Definition TER.h:244
AccountID pseudoAccountAddress(ReadView const &view, uint256 const &pseudoOwnerKey)
Definition View.cpp:1066
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
Definition View.cpp:384
-
bool isTesSuccess(TER x) noexcept
Definition TER.h:674
STAmount ammLPTokens(STAmount const &asset1, STAmount const &asset2, Issue const &lptIssue)
Calculate LP Tokens given AMM pool reserves.
-
constexpr std::uint32_t tfUniversalMask
Definition TxFlags.h:63
@ terADDRESS_COLLISION
Definition TER.h:228
@ terNO_RIPPLE
Definition TER.h:224
TERSubset< CanCvtToTER > TER
Definition TER.h:645
std::uint16_t constexpr TRADING_FEE_THRESHOLD
Definition AMMCore.h:31
-
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:605
TER dirLink(ApplyView &view, AccountID const &owner, std::shared_ptr< SLE > &object)
Definition View.cpp:1055
XRPAmount xrpLiquid(ReadView const &view, AccountID const &id, std::int32_t ownerCountAdj, beast::Journal j)
Definition View.cpp:615
@ temBAD_FEE
Definition TER.h:92
@ temBAD_AMM_TOKENS
Definition TER.h:129
-
@ temINVALID_FLAG
Definition TER.h:111
-
@ temDISABLED
Definition TER.h:114
-
XRPAmount increment
uint256 key
Definition Keylet.h:40
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:80
ReadView const & view
Definition Transactor.h:83
diff --git a/AMMCreate_8h_source.html b/AMMCreate_8h_source.html index a834bdb201..f957be7fd0 100644 --- a/AMMCreate_8h_source.html +++ b/AMMCreate_8h_source.html @@ -119,38 +119,42 @@ $(document).ready(function() { init_codefold(0); });
64 }
65
-
66 static NotTEC
-
67 preflight(PreflightContext const& ctx);
+
66 static bool
+
68
-
69 static XRPAmount
-
70 calculateBaseFee(ReadView const& view, STTx const& tx);
+
69 static NotTEC
+
70 preflight(PreflightContext const& ctx);
71
-
72 static TER
-
73 preclaim(PreclaimContext const& ctx);
+
72 static XRPAmount
+
73 calculateBaseFee(ReadView const& view, STTx const& tx);
74
-
76 TER
-
77 doApply() override;
-
78};
+
75 static TER
+
76 preclaim(PreclaimContext const& ctx);
+
77
+
79 TER
+
80 doApply() override;
+
81};
-
79
-
80} // namespace ripple
-
81
-
82#endif // RIPPLE_TX_AMMCREATE_H_INCLUDED
+
82
+
83} // namespace ripple
+
84
+
85#endif // RIPPLE_TX_AMMCREATE_H_INCLUDED
AMMCreate implements Automatic Market Maker(AMM) creation Transactor.
Definition AMMCreate.h:58
-
static TER preclaim(PreclaimContext const &ctx)
Definition AMMCreate.cpp:88
-
TER doApply() override
Attempt to create the AMM instance.
-
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMCreate.cpp:35
+
static TER preclaim(PreclaimContext const &ctx)
Definition AMMCreate.cpp:82
+
static bool checkExtraFeatures(PreflightContext const &ctx)
Definition AMMCreate.cpp:35
+
TER doApply() override
Attempt to create the AMM instance.
+
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMCreate.cpp:41
static constexpr ConsequencesFactoryType ConsequencesFactory
Definition AMMCreate.h:60
AMMCreate(ApplyContext &ctx)
Definition AMMCreate.h:62
-
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Definition AMMCreate.cpp:81
+
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Definition AMMCreate.cpp:75
State information when applying a tx.
A view into a ledger.
Definition ReadView.h:51
- - - -
ApplyView & view()
Definition Transactor.h:161
+ + + +
ApplyView & view()
Definition Transactor.h:163
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:80
diff --git a/AMMDelete_8cpp_source.html b/AMMDelete_8cpp_source.html index eb3d3da019..6e9871dd40 100644 --- a/AMMDelete_8cpp_source.html +++ b/AMMDelete_8cpp_source.html @@ -110,102 +110,89 @@ $(document).ready(function() { init_codefold(0); });
27
28namespace ripple {
29
- +
30bool
- +
32{
-
33 if (!ammEnabled(ctx.rules))
-
34 return temDISABLED;
+
33 return ammEnabled(ctx.rules);
+
34}
+
35
-
36 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
-
37 return ret;
-
38
-
39 if (ctx.tx.getFlags() & tfUniversalMask)
-
40 {
-
41 JLOG(ctx.j.debug()) << "AMM Delete: invalid flags.";
-
42 return temINVALID_FLAG;
-
43 }
-
44
-
45 return preflight2(ctx);
-
46}
+ +
+ +
38{
+
39 return tesSUCCESS;
+
40}
-
47
-
48TER
-
- -
50{
-
51 auto const ammSle =
-
52 ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
-
53 if (!ammSle)
-
54 {
-
55 JLOG(ctx.j.debug()) << "AMM Delete: Invalid asset pair.";
-
56 return terNO_AMM;
-
57 }
-
58
-
59 auto const lpTokensBalance = (*ammSle)[sfLPTokenBalance];
-
60 if (lpTokensBalance != beast::zero)
-
61 return tecAMM_NOT_EMPTY;
-
62
-
63 return tesSUCCESS;
-
64}
+
41
+
42TER
+
+ +
44{
+
45 auto const ammSle =
+
46 ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
+
47 if (!ammSle)
+
48 {
+
49 JLOG(ctx.j.debug()) << "AMM Delete: Invalid asset pair.";
+
50 return terNO_AMM;
+
51 }
+
52
+
53 auto const lpTokensBalance = (*ammSle)[sfLPTokenBalance];
+
54 if (lpTokensBalance != beast::zero)
+
55 return tecAMM_NOT_EMPTY;
+
56
+
57 return tesSUCCESS;
+
58}
-
65
-
66TER
-
- -
68{
-
69 // This is the ledger view that we work against. Transactions are applied
-
70 // as we go on processing transactions.
-
71 Sandbox sb(&ctx_.view());
-
72
-
73 auto const ter = deleteAMMAccount(
-
74 sb, ctx_.tx[sfAsset].get<Issue>(), ctx_.tx[sfAsset2].get<Issue>(), j_);
-
75 if (ter == tesSUCCESS || ter == tecINCOMPLETE)
-
76 sb.apply(ctx_.rawView());
-
77
-
78 return ter;
-
79}
+
59
+
60TER
+
+ +
62{
+
63 // This is the ledger view that we work against. Transactions are applied
+
64 // as we go on processing transactions.
+
65 Sandbox sb(&ctx_.view());
+
66
+
67 auto const ter = deleteAMMAccount(
+
68 sb, ctx_.tx[sfAsset].get<Issue>(), ctx_.tx[sfAsset2].get<Issue>(), j_);
+
69 if (ter == tesSUCCESS || ter == tecINCOMPLETE)
+
70 sb.apply(ctx_.rawView());
+
71
+
72 return ter;
+
73}
-
80
-
81} // namespace ripple
+
74
+
75} // namespace ripple
Stream debug() const
Definition Journal.h:328
-
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMDelete.cpp:31
-
TER doApply() override
Definition AMMDelete.cpp:67
-
static TER preclaim(PreclaimContext const &ctx)
Definition AMMDelete.cpp:49
+
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMDelete.cpp:37
+
TER doApply() override
Definition AMMDelete.cpp:61
+
static TER preclaim(PreclaimContext const &ctx)
Definition AMMDelete.cpp:43
+
static bool checkExtraFeatures(PreflightContext const &ctx)
Definition AMMDelete.cpp:31
ApplyView & view()
A currency issued by an account.
Definition Issue.h:33
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
-
std::uint32_t getFlags() const
Definition STObject.cpp:537
Discardable, editable view to a ledger.
Definition Sandbox.h:35
void apply(RawView &to)
Definition Sandbox.h:55
- -
beast::Journal const j_
Definition Transactor.h:143
-
ApplyContext & ctx_
Definition Transactor.h:141
+ +
beast::Journal const j_
Definition Transactor.h:145
+
ApplyContext & ctx_
Definition Transactor.h:143
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Definition Indexes.cpp:446
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
TER deleteAMMAccount(Sandbox &view, Issue const &asset, Issue const &asset2, beast::Journal j)
Delete trustlines to AMM.
Definition AMMUtils.cpp:283
bool ammEnabled(Rules const &)
Return true if required AMM amendments are enabled.
Definition AMMCore.cpp:129
-
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
-
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
@ tecINCOMPLETE
Definition TER.h:335
@ tecAMM_NOT_EMPTY
Definition TER.h:333
@ tesSUCCESS
Definition TER.h:244
-
bool isTesSuccess(TER x) noexcept
Definition TER.h:674
-
constexpr std::uint32_t tfUniversalMask
Definition TxFlags.h:63
@ terNO_AMM
Definition TER.h:227
-
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:605
-
@ temINVALID_FLAG
Definition TER.h:111
-
@ temDISABLED
Definition TER.h:114
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:80
ReadView const & view
Definition Transactor.h:83
beast::Journal const j
Definition Transactor.h:88
State information when preflighting a tx.
Definition Transactor.h:35
-
beast::Journal const j
Definition Transactor.h:42
-
41
-
42 static NotTEC
-
43 preflight(PreflightContext const& ctx);
+
42 static bool
+
44
-
45 static TER
-
46 preclaim(PreclaimContext const& ctx);
+
45 static NotTEC
+
46 preflight(PreflightContext const& ctx);
47
-
48 TER
-
49 doApply() override;
-
50};
+
48 static TER
+
49 preclaim(PreclaimContext const& ctx);
+
50
+
51 TER
+
52 doApply() override;
+
53};
-
51
-
52} // namespace ripple
-
53
-
54#endif // RIPPLE_TX_AMMDELETE_H_INCLUDED
+
54
+
55} // namespace ripple
+
56
+
57#endif // RIPPLE_TX_AMMDELETE_H_INCLUDED
AMMDelete implements AMM delete transactor.
Definition AMMDelete.h:34
-
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMDelete.cpp:31
-
TER doApply() override
Definition AMMDelete.cpp:67
+
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMDelete.cpp:37
+
TER doApply() override
Definition AMMDelete.cpp:61
AMMDelete(ApplyContext &ctx)
Definition AMMDelete.h:38
static constexpr ConsequencesFactoryType ConsequencesFactory
Definition AMMDelete.h:36
-
static TER preclaim(PreclaimContext const &ctx)
Definition AMMDelete.cpp:49
+
static TER preclaim(PreclaimContext const &ctx)
Definition AMMDelete.cpp:43
+
static bool checkExtraFeatures(PreflightContext const &ctx)
Definition AMMDelete.cpp:31
State information when applying a tx.
- - - + + +
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:80
State information when preflighting a tx.
Definition Transactor.h:35
diff --git a/AMMDeposit_8cpp_source.html b/AMMDeposit_8cpp_source.html index 2ae645ff49..1ac2673a63 100644 --- a/AMMDeposit_8cpp_source.html +++ b/AMMDeposit_8cpp_source.html @@ -112,969 +112,977 @@ $(document).ready(function() { init_codefold(0); });
29
30namespace ripple {
31
- +
32bool
- +
34{
-
35 if (!ammEnabled(ctx.rules))
-
36 return temDISABLED;
+
35 return ammEnabled(ctx.rules);
+
36}
+
37
-
38 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
-
39 return ret;
+ +
+
40
-
41 auto const flags = ctx.tx.getFlags();
-
42 if (flags & tfDepositMask)
-
43 {
-
44 JLOG(ctx.j.debug()) << "AMM Deposit: invalid flags.";
-
45 return temINVALID_FLAG;
-
46 }
-
47
-
48 auto const amount = ctx.tx[~sfAmount];
-
49 auto const amount2 = ctx.tx[~sfAmount2];
-
50 auto const ePrice = ctx.tx[~sfEPrice];
-
51 auto const lpTokens = ctx.tx[~sfLPTokenOut];
-
52 auto const tradingFee = ctx.tx[~sfTradingFee];
-
53 // Valid options for the flags are:
-
54 // tfLPTokens: LPTokenOut, [Amount, Amount2]
-
55 // tfSingleAsset: Amount, [LPTokenOut]
-
56 // tfTwoAsset: Amount, Amount2, [LPTokenOut]
-
57 // tfTwoAssetIfEmpty: Amount, Amount2, [sfTradingFee]
-
58 // tfOnAssetLPToken: Amount and LPTokenOut
-
59 // tfLimitLPToken: Amount and EPrice
-
60 if (std::popcount(flags & tfDepositSubTx) != 1)
-
61 {
-
62 JLOG(ctx.j.debug()) << "AMM Deposit: invalid flags.";
-
63 return temMALFORMED;
-
64 }
-
65 if (flags & tfLPToken)
-
66 {
-
67 // if included then both amount and amount2 are deposit min
-
68 if (!lpTokens || ePrice || (amount && !amount2) ||
-
69 (!amount && amount2) || tradingFee)
-
70 return temMALFORMED;
-
71 }
-
72 else if (flags & tfSingleAsset)
-
73 {
-
74 // if included then lpTokens is deposit min
-
75 if (!amount || amount2 || ePrice || tradingFee)
-
76 return temMALFORMED;
-
77 }
-
78 else if (flags & tfTwoAsset)
-
79 {
-
80 // if included then lpTokens is deposit min
-
81 if (!amount || !amount2 || ePrice || tradingFee)
-
82 return temMALFORMED;
-
83 }
-
84 else if (flags & tfOneAssetLPToken)
-
85 {
-
86 if (!amount || !lpTokens || amount2 || ePrice || tradingFee)
-
87 return temMALFORMED;
-
88 }
-
89 else if (flags & tfLimitLPToken)
-
90 {
-
91 if (!amount || !ePrice || lpTokens || amount2 || tradingFee)
-
92 return temMALFORMED;
-
93 }
-
94 else if (flags & tfTwoAssetIfEmpty)
-
95 {
-
96 if (!amount || !amount2 || ePrice || lpTokens)
-
97 return temMALFORMED;
-
98 }
-
99
-
100 auto const asset = ctx.tx[sfAsset].get<Issue>();
-
101 auto const asset2 = ctx.tx[sfAsset2].get<Issue>();
-
102 if (auto const res = invalidAMMAssetPair(asset, asset2))
-
103 {
-
104 JLOG(ctx.j.debug()) << "AMM Deposit: invalid asset pair.";
-
105 return res;
-
106 }
-
107
-
108 if (amount && amount2 && amount->issue() == amount2->issue())
-
109 {
-
110 JLOG(ctx.j.debug()) << "AMM Deposit: invalid tokens, same issue."
-
111 << amount->issue() << " " << amount2->issue();
-
112 return temBAD_AMM_TOKENS;
-
113 }
-
114
-
115 if (lpTokens && *lpTokens <= beast::zero)
-
116 {
-
117 JLOG(ctx.j.debug()) << "AMM Deposit: invalid LPTokens";
-
118 return temBAD_AMM_TOKENS;
-
119 }
-
120
-
121 if (amount)
-
122 {
-
123 if (auto const res = invalidAMMAmount(
-
124 *amount,
-
125 std::make_optional(std::make_pair(asset, asset2)),
-
126 ePrice.has_value()))
-
127 {
-
128 JLOG(ctx.j.debug()) << "AMM Deposit: invalid amount";
-
129 return res;
-
130 }
-
131 }
-
132
-
133 if (amount2)
-
134 {
-
135 if (auto const res = invalidAMMAmount(
-
136 *amount2, std::make_optional(std::make_pair(asset, asset2))))
-
137 {
-
138 JLOG(ctx.j.debug()) << "AMM Deposit: invalid amount2";
-
139 return res;
-
140 }
-
141 }
-
142
-
143 // must be amount issue
-
144 if (amount && ePrice)
-
145 {
-
146 if (auto const res = invalidAMMAmount(
-
147 *ePrice,
- -
149 std::make_pair(amount->issue(), amount->issue()))))
-
150 {
-
151 JLOG(ctx.j.debug()) << "AMM Deposit: invalid EPrice";
-
152 return res;
-
153 }
-
154 }
-
155
-
156 if (tradingFee > TRADING_FEE_THRESHOLD)
-
157 {
-
158 JLOG(ctx.j.debug()) << "AMM Deposit: invalid trading fee.";
-
159 return temBAD_FEE;
-
160 }
-
161
-
162 return preflight2(ctx);
-
163}
+
41{
+
42 return tfDepositMask;
+
43}
-
164
-
165TER
-
- -
167{
-
168 auto const accountID = ctx.tx[sfAccount];
-
169
-
170 auto const ammSle =
-
171 ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
-
172 if (!ammSle)
-
173 {
-
174 JLOG(ctx.j.debug()) << "AMM Deposit: Invalid asset pair.";
-
175 return terNO_AMM;
-
176 }
-
177
-
178 auto const expected = ammHolds(
-
179 ctx.view,
-
180 *ammSle,
- - - -
184 ctx.j);
-
185 if (!expected)
-
186 return expected.error(); // LCOV_EXCL_LINE
-
187 auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected;
-
188 if (ctx.tx.getFlags() & tfTwoAssetIfEmpty)
-
189 {
-
190 if (lptAMMBalance != beast::zero)
-
191 return tecAMM_NOT_EMPTY;
-
192 if (amountBalance != beast::zero || amount2Balance != beast::zero)
-
193 {
-
194 // LCOV_EXCL_START
-
195 JLOG(ctx.j.debug()) << "AMM Deposit: tokens balance is not zero.";
-
196 return tecINTERNAL;
-
197 // LCOV_EXCL_STOP
-
198 }
-
199 }
-
200 else
-
201 {
-
202 if (lptAMMBalance == beast::zero)
-
203 return tecAMM_EMPTY;
-
204 if (amountBalance <= beast::zero || amount2Balance <= beast::zero ||
-
205 lptAMMBalance < beast::zero)
-
206 {
-
207 // LCOV_EXCL_START
-
208 JLOG(ctx.j.debug())
-
209 << "AMM Deposit: reserves or tokens balance is zero.";
-
210 return tecINTERNAL;
-
211 // LCOV_EXCL_STOP
-
212 }
-
213 }
-
214
-
215 // Check account has sufficient funds.
-
216 // Return tesSUCCESS if it does, error otherwise.
-
217 // Have to check again in deposit() because
-
218 // amounts might be derived based on tokens or
-
219 // limits.
-
220 auto balance = [&](auto const& deposit) -> TER {
-
221 if (isXRP(deposit))
-
222 {
-
223 auto const lpIssue = (*ammSle)[sfLPTokenBalance].issue();
-
224 // Adjust the reserve if LP doesn't have LPToken trustline
-
225 auto const sle = ctx.view.read(
-
226 keylet::line(accountID, lpIssue.account, lpIssue.currency));
-
227 if (xrpLiquid(ctx.view, accountID, !sle, ctx.j) >= deposit)
-
228 return TER(tesSUCCESS);
-
229 if (sle)
-
230 return tecUNFUNDED_AMM;
- -
232 }
-
233 return (accountID == deposit.issue().account ||
- -
235 ctx.view,
-
236 accountID,
-
237 deposit.issue(),
- -
239 ctx.j) >= deposit)
-
240 ? TER(tesSUCCESS)
- -
242 };
-
243
-
244 if (ctx.view.rules().enabled(featureAMMClawback))
-
245 {
-
246 // Check if either of the assets is frozen, AMMDeposit is not allowed
-
247 // if either asset is frozen
-
248 auto checkAsset = [&](Issue const& asset) -> TER {
-
249 if (auto const ter = requireAuth(ctx.view, asset, accountID))
-
250 {
-
251 JLOG(ctx.j.debug())
-
252 << "AMM Deposit: account is not authorized, " << asset;
-
253 return ter;
-
254 }
-
255
-
256 if (isFrozen(ctx.view, accountID, asset))
-
257 {
-
258 JLOG(ctx.j.debug())
-
259 << "AMM Deposit: account or currency is frozen, "
-
260 << to_string(accountID) << " " << to_string(asset.currency);
-
261
-
262 return tecFROZEN;
-
263 }
-
264
-
265 return tesSUCCESS;
-
266 };
-
267
-
268 if (auto const ter = checkAsset(ctx.tx[sfAsset].get<Issue>()))
-
269 return ter;
-
270
-
271 if (auto const ter = checkAsset(ctx.tx[sfAsset2].get<Issue>()))
-
272 return ter;
-
273 }
-
274
-
275 auto const amount = ctx.tx[~sfAmount];
-
276 auto const amount2 = ctx.tx[~sfAmount2];
-
277 auto const ammAccountID = ammSle->getAccountID(sfAccount);
-
278
-
279 auto checkAmount = [&](std::optional<STAmount> const& amount,
-
280 bool checkBalance) -> TER {
-
281 if (amount)
-
282 {
-
283 // This normally should not happen.
-
284 // Account is not authorized to hold the assets it's depositing,
-
285 // or it doesn't even have a trust line for them
-
286 if (auto const ter =
-
287 requireAuth(ctx.view, amount->issue(), accountID))
-
288 {
-
289 // LCOV_EXCL_START
-
290 JLOG(ctx.j.debug())
-
291 << "AMM Deposit: account is not authorized, "
-
292 << amount->issue();
-
293 return ter;
-
294 // LCOV_EXCL_STOP
-
295 }
-
296 // AMM account or currency frozen
-
297 if (isFrozen(ctx.view, ammAccountID, amount->issue()))
-
298 {
-
299 JLOG(ctx.j.debug())
-
300 << "AMM Deposit: AMM account or currency is frozen, "
-
301 << to_string(accountID);
-
302 return tecFROZEN;
-
303 }
-
304 // Account frozen
-
305 if (isIndividualFrozen(ctx.view, accountID, amount->issue()))
-
306 {
-
307 JLOG(ctx.j.debug()) << "AMM Deposit: account is frozen, "
-
308 << to_string(accountID) << " "
-
309 << to_string(amount->issue().currency);
-
310 return tecFROZEN;
-
311 }
-
312 if (checkBalance)
-
313 {
-
314 if (auto const ter = balance(*amount))
-
315 {
-
316 JLOG(ctx.j.debug())
-
317 << "AMM Deposit: account has insufficient funds, "
-
318 << *amount;
-
319 return ter;
-
320 }
-
321 }
-
322 }
-
323 return tesSUCCESS;
-
324 };
-
325
-
326 // amount and amount2 are deposit min in case of tfLPToken
-
327 if (!(ctx.tx.getFlags() & tfLPToken))
-
328 {
-
329 if (auto const ter = checkAmount(amount, true))
-
330 return ter;
-
331
-
332 if (auto const ter = checkAmount(amount2, true))
-
333 return ter;
-
334 }
-
335 else
-
336 {
-
337 if (auto const ter = checkAmount(amountBalance, false))
-
338 return ter;
-
339 if (auto const ter = checkAmount(amount2Balance, false))
+
44
+ +
+ +
47{
+
48 auto const flags = ctx.tx.getFlags();
+
49
+
50 auto const amount = ctx.tx[~sfAmount];
+
51 auto const amount2 = ctx.tx[~sfAmount2];
+
52 auto const ePrice = ctx.tx[~sfEPrice];
+
53 auto const lpTokens = ctx.tx[~sfLPTokenOut];
+
54 auto const tradingFee = ctx.tx[~sfTradingFee];
+
55 // Valid options for the flags are:
+
56 // tfLPTokens: LPTokenOut, [Amount, Amount2]
+
57 // tfSingleAsset: Amount, [LPTokenOut]
+
58 // tfTwoAsset: Amount, Amount2, [LPTokenOut]
+
59 // tfTwoAssetIfEmpty: Amount, Amount2, [sfTradingFee]
+
60 // tfOnAssetLPToken: Amount and LPTokenOut
+
61 // tfLimitLPToken: Amount and EPrice
+
62 if (std::popcount(flags & tfDepositSubTx) != 1)
+
63 {
+
64 JLOG(ctx.j.debug()) << "AMM Deposit: invalid flags.";
+
65 return temMALFORMED;
+
66 }
+
67 if (flags & tfLPToken)
+
68 {
+
69 // if included then both amount and amount2 are deposit min
+
70 if (!lpTokens || ePrice || (amount && !amount2) ||
+
71 (!amount && amount2) || tradingFee)
+
72 return temMALFORMED;
+
73 }
+
74 else if (flags & tfSingleAsset)
+
75 {
+
76 // if included then lpTokens is deposit min
+
77 if (!amount || amount2 || ePrice || tradingFee)
+
78 return temMALFORMED;
+
79 }
+
80 else if (flags & tfTwoAsset)
+
81 {
+
82 // if included then lpTokens is deposit min
+
83 if (!amount || !amount2 || ePrice || tradingFee)
+
84 return temMALFORMED;
+
85 }
+
86 else if (flags & tfOneAssetLPToken)
+
87 {
+
88 if (!amount || !lpTokens || amount2 || ePrice || tradingFee)
+
89 return temMALFORMED;
+
90 }
+
91 else if (flags & tfLimitLPToken)
+
92 {
+
93 if (!amount || !ePrice || lpTokens || amount2 || tradingFee)
+
94 return temMALFORMED;
+
95 }
+
96 else if (flags & tfTwoAssetIfEmpty)
+
97 {
+
98 if (!amount || !amount2 || ePrice || lpTokens)
+
99 return temMALFORMED;
+
100 }
+
101
+
102 auto const asset = ctx.tx[sfAsset].get<Issue>();
+
103 auto const asset2 = ctx.tx[sfAsset2].get<Issue>();
+
104 if (auto const res = invalidAMMAssetPair(asset, asset2))
+
105 {
+
106 JLOG(ctx.j.debug()) << "AMM Deposit: invalid asset pair.";
+
107 return res;
+
108 }
+
109
+
110 if (amount && amount2 && amount->issue() == amount2->issue())
+
111 {
+
112 JLOG(ctx.j.debug()) << "AMM Deposit: invalid tokens, same issue."
+
113 << amount->issue() << " " << amount2->issue();
+
114 return temBAD_AMM_TOKENS;
+
115 }
+
116
+
117 if (lpTokens && *lpTokens <= beast::zero)
+
118 {
+
119 JLOG(ctx.j.debug()) << "AMM Deposit: invalid LPTokens";
+
120 return temBAD_AMM_TOKENS;
+
121 }
+
122
+
123 if (amount)
+
124 {
+
125 if (auto const res = invalidAMMAmount(
+
126 *amount,
+
127 std::make_optional(std::make_pair(asset, asset2)),
+
128 ePrice.has_value()))
+
129 {
+
130 JLOG(ctx.j.debug()) << "AMM Deposit: invalid amount";
+
131 return res;
+
132 }
+
133 }
+
134
+
135 if (amount2)
+
136 {
+
137 if (auto const res = invalidAMMAmount(
+
138 *amount2, std::make_optional(std::make_pair(asset, asset2))))
+
139 {
+
140 JLOG(ctx.j.debug()) << "AMM Deposit: invalid amount2";
+
141 return res;
+
142 }
+
143 }
+
144
+
145 // must be amount issue
+
146 if (amount && ePrice)
+
147 {
+
148 if (auto const res = invalidAMMAmount(
+
149 *ePrice,
+ +
151 std::make_pair(amount->issue(), amount->issue()))))
+
152 {
+
153 JLOG(ctx.j.debug()) << "AMM Deposit: invalid EPrice";
+
154 return res;
+
155 }
+
156 }
+
157
+
158 if (tradingFee > TRADING_FEE_THRESHOLD)
+
159 {
+
160 JLOG(ctx.j.debug()) << "AMM Deposit: invalid trading fee.";
+
161 return temBAD_FEE;
+
162 }
+
163
+
164 return tesSUCCESS;
+
165}
+
+
166
+
167TER
+
+ +
169{
+
170 auto const accountID = ctx.tx[sfAccount];
+
171
+
172 auto const ammSle =
+
173 ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
+
174 if (!ammSle)
+
175 {
+
176 JLOG(ctx.j.debug()) << "AMM Deposit: Invalid asset pair.";
+
177 return terNO_AMM;
+
178 }
+
179
+
180 auto const expected = ammHolds(
+
181 ctx.view,
+
182 *ammSle,
+ + + +
186 ctx.j);
+
187 if (!expected)
+
188 return expected.error(); // LCOV_EXCL_LINE
+
189 auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected;
+
190 if (ctx.tx.getFlags() & tfTwoAssetIfEmpty)
+
191 {
+
192 if (lptAMMBalance != beast::zero)
+
193 return tecAMM_NOT_EMPTY;
+
194 if (amountBalance != beast::zero || amount2Balance != beast::zero)
+
195 {
+
196 // LCOV_EXCL_START
+
197 JLOG(ctx.j.debug()) << "AMM Deposit: tokens balance is not zero.";
+
198 return tecINTERNAL;
+
199 // LCOV_EXCL_STOP
+
200 }
+
201 }
+
202 else
+
203 {
+
204 if (lptAMMBalance == beast::zero)
+
205 return tecAMM_EMPTY;
+
206 if (amountBalance <= beast::zero || amount2Balance <= beast::zero ||
+
207 lptAMMBalance < beast::zero)
+
208 {
+
209 // LCOV_EXCL_START
+
210 JLOG(ctx.j.debug())
+
211 << "AMM Deposit: reserves or tokens balance is zero.";
+
212 return tecINTERNAL;
+
213 // LCOV_EXCL_STOP
+
214 }
+
215 }
+
216
+
217 // Check account has sufficient funds.
+
218 // Return tesSUCCESS if it does, error otherwise.
+
219 // Have to check again in deposit() because
+
220 // amounts might be derived based on tokens or
+
221 // limits.
+
222 auto balance = [&](auto const& deposit) -> TER {
+
223 if (isXRP(deposit))
+
224 {
+
225 auto const lpIssue = (*ammSle)[sfLPTokenBalance].issue();
+
226 // Adjust the reserve if LP doesn't have LPToken trustline
+
227 auto const sle = ctx.view.read(
+
228 keylet::line(accountID, lpIssue.account, lpIssue.currency));
+
229 if (xrpLiquid(ctx.view, accountID, !sle, ctx.j) >= deposit)
+
230 return TER(tesSUCCESS);
+
231 if (sle)
+
232 return tecUNFUNDED_AMM;
+ +
234 }
+
235 return (accountID == deposit.issue().account ||
+ +
237 ctx.view,
+
238 accountID,
+
239 deposit.issue(),
+ +
241 ctx.j) >= deposit)
+
242 ? TER(tesSUCCESS)
+ +
244 };
+
245
+
246 if (ctx.view.rules().enabled(featureAMMClawback))
+
247 {
+
248 // Check if either of the assets is frozen, AMMDeposit is not allowed
+
249 // if either asset is frozen
+
250 auto checkAsset = [&](Issue const& asset) -> TER {
+
251 if (auto const ter = requireAuth(ctx.view, asset, accountID))
+
252 {
+
253 JLOG(ctx.j.debug())
+
254 << "AMM Deposit: account is not authorized, " << asset;
+
255 return ter;
+
256 }
+
257
+
258 if (isFrozen(ctx.view, accountID, asset))
+
259 {
+
260 JLOG(ctx.j.debug())
+
261 << "AMM Deposit: account or currency is frozen, "
+
262 << to_string(accountID) << " " << to_string(asset.currency);
+
263
+
264 return tecFROZEN;
+
265 }
+
266
+
267 return tesSUCCESS;
+
268 };
+
269
+
270 if (auto const ter = checkAsset(ctx.tx[sfAsset].get<Issue>()))
+
271 return ter;
+
272
+
273 if (auto const ter = checkAsset(ctx.tx[sfAsset2].get<Issue>()))
+
274 return ter;
+
275 }
+
276
+
277 auto const amount = ctx.tx[~sfAmount];
+
278 auto const amount2 = ctx.tx[~sfAmount2];
+
279 auto const ammAccountID = ammSle->getAccountID(sfAccount);
+
280
+
281 auto checkAmount = [&](std::optional<STAmount> const& amount,
+
282 bool checkBalance) -> TER {
+
283 if (amount)
+
284 {
+
285 // This normally should not happen.
+
286 // Account is not authorized to hold the assets it's depositing,
+
287 // or it doesn't even have a trust line for them
+
288 if (auto const ter =
+
289 requireAuth(ctx.view, amount->issue(), accountID))
+
290 {
+
291 // LCOV_EXCL_START
+
292 JLOG(ctx.j.debug())
+
293 << "AMM Deposit: account is not authorized, "
+
294 << amount->issue();
+
295 return ter;
+
296 // LCOV_EXCL_STOP
+
297 }
+
298 // AMM account or currency frozen
+
299 if (isFrozen(ctx.view, ammAccountID, amount->issue()))
+
300 {
+
301 JLOG(ctx.j.debug())
+
302 << "AMM Deposit: AMM account or currency is frozen, "
+
303 << to_string(accountID);
+
304 return tecFROZEN;
+
305 }
+
306 // Account frozen
+
307 if (isIndividualFrozen(ctx.view, accountID, amount->issue()))
+
308 {
+
309 JLOG(ctx.j.debug()) << "AMM Deposit: account is frozen, "
+
310 << to_string(accountID) << " "
+
311 << to_string(amount->issue().currency);
+
312 return tecFROZEN;
+
313 }
+
314 if (checkBalance)
+
315 {
+
316 if (auto const ter = balance(*amount))
+
317 {
+
318 JLOG(ctx.j.debug())
+
319 << "AMM Deposit: account has insufficient funds, "
+
320 << *amount;
+
321 return ter;
+
322 }
+
323 }
+
324 }
+
325 return tesSUCCESS;
+
326 };
+
327
+
328 // amount and amount2 are deposit min in case of tfLPToken
+
329 if (!(ctx.tx.getFlags() & tfLPToken))
+
330 {
+
331 if (auto const ter = checkAmount(amount, true))
+
332 return ter;
+
333
+
334 if (auto const ter = checkAmount(amount2, true))
+
335 return ter;
+
336 }
+
337 else
+
338 {
+
339 if (auto const ter = checkAmount(amountBalance, false))
340 return ter;
-
341 }
-
342
-
343 // Equal deposit lp tokens
-
344 if (auto const lpTokens = ctx.tx[~sfLPTokenOut];
-
345 lpTokens && lpTokens->issue() != lptAMMBalance.issue())
-
346 {
-
347 JLOG(ctx.j.debug()) << "AMM Deposit: invalid LPTokens.";
-
348 return temBAD_AMM_TOKENS;
-
349 }
-
350
-
351 // Check the reserve for LPToken trustline if not LP.
-
352 // We checked above but need to check again if depositing IOU only.
-
353 if (ammLPHolds(ctx.view, *ammSle, accountID, ctx.j) == beast::zero)
-
354 {
-
355 STAmount const xrpBalance = xrpLiquid(ctx.view, accountID, 1, ctx.j);
-
356 // Insufficient reserve
-
357 if (xrpBalance <= beast::zero)
-
358 {
-
359 JLOG(ctx.j.debug()) << "AMM Instance: insufficient reserves";
- -
361 }
-
362 }
-
363
-
364 return tesSUCCESS;
-
365}
+
341 if (auto const ter = checkAmount(amount2Balance, false))
+
342 return ter;
+
343 }
+
344
+
345 // Equal deposit lp tokens
+
346 if (auto const lpTokens = ctx.tx[~sfLPTokenOut];
+
347 lpTokens && lpTokens->issue() != lptAMMBalance.issue())
+
348 {
+
349 JLOG(ctx.j.debug()) << "AMM Deposit: invalid LPTokens.";
+
350 return temBAD_AMM_TOKENS;
+
351 }
+
352
+
353 // Check the reserve for LPToken trustline if not LP.
+
354 // We checked above but need to check again if depositing IOU only.
+
355 if (ammLPHolds(ctx.view, *ammSle, accountID, ctx.j) == beast::zero)
+
356 {
+
357 STAmount const xrpBalance = xrpLiquid(ctx.view, accountID, 1, ctx.j);
+
358 // Insufficient reserve
+
359 if (xrpBalance <= beast::zero)
+
360 {
+
361 JLOG(ctx.j.debug()) << "AMM Instance: insufficient reserves";
+ +
363 }
+
364 }
+
365
+
366 return tesSUCCESS;
+
367}
-
366
- -
- -
369{
-
370 auto const amount = ctx_.tx[~sfAmount];
-
371 auto const amount2 = ctx_.tx[~sfAmount2];
-
372 auto const ePrice = ctx_.tx[~sfEPrice];
-
373 auto const lpTokensDeposit = ctx_.tx[~sfLPTokenOut];
-
374 auto ammSle = sb.peek(keylet::amm(ctx_.tx[sfAsset], ctx_.tx[sfAsset2]));
-
375 if (!ammSle)
-
376 return {tecINTERNAL, false}; // LCOV_EXCL_LINE
-
377 auto const ammAccountID = (*ammSle)[sfAccount];
-
378
-
379 auto const expected = ammHolds(
-
380 sb,
-
381 *ammSle,
-
382 amount ? amount->issue() : std::optional<Issue>{},
-
383 amount2 ? amount2->issue() : std::optional<Issue>{},
- -
385 ctx_.journal);
-
386 if (!expected)
-
387 return {expected.error(), false}; // LCOV_EXCL_LINE
-
388 auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected;
-
389 auto const tfee = (lptAMMBalance == beast::zero)
-
390 ? ctx_.tx[~sfTradingFee].value_or(0)
-
391 : getTradingFee(ctx_.view(), *ammSle, account_);
-
392
-
393 auto const subTxType = ctx_.tx.getFlags() & tfDepositSubTx;
+
368
+ +
+ +
371{
+
372 auto const amount = ctx_.tx[~sfAmount];
+
373 auto const amount2 = ctx_.tx[~sfAmount2];
+
374 auto const ePrice = ctx_.tx[~sfEPrice];
+
375 auto const lpTokensDeposit = ctx_.tx[~sfLPTokenOut];
+
376 auto ammSle = sb.peek(keylet::amm(ctx_.tx[sfAsset], ctx_.tx[sfAsset2]));
+
377 if (!ammSle)
+
378 return {tecINTERNAL, false}; // LCOV_EXCL_LINE
+
379 auto const ammAccountID = (*ammSle)[sfAccount];
+
380
+
381 auto const expected = ammHolds(
+
382 sb,
+
383 *ammSle,
+
384 amount ? amount->issue() : std::optional<Issue>{},
+
385 amount2 ? amount2->issue() : std::optional<Issue>{},
+ +
387 ctx_.journal);
+
388 if (!expected)
+
389 return {expected.error(), false}; // LCOV_EXCL_LINE
+
390 auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected;
+
391 auto const tfee = (lptAMMBalance == beast::zero)
+
392 ? ctx_.tx[~sfTradingFee].value_or(0)
+
393 : getTradingFee(ctx_.view(), *ammSle, account_);
394
-
395 auto const [result, newLPTokenBalance] =
-
396 [&,
-
397 &amountBalance = amountBalance,
-
398 &amount2Balance = amount2Balance,
-
399 &lptAMMBalance = lptAMMBalance]() -> std::pair<TER, STAmount> {
-
400 if (subTxType & tfTwoAsset)
-
401 return equalDepositLimit(
-
402 sb,
-
403 ammAccountID,
-
404 amountBalance,
-
405 amount2Balance,
-
406 lptAMMBalance,
-
407 *amount,
-
408 *amount2,
-
409 lpTokensDeposit,
-
410 tfee);
-
411 if (subTxType & tfOneAssetLPToken)
-
412 return singleDepositTokens(
-
413 sb,
-
414 ammAccountID,
-
415 amountBalance,
-
416 *amount,
-
417 lptAMMBalance,
-
418 *lpTokensDeposit,
-
419 tfee);
-
420 if (subTxType & tfLimitLPToken)
-
421 return singleDepositEPrice(
-
422 sb,
-
423 ammAccountID,
-
424 amountBalance,
-
425 *amount,
-
426 lptAMMBalance,
-
427 *ePrice,
-
428 tfee);
-
429 if (subTxType & tfSingleAsset)
-
430 return singleDeposit(
-
431 sb,
-
432 ammAccountID,
-
433 amountBalance,
-
434 lptAMMBalance,
-
435 *amount,
-
436 lpTokensDeposit,
-
437 tfee);
-
438 if (subTxType & tfLPToken)
-
439 return equalDepositTokens(
-
440 sb,
-
441 ammAccountID,
-
442 amountBalance,
-
443 amount2Balance,
-
444 lptAMMBalance,
-
445 *lpTokensDeposit,
-
446 amount,
-
447 amount2,
-
448 tfee);
-
449 if (subTxType & tfTwoAssetIfEmpty)
- -
451 sb,
-
452 ammAccountID,
-
453 *amount,
-
454 *amount2,
-
455 lptAMMBalance.issue(),
-
456 tfee);
-
457 // should not happen.
-
458 // LCOV_EXCL_START
-
459 JLOG(j_.error()) << "AMM Deposit: invalid options.";
- -
461 // LCOV_EXCL_STOP
-
462 }();
-
463
-
464 if (result == tesSUCCESS)
-
465 {
-
466 XRPL_ASSERT(
-
467 newLPTokenBalance > beast::zero,
-
468 "ripple::AMMDeposit::applyGuts : valid new LP token balance");
-
469 ammSle->setFieldAmount(sfLPTokenBalance, newLPTokenBalance);
-
470 // LP depositing into AMM empty state gets the auction slot
-
471 // and the voting
-
472 if (lptAMMBalance == beast::zero)
- -
474 sb, ammSle, account_, lptAMMBalance.issue(), tfee);
-
475
-
476 sb.update(ammSle);
-
477 }
-
478
-
479 return {result, result == tesSUCCESS};
-
480}
+
395 auto const subTxType = ctx_.tx.getFlags() & tfDepositSubTx;
+
396
+
397 auto const [result, newLPTokenBalance] =
+
398 [&,
+
399 &amountBalance = amountBalance,
+
400 &amount2Balance = amount2Balance,
+
401 &lptAMMBalance = lptAMMBalance]() -> std::pair<TER, STAmount> {
+
402 if (subTxType & tfTwoAsset)
+
403 return equalDepositLimit(
+
404 sb,
+
405 ammAccountID,
+
406 amountBalance,
+
407 amount2Balance,
+
408 lptAMMBalance,
+
409 *amount,
+
410 *amount2,
+
411 lpTokensDeposit,
+
412 tfee);
+
413 if (subTxType & tfOneAssetLPToken)
+
414 return singleDepositTokens(
+
415 sb,
+
416 ammAccountID,
+
417 amountBalance,
+
418 *amount,
+
419 lptAMMBalance,
+
420 *lpTokensDeposit,
+
421 tfee);
+
422 if (subTxType & tfLimitLPToken)
+
423 return singleDepositEPrice(
+
424 sb,
+
425 ammAccountID,
+
426 amountBalance,
+
427 *amount,
+
428 lptAMMBalance,
+
429 *ePrice,
+
430 tfee);
+
431 if (subTxType & tfSingleAsset)
+
432 return singleDeposit(
+
433 sb,
+
434 ammAccountID,
+
435 amountBalance,
+
436 lptAMMBalance,
+
437 *amount,
+
438 lpTokensDeposit,
+
439 tfee);
+
440 if (subTxType & tfLPToken)
+
441 return equalDepositTokens(
+
442 sb,
+
443 ammAccountID,
+
444 amountBalance,
+
445 amount2Balance,
+
446 lptAMMBalance,
+
447 *lpTokensDeposit,
+
448 amount,
+
449 amount2,
+
450 tfee);
+
451 if (subTxType & tfTwoAssetIfEmpty)
+ +
453 sb,
+
454 ammAccountID,
+
455 *amount,
+
456 *amount2,
+
457 lptAMMBalance.issue(),
+
458 tfee);
+
459 // should not happen.
+
460 // LCOV_EXCL_START
+
461 JLOG(j_.error()) << "AMM Deposit: invalid options.";
+ +
463 // LCOV_EXCL_STOP
+
464 }();
+
465
+
466 if (result == tesSUCCESS)
+
467 {
+
468 XRPL_ASSERT(
+
469 newLPTokenBalance > beast::zero,
+
470 "ripple::AMMDeposit::applyGuts : valid new LP token balance");
+
471 ammSle->setFieldAmount(sfLPTokenBalance, newLPTokenBalance);
+
472 // LP depositing into AMM empty state gets the auction slot
+
473 // and the voting
+
474 if (lptAMMBalance == beast::zero)
+ +
476 sb, ammSle, account_, lptAMMBalance.issue(), tfee);
+
477
+
478 sb.update(ammSle);
+
479 }
+
480
+
481 return {result, result == tesSUCCESS};
+
482}
-
481
-
482TER
-
- -
484{
-
485 // This is the ledger view that we work against. Transactions are applied
-
486 // as we go on processing transactions.
-
487 Sandbox sb(&ctx_.view());
-
488
-
489 auto const result = applyGuts(sb);
-
490 if (result.second)
-
491 sb.apply(ctx_.rawView());
-
492
-
493 return result.first;
-
494}
+
483
+
484TER
+
+ +
486{
+
487 // This is the ledger view that we work against. Transactions are applied
+
488 // as we go on processing transactions.
+
489 Sandbox sb(&ctx_.view());
+
490
+
491 auto const result = applyGuts(sb);
+
492 if (result.second)
+
493 sb.apply(ctx_.rawView());
+
494
+
495 return result.first;
+
496}
-
495
- -
- -
498 Sandbox& view,
-
499 AccountID const& ammAccount,
-
500 STAmount const& amountBalance,
-
501 STAmount const& amountDeposit,
-
502 std::optional<STAmount> const& amount2Deposit,
-
503 STAmount const& lptAMMBalance,
-
504 STAmount const& lpTokensDeposit,
-
505 std::optional<STAmount> const& depositMin,
-
506 std::optional<STAmount> const& deposit2Min,
-
507 std::optional<STAmount> const& lpTokensDepositMin,
-
508 std::uint16_t tfee)
-
509{
-
510 // Check account has sufficient funds.
-
511 // Return true if it does, false otherwise.
-
512 auto checkBalance = [&](auto const& depositAmount) -> TER {
-
513 if (depositAmount <= beast::zero)
-
514 return temBAD_AMOUNT;
-
515 if (isXRP(depositAmount))
-
516 {
-
517 auto const& lpIssue = lpTokensDeposit.issue();
-
518 // Adjust the reserve if LP doesn't have LPToken trustline
-
519 auto const sle = view.read(
-
520 keylet::line(account_, lpIssue.account, lpIssue.currency));
-
521 if (xrpLiquid(view, account_, !sle, j_) >= depositAmount)
-
522 return tesSUCCESS;
-
523 }
-
524 else if (
-
525 account_ == depositAmount.issue().account ||
- -
527 view,
-
528 account_,
-
529 depositAmount.issue(),
- -
531 ctx_.journal) >= depositAmount)
-
532 return tesSUCCESS;
-
533 return tecUNFUNDED_AMM;
-
534 };
-
535
-
536 auto const
-
537 [amountDepositActual, amount2DepositActual, lpTokensDepositActual] =
- -
539 amountBalance,
-
540 amountDeposit,
-
541 amount2Deposit,
-
542 lptAMMBalance,
-
543 lpTokensDeposit,
-
544 tfee,
- -
546
-
547 if (lpTokensDepositActual <= beast::zero)
-
548 {
-
549 JLOG(ctx_.journal.debug()) << "AMM Deposit: adjusted tokens zero";
- -
551 }
-
552
-
553 if (amountDepositActual < depositMin ||
-
554 amount2DepositActual < deposit2Min ||
-
555 lpTokensDepositActual < lpTokensDepositMin)
-
556 {
-
557 JLOG(ctx_.journal.debug())
-
558 << "AMM Deposit: min deposit fails " << amountDepositActual << " "
-
559 << depositMin.value_or(STAmount{}) << " "
-
560 << amount2DepositActual.value_or(STAmount{}) << " "
-
561 << deposit2Min.value_or(STAmount{}) << " " << lpTokensDepositActual
-
562 << " " << lpTokensDepositMin.value_or(STAmount{});
-
563 return {tecAMM_FAILED, STAmount{}};
-
564 }
-
565
-
566 // Deposit amountDeposit
-
567 if (auto const ter = checkBalance(amountDepositActual))
-
568 {
-
569 JLOG(ctx_.journal.debug()) << "AMM Deposit: account has insufficient "
-
570 "checkBalance to deposit or is 0"
-
571 << amountDepositActual;
-
572 return {ter, STAmount{}};
-
573 }
-
574
-
575 auto res = accountSend(
-
576 view,
-
577 account_,
-
578 ammAccount,
-
579 amountDepositActual,
- - -
582 if (res != tesSUCCESS)
-
583 {
-
584 JLOG(ctx_.journal.debug())
-
585 << "AMM Deposit: failed to deposit " << amountDepositActual;
-
586 return {res, STAmount{}};
-
587 }
-
588
-
589 // Deposit amount2Deposit
-
590 if (amount2DepositActual)
-
591 {
-
592 if (auto const ter = checkBalance(*amount2DepositActual))
-
593 {
-
594 JLOG(ctx_.journal.debug())
-
595 << "AMM Deposit: account has insufficient checkBalance to "
-
596 "deposit or is 0 "
-
597 << *amount2DepositActual;
-
598 return {ter, STAmount{}};
-
599 }
-
600
-
601 res = accountSend(
-
602 view,
-
603 account_,
-
604 ammAccount,
-
605 *amount2DepositActual,
- - -
608 if (res != tesSUCCESS)
-
609 {
-
610 JLOG(ctx_.journal.debug())
-
611 << "AMM Deposit: failed to deposit " << *amount2DepositActual;
-
612 return {res, STAmount{}};
-
613 }
-
614 }
-
615
-
616 // Deposit LP tokens
-
617 res = accountSend(
-
618 view, ammAccount, account_, lpTokensDepositActual, ctx_.journal);
-
619 if (res != tesSUCCESS)
-
620 {
-
621 JLOG(ctx_.journal.debug()) << "AMM Deposit: failed to deposit LPTokens";
-
622 return {res, STAmount{}};
-
623 }
-
624
-
625 return {tesSUCCESS, lptAMMBalance + lpTokensDepositActual};
-
626}
+
497
+ +
+ +
500 Sandbox& view,
+
501 AccountID const& ammAccount,
+
502 STAmount const& amountBalance,
+
503 STAmount const& amountDeposit,
+
504 std::optional<STAmount> const& amount2Deposit,
+
505 STAmount const& lptAMMBalance,
+
506 STAmount const& lpTokensDeposit,
+
507 std::optional<STAmount> const& depositMin,
+
508 std::optional<STAmount> const& deposit2Min,
+
509 std::optional<STAmount> const& lpTokensDepositMin,
+
510 std::uint16_t tfee)
+
511{
+
512 // Check account has sufficient funds.
+
513 // Return true if it does, false otherwise.
+
514 auto checkBalance = [&](auto const& depositAmount) -> TER {
+
515 if (depositAmount <= beast::zero)
+
516 return temBAD_AMOUNT;
+
517 if (isXRP(depositAmount))
+
518 {
+
519 auto const& lpIssue = lpTokensDeposit.issue();
+
520 // Adjust the reserve if LP doesn't have LPToken trustline
+
521 auto const sle = view.read(
+
522 keylet::line(account_, lpIssue.account, lpIssue.currency));
+
523 if (xrpLiquid(view, account_, !sle, j_) >= depositAmount)
+
524 return tesSUCCESS;
+
525 }
+
526 else if (
+
527 account_ == depositAmount.issue().account ||
+ +
529 view,
+
530 account_,
+
531 depositAmount.issue(),
+ +
533 ctx_.journal) >= depositAmount)
+
534 return tesSUCCESS;
+
535 return tecUNFUNDED_AMM;
+
536 };
+
537
+
538 auto const
+
539 [amountDepositActual, amount2DepositActual, lpTokensDepositActual] =
+ +
541 amountBalance,
+
542 amountDeposit,
+
543 amount2Deposit,
+
544 lptAMMBalance,
+
545 lpTokensDeposit,
+
546 tfee,
+ +
548
+
549 if (lpTokensDepositActual <= beast::zero)
+
550 {
+
551 JLOG(ctx_.journal.debug()) << "AMM Deposit: adjusted tokens zero";
+ +
553 }
+
554
+
555 if (amountDepositActual < depositMin ||
+
556 amount2DepositActual < deposit2Min ||
+
557 lpTokensDepositActual < lpTokensDepositMin)
+
558 {
+
559 JLOG(ctx_.journal.debug())
+
560 << "AMM Deposit: min deposit fails " << amountDepositActual << " "
+
561 << depositMin.value_or(STAmount{}) << " "
+
562 << amount2DepositActual.value_or(STAmount{}) << " "
+
563 << deposit2Min.value_or(STAmount{}) << " " << lpTokensDepositActual
+
564 << " " << lpTokensDepositMin.value_or(STAmount{});
+
565 return {tecAMM_FAILED, STAmount{}};
+
566 }
+
567
+
568 // Deposit amountDeposit
+
569 if (auto const ter = checkBalance(amountDepositActual))
+
570 {
+
571 JLOG(ctx_.journal.debug()) << "AMM Deposit: account has insufficient "
+
572 "checkBalance to deposit or is 0"
+
573 << amountDepositActual;
+
574 return {ter, STAmount{}};
+
575 }
+
576
+
577 auto res = accountSend(
+
578 view,
+
579 account_,
+
580 ammAccount,
+
581 amountDepositActual,
+ + +
584 if (res != tesSUCCESS)
+
585 {
+
586 JLOG(ctx_.journal.debug())
+
587 << "AMM Deposit: failed to deposit " << amountDepositActual;
+
588 return {res, STAmount{}};
+
589 }
+
590
+
591 // Deposit amount2Deposit
+
592 if (amount2DepositActual)
+
593 {
+
594 if (auto const ter = checkBalance(*amount2DepositActual))
+
595 {
+
596 JLOG(ctx_.journal.debug())
+
597 << "AMM Deposit: account has insufficient checkBalance to "
+
598 "deposit or is 0 "
+
599 << *amount2DepositActual;
+
600 return {ter, STAmount{}};
+
601 }
+
602
+
603 res = accountSend(
+
604 view,
+
605 account_,
+
606 ammAccount,
+
607 *amount2DepositActual,
+ + +
610 if (res != tesSUCCESS)
+
611 {
+
612 JLOG(ctx_.journal.debug())
+
613 << "AMM Deposit: failed to deposit " << *amount2DepositActual;
+
614 return {res, STAmount{}};
+
615 }
+
616 }
+
617
+
618 // Deposit LP tokens
+
619 res = accountSend(
+
620 view, ammAccount, account_, lpTokensDepositActual, ctx_.journal);
+
621 if (res != tesSUCCESS)
+
622 {
+
623 JLOG(ctx_.journal.debug()) << "AMM Deposit: failed to deposit LPTokens";
+
624 return {res, STAmount{}};
+
625 }
+
626
+
627 return {tesSUCCESS, lptAMMBalance + lpTokensDepositActual};
+
628}
-
627
-
628static STAmount
-
- -
630 Rules const& rules,
-
631 STAmount const& lptAMMBalance,
-
632 STAmount const& lpTokensDeposit)
-
633{
-
634 if (!rules.enabled(fixAMMv1_3))
-
635 return lpTokensDeposit;
-
636 return adjustLPTokens(lptAMMBalance, lpTokensDeposit, IsDeposit::Yes);
-
637}
+
629
+
630static STAmount
+
+ +
632 Rules const& rules,
+
633 STAmount const& lptAMMBalance,
+
634 STAmount const& lpTokensDeposit)
+
635{
+
636 if (!rules.enabled(fixAMMv1_3))
+
637 return lpTokensDeposit;
+
638 return adjustLPTokens(lptAMMBalance, lpTokensDeposit, IsDeposit::Yes);
+
639}
-
638
- -
- -
644 Sandbox& view,
-
645 AccountID const& ammAccount,
-
646 STAmount const& amountBalance,
-
647 STAmount const& amount2Balance,
-
648 STAmount const& lptAMMBalance,
-
649 STAmount const& lpTokensDeposit,
-
650 std::optional<STAmount> const& depositMin,
-
651 std::optional<STAmount> const& deposit2Min,
-
652 std::uint16_t tfee)
-
653{
-
654 try
-
655 {
-
656 auto const tokensAdj =
-
657 adjustLPTokensOut(view.rules(), lptAMMBalance, lpTokensDeposit);
-
658 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
- -
660 auto const frac =
-
661 divide(tokensAdj, lptAMMBalance, lptAMMBalance.issue());
-
662 // amounts factor in the adjusted tokens
-
663 auto const amountDeposit =
-
664 getRoundedAsset(view.rules(), amountBalance, frac, IsDeposit::Yes);
-
665 auto const amount2Deposit =
-
666 getRoundedAsset(view.rules(), amount2Balance, frac, IsDeposit::Yes);
-
667 return deposit(
-
668 view,
-
669 ammAccount,
-
670 amountBalance,
-
671 amountDeposit,
-
672 amount2Deposit,
-
673 lptAMMBalance,
-
674 tokensAdj,
-
675 depositMin,
-
676 deposit2Min,
- -
678 tfee);
-
679 }
-
680 catch (std::exception const& e)
-
681 {
-
682 // LCOV_EXCL_START
-
683 JLOG(j_.error()) << "AMMDeposit::equalDepositTokens exception "
-
684 << e.what();
-
685 return {tecINTERNAL, STAmount{}};
-
686 // LCOV_EXCL_STOP
-
687 }
-
688}
+
640
+ +
+ +
646 Sandbox& view,
+
647 AccountID const& ammAccount,
+
648 STAmount const& amountBalance,
+
649 STAmount const& amount2Balance,
+
650 STAmount const& lptAMMBalance,
+
651 STAmount const& lpTokensDeposit,
+
652 std::optional<STAmount> const& depositMin,
+
653 std::optional<STAmount> const& deposit2Min,
+
654 std::uint16_t tfee)
+
655{
+
656 try
+
657 {
+
658 auto const tokensAdj =
+
659 adjustLPTokensOut(view.rules(), lptAMMBalance, lpTokensDeposit);
+
660 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
+ +
662 auto const frac =
+
663 divide(tokensAdj, lptAMMBalance, lptAMMBalance.issue());
+
664 // amounts factor in the adjusted tokens
+
665 auto const amountDeposit =
+
666 getRoundedAsset(view.rules(), amountBalance, frac, IsDeposit::Yes);
+
667 auto const amount2Deposit =
+
668 getRoundedAsset(view.rules(), amount2Balance, frac, IsDeposit::Yes);
+
669 return deposit(
+
670 view,
+
671 ammAccount,
+
672 amountBalance,
+
673 amountDeposit,
+
674 amount2Deposit,
+
675 lptAMMBalance,
+
676 tokensAdj,
+
677 depositMin,
+
678 deposit2Min,
+ +
680 tfee);
+
681 }
+
682 catch (std::exception const& e)
+
683 {
+
684 // LCOV_EXCL_START
+
685 JLOG(j_.error()) << "AMMDeposit::equalDepositTokens exception "
+
686 << e.what();
+
687 return {tecINTERNAL, STAmount{}};
+
688 // LCOV_EXCL_STOP
+
689 }
+
690}
-
689
- -
- -
720 Sandbox& view,
-
721 AccountID const& ammAccount,
-
722 STAmount const& amountBalance,
-
723 STAmount const& amount2Balance,
-
724 STAmount const& lptAMMBalance,
-
725 STAmount const& amount,
-
726 STAmount const& amount2,
-
727 std::optional<STAmount> const& lpTokensDepositMin,
-
728 std::uint16_t tfee)
-
729{
-
730 auto frac = Number{amount} / amountBalance;
-
731 auto tokensAdj =
-
732 getRoundedLPTokens(view.rules(), lptAMMBalance, frac, IsDeposit::Yes);
-
733 if (tokensAdj == beast::zero)
-
734 {
-
735 if (!view.rules().enabled(fixAMMv1_3))
-
736 return {tecAMM_FAILED, STAmount{}}; // LCOV_EXCL_LINE
-
737 else
- -
739 }
-
740 // factor in the adjusted tokens
-
741 frac = adjustFracByTokens(view.rules(), lptAMMBalance, tokensAdj, frac);
-
742 auto const amount2Deposit =
-
743 getRoundedAsset(view.rules(), amount2Balance, frac, IsDeposit::Yes);
-
744 if (amount2Deposit <= amount2)
-
745 return deposit(
-
746 view,
-
747 ammAccount,
-
748 amountBalance,
-
749 amount,
-
750 amount2Deposit,
-
751 lptAMMBalance,
-
752 tokensAdj,
- - -
755 lpTokensDepositMin,
-
756 tfee);
-
757 frac = Number{amount2} / amount2Balance;
-
758 tokensAdj =
-
759 getRoundedLPTokens(view.rules(), lptAMMBalance, frac, IsDeposit::Yes);
-
760 if (tokensAdj == beast::zero)
-
761 {
-
762 if (!view.rules().enabled(fixAMMv1_3))
-
763 return {tecAMM_FAILED, STAmount{}}; // LCOV_EXCL_LINE
-
764 else
-
765 return {tecAMM_INVALID_TOKENS, STAmount{}}; // LCOV_EXCL_LINE
-
766 }
-
767 // factor in the adjusted tokens
-
768 frac = adjustFracByTokens(view.rules(), lptAMMBalance, tokensAdj, frac);
-
769 auto const amountDeposit =
-
770 getRoundedAsset(view.rules(), amountBalance, frac, IsDeposit::Yes);
-
771 if (amountDeposit <= amount)
-
772 return deposit(
-
773 view,
-
774 ammAccount,
-
775 amountBalance,
-
776 amountDeposit,
-
777 amount2,
-
778 lptAMMBalance,
-
779 tokensAdj,
- - -
782 lpTokensDepositMin,
-
783 tfee);
-
784 return {tecAMM_FAILED, STAmount{}};
-
785}
+
691
+ +
+ +
722 Sandbox& view,
+
723 AccountID const& ammAccount,
+
724 STAmount const& amountBalance,
+
725 STAmount const& amount2Balance,
+
726 STAmount const& lptAMMBalance,
+
727 STAmount const& amount,
+
728 STAmount const& amount2,
+
729 std::optional<STAmount> const& lpTokensDepositMin,
+
730 std::uint16_t tfee)
+
731{
+
732 auto frac = Number{amount} / amountBalance;
+
733 auto tokensAdj =
+
734 getRoundedLPTokens(view.rules(), lptAMMBalance, frac, IsDeposit::Yes);
+
735 if (tokensAdj == beast::zero)
+
736 {
+
737 if (!view.rules().enabled(fixAMMv1_3))
+
738 return {tecAMM_FAILED, STAmount{}}; // LCOV_EXCL_LINE
+
739 else
+ +
741 }
+
742 // factor in the adjusted tokens
+
743 frac = adjustFracByTokens(view.rules(), lptAMMBalance, tokensAdj, frac);
+
744 auto const amount2Deposit =
+
745 getRoundedAsset(view.rules(), amount2Balance, frac, IsDeposit::Yes);
+
746 if (amount2Deposit <= amount2)
+
747 return deposit(
+
748 view,
+
749 ammAccount,
+
750 amountBalance,
+
751 amount,
+
752 amount2Deposit,
+
753 lptAMMBalance,
+
754 tokensAdj,
+ + +
757 lpTokensDepositMin,
+
758 tfee);
+
759 frac = Number{amount2} / amount2Balance;
+
760 tokensAdj =
+
761 getRoundedLPTokens(view.rules(), lptAMMBalance, frac, IsDeposit::Yes);
+
762 if (tokensAdj == beast::zero)
+
763 {
+
764 if (!view.rules().enabled(fixAMMv1_3))
+
765 return {tecAMM_FAILED, STAmount{}}; // LCOV_EXCL_LINE
+
766 else
+
767 return {tecAMM_INVALID_TOKENS, STAmount{}}; // LCOV_EXCL_LINE
+
768 }
+
769 // factor in the adjusted tokens
+
770 frac = adjustFracByTokens(view.rules(), lptAMMBalance, tokensAdj, frac);
+
771 auto const amountDeposit =
+
772 getRoundedAsset(view.rules(), amountBalance, frac, IsDeposit::Yes);
+
773 if (amountDeposit <= amount)
+
774 return deposit(
+
775 view,
+
776 ammAccount,
+
777 amountBalance,
+
778 amountDeposit,
+
779 amount2,
+
780 lptAMMBalance,
+
781 tokensAdj,
+ + +
784 lpTokensDepositMin,
+
785 tfee);
+
786 return {tecAMM_FAILED, STAmount{}};
+
787}
-
786
- -
- -
797 Sandbox& view,
-
798 AccountID const& ammAccount,
-
799 STAmount const& amountBalance,
-
800 STAmount const& lptAMMBalance,
-
801 STAmount const& amount,
-
802 std::optional<STAmount> const& lpTokensDepositMin,
-
803 std::uint16_t tfee)
-
804{
-
805 auto const tokens = adjustLPTokensOut(
-
806 view.rules(),
-
807 lptAMMBalance,
-
808 lpTokensOut(amountBalance, amount, lptAMMBalance, tfee));
-
809 if (tokens == beast::zero)
-
810 {
-
811 if (!view.rules().enabled(fixAMMv1_3))
-
812 return {tecAMM_FAILED, STAmount{}}; // LCOV_EXCL_LINE
-
813 else
- -
815 }
-
816 // factor in the adjusted tokens
-
817 auto const [tokensAdj, amountDepositAdj] = adjustAssetInByTokens(
-
818 view.rules(), amountBalance, amount, lptAMMBalance, tokens, tfee);
-
819 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
-
820 return {tecAMM_INVALID_TOKENS, STAmount{}}; // LCOV_EXCL_LINE
-
821 return deposit(
-
822 view,
-
823 ammAccount,
-
824 amountBalance,
-
825 amountDepositAdj,
- -
827 lptAMMBalance,
-
828 tokensAdj,
- - -
831 lpTokensDepositMin,
-
832 tfee);
-
833}
+
788
+ +
+ +
799 Sandbox& view,
+
800 AccountID const& ammAccount,
+
801 STAmount const& amountBalance,
+
802 STAmount const& lptAMMBalance,
+
803 STAmount const& amount,
+
804 std::optional<STAmount> const& lpTokensDepositMin,
+
805 std::uint16_t tfee)
+
806{
+
807 auto const tokens = adjustLPTokensOut(
+
808 view.rules(),
+
809 lptAMMBalance,
+
810 lpTokensOut(amountBalance, amount, lptAMMBalance, tfee));
+
811 if (tokens == beast::zero)
+
812 {
+
813 if (!view.rules().enabled(fixAMMv1_3))
+
814 return {tecAMM_FAILED, STAmount{}}; // LCOV_EXCL_LINE
+
815 else
+ +
817 }
+
818 // factor in the adjusted tokens
+
819 auto const [tokensAdj, amountDepositAdj] = adjustAssetInByTokens(
+
820 view.rules(), amountBalance, amount, lptAMMBalance, tokens, tfee);
+
821 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
+
822 return {tecAMM_INVALID_TOKENS, STAmount{}}; // LCOV_EXCL_LINE
+
823 return deposit(
+
824 view,
+
825 ammAccount,
+
826 amountBalance,
+
827 amountDepositAdj,
+ +
829 lptAMMBalance,
+
830 tokensAdj,
+ + +
833 lpTokensDepositMin,
+
834 tfee);
+
835}
-
834
- -
- -
844 Sandbox& view,
-
845 AccountID const& ammAccount,
-
846 STAmount const& amountBalance,
-
847 STAmount const& amount,
-
848 STAmount const& lptAMMBalance,
-
849 STAmount const& lpTokensDeposit,
-
850 std::uint16_t tfee)
-
851{
-
852 auto const tokensAdj =
-
853 adjustLPTokensOut(view.rules(), lptAMMBalance, lpTokensDeposit);
-
854 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
- -
856 // the adjusted tokens are factored in
-
857 auto const amountDeposit =
-
858 ammAssetIn(amountBalance, lptAMMBalance, tokensAdj, tfee);
-
859 if (amountDeposit > amount)
-
860 return {tecAMM_FAILED, STAmount{}};
-
861 return deposit(
-
862 view,
-
863 ammAccount,
-
864 amountBalance,
-
865 amountDeposit,
- -
867 lptAMMBalance,
-
868 tokensAdj,
- - +
836
+ +
+ +
846 Sandbox& view,
+
847 AccountID const& ammAccount,
+
848 STAmount const& amountBalance,
+
849 STAmount const& amount,
+
850 STAmount const& lptAMMBalance,
+
851 STAmount const& lpTokensDeposit,
+
852 std::uint16_t tfee)
+
853{
+
854 auto const tokensAdj =
+
855 adjustLPTokensOut(view.rules(), lptAMMBalance, lpTokensDeposit);
+
856 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
+ +
858 // the adjusted tokens are factored in
+
859 auto const amountDeposit =
+
860 ammAssetIn(amountBalance, lptAMMBalance, tokensAdj, tfee);
+
861 if (amountDeposit > amount)
+
862 return {tecAMM_FAILED, STAmount{}};
+
863 return deposit(
+
864 view,
+
865 ammAccount,
+
866 amountBalance,
+
867 amountDeposit,
+ +
869 lptAMMBalance,
+
870 tokensAdj,
-
872 tfee);
-
873}
+ + +
874 tfee);
+
875}
-
874
- -
- -
902 Sandbox& view,
-
903 AccountID const& ammAccount,
-
904 STAmount const& amountBalance,
-
905 STAmount const& amount,
-
906 STAmount const& lptAMMBalance,
-
907 STAmount const& ePrice,
-
908 std::uint16_t tfee)
-
909{
-
910 if (amount != beast::zero)
-
911 {
-
912 auto const tokens = adjustLPTokensOut(
-
913 view.rules(),
-
914 lptAMMBalance,
-
915 lpTokensOut(amountBalance, amount, lptAMMBalance, tfee));
-
916 if (tokens <= beast::zero)
-
917 {
-
918 if (!view.rules().enabled(fixAMMv1_3))
-
919 return {tecAMM_FAILED, STAmount{}}; // LCOV_EXCL_LINE
-
920 else
- -
922 }
-
923 // factor in the adjusted tokens
-
924 auto const [tokensAdj, amountDepositAdj] = adjustAssetInByTokens(
-
925 view.rules(), amountBalance, amount, lptAMMBalance, tokens, tfee);
-
926 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
-
927 return {tecAMM_INVALID_TOKENS, STAmount{}}; // LCOV_EXCL_LINE
-
928 auto const ep = Number{amountDepositAdj} / tokensAdj;
-
929 if (ep <= ePrice)
-
930 return deposit(
-
931 view,
-
932 ammAccount,
-
933 amountBalance,
-
934 amountDepositAdj,
- -
936 lptAMMBalance,
-
937 tokensAdj,
- - +
876
+ +
+ +
904 Sandbox& view,
+
905 AccountID const& ammAccount,
+
906 STAmount const& amountBalance,
+
907 STAmount const& amount,
+
908 STAmount const& lptAMMBalance,
+
909 STAmount const& ePrice,
+
910 std::uint16_t tfee)
+
911{
+
912 if (amount != beast::zero)
+
913 {
+
914 auto const tokens = adjustLPTokensOut(
+
915 view.rules(),
+
916 lptAMMBalance,
+
917 lpTokensOut(amountBalance, amount, lptAMMBalance, tfee));
+
918 if (tokens <= beast::zero)
+
919 {
+
920 if (!view.rules().enabled(fixAMMv1_3))
+
921 return {tecAMM_FAILED, STAmount{}}; // LCOV_EXCL_LINE
+
922 else
+ +
924 }
+
925 // factor in the adjusted tokens
+
926 auto const [tokensAdj, amountDepositAdj] = adjustAssetInByTokens(
+
927 view.rules(), amountBalance, amount, lptAMMBalance, tokens, tfee);
+
928 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
+
929 return {tecAMM_INVALID_TOKENS, STAmount{}}; // LCOV_EXCL_LINE
+
930 auto const ep = Number{amountDepositAdj} / tokensAdj;
+
931 if (ep <= ePrice)
+
932 return deposit(
+
933 view,
+
934 ammAccount,
+
935 amountBalance,
+
936 amountDepositAdj,
+ +
938 lptAMMBalance,
+
939 tokensAdj,
-
941 tfee);
-
942 }
-
943
-
944 // LPTokens is asset out => E = b / t
-
945 // substituting t in formula (3) as b/E:
-
946 // b/E = T * [b/B - sqrt(t2**2 + b/(f1*B)) + t2]/
-
947 // [1 + sqrt(t2**2 + b/(f1*B)) -t2] (A)
-
948 // where f1 = 1 - fee, f2 = (1 - fee/2)/f1
-
949 // Let R = b/(f1*B), then b/B = f1*R and b = R*f1*B
-
950 // Then (A) is
-
951 // R*f1*B = E*T*[R*f1 -sqrt(f2**2 + R) + f2]/[1 + sqrt(f2**2 + R) - f2] =>
-
952 // Let c = f1*B/(E*T) =>
-
953 // R*c*(1 + sqrt(f2**2 + R) + f2) = R*f1 - sqrt(f2**2 + R) - f2 =>
-
954 // (R*c + 1)*sqrt(f2**2 + R) = R*(f1 + c*f2 - c) + f2 =>
-
955 // Let d = f1 + c*f2 - c =>
-
956 // (R*c + 1)*sqrt(f2**2 + R) = R*d + f2 =>
-
957 // (R*c + 1)**2 * (f2**2 + R) = (R*d + f2)**2 =>
-
958 // (R*c)**2 + R*((c*f2)**2 + 2*c - d**2) + 2*c*f2**2 + 1 -2*d*f2 = 0 =>
-
959 // a1 = c**2, b1 = (c*f2)**2 + 2*c - d**2, c1 = 2*c*f2**2 + 1 - 2*d*f2
-
960 // R = (-b1 + sqrt(b1**2 + 4*a1*c1))/(2*a1)
-
961 auto const f1 = feeMult(tfee);
-
962 auto const f2 = feeMultHalf(tfee) / f1;
-
963 auto const c = f1 * amountBalance / (ePrice * lptAMMBalance);
-
964 auto const d = f1 + c * f2 - c;
-
965 auto const a1 = c * c;
-
966 auto const b1 = c * c * f2 * f2 + 2 * c - d * d;
-
967 auto const c1 = 2 * c * f2 * f2 + 1 - 2 * d * f2;
-
968 auto amtNoRoundCb = [&] {
-
969 return f1 * amountBalance * solveQuadraticEq(a1, b1, c1);
-
970 };
-
971 auto amtProdCb = [&] { return f1 * solveQuadraticEq(a1, b1, c1); };
-
972 auto const amountDeposit = getRoundedAsset(
-
973 view.rules(), amtNoRoundCb, amountBalance, amtProdCb, IsDeposit::Yes);
-
974 if (amountDeposit <= beast::zero)
-
975 return {tecAMM_FAILED, STAmount{}};
-
976 auto tokNoRoundCb = [&] { return amountDeposit / ePrice; };
-
977 auto tokProdCb = [&] { return amountDeposit / ePrice; };
-
978 auto const tokens = getRoundedLPTokens(
-
979 view.rules(), tokNoRoundCb, lptAMMBalance, tokProdCb, IsDeposit::Yes);
-
980 // factor in the adjusted tokens
-
981 auto const [tokensAdj, amountDepositAdj] = adjustAssetInByTokens(
-
982 view.rules(),
-
983 amountBalance,
-
984 amountDeposit,
-
985 lptAMMBalance,
-
986 tokens,
-
987 tfee);
-
988 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
-
989 return {tecAMM_INVALID_TOKENS, STAmount{}}; // LCOV_EXCL_LINE
-
990
-
991 return deposit(
-
992 view,
-
993 ammAccount,
-
994 amountBalance,
-
995 amountDepositAdj,
- -
997 lptAMMBalance,
-
998 tokensAdj,
- - + + +
943 tfee);
+
944 }
+
945
+
946 // LPTokens is asset out => E = b / t
+
947 // substituting t in formula (3) as b/E:
+
948 // b/E = T * [b/B - sqrt(t2**2 + b/(f1*B)) + t2]/
+
949 // [1 + sqrt(t2**2 + b/(f1*B)) -t2] (A)
+
950 // where f1 = 1 - fee, f2 = (1 - fee/2)/f1
+
951 // Let R = b/(f1*B), then b/B = f1*R and b = R*f1*B
+
952 // Then (A) is
+
953 // R*f1*B = E*T*[R*f1 -sqrt(f2**2 + R) + f2]/[1 + sqrt(f2**2 + R) - f2] =>
+
954 // Let c = f1*B/(E*T) =>
+
955 // R*c*(1 + sqrt(f2**2 + R) + f2) = R*f1 - sqrt(f2**2 + R) - f2 =>
+
956 // (R*c + 1)*sqrt(f2**2 + R) = R*(f1 + c*f2 - c) + f2 =>
+
957 // Let d = f1 + c*f2 - c =>
+
958 // (R*c + 1)*sqrt(f2**2 + R) = R*d + f2 =>
+
959 // (R*c + 1)**2 * (f2**2 + R) = (R*d + f2)**2 =>
+
960 // (R*c)**2 + R*((c*f2)**2 + 2*c - d**2) + 2*c*f2**2 + 1 -2*d*f2 = 0 =>
+
961 // a1 = c**2, b1 = (c*f2)**2 + 2*c - d**2, c1 = 2*c*f2**2 + 1 - 2*d*f2
+
962 // R = (-b1 + sqrt(b1**2 + 4*a1*c1))/(2*a1)
+
963 auto const f1 = feeMult(tfee);
+
964 auto const f2 = feeMultHalf(tfee) / f1;
+
965 auto const c = f1 * amountBalance / (ePrice * lptAMMBalance);
+
966 auto const d = f1 + c * f2 - c;
+
967 auto const a1 = c * c;
+
968 auto const b1 = c * c * f2 * f2 + 2 * c - d * d;
+
969 auto const c1 = 2 * c * f2 * f2 + 1 - 2 * d * f2;
+
970 auto amtNoRoundCb = [&] {
+
971 return f1 * amountBalance * solveQuadraticEq(a1, b1, c1);
+
972 };
+
973 auto amtProdCb = [&] { return f1 * solveQuadraticEq(a1, b1, c1); };
+
974 auto const amountDeposit = getRoundedAsset(
+
975 view.rules(), amtNoRoundCb, amountBalance, amtProdCb, IsDeposit::Yes);
+
976 if (amountDeposit <= beast::zero)
+
977 return {tecAMM_FAILED, STAmount{}};
+
978 auto tokNoRoundCb = [&] { return amountDeposit / ePrice; };
+
979 auto tokProdCb = [&] { return amountDeposit / ePrice; };
+
980 auto const tokens = getRoundedLPTokens(
+
981 view.rules(), tokNoRoundCb, lptAMMBalance, tokProdCb, IsDeposit::Yes);
+
982 // factor in the adjusted tokens
+
983 auto const [tokensAdj, amountDepositAdj] = adjustAssetInByTokens(
+
984 view.rules(),
+
985 amountBalance,
+
986 amountDeposit,
+
987 lptAMMBalance,
+
988 tokens,
+
989 tfee);
+
990 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
+
991 return {tecAMM_INVALID_TOKENS, STAmount{}}; // LCOV_EXCL_LINE
+
992
+
993 return deposit(
+
994 view,
+
995 ammAccount,
+
996 amountBalance,
+
997 amountDepositAdj,
+ +
999 lptAMMBalance,
+
1000 tokensAdj,
-
1002 tfee);
-
1003}
+ + +
1004 tfee);
+
1005}
-
1004
- -
- -
1007 Sandbox& view,
-
1008 AccountID const& ammAccount,
-
1009 STAmount const& amount,
-
1010 STAmount const& amount2,
-
1011 Issue const& lptIssue,
-
1012 std::uint16_t tfee)
-
1013{
-
1014 return deposit(
-
1015 view,
-
1016 ammAccount,
-
1017 amount,
-
1018 amount,
-
1019 amount2,
-
1020 STAmount{lptIssue, 0},
-
1021 ammLPTokens(amount, amount2, lptIssue),
- - +
1006
+ +
+ +
1009 Sandbox& view,
+
1010 AccountID const& ammAccount,
+
1011 STAmount const& amount,
+
1012 STAmount const& amount2,
+
1013 Issue const& lptIssue,
+
1014 std::uint16_t tfee)
+
1015{
+
1016 return deposit(
+
1017 view,
+
1018 ammAccount,
+
1019 amount,
+
1020 amount,
+
1021 amount2,
+
1022 STAmount{lptIssue, 0},
+
1023 ammLPTokens(amount, amount2, lptIssue),
-
1025 tfee);
-
1026}
+ + +
1027 tfee);
+
1028}
-
1027
-
1028} // namespace ripple
+
1029
+
1030} // namespace ripple
Stream error() const
Definition Journal.h:346
Stream debug() const
Definition Journal.h:328
-
std::pair< TER, bool > applyGuts(Sandbox &view)
-
std::pair< TER, STAmount > equalDepositLimit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &amount2, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)
Equal asset deposit (Asset1In, Asset2In) with the constraint on the maximum amount of both assets tha...
-
std::pair< TER, STAmount > singleDepositEPrice(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &ePrice, std::uint16_t tfee)
Single asset deposit (Asset1In, EPrice) with two constraints.
-
static TER preclaim(PreclaimContext const &ctx)
-
std::pair< TER, STAmount > singleDeposit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)
Single asset deposit (Asset1In) by the amount.
-
static NotTEC preflight(PreflightContext const &ctx)
-
std::pair< TER, STAmount > equalDepositTokens(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::optional< STAmount > const &depositMin, std::optional< STAmount > const &deposit2Min, std::uint16_t tfee)
Equal asset deposit (LPTokens) for the specified share of the AMM instance pools.
-
TER doApply() override
-
std::pair< TER, STAmount > equalDepositInEmptyState(Sandbox &view, AccountID const &ammAccount, STAmount const &amount, STAmount const &amount2, Issue const &lptIssue, std::uint16_t tfee)
Equal deposit in empty AMM state (LP tokens balance is 0)
-
std::pair< TER, STAmount > singleDepositTokens(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::uint16_t tfee)
Single asset deposit (Asset1In, LPTokens) by the tokens.
-
std::pair< TER, STAmount > deposit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amountDeposit, std::optional< STAmount > const &amount2Deposit, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::optional< STAmount > const &depositMin, std::optional< STAmount > const &deposit2Min, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)
Deposit requested assets and token amount into LP account.
+
std::pair< TER, bool > applyGuts(Sandbox &view)
+
std::pair< TER, STAmount > equalDepositLimit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &amount2, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)
Equal asset deposit (Asset1In, Asset2In) with the constraint on the maximum amount of both assets tha...
+
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
+
std::pair< TER, STAmount > singleDepositEPrice(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &ePrice, std::uint16_t tfee)
Single asset deposit (Asset1In, EPrice) with two constraints.
+
static TER preclaim(PreclaimContext const &ctx)
+
std::pair< TER, STAmount > singleDeposit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)
Single asset deposit (Asset1In) by the amount.
+
static NotTEC preflight(PreflightContext const &ctx)
+
std::pair< TER, STAmount > equalDepositTokens(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::optional< STAmount > const &depositMin, std::optional< STAmount > const &deposit2Min, std::uint16_t tfee)
Equal asset deposit (LPTokens) for the specified share of the AMM instance pools.
+
static bool checkExtraFeatures(PreflightContext const &ctx)
+
TER doApply() override
+
std::pair< TER, STAmount > equalDepositInEmptyState(Sandbox &view, AccountID const &ammAccount, STAmount const &amount, STAmount const &amount2, Issue const &lptIssue, std::uint16_t tfee)
Equal deposit in empty AMM state (LP tokens balance is 0)
+
std::pair< TER, STAmount > singleDepositTokens(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::uint16_t tfee)
Single asset deposit (Asset1In, LPTokens) by the tokens.
+
std::pair< TER, STAmount > deposit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amountDeposit, std::optional< STAmount > const &amount2Deposit, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::optional< STAmount > const &depositMin, std::optional< STAmount > const &deposit2Min, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)
Deposit requested assets and token amount into LP account.
ApplyView & view()
beast::Journal const journal
@@ -1091,16 +1099,16 @@ $(document).ready(function() { init_codefold(0); });
std::uint32_t getFlags() const
Definition STObject.cpp:537
Discardable, editable view to a ledger.
Definition Sandbox.h:35
void apply(RawView &to)
Definition Sandbox.h:55
- -
AccountID const account_
Definition Transactor.h:145
-
ApplyView & view()
Definition Transactor.h:161
-
beast::Journal const j_
Definition Transactor.h:143
-
ApplyContext & ctx_
Definition Transactor.h:141
+ +
AccountID const account_
Definition Transactor.h:147
+
ApplyView & view()
Definition Transactor.h:163
+
beast::Journal const j_
Definition Transactor.h:145
+
ApplyContext & ctx_
Definition Transactor.h:143
void update(std::shared_ptr< SLE > const &sle) override
Indicate changes to a peeked SLE.
std::shared_ptr< SLE > peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
- +
T is_same_v
T make_optional(T... args)
T make_pair(T... args)
@@ -1120,7 +1128,6 @@ $(document).ready(function() { init_codefold(0); });
constexpr std::uint32_t tfLimitLPToken
Definition TxFlags.h:250
STAmount ammAssetIn(STAmount const &asset1Balance, STAmount const &lptAMMBalance, STAmount const &lpTokens, std::uint16_t tfee)
Calculate asset deposit given LP Tokens.
bool ammEnabled(Rules const &)
Return true if required AMM amendments are enabled.
Definition AMMCore.cpp:129
-
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
constexpr std::uint32_t tfOneAssetLPToken
Definition TxFlags.h:249
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No)
Calls static accountSendIOU if saAmount represents Issue.
Definition View.cpp:2174
STAmount getRoundedLPTokens(Rules const &rules, STAmount const &balance, Number const &frac, IsDeposit isDeposit)
Round AMM deposit/withdrawal LPToken amount.
@@ -1133,8 +1140,7 @@ $(document).ready(function() { init_codefold(0); });
STAmount ammLPHolds(ReadView const &view, Currency const &cur1, Currency const &cur2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
Definition AMMUtils.cpp:113
std::tuple< STAmount, std::optional< STAmount >, STAmount > adjustAmountsByLPTokens(STAmount const &amountBalance, STAmount const &amount, std::optional< STAmount > const &amount2, STAmount const &lptAMMBalance, STAmount const &lpTokens, std::uint16_t tfee, IsDeposit isDeposit)
Calls adjustLPTokens() and adjusts deposit or withdraw amounts if the adjusted LP tokens are less tha...
constexpr std::uint32_t tfDepositSubTx
Definition TxFlags.h:255
-
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
-
static STAmount adjustLPTokensOut(Rules const &rules, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit)
+
static STAmount adjustLPTokensOut(Rules const &rules, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit)
@ tecINSUF_RESERVE_LINE
Definition TER.h:288
@ tecFROZEN
Definition TER.h:303
@@ -1149,7 +1155,6 @@ $(document).ready(function() { init_codefold(0); });
@ tesSUCCESS
Definition TER.h:244
NotTEC invalidAMMAssetPair(Issue const &issue1, Issue const &issue2, std::optional< std::pair< Issue, Issue > > const &pair=std::nullopt)
Definition AMMCore.cpp:80
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
Definition View.cpp:384
-
bool isTesSuccess(TER x) noexcept
Definition TER.h:674
constexpr std::uint32_t tfDepositMask
Definition TxFlags.h:259
Expected< std::tuple< STAmount, STAmount, STAmount >, TER > ammHolds(ReadView const &view, SLE const &ammSle, std::optional< Issue > const &optIssue1, std::optional< Issue > const &optIssue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool and LP token balances.
Definition AMMUtils.cpp:47
STAmount ammLPTokens(STAmount const &asset1, STAmount const &asset2, Issue const &lptIssue)
Calculate LP Tokens given AMM pool reserves.
@@ -1162,14 +1167,11 @@ $(document).ready(function() { init_codefold(0); });
std::uint16_t constexpr TRADING_FEE_THRESHOLD
Definition AMMCore.h:31
STAmount getRoundedAsset(Rules const &rules, STAmount const &balance, A const &frac, IsDeposit isDeposit)
Round AMM equal deposit/withdrawal amount.
Definition AMMHelpers.h:678
Number adjustFracByTokens(Rules const &rules, STAmount const &lptAMMBalance, STAmount const &tokens, Number const &frac)
Find a fraction of tokens after the tokens are adjusted.
-
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:605
XRPAmount xrpLiquid(ReadView const &view, AccountID const &id, std::int32_t ownerCountAdj, beast::Journal j)
Definition View.cpp:615
@ temBAD_AMOUNT
Definition TER.h:89
@ temBAD_FEE
Definition TER.h:92
@ temMALFORMED
Definition TER.h:87
@ temBAD_AMM_TOKENS
Definition TER.h:129
-
@ temINVALID_FLAG
Definition TER.h:111
-
@ temDISABLED
Definition TER.h:114
T popcount(T... args)
diff --git a/AMMDeposit_8h_source.html b/AMMDeposit_8h_source.html index e9c5f73d31..bf8dff4258 100644 --- a/AMMDeposit_8h_source.html +++ b/AMMDeposit_8h_source.html @@ -121,126 +121,134 @@ $(document).ready(function() { init_codefold(0); });
69 }
70
-
71 static NotTEC
-
72 preflight(PreflightContext const& ctx);
+
71 static bool
+
73
-
74 static TER
-
75 preclaim(PreclaimContext const& ctx);
+
74 static std::uint32_t
+
76
-
77 TER
-
78 doApply() override;
+
77 static NotTEC
+
78 preflight(PreflightContext const& ctx);
79
-
80private:
- - -
83
- -
100 deposit(
-
101 Sandbox& view,
-
102 AccountID const& ammAccount,
-
103 STAmount const& amountBalance,
-
104 STAmount const& amountDeposit,
-
105 std::optional<STAmount> const& amount2Deposit,
-
106 STAmount const& lptAMMBalance,
-
107 STAmount const& lpTokensDeposit,
-
108 std::optional<STAmount> const& depositMin,
-
109 std::optional<STAmount> const& deposit2Min,
-
110 std::optional<STAmount> const& lpTokensDepositMin,
-
111 std::uint16_t tfee);
-
112
- - -
128 Sandbox& view,
-
129 AccountID const& ammAccount,
-
130 STAmount const& amountBalance,
-
131 STAmount const& amount2Balance,
-
132 STAmount const& lptAMMBalance,
-
133 STAmount const& lpTokensDeposit,
-
134 std::optional<STAmount> const& depositMin,
-
135 std::optional<STAmount> const& deposit2Min,
-
136 std::uint16_t tfee);
-
137
- - -
154 Sandbox& view,
-
155 AccountID const& ammAccount,
-
156 STAmount const& amountBalance,
-
157 STAmount const& amount2Balance,
-
158 STAmount const& lptAMMBalance,
-
159 STAmount const& amount,
-
160 STAmount const& amount2,
-
161 std::optional<STAmount> const& lpTokensDepositMin,
-
162 std::uint16_t tfee);
-
163
- - -
177 Sandbox& view,
-
178 AccountID const& ammAccount,
-
179 STAmount const& amountBalance,
-
180 STAmount const& lptAMMBalance,
-
181 STAmount const& amount,
-
182 std::optional<STAmount> const& lpTokensDepositMin,
-
183 std::uint16_t tfee);
-
184
- - -
198 Sandbox& view,
-
199 AccountID const& ammAccount,
-
200 STAmount const& amountBalance,
-
201 STAmount const& amount,
-
202 STAmount const& lptAMMBalance,
-
203 STAmount const& lpTokensDeposit,
-
204 std::uint16_t tfee);
-
205
- - -
219 Sandbox& view,
-
220 AccountID const& ammAccount,
-
221 STAmount const& amountBalance,
-
222 STAmount const& amount,
-
223 STAmount const& lptAMMBalance,
-
224 STAmount const& ePrice,
-
225 std::uint16_t tfee);
-
226
- - -
237 Sandbox& view,
-
238 AccountID const& ammAccount,
-
239 STAmount const& amount,
-
240 STAmount const& amount2,
-
241 Issue const& lptIssue,
-
242 std::uint16_t tfee);
-
243};
+
80 static TER
+
81 preclaim(PreclaimContext const& ctx);
+
82
+
83 TER
+
84 doApply() override;
+
85
+
86private:
+ + +
89
+ +
106 deposit(
+
107 Sandbox& view,
+
108 AccountID const& ammAccount,
+
109 STAmount const& amountBalance,
+
110 STAmount const& amountDeposit,
+
111 std::optional<STAmount> const& amount2Deposit,
+
112 STAmount const& lptAMMBalance,
+
113 STAmount const& lpTokensDeposit,
+
114 std::optional<STAmount> const& depositMin,
+
115 std::optional<STAmount> const& deposit2Min,
+
116 std::optional<STAmount> const& lpTokensDepositMin,
+
117 std::uint16_t tfee);
+
118
+ + +
134 Sandbox& view,
+
135 AccountID const& ammAccount,
+
136 STAmount const& amountBalance,
+
137 STAmount const& amount2Balance,
+
138 STAmount const& lptAMMBalance,
+
139 STAmount const& lpTokensDeposit,
+
140 std::optional<STAmount> const& depositMin,
+
141 std::optional<STAmount> const& deposit2Min,
+
142 std::uint16_t tfee);
+
143
+ + +
160 Sandbox& view,
+
161 AccountID const& ammAccount,
+
162 STAmount const& amountBalance,
+
163 STAmount const& amount2Balance,
+
164 STAmount const& lptAMMBalance,
+
165 STAmount const& amount,
+
166 STAmount const& amount2,
+
167 std::optional<STAmount> const& lpTokensDepositMin,
+
168 std::uint16_t tfee);
+
169
+ + +
183 Sandbox& view,
+
184 AccountID const& ammAccount,
+
185 STAmount const& amountBalance,
+
186 STAmount const& lptAMMBalance,
+
187 STAmount const& amount,
+
188 std::optional<STAmount> const& lpTokensDepositMin,
+
189 std::uint16_t tfee);
+
190
+ + +
204 Sandbox& view,
+
205 AccountID const& ammAccount,
+
206 STAmount const& amountBalance,
+
207 STAmount const& amount,
+
208 STAmount const& lptAMMBalance,
+
209 STAmount const& lpTokensDeposit,
+
210 std::uint16_t tfee);
+
211
+ + +
225 Sandbox& view,
+
226 AccountID const& ammAccount,
+
227 STAmount const& amountBalance,
+
228 STAmount const& amount,
+
229 STAmount const& lptAMMBalance,
+
230 STAmount const& ePrice,
+
231 std::uint16_t tfee);
+
232
+ + +
243 Sandbox& view,
+
244 AccountID const& ammAccount,
+
245 STAmount const& amount,
+
246 STAmount const& amount2,
+
247 Issue const& lptIssue,
+
248 std::uint16_t tfee);
+
249};
-
244
-
245} // namespace ripple
-
246
-
247#endif // RIPPLE_TX_AMMDEPOSIT_H_INCLUDED
+
250
+
251} // namespace ripple
+
252
+
253#endif // RIPPLE_TX_AMMDEPOSIT_H_INCLUDED
AMMDeposit implements AMM deposit Transactor.
Definition AMMDeposit.h:63
-
std::pair< TER, bool > applyGuts(Sandbox &view)
-
std::pair< TER, STAmount > equalDepositLimit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &amount2, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)
Equal asset deposit (Asset1In, Asset2In) with the constraint on the maximum amount of both assets tha...
-
std::pair< TER, STAmount > singleDepositEPrice(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &ePrice, std::uint16_t tfee)
Single asset deposit (Asset1In, EPrice) with two constraints.
-
static TER preclaim(PreclaimContext const &ctx)
-
std::pair< TER, STAmount > singleDeposit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)
Single asset deposit (Asset1In) by the amount.
-
static NotTEC preflight(PreflightContext const &ctx)
-
std::pair< TER, STAmount > equalDepositTokens(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::optional< STAmount > const &depositMin, std::optional< STAmount > const &deposit2Min, std::uint16_t tfee)
Equal asset deposit (LPTokens) for the specified share of the AMM instance pools.
+
std::pair< TER, bool > applyGuts(Sandbox &view)
+
std::pair< TER, STAmount > equalDepositLimit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &amount2, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)
Equal asset deposit (Asset1In, Asset2In) with the constraint on the maximum amount of both assets tha...
+
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
+
std::pair< TER, STAmount > singleDepositEPrice(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &ePrice, std::uint16_t tfee)
Single asset deposit (Asset1In, EPrice) with two constraints.
+
static TER preclaim(PreclaimContext const &ctx)
+
std::pair< TER, STAmount > singleDeposit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)
Single asset deposit (Asset1In) by the amount.
+
static NotTEC preflight(PreflightContext const &ctx)
+
std::pair< TER, STAmount > equalDepositTokens(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::optional< STAmount > const &depositMin, std::optional< STAmount > const &deposit2Min, std::uint16_t tfee)
Equal asset deposit (LPTokens) for the specified share of the AMM instance pools.
+
static bool checkExtraFeatures(PreflightContext const &ctx)
static constexpr ConsequencesFactoryType ConsequencesFactory
Definition AMMDeposit.h:65
-
TER doApply() override
-
std::pair< TER, STAmount > equalDepositInEmptyState(Sandbox &view, AccountID const &ammAccount, STAmount const &amount, STAmount const &amount2, Issue const &lptIssue, std::uint16_t tfee)
Equal deposit in empty AMM state (LP tokens balance is 0)
-
std::pair< TER, STAmount > singleDepositTokens(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::uint16_t tfee)
Single asset deposit (Asset1In, LPTokens) by the tokens.
-
std::pair< TER, STAmount > deposit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amountDeposit, std::optional< STAmount > const &amount2Deposit, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::optional< STAmount > const &depositMin, std::optional< STAmount > const &deposit2Min, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)
Deposit requested assets and token amount into LP account.
+
TER doApply() override
+
std::pair< TER, STAmount > equalDepositInEmptyState(Sandbox &view, AccountID const &ammAccount, STAmount const &amount, STAmount const &amount2, Issue const &lptIssue, std::uint16_t tfee)
Equal deposit in empty AMM state (LP tokens balance is 0)
+
std::pair< TER, STAmount > singleDepositTokens(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::uint16_t tfee)
Single asset deposit (Asset1In, LPTokens) by the tokens.
+
std::pair< TER, STAmount > deposit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amountDeposit, std::optional< STAmount > const &amount2Deposit, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::optional< STAmount > const &depositMin, std::optional< STAmount > const &deposit2Min, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)
Deposit requested assets and token amount into LP account.
AMMDeposit(ApplyContext &ctx)
Definition AMMDeposit.h:67
State information when applying a tx.
A currency issued by an account.
Definition Issue.h:33
Discardable, editable view to a ledger.
Definition Sandbox.h:35
- - - -
ApplyView & view()
Definition Transactor.h:161
+ + + +
ApplyView & view()
Definition Transactor.h:163
- +
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
diff --git a/AMMVote_8cpp_source.html b/AMMVote_8cpp_source.html index d310cd9a09..1317ac35a8 100644 --- a/AMMVote_8cpp_source.html +++ b/AMMVote_8cpp_source.html @@ -110,16 +110,18 @@ $(document).ready(function() { init_codefold(0); });
27
28namespace ripple {
29
- +
30bool
- +
32{
-
33 if (!ammEnabled(ctx.rules))
-
34 return temDISABLED;
+
33 return ammEnabled(ctx.rules);
+
34}
+
35
-
36 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
-
37 return ret;
-
38
+ +
+ +
38{
39 if (auto const res = invalidAMMAssetPair(
40 ctx.tx[sfAsset].get<Issue>(), ctx.tx[sfAsset2].get<Issue>()))
41 {
@@ -127,225 +129,220 @@ $(document).ready(function() { init_codefold(0); });
43 return res;
44 }
45
-
46 if (ctx.tx.getFlags() & tfUniversalMask)
+
46 if (ctx.tx[sfTradingFee] > TRADING_FEE_THRESHOLD)
47 {
-
48 JLOG(ctx.j.debug()) << "AMM Vote: invalid flags.";
-
49 return temINVALID_FLAG;
+
48 JLOG(ctx.j.debug()) << "AMM Vote: invalid trading fee.";
+
49 return temBAD_FEE;
50 }
51
-
52 if (ctx.tx[sfTradingFee] > TRADING_FEE_THRESHOLD)
-
53 {
-
54 JLOG(ctx.j.debug()) << "AMM Vote: invalid trading fee.";
-
55 return temBAD_FEE;
-
56 }
-
57
-
58 return preflight2(ctx);
-
59}
+
52 return tesSUCCESS;
+
53}
-
60
-
61TER
-
- -
63{
-
64 if (auto const ammSle =
-
65 ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
-
66 !ammSle)
-
67 {
-
68 JLOG(ctx.j.debug()) << "AMM Vote: Invalid asset pair.";
-
69 return terNO_AMM;
-
70 }
-
71 else if (ammSle->getFieldAmount(sfLPTokenBalance) == beast::zero)
-
72 return tecAMM_EMPTY;
-
73 else if (auto const lpTokensNew =
-
74 ammLPHolds(ctx.view, *ammSle, ctx.tx[sfAccount], ctx.j);
-
75 lpTokensNew == beast::zero)
-
76 {
-
77 JLOG(ctx.j.debug()) << "AMM Vote: account is not LP.";
- -
79 }
-
80
-
81 return tesSUCCESS;
-
82}
+
54
+
55TER
+
+ +
57{
+
58 if (auto const ammSle =
+
59 ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
+
60 !ammSle)
+
61 {
+
62 JLOG(ctx.j.debug()) << "AMM Vote: Invalid asset pair.";
+
63 return terNO_AMM;
+
64 }
+
65 else if (ammSle->getFieldAmount(sfLPTokenBalance) == beast::zero)
+
66 return tecAMM_EMPTY;
+
67 else if (auto const lpTokensNew =
+
68 ammLPHolds(ctx.view, *ammSle, ctx.tx[sfAccount], ctx.j);
+
69 lpTokensNew == beast::zero)
+
70 {
+
71 JLOG(ctx.j.debug()) << "AMM Vote: account is not LP.";
+ +
73 }
+
74
+
75 return tesSUCCESS;
+
76}
-
83
- -
- -
86 ApplyContext& ctx_,
-
87 Sandbox& sb,
-
88 AccountID const& account_,
- -
90{
-
91 auto const feeNew = ctx_.tx[sfTradingFee];
-
92 auto ammSle = sb.peek(keylet::amm(ctx_.tx[sfAsset], ctx_.tx[sfAsset2]));
-
93 if (!ammSle)
-
94 return {tecINTERNAL, false};
-
95 STAmount const lptAMMBalance = (*ammSle)[sfLPTokenBalance];
-
96 auto const lpTokensNew = ammLPHolds(sb, *ammSle, account_, ctx_.journal);
- -
98 std::size_t minPos{0};
-
99 AccountID minAccount{0};
-
100 std::uint32_t minFee{0};
-
101 STArray updatedVoteSlots;
-
102 Number num{0};
-
103 Number den{0};
-
104 // Account already has vote entry
-
105 bool foundAccount = false;
-
106
-
107 // Iterate over the current vote entries and update each entry
-
108 // per current total tokens balance and each LP tokens balance.
-
109 // Find the entry with the least tokens and whether the account
-
110 // has the vote entry.
-
111 for (auto const& entry : ammSle->getFieldArray(sfVoteSlots))
-
112 {
-
113 auto const account = entry[sfAccount];
-
114 auto lpTokens = ammLPHolds(sb, *ammSle, account, ctx_.journal);
-
115 if (lpTokens == beast::zero)
-
116 {
-
117 JLOG(j_.debug())
-
118 << "AMMVote::applyVote, account " << account << " is not LP";
-
119 continue;
-
120 }
-
121 auto feeVal = entry[sfTradingFee];
-
122 STObject newEntry = STObject::makeInnerObject(sfVoteEntry);
-
123 // The account already has the vote entry.
-
124 if (account == account_)
-
125 {
-
126 lpTokens = lpTokensNew;
-
127 feeVal = feeNew;
-
128 foundAccount = true;
-
129 }
-
130 // Keep running numerator/denominator to calculate the updated fee.
-
131 num += feeVal * lpTokens;
-
132 den += lpTokens;
-
133 newEntry.setAccountID(sfAccount, account);
-
134 if (feeVal != 0)
-
135 newEntry.setFieldU16(sfTradingFee, feeVal);
-
136 newEntry.setFieldU32(
-
137 sfVoteWeight,
-
138 static_cast<std::int64_t>(
-
139 Number(lpTokens) * VOTE_WEIGHT_SCALE_FACTOR / lptAMMBalance));
-
140
-
141 // Find an entry with the least tokens/fee. Make the order deterministic
-
142 // if the tokens/fees are equal.
-
143 if (!minTokens ||
-
144 (lpTokens < *minTokens ||
-
145 (lpTokens == *minTokens &&
-
146 (feeVal < minFee || (feeVal == minFee && account < minAccount)))))
-
147 {
-
148 minTokens = lpTokens;
-
149 minPos = updatedVoteSlots.size();
-
150 minAccount = account;
-
151 minFee = feeVal;
-
152 }
-
153 updatedVoteSlots.push_back(std::move(newEntry));
-
154 }
-
155
-
156 // The account doesn't have the vote entry.
-
157 if (!foundAccount)
-
158 {
-
159 auto update = [&](std::optional<std::uint8_t> const& minPos =
-
160 std::nullopt) {
-
161 STObject newEntry = STObject::makeInnerObject(sfVoteEntry);
-
162 if (feeNew != 0)
-
163 newEntry.setFieldU16(sfTradingFee, feeNew);
-
164 newEntry.setFieldU32(
-
165 sfVoteWeight,
-
166 static_cast<std::int64_t>(
-
167 Number(lpTokensNew) * VOTE_WEIGHT_SCALE_FACTOR /
-
168 lptAMMBalance));
-
169 newEntry.setAccountID(sfAccount, account_);
-
170 num += feeNew * lpTokensNew;
-
171 den += lpTokensNew;
-
172 if (minPos)
-
173 *(updatedVoteSlots.begin() + *minPos) = std::move(newEntry);
-
174 else
-
175 updatedVoteSlots.push_back(std::move(newEntry));
-
176 };
-
177 // Add new entry if the number of the vote entries
-
178 // is less than Max.
-
179 if (updatedVoteSlots.size() < VOTE_MAX_SLOTS)
-
180 update();
-
181 // Add the entry if the account has more tokens than
-
182 // the least token holder or same tokens and higher fee.
-
183 else if (
-
184 lpTokensNew > *minTokens ||
-
185 (lpTokensNew == *minTokens && feeNew > minFee))
-
186 {
-
187 auto const entry = updatedVoteSlots.begin() + minPos;
-
188 // Remove the least token vote entry.
-
189 num -= Number((*entry)[~sfTradingFee].value_or(0)) * *minTokens;
-
190 den -= *minTokens;
-
191 update(minPos);
-
192 }
-
193 // All slots are full and the account does not hold more LPTokens.
-
194 // Update anyway to refresh the slots.
-
195 else
-
196 {
-
197 JLOG(j_.debug()) << "AMMVote::applyVote, insufficient tokens to "
-
198 "override other votes";
-
199 }
-
200 }
-
201
-
202 XRPL_ASSERT(
-
203 !ctx_.view().rules().enabled(fixInnerObjTemplate) ||
-
204 ammSle->isFieldPresent(sfAuctionSlot),
-
205 "ripple::applyVote : has auction slot");
-
206
-
207 // Update the vote entries and the trading/discounted fee.
-
208 ammSle->setFieldArray(sfVoteSlots, updatedVoteSlots);
-
209 if (auto const fee = static_cast<std::int64_t>(num / den))
-
210 {
-
211 ammSle->setFieldU16(sfTradingFee, fee);
-
212 if (ammSle->isFieldPresent(sfAuctionSlot))
-
213 {
-
214 auto& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);
-
215 if (auto const discountedFee =
- -
217 auctionSlot.setFieldU16(sfDiscountedFee, discountedFee);
-
218 else if (auctionSlot.isFieldPresent(sfDiscountedFee))
-
219 auctionSlot.makeFieldAbsent(sfDiscountedFee);
-
220 }
-
221 }
-
222 else
-
223 {
-
224 if (ammSle->isFieldPresent(sfTradingFee))
-
225 ammSle->makeFieldAbsent(sfTradingFee);
-
226 if (ammSle->isFieldPresent(sfAuctionSlot))
-
227 {
-
228 auto& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);
-
229 if (auctionSlot.isFieldPresent(sfDiscountedFee))
-
230 auctionSlot.makeFieldAbsent(sfDiscountedFee);
-
231 }
-
232 }
-
233 sb.update(ammSle);
-
234
-
235 return {tesSUCCESS, true};
-
236}
+
77
+ +
+ +
80 ApplyContext& ctx_,
+
81 Sandbox& sb,
+
82 AccountID const& account_,
+ +
84{
+
85 auto const feeNew = ctx_.tx[sfTradingFee];
+
86 auto ammSle = sb.peek(keylet::amm(ctx_.tx[sfAsset], ctx_.tx[sfAsset2]));
+
87 if (!ammSle)
+
88 return {tecINTERNAL, false};
+
89 STAmount const lptAMMBalance = (*ammSle)[sfLPTokenBalance];
+
90 auto const lpTokensNew = ammLPHolds(sb, *ammSle, account_, ctx_.journal);
+ +
92 std::size_t minPos{0};
+
93 AccountID minAccount{0};
+
94 std::uint32_t minFee{0};
+
95 STArray updatedVoteSlots;
+
96 Number num{0};
+
97 Number den{0};
+
98 // Account already has vote entry
+
99 bool foundAccount = false;
+
100
+
101 // Iterate over the current vote entries and update each entry
+
102 // per current total tokens balance and each LP tokens balance.
+
103 // Find the entry with the least tokens and whether the account
+
104 // has the vote entry.
+
105 for (auto const& entry : ammSle->getFieldArray(sfVoteSlots))
+
106 {
+
107 auto const account = entry[sfAccount];
+
108 auto lpTokens = ammLPHolds(sb, *ammSle, account, ctx_.journal);
+
109 if (lpTokens == beast::zero)
+
110 {
+
111 JLOG(j_.debug())
+
112 << "AMMVote::applyVote, account " << account << " is not LP";
+
113 continue;
+
114 }
+
115 auto feeVal = entry[sfTradingFee];
+
116 STObject newEntry = STObject::makeInnerObject(sfVoteEntry);
+
117 // The account already has the vote entry.
+
118 if (account == account_)
+
119 {
+
120 lpTokens = lpTokensNew;
+
121 feeVal = feeNew;
+
122 foundAccount = true;
+
123 }
+
124 // Keep running numerator/denominator to calculate the updated fee.
+
125 num += feeVal * lpTokens;
+
126 den += lpTokens;
+
127 newEntry.setAccountID(sfAccount, account);
+
128 if (feeVal != 0)
+
129 newEntry.setFieldU16(sfTradingFee, feeVal);
+
130 newEntry.setFieldU32(
+
131 sfVoteWeight,
+
132 static_cast<std::int64_t>(
+
133 Number(lpTokens) * VOTE_WEIGHT_SCALE_FACTOR / lptAMMBalance));
+
134
+
135 // Find an entry with the least tokens/fee. Make the order deterministic
+
136 // if the tokens/fees are equal.
+
137 if (!minTokens ||
+
138 (lpTokens < *minTokens ||
+
139 (lpTokens == *minTokens &&
+
140 (feeVal < minFee || (feeVal == minFee && account < minAccount)))))
+
141 {
+
142 minTokens = lpTokens;
+
143 minPos = updatedVoteSlots.size();
+
144 minAccount = account;
+
145 minFee = feeVal;
+
146 }
+
147 updatedVoteSlots.push_back(std::move(newEntry));
+
148 }
+
149
+
150 // The account doesn't have the vote entry.
+
151 if (!foundAccount)
+
152 {
+
153 auto update = [&](std::optional<std::uint8_t> const& minPos =
+
154 std::nullopt) {
+
155 STObject newEntry = STObject::makeInnerObject(sfVoteEntry);
+
156 if (feeNew != 0)
+
157 newEntry.setFieldU16(sfTradingFee, feeNew);
+
158 newEntry.setFieldU32(
+
159 sfVoteWeight,
+
160 static_cast<std::int64_t>(
+
161 Number(lpTokensNew) * VOTE_WEIGHT_SCALE_FACTOR /
+
162 lptAMMBalance));
+
163 newEntry.setAccountID(sfAccount, account_);
+
164 num += feeNew * lpTokensNew;
+
165 den += lpTokensNew;
+
166 if (minPos)
+
167 *(updatedVoteSlots.begin() + *minPos) = std::move(newEntry);
+
168 else
+
169 updatedVoteSlots.push_back(std::move(newEntry));
+
170 };
+
171 // Add new entry if the number of the vote entries
+
172 // is less than Max.
+
173 if (updatedVoteSlots.size() < VOTE_MAX_SLOTS)
+
174 update();
+
175 // Add the entry if the account has more tokens than
+
176 // the least token holder or same tokens and higher fee.
+
177 else if (
+
178 lpTokensNew > *minTokens ||
+
179 (lpTokensNew == *minTokens && feeNew > minFee))
+
180 {
+
181 auto const entry = updatedVoteSlots.begin() + minPos;
+
182 // Remove the least token vote entry.
+
183 num -= Number((*entry)[~sfTradingFee].value_or(0)) * *minTokens;
+
184 den -= *minTokens;
+
185 update(minPos);
+
186 }
+
187 // All slots are full and the account does not hold more LPTokens.
+
188 // Update anyway to refresh the slots.
+
189 else
+
190 {
+
191 JLOG(j_.debug()) << "AMMVote::applyVote, insufficient tokens to "
+
192 "override other votes";
+
193 }
+
194 }
+
195
+
196 XRPL_ASSERT(
+
197 !ctx_.view().rules().enabled(fixInnerObjTemplate) ||
+
198 ammSle->isFieldPresent(sfAuctionSlot),
+
199 "ripple::applyVote : has auction slot");
+
200
+
201 // Update the vote entries and the trading/discounted fee.
+
202 ammSle->setFieldArray(sfVoteSlots, updatedVoteSlots);
+
203 if (auto const fee = static_cast<std::int64_t>(num / den))
+
204 {
+
205 ammSle->setFieldU16(sfTradingFee, fee);
+
206 if (ammSle->isFieldPresent(sfAuctionSlot))
+
207 {
+
208 auto& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);
+
209 if (auto const discountedFee =
+ +
211 auctionSlot.setFieldU16(sfDiscountedFee, discountedFee);
+
212 else if (auctionSlot.isFieldPresent(sfDiscountedFee))
+
213 auctionSlot.makeFieldAbsent(sfDiscountedFee);
+
214 }
+
215 }
+
216 else
+
217 {
+
218 if (ammSle->isFieldPresent(sfTradingFee))
+
219 ammSle->makeFieldAbsent(sfTradingFee);
+
220 if (ammSle->isFieldPresent(sfAuctionSlot))
+
221 {
+
222 auto& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot);
+
223 if (auctionSlot.isFieldPresent(sfDiscountedFee))
+
224 auctionSlot.makeFieldAbsent(sfDiscountedFee);
+
225 }
+
226 }
+
227 sb.update(ammSle);
+
228
+
229 return {tesSUCCESS, true};
+
230}
-
237
-
238TER
-
- -
240{
-
241 // This is the ledger view that we work against. Transactions are applied
-
242 // as we go on processing transactions.
-
243 Sandbox sb(&ctx_.view());
-
244
-
245 auto const result = applyVote(ctx_, sb, account_, j_);
-
246 if (result.second)
-
247 sb.apply(ctx_.rawView());
-
248
-
249 return result.first;
-
250}
+
231
+
232TER
+
+ +
234{
+
235 // This is the ledger view that we work against. Transactions are applied
+
236 // as we go on processing transactions.
+
237 Sandbox sb(&ctx_.view());
+
238
+
239 auto const result = applyVote(ctx_, sb, account_, j_);
+
240 if (result.second)
+
241 sb.apply(ctx_.rawView());
+
242
+
243 return result.first;
+
244}
-
251
-
252} // namespace ripple
+
245
+
246} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:60
Stream debug() const
Definition Journal.h:328
-
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMVote.cpp:31
-
static TER preclaim(PreclaimContext const &ctx)
Definition AMMVote.cpp:62
-
TER doApply() override
Definition AMMVote.cpp:239
+
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMVote.cpp:37
+
static TER preclaim(PreclaimContext const &ctx)
Definition AMMVote.cpp:56
+
TER doApply() override
Definition AMMVote.cpp:233
+
static bool checkExtraFeatures(PreflightContext const &ctx)
Definition AMMVote.cpp:31
State information when applying a tx.
ApplyView & view()
@@ -366,13 +363,12 @@ $(document).ready(function() { init_codefold(0); });
static STObject makeInnerObject(SField const &name)
Definition STObject.cpp:95
void setAccountID(SField const &field, AccountID const &)
Definition STObject.cpp:783
void setFieldU32(SField const &field, std::uint32_t)
Definition STObject.cpp:747
-
std::uint32_t getFlags() const
Definition STObject.cpp:537
Discardable, editable view to a ledger.
Definition Sandbox.h:35
void apply(RawView &to)
Definition Sandbox.h:55
- -
AccountID const account_
Definition Transactor.h:145
-
beast::Journal const j_
Definition Transactor.h:143
-
ApplyContext & ctx_
Definition Transactor.h:141
+ +
AccountID const account_
Definition Transactor.h:147
+
beast::Journal const j_
Definition Transactor.h:145
+
ApplyContext & ctx_
Definition Transactor.h:143
void update(std::shared_ptr< SLE > const &sle) override
Indicate changes to a peeked SLE.
std::shared_ptr< SLE > peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
@@ -380,28 +376,21 @@ $(document).ready(function() { init_codefold(0); });
T is_same_v
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Definition Indexes.cpp:446
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
-
static std::pair< TER, bool > applyVote(ApplyContext &ctx_, Sandbox &sb, AccountID const &account_, beast::Journal j_)
Definition AMMVote.cpp:85
+
static std::pair< TER, bool > applyVote(ApplyContext &ctx_, Sandbox &sb, AccountID const &account_, beast::Journal j_)
Definition AMMVote.cpp:79
bool ammEnabled(Rules const &)
Return true if required AMM amendments are enabled.
Definition AMMCore.cpp:129
-
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
STAmount ammLPHolds(ReadView const &view, Currency const &cur1, Currency const &cur2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
Definition AMMUtils.cpp:113
-
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
@ tecAMM_EMPTY
Definition TER.h:332
@ tecINTERNAL
Definition TER.h:310
@ tecAMM_INVALID_TOKENS
Definition TER.h:331
std::uint32_t constexpr VOTE_WEIGHT_SCALE_FACTOR
Definition AMMCore.h:45
@ tesSUCCESS
Definition TER.h:244
NotTEC invalidAMMAssetPair(Issue const &issue1, Issue const &issue2, std::optional< std::pair< Issue, Issue > > const &pair=std::nullopt)
Definition AMMCore.cpp:80
-
bool isTesSuccess(TER x) noexcept
Definition TER.h:674
-
constexpr std::uint32_t tfUniversalMask
Definition TxFlags.h:63
std::uint16_t constexpr VOTE_MAX_SLOTS
Definition AMMCore.h:44
@ terNO_AMM
Definition TER.h:227
TERSubset< CanCvtToTER > TER
Definition TER.h:645
std::uint16_t constexpr TRADING_FEE_THRESHOLD
Definition AMMCore.h:31
-
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:605
std::uint32_t constexpr AUCTION_SLOT_DISCOUNTED_FEE_FRACTION
Definition AMMCore.h:38
@ temBAD_FEE
Definition TER.h:92
-
@ temINVALID_FLAG
Definition TER.h:111
-
@ temDISABLED
Definition TER.h:114
diff --git a/AMMVote_8h_source.html b/AMMVote_8h_source.html index 1fc6a82b53..850f4b195c 100644 --- a/AMMVote_8h_source.html +++ b/AMMVote_8h_source.html @@ -119,31 +119,35 @@ $(document).ready(function() { init_codefold(0); });
57 }
58
-
59 static NotTEC
-
60 preflight(PreflightContext const& ctx);
+
59 static bool
+
61
-
62 static TER
-
63 preclaim(PreclaimContext const& ctx);
+
62 static NotTEC
+
63 preflight(PreflightContext const& ctx);
64
-
65 TER
-
66 doApply() override;
-
67};
+
65 static TER
+
66 preclaim(PreclaimContext const& ctx);
+
67
+
68 TER
+
69 doApply() override;
+
70};
-
68
-
69} // namespace ripple
-
70
-
71#endif // RIPPLE_TX_AMMVOTE_H_INCLUDED
+
71
+
72} // namespace ripple
+
73
+
74#endif // RIPPLE_TX_AMMVOTE_H_INCLUDED
AMMVote implements AMM vote Transactor.
Definition AMMVote.h:51
-
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMVote.cpp:31
-
static TER preclaim(PreclaimContext const &ctx)
Definition AMMVote.cpp:62
-
TER doApply() override
Definition AMMVote.cpp:239
+
static NotTEC preflight(PreflightContext const &ctx)
Definition AMMVote.cpp:37
+
static TER preclaim(PreclaimContext const &ctx)
Definition AMMVote.cpp:56
+
TER doApply() override
Definition AMMVote.cpp:233
+
static bool checkExtraFeatures(PreflightContext const &ctx)
Definition AMMVote.cpp:31
AMMVote(ApplyContext &ctx)
Definition AMMVote.h:55
static constexpr ConsequencesFactoryType ConsequencesFactory
Definition AMMVote.h:53
State information when applying a tx.
- - - + + +
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:80
State information when preflighting a tx.
Definition Transactor.h:35
diff --git a/AMMWithdraw_8cpp_source.html b/AMMWithdraw_8cpp_source.html index 7b9ab37264..6b0e454aef 100644 --- a/AMMWithdraw_8cpp_source.html +++ b/AMMWithdraw_8cpp_source.html @@ -111,1064 +111,1071 @@ $(document).ready(function() { init_codefold(0); });
28
29namespace ripple {
30
- +
31bool
- +
33{
-
34 if (!ammEnabled(ctx.rules))
-
35 return temDISABLED;
+
34 return ammEnabled(ctx.rules);
+
35}
+
36
-
37 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
-
38 return ret;
-
39
-
40 auto const flags = ctx.tx.getFlags();
-
41 if (flags & tfWithdrawMask)
-
42 {
-
43 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid flags.";
-
44 return temINVALID_FLAG;
-
45 }
-
46
-
47 auto const amount = ctx.tx[~sfAmount];
-
48 auto const amount2 = ctx.tx[~sfAmount2];
-
49 auto const ePrice = ctx.tx[~sfEPrice];
-
50 auto const lpTokens = ctx.tx[~sfLPTokenIn];
-
51 // Valid combinations are:
-
52 // LPTokens
-
53 // tfWithdrawAll
-
54 // Amount
-
55 // tfOneAssetWithdrawAll & Amount
-
56 // Amount and Amount2
-
57 // Amount and LPTokens
-
58 // Amount and EPrice
-
59 if (std::popcount(flags & tfWithdrawSubTx) != 1)
-
60 {
-
61 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid flags.";
-
62 return temMALFORMED;
-
63 }
-
64 if (flags & tfLPToken)
-
65 {
-
66 if (!lpTokens || amount || amount2 || ePrice)
-
67 return temMALFORMED;
-
68 }
-
69 else if (flags & tfWithdrawAll)
-
70 {
-
71 if (lpTokens || amount || amount2 || ePrice)
-
72 return temMALFORMED;
-
73 }
-
74 else if (flags & tfOneAssetWithdrawAll)
-
75 {
-
76 if (!amount || lpTokens || amount2 || ePrice)
-
77 return temMALFORMED;
-
78 }
-
79 else if (flags & tfSingleAsset)
-
80 {
-
81 if (!amount || lpTokens || amount2 || ePrice)
-
82 return temMALFORMED;
-
83 }
-
84 else if (flags & tfTwoAsset)
-
85 {
-
86 if (!amount || !amount2 || lpTokens || ePrice)
-
87 return temMALFORMED;
-
88 }
-
89 else if (flags & tfOneAssetLPToken)
-
90 {
-
91 if (!amount || !lpTokens || amount2 || ePrice)
-
92 return temMALFORMED;
-
93 }
-
94 else if (flags & tfLimitLPToken)
-
95 {
-
96 if (!amount || !ePrice || lpTokens || amount2)
-
97 return temMALFORMED;
-
98 }
-
99
-
100 auto const asset = ctx.tx[sfAsset].get<Issue>();
-
101 auto const asset2 = ctx.tx[sfAsset2].get<Issue>();
-
102 if (auto const res = invalidAMMAssetPair(asset, asset2))
-
103 {
-
104 JLOG(ctx.j.debug()) << "AMM Withdraw: Invalid asset pair.";
-
105 return res;
-
106 }
-
107
-
108 if (amount && amount2 && amount->issue() == amount2->issue())
-
109 {
-
110 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid tokens, same issue."
-
111 << amount->issue() << " " << amount2->issue();
-
112 return temBAD_AMM_TOKENS;
-
113 }
-
114
-
115 if (lpTokens && *lpTokens <= beast::zero)
-
116 {
-
117 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid tokens.";
-
118 return temBAD_AMM_TOKENS;
-
119 }
-
120
-
121 if (amount)
-
122 {
-
123 if (auto const res = invalidAMMAmount(
-
124 *amount,
-
125 std::make_optional(std::make_pair(asset, asset2)),
- -
127 ePrice))
-
128 {
-
129 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid Asset1Out";
-
130 return res;
-
131 }
-
132 }
-
133
-
134 if (amount2)
-
135 {
-
136 if (auto const res = invalidAMMAmount(
-
137 *amount2, std::make_optional(std::make_pair(asset, asset2))))
-
138 {
-
139 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid Asset2OutAmount";
-
140 return res;
-
141 }
-
142 }
-
143
-
144 if (ePrice)
-
145 {
-
146 if (auto const res = invalidAMMAmount(*ePrice))
-
147 {
-
148 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid EPrice";
-
149 return res;
-
150 }
-
151 }
-
152
-
153 return preflight2(ctx);
-
154}
+ +
+ +
39{
+
40 return tfWithdrawMask;
+
41}
-
155
- -
- -
158 STAmount const& lpTokens,
-
159 std::optional<STAmount> const& tokensIn,
-
160 std::uint32_t flags)
-
161{
-
162 if (flags & (tfWithdrawAll | tfOneAssetWithdrawAll))
-
163 return lpTokens;
-
164 return tokensIn;
-
165}
+
42
+ +
+ +
45{
+
46 auto const flags = ctx.tx.getFlags();
+
47
+
48 auto const amount = ctx.tx[~sfAmount];
+
49 auto const amount2 = ctx.tx[~sfAmount2];
+
50 auto const ePrice = ctx.tx[~sfEPrice];
+
51 auto const lpTokens = ctx.tx[~sfLPTokenIn];
+
52 // Valid combinations are:
+
53 // LPTokens
+
54 // tfWithdrawAll
+
55 // Amount
+
56 // tfOneAssetWithdrawAll & Amount
+
57 // Amount and Amount2
+
58 // Amount and LPTokens
+
59 // Amount and EPrice
+
60 if (std::popcount(flags & tfWithdrawSubTx) != 1)
+
61 {
+
62 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid flags.";
+
63 return temMALFORMED;
+
64 }
+
65 if (flags & tfLPToken)
+
66 {
+
67 if (!lpTokens || amount || amount2 || ePrice)
+
68 return temMALFORMED;
+
69 }
+
70 else if (flags & tfWithdrawAll)
+
71 {
+
72 if (lpTokens || amount || amount2 || ePrice)
+
73 return temMALFORMED;
+
74 }
+
75 else if (flags & tfOneAssetWithdrawAll)
+
76 {
+
77 if (!amount || lpTokens || amount2 || ePrice)
+
78 return temMALFORMED;
+
79 }
+
80 else if (flags & tfSingleAsset)
+
81 {
+
82 if (!amount || lpTokens || amount2 || ePrice)
+
83 return temMALFORMED;
+
84 }
+
85 else if (flags & tfTwoAsset)
+
86 {
+
87 if (!amount || !amount2 || lpTokens || ePrice)
+
88 return temMALFORMED;
+
89 }
+
90 else if (flags & tfOneAssetLPToken)
+
91 {
+
92 if (!amount || !lpTokens || amount2 || ePrice)
+
93 return temMALFORMED;
+
94 }
+
95 else if (flags & tfLimitLPToken)
+
96 {
+
97 if (!amount || !ePrice || lpTokens || amount2)
+
98 return temMALFORMED;
+
99 }
+
100
+
101 auto const asset = ctx.tx[sfAsset].get<Issue>();
+
102 auto const asset2 = ctx.tx[sfAsset2].get<Issue>();
+
103 if (auto const res = invalidAMMAssetPair(asset, asset2))
+
104 {
+
105 JLOG(ctx.j.debug()) << "AMM Withdraw: Invalid asset pair.";
+
106 return res;
+
107 }
+
108
+
109 if (amount && amount2 && amount->issue() == amount2->issue())
+
110 {
+
111 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid tokens, same issue."
+
112 << amount->issue() << " " << amount2->issue();
+
113 return temBAD_AMM_TOKENS;
+
114 }
+
115
+
116 if (lpTokens && *lpTokens <= beast::zero)
+
117 {
+
118 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid tokens.";
+
119 return temBAD_AMM_TOKENS;
+
120 }
+
121
+
122 if (amount)
+
123 {
+
124 if (auto const res = invalidAMMAmount(
+
125 *amount,
+
126 std::make_optional(std::make_pair(asset, asset2)),
+ +
128 ePrice))
+
129 {
+
130 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid Asset1Out";
+
131 return res;
+
132 }
+
133 }
+
134
+
135 if (amount2)
+
136 {
+
137 if (auto const res = invalidAMMAmount(
+
138 *amount2, std::make_optional(std::make_pair(asset, asset2))))
+
139 {
+
140 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid Asset2OutAmount";
+
141 return res;
+
142 }
+
143 }
+
144
+
145 if (ePrice)
+
146 {
+
147 if (auto const res = invalidAMMAmount(*ePrice))
+
148 {
+
149 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid EPrice";
+
150 return res;
+
151 }
+
152 }
+
153
+
154 return tesSUCCESS;
+
155}
-
166
-
167TER
-
- -
169{
-
170 auto const accountID = ctx.tx[sfAccount];
-
171
-
172 auto const ammSle =
-
173 ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
-
174 if (!ammSle)
-
175 {
-
176 JLOG(ctx.j.debug()) << "AMM Withdraw: Invalid asset pair.";
-
177 return terNO_AMM;
-
178 }
-
179
-
180 auto const amount = ctx.tx[~sfAmount];
-
181 auto const amount2 = ctx.tx[~sfAmount2];
-
182
-
183 auto const expected = ammHolds(
-
184 ctx.view,
-
185 *ammSle,
-
186 amount ? amount->issue() : std::optional<Issue>{},
-
187 amount2 ? amount2->issue() : std::optional<Issue>{},
- -
189 ctx.j);
-
190 if (!expected)
-
191 return expected.error();
-
192 auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected;
-
193 if (lptAMMBalance == beast::zero)
-
194 return tecAMM_EMPTY;
-
195 if (amountBalance <= beast::zero || amount2Balance <= beast::zero ||
-
196 lptAMMBalance < beast::zero)
-
197 {
-
198 JLOG(ctx.j.debug())
-
199 << "AMM Withdraw: reserves or tokens balance is zero.";
-
200 return tecINTERNAL; // LCOV_EXCL_LINE
-
201 }
-
202
-
203 auto const ammAccountID = ammSle->getAccountID(sfAccount);
-
204
-
205 auto checkAmount = [&](std::optional<STAmount> const& amount,
-
206 auto const& balance) -> TER {
-
207 if (amount)
-
208 {
-
209 if (amount > balance)
-
210 {
-
211 JLOG(ctx.j.debug())
-
212 << "AMM Withdraw: withdrawing more than the balance, "
-
213 << *amount;
-
214 return tecAMM_BALANCE;
-
215 }
-
216 if (auto const ter =
-
217 requireAuth(ctx.view, amount->issue(), accountID))
-
218 {
-
219 JLOG(ctx.j.debug())
-
220 << "AMM Withdraw: account is not authorized, "
-
221 << amount->issue();
-
222 return ter;
-
223 }
-
224 // AMM account or currency frozen
-
225 if (isFrozen(ctx.view, ammAccountID, amount->issue()))
-
226 {
-
227 JLOG(ctx.j.debug())
-
228 << "AMM Withdraw: AMM account or currency is frozen, "
-
229 << to_string(accountID);
-
230 return tecFROZEN;
-
231 }
-
232 // Account frozen
-
233 if (isIndividualFrozen(ctx.view, accountID, amount->issue()))
-
234 {
-
235 JLOG(ctx.j.debug()) << "AMM Withdraw: account is frozen, "
-
236 << to_string(accountID) << " "
-
237 << to_string(amount->issue().currency);
-
238 return tecFROZEN;
-
239 }
-
240 }
-
241 return tesSUCCESS;
-
242 };
-
243
-
244 if (auto const ter = checkAmount(amount, amountBalance))
-
245 return ter;
-
246
-
247 if (auto const ter = checkAmount(amount2, amount2Balance))
-
248 return ter;
-
249
-
250 auto const lpTokens =
-
251 ammLPHolds(ctx.view, *ammSle, ctx.tx[sfAccount], ctx.j);
-
252 auto const lpTokensWithdraw =
-
253 tokensWithdraw(lpTokens, ctx.tx[~sfLPTokenIn], ctx.tx.getFlags());
-
254
-
255 if (lpTokens <= beast::zero)
-
256 {
-
257 JLOG(ctx.j.debug()) << "AMM Withdraw: tokens balance is zero.";
-
258 return tecAMM_BALANCE;
-
259 }
-
260
-
261 if (lpTokensWithdraw && lpTokensWithdraw->issue() != lpTokens.issue())
-
262 {
-
263 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid LPTokens.";
-
264 return temBAD_AMM_TOKENS;
-
265 }
-
266
-
267 if (lpTokensWithdraw && *lpTokensWithdraw > lpTokens)
-
268 {
-
269 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid tokens.";
- -
271 }
-
272
-
273 if (auto const ePrice = ctx.tx[~sfEPrice];
-
274 ePrice && ePrice->issue() != lpTokens.issue())
-
275 {
-
276 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid EPrice.";
-
277 return temBAD_AMM_TOKENS;
-
278 }
-
279
-
280 if (ctx.tx.getFlags() & (tfLPToken | tfWithdrawAll))
-
281 {
-
282 if (auto const ter = checkAmount(amountBalance, amountBalance))
-
283 return ter;
-
284 if (auto const ter = checkAmount(amount2Balance, amount2Balance))
-
285 return ter;
-
286 }
-
287
-
288 return tesSUCCESS;
-
289}
+
156
+ +
+ +
159 STAmount const& lpTokens,
+
160 std::optional<STAmount> const& tokensIn,
+
161 std::uint32_t flags)
+
162{
+
163 if (flags & (tfWithdrawAll | tfOneAssetWithdrawAll))
+
164 return lpTokens;
+
165 return tokensIn;
+
166}
-
290
- -
- -
293{
-
294 auto const amount = ctx_.tx[~sfAmount];
-
295 auto const amount2 = ctx_.tx[~sfAmount2];
-
296 auto const ePrice = ctx_.tx[~sfEPrice];
-
297 auto ammSle = sb.peek(keylet::amm(ctx_.tx[sfAsset], ctx_.tx[sfAsset2]));
-
298 if (!ammSle)
-
299 return {tecINTERNAL, false}; // LCOV_EXCL_LINE
-
300 auto const ammAccountID = (*ammSle)[sfAccount];
-
301 auto const accountSle = sb.read(keylet::account(ammAccountID));
-
302 if (!accountSle)
-
303 return {tecINTERNAL, false}; // LCOV_EXCL_LINE
-
304 auto const lpTokens =
-
305 ammLPHolds(ctx_.view(), *ammSle, ctx_.tx[sfAccount], ctx_.journal);
-
306 auto const lpTokensWithdraw =
-
307 tokensWithdraw(lpTokens, ctx_.tx[~sfLPTokenIn], ctx_.tx.getFlags());
-
308
-
309 // Due to rounding, the LPTokenBalance of the last LP
-
310 // might not match the LP's trustline balance
-
311 if (sb.rules().enabled(fixAMMv1_1))
-
312 {
-
313 if (auto const res =
-
314 verifyAndAdjustLPTokenBalance(sb, lpTokens, ammSle, account_);
-
315 !res)
-
316 return {res.error(), false};
-
317 }
-
318
-
319 auto const tfee = getTradingFee(ctx_.view(), *ammSle, account_);
-
320
-
321 auto const expected = ammHolds(
-
322 sb,
-
323 *ammSle,
-
324 amount ? amount->issue() : std::optional<Issue>{},
-
325 amount2 ? amount2->issue() : std::optional<Issue>{},
- -
327 ctx_.journal);
-
328 if (!expected)
-
329 return {expected.error(), false};
-
330 auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected;
-
331
-
332 auto const subTxType = ctx_.tx.getFlags() & tfWithdrawSubTx;
-
333
-
334 auto const [result, newLPTokenBalance] =
-
335 [&,
-
336 &amountBalance = amountBalance,
-
337 &amount2Balance = amount2Balance,
-
338 &lptAMMBalance = lptAMMBalance]() -> std::pair<TER, STAmount> {
-
339 if (subTxType & tfTwoAsset)
-
340 return equalWithdrawLimit(
-
341 sb,
-
342 *ammSle,
-
343 ammAccountID,
-
344 amountBalance,
-
345 amount2Balance,
-
346 lptAMMBalance,
-
347 *amount,
-
348 *amount2,
-
349 tfee);
-
350 if (subTxType & tfOneAssetLPToken || subTxType & tfOneAssetWithdrawAll)
- -
352 sb,
-
353 *ammSle,
-
354 ammAccountID,
-
355 amountBalance,
-
356 lptAMMBalance,
-
357 *amount,
-
358 *lpTokensWithdraw,
-
359 tfee);
-
360 if (subTxType & tfLimitLPToken)
- -
362 sb,
-
363 *ammSle,
-
364 ammAccountID,
-
365 amountBalance,
-
366 lptAMMBalance,
-
367 *amount,
-
368 *ePrice,
-
369 tfee);
-
370 if (subTxType & tfSingleAsset)
-
371 return singleWithdraw(
-
372 sb,
-
373 *ammSle,
-
374 ammAccountID,
-
375 amountBalance,
-
376 lptAMMBalance,
-
377 *amount,
-
378 tfee);
-
379 if (subTxType & tfLPToken || subTxType & tfWithdrawAll)
-
380 {
-
381 return equalWithdrawTokens(
-
382 sb,
-
383 *ammSle,
-
384 ammAccountID,
-
385 amountBalance,
-
386 amount2Balance,
-
387 lptAMMBalance,
-
388 lpTokens,
-
389 *lpTokensWithdraw,
-
390 tfee);
-
391 }
-
392 // should not happen.
-
393 // LCOV_EXCL_START
-
394 JLOG(j_.error()) << "AMM Withdraw: invalid options.";
- -
396 // LCOV_EXCL_STOP
-
397 }();
-
398
-
399 if (result != tesSUCCESS)
-
400 return {result, false};
-
401
-
402 auto const res = deleteAMMAccountIfEmpty(
-
403 sb,
-
404 ammSle,
-
405 newLPTokenBalance,
-
406 ctx_.tx[sfAsset].get<Issue>(),
-
407 ctx_.tx[sfAsset2].get<Issue>(),
-
408 j_);
-
409 // LCOV_EXCL_START
-
410 if (!res.second)
-
411 return {res.first, false};
-
412 // LCOV_EXCL_STOP
-
413
-
414 JLOG(ctx_.journal.trace())
-
415 << "AMM Withdraw: tokens " << to_string(newLPTokenBalance.iou()) << " "
-
416 << to_string(lpTokens.iou()) << " " << to_string(lptAMMBalance.iou());
-
417
-
418 return {tesSUCCESS, true};
-
419}
+
167
+
168TER
+
+ +
170{
+
171 auto const accountID = ctx.tx[sfAccount];
+
172
+
173 auto const ammSle =
+
174 ctx.view.read(keylet::amm(ctx.tx[sfAsset], ctx.tx[sfAsset2]));
+
175 if (!ammSle)
+
176 {
+
177 JLOG(ctx.j.debug()) << "AMM Withdraw: Invalid asset pair.";
+
178 return terNO_AMM;
+
179 }
+
180
+
181 auto const amount = ctx.tx[~sfAmount];
+
182 auto const amount2 = ctx.tx[~sfAmount2];
+
183
+
184 auto const expected = ammHolds(
+
185 ctx.view,
+
186 *ammSle,
+
187 amount ? amount->issue() : std::optional<Issue>{},
+
188 amount2 ? amount2->issue() : std::optional<Issue>{},
+ +
190 ctx.j);
+
191 if (!expected)
+
192 return expected.error();
+
193 auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected;
+
194 if (lptAMMBalance == beast::zero)
+
195 return tecAMM_EMPTY;
+
196 if (amountBalance <= beast::zero || amount2Balance <= beast::zero ||
+
197 lptAMMBalance < beast::zero)
+
198 {
+
199 JLOG(ctx.j.debug())
+
200 << "AMM Withdraw: reserves or tokens balance is zero.";
+
201 return tecINTERNAL; // LCOV_EXCL_LINE
+
202 }
+
203
+
204 auto const ammAccountID = ammSle->getAccountID(sfAccount);
+
205
+
206 auto checkAmount = [&](std::optional<STAmount> const& amount,
+
207 auto const& balance) -> TER {
+
208 if (amount)
+
209 {
+
210 if (amount > balance)
+
211 {
+
212 JLOG(ctx.j.debug())
+
213 << "AMM Withdraw: withdrawing more than the balance, "
+
214 << *amount;
+
215 return tecAMM_BALANCE;
+
216 }
+
217 if (auto const ter =
+
218 requireAuth(ctx.view, amount->issue(), accountID))
+
219 {
+
220 JLOG(ctx.j.debug())
+
221 << "AMM Withdraw: account is not authorized, "
+
222 << amount->issue();
+
223 return ter;
+
224 }
+
225 // AMM account or currency frozen
+
226 if (isFrozen(ctx.view, ammAccountID, amount->issue()))
+
227 {
+
228 JLOG(ctx.j.debug())
+
229 << "AMM Withdraw: AMM account or currency is frozen, "
+
230 << to_string(accountID);
+
231 return tecFROZEN;
+
232 }
+
233 // Account frozen
+
234 if (isIndividualFrozen(ctx.view, accountID, amount->issue()))
+
235 {
+
236 JLOG(ctx.j.debug()) << "AMM Withdraw: account is frozen, "
+
237 << to_string(accountID) << " "
+
238 << to_string(amount->issue().currency);
+
239 return tecFROZEN;
+
240 }
+
241 }
+
242 return tesSUCCESS;
+
243 };
+
244
+
245 if (auto const ter = checkAmount(amount, amountBalance))
+
246 return ter;
+
247
+
248 if (auto const ter = checkAmount(amount2, amount2Balance))
+
249 return ter;
+
250
+
251 auto const lpTokens =
+
252 ammLPHolds(ctx.view, *ammSle, ctx.tx[sfAccount], ctx.j);
+
253 auto const lpTokensWithdraw =
+
254 tokensWithdraw(lpTokens, ctx.tx[~sfLPTokenIn], ctx.tx.getFlags());
+
255
+
256 if (lpTokens <= beast::zero)
+
257 {
+
258 JLOG(ctx.j.debug()) << "AMM Withdraw: tokens balance is zero.";
+
259 return tecAMM_BALANCE;
+
260 }
+
261
+
262 if (lpTokensWithdraw && lpTokensWithdraw->issue() != lpTokens.issue())
+
263 {
+
264 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid LPTokens.";
+
265 return temBAD_AMM_TOKENS;
+
266 }
+
267
+
268 if (lpTokensWithdraw && *lpTokensWithdraw > lpTokens)
+
269 {
+
270 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid tokens.";
+ +
272 }
+
273
+
274 if (auto const ePrice = ctx.tx[~sfEPrice];
+
275 ePrice && ePrice->issue() != lpTokens.issue())
+
276 {
+
277 JLOG(ctx.j.debug()) << "AMM Withdraw: invalid EPrice.";
+
278 return temBAD_AMM_TOKENS;
+
279 }
+
280
+
281 if (ctx.tx.getFlags() & (tfLPToken | tfWithdrawAll))
+
282 {
+
283 if (auto const ter = checkAmount(amountBalance, amountBalance))
+
284 return ter;
+
285 if (auto const ter = checkAmount(amount2Balance, amount2Balance))
+
286 return ter;
+
287 }
+
288
+
289 return tesSUCCESS;
+
290}
-
420
-
421TER
-
- -
423{
-
424 // This is the ledger view that we work against. Transactions are applied
-
425 // as we go on processing transactions.
-
426 Sandbox sb(&ctx_.view());
-
427
-
428 auto const result = applyGuts(sb);
-
429 if (result.second)
-
430 sb.apply(ctx_.rawView());
-
431
-
432 return result.first;
-
433}
+
291
+ +
+ +
294{
+
295 auto const amount = ctx_.tx[~sfAmount];
+
296 auto const amount2 = ctx_.tx[~sfAmount2];
+
297 auto const ePrice = ctx_.tx[~sfEPrice];
+
298 auto ammSle = sb.peek(keylet::amm(ctx_.tx[sfAsset], ctx_.tx[sfAsset2]));
+
299 if (!ammSle)
+
300 return {tecINTERNAL, false}; // LCOV_EXCL_LINE
+
301 auto const ammAccountID = (*ammSle)[sfAccount];
+
302 auto const accountSle = sb.read(keylet::account(ammAccountID));
+
303 if (!accountSle)
+
304 return {tecINTERNAL, false}; // LCOV_EXCL_LINE
+
305 auto const lpTokens =
+
306 ammLPHolds(ctx_.view(), *ammSle, ctx_.tx[sfAccount], ctx_.journal);
+
307 auto const lpTokensWithdraw =
+
308 tokensWithdraw(lpTokens, ctx_.tx[~sfLPTokenIn], ctx_.tx.getFlags());
+
309
+
310 // Due to rounding, the LPTokenBalance of the last LP
+
311 // might not match the LP's trustline balance
+
312 if (sb.rules().enabled(fixAMMv1_1))
+
313 {
+
314 if (auto const res =
+
315 verifyAndAdjustLPTokenBalance(sb, lpTokens, ammSle, account_);
+
316 !res)
+
317 return {res.error(), false};
+
318 }
+
319
+
320 auto const tfee = getTradingFee(ctx_.view(), *ammSle, account_);
+
321
+
322 auto const expected = ammHolds(
+
323 sb,
+
324 *ammSle,
+
325 amount ? amount->issue() : std::optional<Issue>{},
+
326 amount2 ? amount2->issue() : std::optional<Issue>{},
+ +
328 ctx_.journal);
+
329 if (!expected)
+
330 return {expected.error(), false};
+
331 auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected;
+
332
+
333 auto const subTxType = ctx_.tx.getFlags() & tfWithdrawSubTx;
+
334
+
335 auto const [result, newLPTokenBalance] =
+
336 [&,
+
337 &amountBalance = amountBalance,
+
338 &amount2Balance = amount2Balance,
+
339 &lptAMMBalance = lptAMMBalance]() -> std::pair<TER, STAmount> {
+
340 if (subTxType & tfTwoAsset)
+
341 return equalWithdrawLimit(
+
342 sb,
+
343 *ammSle,
+
344 ammAccountID,
+
345 amountBalance,
+
346 amount2Balance,
+
347 lptAMMBalance,
+
348 *amount,
+
349 *amount2,
+
350 tfee);
+
351 if (subTxType & tfOneAssetLPToken || subTxType & tfOneAssetWithdrawAll)
+ +
353 sb,
+
354 *ammSle,
+
355 ammAccountID,
+
356 amountBalance,
+
357 lptAMMBalance,
+
358 *amount,
+
359 *lpTokensWithdraw,
+
360 tfee);
+
361 if (subTxType & tfLimitLPToken)
+ +
363 sb,
+
364 *ammSle,
+
365 ammAccountID,
+
366 amountBalance,
+
367 lptAMMBalance,
+
368 *amount,
+
369 *ePrice,
+
370 tfee);
+
371 if (subTxType & tfSingleAsset)
+
372 return singleWithdraw(
+
373 sb,
+
374 *ammSle,
+
375 ammAccountID,
+
376 amountBalance,
+
377 lptAMMBalance,
+
378 *amount,
+
379 tfee);
+
380 if (subTxType & tfLPToken || subTxType & tfWithdrawAll)
+
381 {
+
382 return equalWithdrawTokens(
+
383 sb,
+
384 *ammSle,
+
385 ammAccountID,
+
386 amountBalance,
+
387 amount2Balance,
+
388 lptAMMBalance,
+
389 lpTokens,
+
390 *lpTokensWithdraw,
+
391 tfee);
+
392 }
+
393 // should not happen.
+
394 // LCOV_EXCL_START
+
395 JLOG(j_.error()) << "AMM Withdraw: invalid options.";
+ +
397 // LCOV_EXCL_STOP
+
398 }();
+
399
+
400 if (result != tesSUCCESS)
+
401 return {result, false};
+
402
+
403 auto const res = deleteAMMAccountIfEmpty(
+
404 sb,
+
405 ammSle,
+
406 newLPTokenBalance,
+
407 ctx_.tx[sfAsset].get<Issue>(),
+
408 ctx_.tx[sfAsset2].get<Issue>(),
+
409 j_);
+
410 // LCOV_EXCL_START
+
411 if (!res.second)
+
412 return {res.first, false};
+
413 // LCOV_EXCL_STOP
+
414
+
415 JLOG(ctx_.journal.trace())
+
416 << "AMM Withdraw: tokens " << to_string(newLPTokenBalance.iou()) << " "
+
417 << to_string(lpTokens.iou()) << " " << to_string(lptAMMBalance.iou());
+
418
+
419 return {tesSUCCESS, true};
+
420}
-
434
- -
- -
437 Sandbox& view,
-
438 SLE const& ammSle,
-
439 AccountID const& ammAccount,
-
440 STAmount const& amountBalance,
-
441 STAmount const& amountWithdraw,
-
442 std::optional<STAmount> const& amount2Withdraw,
-
443 STAmount const& lpTokensAMMBalance,
-
444 STAmount const& lpTokensWithdraw,
-
445 std::uint16_t tfee)
-
446{
-
447 TER ter;
-
448 STAmount newLPTokenBalance;
-
449 std::tie(ter, newLPTokenBalance, std::ignore, std::ignore) = withdraw(
-
450 view,
-
451 ammSle,
-
452 ammAccount,
-
453 account_,
-
454 amountBalance,
-
455 amountWithdraw,
-
456 amount2Withdraw,
-
457 lpTokensAMMBalance,
-
458 lpTokensWithdraw,
-
459 tfee,
- - - -
463 j_);
-
464 return {ter, newLPTokenBalance};
-
465}
+
421
+
422TER
+
+ +
424{
+
425 // This is the ledger view that we work against. Transactions are applied
+
426 // as we go on processing transactions.
+
427 Sandbox sb(&ctx_.view());
+
428
+
429 auto const result = applyGuts(sb);
+
430 if (result.second)
+
431 sb.apply(ctx_.rawView());
+
432
+
433 return result.first;
+
434}
-
466
- -
- -
469 Sandbox& view,
-
470 SLE const& ammSle,
-
471 AccountID const& ammAccount,
-
472 AccountID const& account,
-
473 STAmount const& amountBalance,
-
474 STAmount const& amountWithdraw,
-
475 std::optional<STAmount> const& amount2Withdraw,
-
476 STAmount const& lpTokensAMMBalance,
-
477 STAmount const& lpTokensWithdraw,
-
478 std::uint16_t tfee,
-
479 FreezeHandling freezeHandling,
-
480 WithdrawAll withdrawAll,
-
481 XRPAmount const& priorBalance,
-
482 beast::Journal const& journal)
-
483{
-
484 auto const lpTokens = ammLPHolds(view, ammSle, account, journal);
-
485 auto const expected = ammHolds(
-
486 view,
-
487 ammSle,
-
488 amountWithdraw.issue(),
- -
490 freezeHandling,
-
491 journal);
-
492 // LCOV_EXCL_START
-
493 if (!expected)
-
494 return {expected.error(), STAmount{}, STAmount{}, STAmount{}};
-
495 // LCOV_EXCL_STOP
-
496 auto const [curBalance, curBalance2, _] = *expected;
-
497 (void)_;
-
498
-
499 auto const
-
500 [amountWithdrawActual, amount2WithdrawActual, lpTokensWithdrawActual] =
- -
502 if (withdrawAll == WithdrawAll::No)
- -
504 amountBalance,
-
505 amountWithdraw,
-
506 amount2Withdraw,
-
507 lpTokensAMMBalance,
-
508 lpTokensWithdraw,
-
509 tfee,
- -
511 return std::make_tuple(
-
512 amountWithdraw, amount2Withdraw, lpTokensWithdraw);
-
513 }();
-
514
-
515 if (lpTokensWithdrawActual <= beast::zero ||
-
516 lpTokensWithdrawActual > lpTokens)
-
517 {
-
518 JLOG(journal.debug())
-
519 << "AMM Withdraw: failed to withdraw, invalid LP tokens: "
-
520 << lpTokensWithdrawActual << " " << lpTokens << " "
-
521 << lpTokensAMMBalance;
- -
523 }
-
524
-
525 // Should not happen since the only LP on last withdraw
-
526 // has the balance set to the lp token trustline balance.
-
527 if (view.rules().enabled(fixAMMv1_1) &&
-
528 lpTokensWithdrawActual > lpTokensAMMBalance)
-
529 {
-
530 // LCOV_EXCL_START
-
531 JLOG(journal.debug())
-
532 << "AMM Withdraw: failed to withdraw, unexpected LP tokens: "
-
533 << lpTokensWithdrawActual << " " << lpTokens << " "
-
534 << lpTokensAMMBalance;
-
535 return {tecINTERNAL, STAmount{}, STAmount{}, STAmount{}};
-
536 // LCOV_EXCL_STOP
-
537 }
-
538
-
539 // Withdrawing one side of the pool
-
540 if ((amountWithdrawActual == curBalance &&
-
541 amount2WithdrawActual != curBalance2) ||
-
542 (amount2WithdrawActual == curBalance2 &&
-
543 amountWithdrawActual != curBalance))
-
544 {
-
545 JLOG(journal.debug())
-
546 << "AMM Withdraw: failed to withdraw one side of the pool "
-
547 << " curBalance: " << curBalance << " " << amountWithdrawActual
-
548 << " lpTokensBalance: " << lpTokensWithdraw << " lptBalance "
-
549 << lpTokensAMMBalance;
-
550 return {tecAMM_BALANCE, STAmount{}, STAmount{}, STAmount{}};
-
551 }
-
552
-
553 // May happen if withdrawing an amount close to one side of the pool
-
554 if (lpTokensWithdrawActual == lpTokensAMMBalance &&
-
555 (amountWithdrawActual != curBalance ||
-
556 amount2WithdrawActual != curBalance2))
-
557 {
-
558 JLOG(journal.debug())
-
559 << "AMM Withdraw: failed to withdraw all tokens "
-
560 << " curBalance: " << curBalance << " " << amountWithdrawActual
-
561 << " curBalance2: " << amount2WithdrawActual.value_or(STAmount{0})
-
562 << " lpTokensBalance: " << lpTokensWithdraw << " lptBalance "
-
563 << lpTokensAMMBalance;
-
564 return {tecAMM_BALANCE, STAmount{}, STAmount{}, STAmount{}};
-
565 }
-
566
-
567 // Withdrawing more than the pool's balance
-
568 if (amountWithdrawActual > curBalance ||
-
569 amount2WithdrawActual > curBalance2)
-
570 {
-
571 JLOG(journal.debug())
-
572 << "AMM Withdraw: withdrawing more than the pool's balance "
-
573 << " curBalance: " << curBalance << " " << amountWithdrawActual
-
574 << " curBalance2: " << curBalance2 << " "
-
575 << (amount2WithdrawActual ? *amount2WithdrawActual : STAmount{})
-
576 << " lpTokensBalance: " << lpTokensWithdraw << " lptBalance "
-
577 << lpTokensAMMBalance;
-
578 return {tecAMM_BALANCE, STAmount{}, STAmount{}, STAmount{}};
-
579 }
-
580
-
581 // Check the reserve in case a trustline has to be created
-
582 bool const enabledFixAMMv1_2 = view.rules().enabled(fixAMMv1_2);
-
583 auto sufficientReserve = [&](Issue const& issue) -> TER {
-
584 if (!enabledFixAMMv1_2 || isXRP(issue))
-
585 return tesSUCCESS;
-
586 if (!view.exists(keylet::line(account, issue)))
-
587 {
-
588 auto const sleAccount = view.read(keylet::account(account));
-
589 if (!sleAccount)
-
590 return tecINTERNAL; // LCOV_EXCL_LINE
-
591 auto const balance = (*sleAccount)[sfBalance].xrp();
-
592 std::uint32_t const ownerCount = sleAccount->at(sfOwnerCount);
-
593
-
594 // See also SetTrust::doApply()
-
595 XRPAmount const reserve(
-
596 (ownerCount < 2) ? XRPAmount(beast::zero)
-
597 : view.fees().accountReserve(ownerCount + 1));
-
598
-
599 if (std::max(priorBalance, balance) < reserve)
- -
601 }
-
602 return tesSUCCESS;
-
603 };
-
604
-
605 if (auto const err = sufficientReserve(amountWithdrawActual.issue()))
-
606 return {err, STAmount{}, STAmount{}, STAmount{}};
-
607
-
608 // Withdraw amountWithdraw
-
609 auto res = accountSend(
-
610 view,
-
611 ammAccount,
-
612 account,
-
613 amountWithdrawActual,
-
614 journal,
- -
616 if (res != tesSUCCESS)
-
617 {
-
618 // LCOV_EXCL_START
-
619 JLOG(journal.debug())
-
620 << "AMM Withdraw: failed to withdraw " << amountWithdrawActual;
-
621 return {res, STAmount{}, STAmount{}, STAmount{}};
-
622 // LCOV_EXCL_STOP
-
623 }
-
624
-
625 // Withdraw amount2Withdraw
-
626 if (amount2WithdrawActual)
-
627 {
-
628 if (auto const err = sufficientReserve(amount2WithdrawActual->issue());
-
629 err != tesSUCCESS)
-
630 return {err, STAmount{}, STAmount{}, STAmount{}};
-
631
-
632 res = accountSend(
-
633 view,
-
634 ammAccount,
-
635 account,
-
636 *amount2WithdrawActual,
-
637 journal,
- -
639 if (res != tesSUCCESS)
-
640 {
-
641 // LCOV_EXCL_START
-
642 JLOG(journal.debug()) << "AMM Withdraw: failed to withdraw "
-
643 << *amount2WithdrawActual;
-
644 return {res, STAmount{}, STAmount{}, STAmount{}};
-
645 // LCOV_EXCL_STOP
-
646 }
-
647 }
-
648
-
649 // Withdraw LP tokens
-
650 res = redeemIOU(
-
651 view,
-
652 account,
-
653 lpTokensWithdrawActual,
-
654 lpTokensWithdrawActual.issue(),
-
655 journal);
-
656 if (res != tesSUCCESS)
-
657 {
-
658 // LCOV_EXCL_START
-
659 JLOG(journal.debug()) << "AMM Withdraw: failed to withdraw LPTokens";
-
660 return {res, STAmount{}, STAmount{}, STAmount{}};
-
661 // LCOV_EXCL_STOP
-
662 }
-
663
-
664 return std::make_tuple(
- -
666 lpTokensAMMBalance - lpTokensWithdrawActual,
-
667 amountWithdrawActual,
-
668 amount2WithdrawActual);
-
669}
+
435
+ +
+ +
438 Sandbox& view,
+
439 SLE const& ammSle,
+
440 AccountID const& ammAccount,
+
441 STAmount const& amountBalance,
+
442 STAmount const& amountWithdraw,
+
443 std::optional<STAmount> const& amount2Withdraw,
+
444 STAmount const& lpTokensAMMBalance,
+
445 STAmount const& lpTokensWithdraw,
+
446 std::uint16_t tfee)
+
447{
+
448 TER ter;
+
449 STAmount newLPTokenBalance;
+
450 std::tie(ter, newLPTokenBalance, std::ignore, std::ignore) = withdraw(
+
451 view,
+
452 ammSle,
+
453 ammAccount,
+
454 account_,
+
455 amountBalance,
+
456 amountWithdraw,
+
457 amount2Withdraw,
+
458 lpTokensAMMBalance,
+
459 lpTokensWithdraw,
+
460 tfee,
+ + + +
464 j_);
+
465 return {ter, newLPTokenBalance};
+
466}
-
670
-
671static STAmount
-
- -
673 Rules const& rules,
-
674 STAmount const& lptAMMBalance,
-
675 STAmount const& lpTokensWithdraw,
-
676 WithdrawAll withdrawAll)
-
677{
-
678 if (!rules.enabled(fixAMMv1_3) || withdrawAll == WithdrawAll::Yes)
-
679 return lpTokensWithdraw;
-
680 return adjustLPTokens(lptAMMBalance, lpTokensWithdraw, IsDeposit::No);
-
681}
+
467
+ +
+ +
470 Sandbox& view,
+
471 SLE const& ammSle,
+
472 AccountID const& ammAccount,
+
473 AccountID const& account,
+
474 STAmount const& amountBalance,
+
475 STAmount const& amountWithdraw,
+
476 std::optional<STAmount> const& amount2Withdraw,
+
477 STAmount const& lpTokensAMMBalance,
+
478 STAmount const& lpTokensWithdraw,
+
479 std::uint16_t tfee,
+
480 FreezeHandling freezeHandling,
+
481 WithdrawAll withdrawAll,
+
482 XRPAmount const& priorBalance,
+
483 beast::Journal const& journal)
+
484{
+
485 auto const lpTokens = ammLPHolds(view, ammSle, account, journal);
+
486 auto const expected = ammHolds(
+
487 view,
+
488 ammSle,
+
489 amountWithdraw.issue(),
+ +
491 freezeHandling,
+
492 journal);
+
493 // LCOV_EXCL_START
+
494 if (!expected)
+
495 return {expected.error(), STAmount{}, STAmount{}, STAmount{}};
+
496 // LCOV_EXCL_STOP
+
497 auto const [curBalance, curBalance2, _] = *expected;
+
498 (void)_;
+
499
+
500 auto const
+
501 [amountWithdrawActual, amount2WithdrawActual, lpTokensWithdrawActual] =
+ +
503 if (withdrawAll == WithdrawAll::No)
+ +
505 amountBalance,
+
506 amountWithdraw,
+
507 amount2Withdraw,
+
508 lpTokensAMMBalance,
+
509 lpTokensWithdraw,
+
510 tfee,
+ +
512 return std::make_tuple(
+
513 amountWithdraw, amount2Withdraw, lpTokensWithdraw);
+
514 }();
+
515
+
516 if (lpTokensWithdrawActual <= beast::zero ||
+
517 lpTokensWithdrawActual > lpTokens)
+
518 {
+
519 JLOG(journal.debug())
+
520 << "AMM Withdraw: failed to withdraw, invalid LP tokens: "
+
521 << lpTokensWithdrawActual << " " << lpTokens << " "
+
522 << lpTokensAMMBalance;
+ +
524 }
+
525
+
526 // Should not happen since the only LP on last withdraw
+
527 // has the balance set to the lp token trustline balance.
+
528 if (view.rules().enabled(fixAMMv1_1) &&
+
529 lpTokensWithdrawActual > lpTokensAMMBalance)
+
530 {
+
531 // LCOV_EXCL_START
+
532 JLOG(journal.debug())
+
533 << "AMM Withdraw: failed to withdraw, unexpected LP tokens: "
+
534 << lpTokensWithdrawActual << " " << lpTokens << " "
+
535 << lpTokensAMMBalance;
+
536 return {tecINTERNAL, STAmount{}, STAmount{}, STAmount{}};
+
537 // LCOV_EXCL_STOP
+
538 }
+
539
+
540 // Withdrawing one side of the pool
+
541 if ((amountWithdrawActual == curBalance &&
+
542 amount2WithdrawActual != curBalance2) ||
+
543 (amount2WithdrawActual == curBalance2 &&
+
544 amountWithdrawActual != curBalance))
+
545 {
+
546 JLOG(journal.debug())
+
547 << "AMM Withdraw: failed to withdraw one side of the pool "
+
548 << " curBalance: " << curBalance << " " << amountWithdrawActual
+
549 << " lpTokensBalance: " << lpTokensWithdraw << " lptBalance "
+
550 << lpTokensAMMBalance;
+
551 return {tecAMM_BALANCE, STAmount{}, STAmount{}, STAmount{}};
+
552 }
+
553
+
554 // May happen if withdrawing an amount close to one side of the pool
+
555 if (lpTokensWithdrawActual == lpTokensAMMBalance &&
+
556 (amountWithdrawActual != curBalance ||
+
557 amount2WithdrawActual != curBalance2))
+
558 {
+
559 JLOG(journal.debug())
+
560 << "AMM Withdraw: failed to withdraw all tokens "
+
561 << " curBalance: " << curBalance << " " << amountWithdrawActual
+
562 << " curBalance2: " << amount2WithdrawActual.value_or(STAmount{0})
+
563 << " lpTokensBalance: " << lpTokensWithdraw << " lptBalance "
+
564 << lpTokensAMMBalance;
+
565 return {tecAMM_BALANCE, STAmount{}, STAmount{}, STAmount{}};
+
566 }
+
567
+
568 // Withdrawing more than the pool's balance
+
569 if (amountWithdrawActual > curBalance ||
+
570 amount2WithdrawActual > curBalance2)
+
571 {
+
572 JLOG(journal.debug())
+
573 << "AMM Withdraw: withdrawing more than the pool's balance "
+
574 << " curBalance: " << curBalance << " " << amountWithdrawActual
+
575 << " curBalance2: " << curBalance2 << " "
+
576 << (amount2WithdrawActual ? *amount2WithdrawActual : STAmount{})
+
577 << " lpTokensBalance: " << lpTokensWithdraw << " lptBalance "
+
578 << lpTokensAMMBalance;
+
579 return {tecAMM_BALANCE, STAmount{}, STAmount{}, STAmount{}};
+
580 }
+
581
+
582 // Check the reserve in case a trustline has to be created
+
583 bool const enabledFixAMMv1_2 = view.rules().enabled(fixAMMv1_2);
+
584 auto sufficientReserve = [&](Issue const& issue) -> TER {
+
585 if (!enabledFixAMMv1_2 || isXRP(issue))
+
586 return tesSUCCESS;
+
587 if (!view.exists(keylet::line(account, issue)))
+
588 {
+
589 auto const sleAccount = view.read(keylet::account(account));
+
590 if (!sleAccount)
+
591 return tecINTERNAL; // LCOV_EXCL_LINE
+
592 auto const balance = (*sleAccount)[sfBalance].xrp();
+
593 std::uint32_t const ownerCount = sleAccount->at(sfOwnerCount);
+
594
+
595 // See also SetTrust::doApply()
+
596 XRPAmount const reserve(
+
597 (ownerCount < 2) ? XRPAmount(beast::zero)
+
598 : view.fees().accountReserve(ownerCount + 1));
+
599
+
600 if (std::max(priorBalance, balance) < reserve)
+ +
602 }
+
603 return tesSUCCESS;
+
604 };
+
605
+
606 if (auto const err = sufficientReserve(amountWithdrawActual.issue()))
+
607 return {err, STAmount{}, STAmount{}, STAmount{}};
+
608
+
609 // Withdraw amountWithdraw
+
610 auto res = accountSend(
+
611 view,
+
612 ammAccount,
+
613 account,
+
614 amountWithdrawActual,
+
615 journal,
+ +
617 if (res != tesSUCCESS)
+
618 {
+
619 // LCOV_EXCL_START
+
620 JLOG(journal.debug())
+
621 << "AMM Withdraw: failed to withdraw " << amountWithdrawActual;
+
622 return {res, STAmount{}, STAmount{}, STAmount{}};
+
623 // LCOV_EXCL_STOP
+
624 }
+
625
+
626 // Withdraw amount2Withdraw
+
627 if (amount2WithdrawActual)
+
628 {
+
629 if (auto const err = sufficientReserve(amount2WithdrawActual->issue());
+
630 err != tesSUCCESS)
+
631 return {err, STAmount{}, STAmount{}, STAmount{}};
+
632
+
633 res = accountSend(
+
634 view,
+
635 ammAccount,
+
636 account,
+
637 *amount2WithdrawActual,
+
638 journal,
+ +
640 if (res != tesSUCCESS)
+
641 {
+
642 // LCOV_EXCL_START
+
643 JLOG(journal.debug()) << "AMM Withdraw: failed to withdraw "
+
644 << *amount2WithdrawActual;
+
645 return {res, STAmount{}, STAmount{}, STAmount{}};
+
646 // LCOV_EXCL_STOP
+
647 }
+
648 }
+
649
+
650 // Withdraw LP tokens
+
651 res = redeemIOU(
+
652 view,
+
653 account,
+
654 lpTokensWithdrawActual,
+
655 lpTokensWithdrawActual.issue(),
+
656 journal);
+
657 if (res != tesSUCCESS)
+
658 {
+
659 // LCOV_EXCL_START
+
660 JLOG(journal.debug()) << "AMM Withdraw: failed to withdraw LPTokens";
+
661 return {res, STAmount{}, STAmount{}, STAmount{}};
+
662 // LCOV_EXCL_STOP
+
663 }
+
664
+
665 return std::make_tuple(
+ +
667 lpTokensAMMBalance - lpTokensWithdrawActual,
+
668 amountWithdrawActual,
+
669 amount2WithdrawActual);
+
670}
-
682
- -
- -
687 Sandbox& view,
-
688 SLE const& ammSle,
-
689 AccountID const& ammAccount,
-
690 STAmount const& amountBalance,
-
691 STAmount const& amount2Balance,
-
692 STAmount const& lptAMMBalance,
-
693 STAmount const& lpTokens,
-
694 STAmount const& lpTokensWithdraw,
-
695 std::uint16_t tfee)
-
696{
-
697 TER ter;
-
698 STAmount newLPTokenBalance;
-
699 std::tie(ter, newLPTokenBalance, std::ignore, std::ignore) =
- -
701 view,
-
702 ammSle,
-
703 account_,
-
704 ammAccount,
-
705 amountBalance,
-
706 amount2Balance,
-
707 lptAMMBalance,
-
708 lpTokens,
-
709 lpTokensWithdraw,
-
710 tfee,
- - - -
714 ctx_.journal);
-
715 return {ter, newLPTokenBalance};
-
716}
+
671
+
672static STAmount
+
+ +
674 Rules const& rules,
+
675 STAmount const& lptAMMBalance,
+
676 STAmount const& lpTokensWithdraw,
+
677 WithdrawAll withdrawAll)
+
678{
+
679 if (!rules.enabled(fixAMMv1_3) || withdrawAll == WithdrawAll::Yes)
+
680 return lpTokensWithdraw;
+
681 return adjustLPTokens(lptAMMBalance, lpTokensWithdraw, IsDeposit::No);
+
682}
-
717
- -
- -
720 Sandbox& sb,
-
721 std::shared_ptr<SLE> const ammSle,
-
722 STAmount const& lpTokenBalance,
-
723 Issue const& issue1,
-
724 Issue const& issue2,
-
725 beast::Journal const& journal)
-
726{
-
727 TER ter;
-
728 bool updateBalance = true;
-
729 if (lpTokenBalance == beast::zero)
-
730 {
-
731 ter = deleteAMMAccount(sb, issue1, issue2, journal);
-
732 if (ter != tesSUCCESS && ter != tecINCOMPLETE)
-
733 return {ter, false}; // LCOV_EXCL_LINE
-
734 else
-
735 updateBalance = (ter == tecINCOMPLETE);
-
736 }
-
737
-
738 if (updateBalance)
-
739 {
-
740 ammSle->setFieldAmount(sfLPTokenBalance, lpTokenBalance);
-
741 sb.update(ammSle);
-
742 }
-
743
-
744 return {ter, true};
-
745}
+
683
+ +
+ +
688 Sandbox& view,
+
689 SLE const& ammSle,
+
690 AccountID const& ammAccount,
+
691 STAmount const& amountBalance,
+
692 STAmount const& amount2Balance,
+
693 STAmount const& lptAMMBalance,
+
694 STAmount const& lpTokens,
+
695 STAmount const& lpTokensWithdraw,
+
696 std::uint16_t tfee)
+
697{
+
698 TER ter;
+
699 STAmount newLPTokenBalance;
+
700 std::tie(ter, newLPTokenBalance, std::ignore, std::ignore) =
+ +
702 view,
+
703 ammSle,
+
704 account_,
+
705 ammAccount,
+
706 amountBalance,
+
707 amount2Balance,
+
708 lptAMMBalance,
+
709 lpTokens,
+
710 lpTokensWithdraw,
+
711 tfee,
+ + + +
715 ctx_.journal);
+
716 return {ter, newLPTokenBalance};
+
717}
-
746
- -
- -
751 Sandbox& view,
-
752 SLE const& ammSle,
-
753 AccountID const account,
-
754 AccountID const& ammAccount,
-
755 STAmount const& amountBalance,
-
756 STAmount const& amount2Balance,
-
757 STAmount const& lptAMMBalance,
-
758 STAmount const& lpTokens,
-
759 STAmount const& lpTokensWithdraw,
-
760 std::uint16_t tfee,
-
761 FreezeHandling freezeHanding,
-
762 WithdrawAll withdrawAll,
-
763 XRPAmount const& priorBalance,
-
764 beast::Journal const& journal)
-
765{
-
766 try
-
767 {
-
768 // Withdrawing all tokens in the pool
-
769 if (lpTokensWithdraw == lptAMMBalance)
-
770 {
-
771 return withdraw(
-
772 view,
-
773 ammSle,
-
774 ammAccount,
-
775 account,
-
776 amountBalance,
+
718
+ +
+ +
721 Sandbox& sb,
+
722 std::shared_ptr<SLE> const ammSle,
+
723 STAmount const& lpTokenBalance,
+
724 Issue const& issue1,
+
725 Issue const& issue2,
+
726 beast::Journal const& journal)
+
727{
+
728 TER ter;
+
729 bool updateBalance = true;
+
730 if (lpTokenBalance == beast::zero)
+
731 {
+
732 ter = deleteAMMAccount(sb, issue1, issue2, journal);
+
733 if (ter != tesSUCCESS && ter != tecINCOMPLETE)
+
734 return {ter, false}; // LCOV_EXCL_LINE
+
735 else
+
736 updateBalance = (ter == tecINCOMPLETE);
+
737 }
+
738
+
739 if (updateBalance)
+
740 {
+
741 ammSle->setFieldAmount(sfLPTokenBalance, lpTokenBalance);
+
742 sb.update(ammSle);
+
743 }
+
744
+
745 return {ter, true};
+
746}
+
+
747
+ +
+ +
752 Sandbox& view,
+
753 SLE const& ammSle,
+
754 AccountID const account,
+
755 AccountID const& ammAccount,
+
756 STAmount const& amountBalance,
+
757 STAmount const& amount2Balance,
+
758 STAmount const& lptAMMBalance,
+
759 STAmount const& lpTokens,
+
760 STAmount const& lpTokensWithdraw,
+
761 std::uint16_t tfee,
+
762 FreezeHandling freezeHanding,
+
763 WithdrawAll withdrawAll,
+
764 XRPAmount const& priorBalance,
+
765 beast::Journal const& journal)
+
766{
+
767 try
+
768 {
+
769 // Withdrawing all tokens in the pool
+
770 if (lpTokensWithdraw == lptAMMBalance)
+
771 {
+
772 return withdraw(
+
773 view,
+
774 ammSle,
+
775 ammAccount,
+
776 account,
777 amountBalance,
-
778 amount2Balance,
-
779 lptAMMBalance,
-
780 lpTokensWithdraw,
-
781 tfee,
-
782 freezeHanding,
- -
784 priorBalance,
-
785 journal);
-
786 }
-
787
-
788 auto const tokensAdj = adjustLPTokensIn(
-
789 view.rules(), lptAMMBalance, lpTokensWithdraw, withdrawAll);
-
790 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
-
791 return {
- -
793 // the adjusted tokens are factored in
-
794 auto const frac = divide(tokensAdj, lptAMMBalance, noIssue());
-
795 auto const amountWithdraw =
-
796 getRoundedAsset(view.rules(), amountBalance, frac, IsDeposit::No);
-
797 auto const amount2Withdraw =
-
798 getRoundedAsset(view.rules(), amount2Balance, frac, IsDeposit::No);
-
799 // LP is making equal withdrawal by tokens but the requested amount
-
800 // of LP tokens is likely too small and results in one-sided pool
-
801 // withdrawal due to round off. Fail so the user withdraws
-
802 // more tokens.
-
803 if (amountWithdraw == beast::zero || amount2Withdraw == beast::zero)
-
804 return {tecAMM_FAILED, STAmount{}, STAmount{}, STAmount{}};
-
805
-
806 return withdraw(
-
807 view,
-
808 ammSle,
-
809 ammAccount,
-
810 account,
-
811 amountBalance,
-
812 amountWithdraw,
-
813 amount2Withdraw,
-
814 lptAMMBalance,
-
815 tokensAdj,
-
816 tfee,
-
817 freezeHanding,
-
818 withdrawAll,
-
819 priorBalance,
-
820 journal);
-
821 }
-
822 // LCOV_EXCL_START
-
823 catch (std::exception const& e)
-
824 {
-
825 JLOG(journal.error())
-
826 << "AMMWithdraw::equalWithdrawTokens exception " << e.what();
-
827 }
-
828 return {tecINTERNAL, STAmount{}, STAmount{}, STAmount{}};
-
829 // LCOV_EXCL_STOP
-
830}
+
778 amountBalance,
+
779 amount2Balance,
+
780 lptAMMBalance,
+
781 lpTokensWithdraw,
+
782 tfee,
+
783 freezeHanding,
+ +
785 priorBalance,
+
786 journal);
+
787 }
+
788
+
789 auto const tokensAdj = adjustLPTokensIn(
+
790 view.rules(), lptAMMBalance, lpTokensWithdraw, withdrawAll);
+
791 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
+
792 return {
+ +
794 // the adjusted tokens are factored in
+
795 auto const frac = divide(tokensAdj, lptAMMBalance, noIssue());
+
796 auto const amountWithdraw =
+
797 getRoundedAsset(view.rules(), amountBalance, frac, IsDeposit::No);
+
798 auto const amount2Withdraw =
+
799 getRoundedAsset(view.rules(), amount2Balance, frac, IsDeposit::No);
+
800 // LP is making equal withdrawal by tokens but the requested amount
+
801 // of LP tokens is likely too small and results in one-sided pool
+
802 // withdrawal due to round off. Fail so the user withdraws
+
803 // more tokens.
+
804 if (amountWithdraw == beast::zero || amount2Withdraw == beast::zero)
+
805 return {tecAMM_FAILED, STAmount{}, STAmount{}, STAmount{}};
+
806
+
807 return withdraw(
+
808 view,
+
809 ammSle,
+
810 ammAccount,
+
811 account,
+
812 amountBalance,
+
813 amountWithdraw,
+
814 amount2Withdraw,
+
815 lptAMMBalance,
+
816 tokensAdj,
+
817 tfee,
+
818 freezeHanding,
+
819 withdrawAll,
+
820 priorBalance,
+
821 journal);
+
822 }
+
823 // LCOV_EXCL_START
+
824 catch (std::exception const& e)
+
825 {
+
826 JLOG(journal.error())
+
827 << "AMMWithdraw::equalWithdrawTokens exception " << e.what();
+
828 }
+
829 return {tecINTERNAL, STAmount{}, STAmount{}, STAmount{}};
+
830 // LCOV_EXCL_STOP
+
831}
-
831
- -
- -
859 Sandbox& view,
-
860 SLE const& ammSle,
-
861 AccountID const& ammAccount,
-
862 STAmount const& amountBalance,
-
863 STAmount const& amount2Balance,
-
864 STAmount const& lptAMMBalance,
-
865 STAmount const& amount,
-
866 STAmount const& amount2,
-
867 std::uint16_t tfee)
-
868{
-
869 auto frac = Number{amount} / amountBalance;
-
870 auto amount2Withdraw =
-
871 getRoundedAsset(view.rules(), amount2Balance, frac, IsDeposit::No);
-
872 auto tokensAdj =
-
873 getRoundedLPTokens(view.rules(), lptAMMBalance, frac, IsDeposit::No);
-
874 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
- -
876 // factor in the adjusted tokens
-
877 frac = adjustFracByTokens(view.rules(), lptAMMBalance, tokensAdj, frac);
-
878 amount2Withdraw =
-
879 getRoundedAsset(view.rules(), amount2Balance, frac, IsDeposit::No);
-
880 if (amount2Withdraw <= amount2)
-
881 {
-
882 return withdraw(
-
883 view,
-
884 ammSle,
-
885 ammAccount,
-
886 amountBalance,
-
887 amount,
-
888 amount2Withdraw,
-
889 lptAMMBalance,
-
890 tokensAdj,
-
891 tfee);
-
892 }
-
893
-
894 frac = Number{amount2} / amount2Balance;
-
895 auto amountWithdraw =
-
896 getRoundedAsset(view.rules(), amountBalance, frac, IsDeposit::No);
-
897 tokensAdj =
-
898 getRoundedLPTokens(view.rules(), lptAMMBalance, frac, IsDeposit::No);
-
899 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
-
900 return {tecAMM_INVALID_TOKENS, STAmount{}}; // LCOV_EXCL_LINE
-
901 // factor in the adjusted tokens
-
902 frac = adjustFracByTokens(view.rules(), lptAMMBalance, tokensAdj, frac);
-
903 amountWithdraw =
-
904 getRoundedAsset(view.rules(), amountBalance, frac, IsDeposit::No);
-
905 if (!view.rules().enabled(fixAMMv1_3))
-
906 {
-
907 // LCOV_EXCL_START
-
908 XRPL_ASSERT(
-
909 amountWithdraw <= amount,
-
910 "ripple::AMMWithdraw::equalWithdrawLimit : maximum amountWithdraw");
-
911 // LCOV_EXCL_STOP
-
912 }
-
913 else if (amountWithdraw > amount)
-
914 return {tecAMM_FAILED, STAmount{}}; // LCOV_EXCL_LINE
-
915 return withdraw(
-
916 view,
-
917 ammSle,
-
918 ammAccount,
-
919 amountBalance,
-
920 amountWithdraw,
-
921 amount2,
-
922 lptAMMBalance,
-
923 tokensAdj,
-
924 tfee);
-
925}
+
832
+ +
+ +
860 Sandbox& view,
+
861 SLE const& ammSle,
+
862 AccountID const& ammAccount,
+
863 STAmount const& amountBalance,
+
864 STAmount const& amount2Balance,
+
865 STAmount const& lptAMMBalance,
+
866 STAmount const& amount,
+
867 STAmount const& amount2,
+
868 std::uint16_t tfee)
+
869{
+
870 auto frac = Number{amount} / amountBalance;
+
871 auto amount2Withdraw =
+
872 getRoundedAsset(view.rules(), amount2Balance, frac, IsDeposit::No);
+
873 auto tokensAdj =
+
874 getRoundedLPTokens(view.rules(), lptAMMBalance, frac, IsDeposit::No);
+
875 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
+ +
877 // factor in the adjusted tokens
+
878 frac = adjustFracByTokens(view.rules(), lptAMMBalance, tokensAdj, frac);
+
879 amount2Withdraw =
+
880 getRoundedAsset(view.rules(), amount2Balance, frac, IsDeposit::No);
+
881 if (amount2Withdraw <= amount2)
+
882 {
+
883 return withdraw(
+
884 view,
+
885 ammSle,
+
886 ammAccount,
+
887 amountBalance,
+
888 amount,
+
889 amount2Withdraw,
+
890 lptAMMBalance,
+
891 tokensAdj,
+
892 tfee);
+
893 }
+
894
+
895 frac = Number{amount2} / amount2Balance;
+
896 auto amountWithdraw =
+
897 getRoundedAsset(view.rules(), amountBalance, frac, IsDeposit::No);
+
898 tokensAdj =
+
899 getRoundedLPTokens(view.rules(), lptAMMBalance, frac, IsDeposit::No);
+
900 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
+
901 return {tecAMM_INVALID_TOKENS, STAmount{}}; // LCOV_EXCL_LINE
+
902 // factor in the adjusted tokens
+
903 frac = adjustFracByTokens(view.rules(), lptAMMBalance, tokensAdj, frac);
+
904 amountWithdraw =
+
905 getRoundedAsset(view.rules(), amountBalance, frac, IsDeposit::No);
+
906 if (!view.rules().enabled(fixAMMv1_3))
+
907 {
+
908 // LCOV_EXCL_START
+
909 XRPL_ASSERT(
+
910 amountWithdraw <= amount,
+
911 "ripple::AMMWithdraw::equalWithdrawLimit : maximum amountWithdraw");
+
912 // LCOV_EXCL_STOP
+
913 }
+
914 else if (amountWithdraw > amount)
+
915 return {tecAMM_FAILED, STAmount{}}; // LCOV_EXCL_LINE
+
916 return withdraw(
+
917 view,
+
918 ammSle,
+
919 ammAccount,
+
920 amountBalance,
+
921 amountWithdraw,
+
922 amount2,
+
923 lptAMMBalance,
+
924 tokensAdj,
+
925 tfee);
+
926}
-
926
- -
- -
934 Sandbox& view,
-
935 SLE const& ammSle,
-
936 AccountID const& ammAccount,
-
937 STAmount const& amountBalance,
-
938 STAmount const& lptAMMBalance,
-
939 STAmount const& amount,
-
940 std::uint16_t tfee)
-
941{
-
942 auto const tokens = adjustLPTokensIn(
-
943 view.rules(),
-
944 lptAMMBalance,
-
945 lpTokensIn(amountBalance, amount, lptAMMBalance, tfee),
- -
947 if (tokens == beast::zero)
-
948 {
-
949 if (!view.rules().enabled(fixAMMv1_3))
-
950 return {tecAMM_FAILED, STAmount{}}; // LCOV_EXCL_LINE
-
951 else
- -
953 }
-
954 // factor in the adjusted tokens
-
955 auto const [tokensAdj, amountWithdrawAdj] = adjustAssetOutByTokens(
-
956 view.rules(), amountBalance, amount, lptAMMBalance, tokens, tfee);
-
957 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
-
958 return {tecAMM_INVALID_TOKENS, STAmount{}}; // LCOV_EXCL_LINE
-
959 return withdraw(
-
960 view,
-
961 ammSle,
-
962 ammAccount,
-
963 amountBalance,
-
964 amountWithdrawAdj,
- -
966 lptAMMBalance,
-
967 tokensAdj,
-
968 tfee);
-
969}
+
927
+ +
+ +
935 Sandbox& view,
+
936 SLE const& ammSle,
+
937 AccountID const& ammAccount,
+
938 STAmount const& amountBalance,
+
939 STAmount const& lptAMMBalance,
+
940 STAmount const& amount,
+
941 std::uint16_t tfee)
+
942{
+
943 auto const tokens = adjustLPTokensIn(
+
944 view.rules(),
+
945 lptAMMBalance,
+
946 lpTokensIn(amountBalance, amount, lptAMMBalance, tfee),
+ +
948 if (tokens == beast::zero)
+
949 {
+
950 if (!view.rules().enabled(fixAMMv1_3))
+
951 return {tecAMM_FAILED, STAmount{}}; // LCOV_EXCL_LINE
+
952 else
+ +
954 }
+
955 // factor in the adjusted tokens
+
956 auto const [tokensAdj, amountWithdrawAdj] = adjustAssetOutByTokens(
+
957 view.rules(), amountBalance, amount, lptAMMBalance, tokens, tfee);
+
958 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
+
959 return {tecAMM_INVALID_TOKENS, STAmount{}}; // LCOV_EXCL_LINE
+
960 return withdraw(
+
961 view,
+
962 ammSle,
+
963 ammAccount,
+
964 amountBalance,
+
965 amountWithdrawAdj,
+ +
967 lptAMMBalance,
+
968 tokensAdj,
+
969 tfee);
+
970}
-
970
- -
- -
983 Sandbox& view,
-
984 SLE const& ammSle,
-
985 AccountID const& ammAccount,
-
986 STAmount const& amountBalance,
-
987 STAmount const& lptAMMBalance,
-
988 STAmount const& amount,
-
989 STAmount const& lpTokensWithdraw,
-
990 std::uint16_t tfee)
-
991{
-
992 auto const tokensAdj = adjustLPTokensIn(
-
993 view.rules(), lptAMMBalance, lpTokensWithdraw, isWithdrawAll(ctx_.tx));
-
994 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
- -
996 // the adjusted tokens are factored in
-
997 auto const amountWithdraw =
-
998 ammAssetOut(amountBalance, lptAMMBalance, tokensAdj, tfee);
-
999 if (amount == beast::zero || amountWithdraw >= amount)
-
1000 {
-
1001 return withdraw(
-
1002 view,
-
1003 ammSle,
-
1004 ammAccount,
-
1005 amountBalance,
-
1006 amountWithdraw,
- -
1008 lptAMMBalance,
-
1009 tokensAdj,
-
1010 tfee);
-
1011 }
-
1012
-
1013 return {tecAMM_FAILED, STAmount{}};
-
1014}
+
971
+ +
+ +
984 Sandbox& view,
+
985 SLE const& ammSle,
+
986 AccountID const& ammAccount,
+
987 STAmount const& amountBalance,
+
988 STAmount const& lptAMMBalance,
+
989 STAmount const& amount,
+
990 STAmount const& lpTokensWithdraw,
+
991 std::uint16_t tfee)
+
992{
+
993 auto const tokensAdj = adjustLPTokensIn(
+
994 view.rules(), lptAMMBalance, lpTokensWithdraw, isWithdrawAll(ctx_.tx));
+
995 if (view.rules().enabled(fixAMMv1_3) && tokensAdj == beast::zero)
+ +
997 // the adjusted tokens are factored in
+
998 auto const amountWithdraw =
+
999 ammAssetOut(amountBalance, lptAMMBalance, tokensAdj, tfee);
+
1000 if (amount == beast::zero || amountWithdraw >= amount)
+
1001 {
+
1002 return withdraw(
+
1003 view,
+
1004 ammSle,
+
1005 ammAccount,
+
1006 amountBalance,
+
1007 amountWithdraw,
+ +
1009 lptAMMBalance,
+
1010 tokensAdj,
+
1011 tfee);
+
1012 }
+
1013
+
1014 return {tecAMM_FAILED, STAmount{}};
+
1015}
-
1015
- -
- -
1037 Sandbox& view,
-
1038 SLE const& ammSle,
-
1039 AccountID const& ammAccount,
-
1040 STAmount const& amountBalance,
-
1041 STAmount const& lptAMMBalance,
-
1042 STAmount const& amount,
-
1043 STAmount const& ePrice,
-
1044 std::uint16_t tfee)
-
1045{
-
1046 // LPTokens is asset in => E = t / a and formula (8) is:
-
1047 // a = A*(t1**2 + t1*(f - 2))/(t1*f - 1)
-
1048 // substitute a as t/E =>
-
1049 // t/E = A*(t1**2 + t1*(f - 2))/(t1*f - 1), t1=t/T => t = t1*T
-
1050 // t1*T/E = A*((t/T)**2 + t*(f - 2)/T)/(t*f/T - 1) =>
-
1051 // T/E = A*(t1 + f-2)/(t1*f - 1) =>
-
1052 // T*(t1*f - 1) = A*E*(t1 + f - 2) =>
-
1053 // t1*T*f - T = t1*A*E + A*E*(f - 2) =>
-
1054 // t1*(T*f - A*E) = T + A*E*(f - 2) =>
-
1055 // t = T*(T + A*E*(f - 2))/(T*f - A*E)
-
1056 Number const ae = amountBalance * ePrice;
-
1057 auto const f = getFee(tfee);
-
1058 auto tokNoRoundCb = [&] {
-
1059 return lptAMMBalance * (lptAMMBalance + ae * (f - 2)) /
-
1060 (lptAMMBalance * f - ae);
-
1061 };
-
1062 auto tokProdCb = [&] {
-
1063 return (lptAMMBalance + ae * (f - 2)) / (lptAMMBalance * f - ae);
-
1064 };
-
1065 auto const tokensAdj = getRoundedLPTokens(
-
1066 view.rules(), tokNoRoundCb, lptAMMBalance, tokProdCb, IsDeposit::No);
-
1067 if (tokensAdj <= beast::zero)
-
1068 {
-
1069 if (!view.rules().enabled(fixAMMv1_3))
-
1070 return {tecAMM_FAILED, STAmount{}};
-
1071 else
-
1072 return {tecAMM_INVALID_TOKENS, STAmount{}};
-
1073 }
-
1074 auto amtNoRoundCb = [&] { return tokensAdj / ePrice; };
-
1075 auto amtProdCb = [&] { return tokensAdj / ePrice; };
-
1076 // the adjusted tokens are factored in
-
1077 auto const amountWithdraw = getRoundedAsset(
-
1078 view.rules(), amtNoRoundCb, amount, amtProdCb, IsDeposit::No);
-
1079 if (amount == beast::zero || amountWithdraw >= amount)
-
1080 {
-
1081 return withdraw(
-
1082 view,
-
1083 ammSle,
-
1084 ammAccount,
-
1085 amountBalance,
-
1086 amountWithdraw,
- -
1088 lptAMMBalance,
-
1089 tokensAdj,
-
1090 tfee);
-
1091 }
-
1092
-
1093 return {tecAMM_FAILED, STAmount{}};
-
1094}
+
1016
+ +
+ +
1038 Sandbox& view,
+
1039 SLE const& ammSle,
+
1040 AccountID const& ammAccount,
+
1041 STAmount const& amountBalance,
+
1042 STAmount const& lptAMMBalance,
+
1043 STAmount const& amount,
+
1044 STAmount const& ePrice,
+
1045 std::uint16_t tfee)
+
1046{
+
1047 // LPTokens is asset in => E = t / a and formula (8) is:
+
1048 // a = A*(t1**2 + t1*(f - 2))/(t1*f - 1)
+
1049 // substitute a as t/E =>
+
1050 // t/E = A*(t1**2 + t1*(f - 2))/(t1*f - 1), t1=t/T => t = t1*T
+
1051 // t1*T/E = A*((t/T)**2 + t*(f - 2)/T)/(t*f/T - 1) =>
+
1052 // T/E = A*(t1 + f-2)/(t1*f - 1) =>
+
1053 // T*(t1*f - 1) = A*E*(t1 + f - 2) =>
+
1054 // t1*T*f - T = t1*A*E + A*E*(f - 2) =>
+
1055 // t1*(T*f - A*E) = T + A*E*(f - 2) =>
+
1056 // t = T*(T + A*E*(f - 2))/(T*f - A*E)
+
1057 Number const ae = amountBalance * ePrice;
+
1058 auto const f = getFee(tfee);
+
1059 auto tokNoRoundCb = [&] {
+
1060 return lptAMMBalance * (lptAMMBalance + ae * (f - 2)) /
+
1061 (lptAMMBalance * f - ae);
+
1062 };
+
1063 auto tokProdCb = [&] {
+
1064 return (lptAMMBalance + ae * (f - 2)) / (lptAMMBalance * f - ae);
+
1065 };
+
1066 auto const tokensAdj = getRoundedLPTokens(
+
1067 view.rules(), tokNoRoundCb, lptAMMBalance, tokProdCb, IsDeposit::No);
+
1068 if (tokensAdj <= beast::zero)
+
1069 {
+
1070 if (!view.rules().enabled(fixAMMv1_3))
+
1071 return {tecAMM_FAILED, STAmount{}};
+
1072 else
+
1073 return {tecAMM_INVALID_TOKENS, STAmount{}};
+
1074 }
+
1075 auto amtNoRoundCb = [&] { return tokensAdj / ePrice; };
+
1076 auto amtProdCb = [&] { return tokensAdj / ePrice; };
+
1077 // the adjusted tokens are factored in
+
1078 auto const amountWithdraw = getRoundedAsset(
+
1079 view.rules(), amtNoRoundCb, amount, amtProdCb, IsDeposit::No);
+
1080 if (amount == beast::zero || amountWithdraw >= amount)
+
1081 {
+
1082 return withdraw(
+
1083 view,
+
1084 ammSle,
+
1085 ammAccount,
+
1086 amountBalance,
+
1087 amountWithdraw,
+ +
1089 lptAMMBalance,
+
1090 tokensAdj,
+
1091 tfee);
+
1092 }
+
1093
+
1094 return {tecAMM_FAILED, STAmount{}};
+
1095}
-
1095
- -
- -
1098{
-
1099 if (tx[sfFlags] & (tfWithdrawAll | tfOneAssetWithdrawAll))
-
1100 return WithdrawAll::Yes;
-
1101 return WithdrawAll::No;
-
1102}
+
1096
+ +
+ +
1099{
+
1100 if (tx[sfFlags] & (tfWithdrawAll | tfOneAssetWithdrawAll))
+
1101 return WithdrawAll::Yes;
+
1102 return WithdrawAll::No;
+
1103}
-
1103} // namespace ripple
+
1104} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:60
Stream error() const
Definition Journal.h:346
Stream debug() const
Definition Journal.h:328
Stream trace() const
Severity stream access functions.
Definition Journal.h:322
-
static WithdrawAll isWithdrawAll(STTx const &tx)
Check from the flags if it's withdraw all.
-
std::pair< TER, STAmount > singleWithdrawEPrice(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &ePrice, std::uint16_t tfee)
Withdraw single asset (Asset1Out, EPrice) with two constraints.
-
std::pair< TER, STAmount > equalWithdrawLimit(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &amount2, std::uint16_t tfee)
Withdraw both assets (Asset1Out, Asset2Out) with the constraints on the maximum amount of each asset ...
-
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > equalWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const account, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokens, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHanding, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Equal-asset withdrawal (LPTokens) of some AMM instance pools shares represented by the number of LPTo...
-
std::pair< TER, bool > applyGuts(Sandbox &view)
-
std::pair< TER, STAmount > singleWithdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, std::uint16_t tfee)
Single asset withdrawal (Asset1Out) equivalent to the amount specified in Asset1Out.
-
static std::pair< TER, bool > deleteAMMAccountIfEmpty(Sandbox &sb, std::shared_ptr< SLE > const ammSle, STAmount const &lpTokenBalance, Issue const &issue1, Issue const &issue2, beast::Journal const &journal)
-
static TER preclaim(PreclaimContext const &ctx)
-
static NotTEC preflight(PreflightContext const &ctx)
-
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > withdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, AccountID const &account, STAmount const &amountBalance, STAmount const &amountWithdraw, std::optional< STAmount > const &amount2Withdraw, STAmount const &lpTokensAMMBalance, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHandling, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Withdraw requested assets and token from AMM into LP account.
-
TER doApply() override
-
std::pair< TER, STAmount > singleWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &lpTokensWithdraw, std::uint16_t tfee)
Single asset withdrawal (Asset1Out, LPTokens) proportional to the share specified by tokens.
+
static WithdrawAll isWithdrawAll(STTx const &tx)
Check from the flags if it's withdraw all.
+
static bool checkExtraFeatures(PreflightContext const &ctx)
+
std::pair< TER, STAmount > singleWithdrawEPrice(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &ePrice, std::uint16_t tfee)
Withdraw single asset (Asset1Out, EPrice) with two constraints.
+
std::pair< TER, STAmount > equalWithdrawLimit(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &amount2, std::uint16_t tfee)
Withdraw both assets (Asset1Out, Asset2Out) with the constraints on the maximum amount of each asset ...
+
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > equalWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const account, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokens, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHanding, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Equal-asset withdrawal (LPTokens) of some AMM instance pools shares represented by the number of LPTo...
+
std::pair< TER, bool > applyGuts(Sandbox &view)
+
std::pair< TER, STAmount > singleWithdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, std::uint16_t tfee)
Single asset withdrawal (Asset1Out) equivalent to the amount specified in Asset1Out.
+
static std::pair< TER, bool > deleteAMMAccountIfEmpty(Sandbox &sb, std::shared_ptr< SLE > const ammSle, STAmount const &lpTokenBalance, Issue const &issue1, Issue const &issue2, beast::Journal const &journal)
+
static TER preclaim(PreclaimContext const &ctx)
+
static NotTEC preflight(PreflightContext const &ctx)
+
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > withdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, AccountID const &account, STAmount const &amountBalance, STAmount const &amountWithdraw, std::optional< STAmount > const &amount2Withdraw, STAmount const &lpTokensAMMBalance, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHandling, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Withdraw requested assets and token from AMM into LP account.
+
TER doApply() override
+
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
+
std::pair< TER, STAmount > singleWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &lpTokensWithdraw, std::uint16_t tfee)
Single asset withdrawal (Asset1Out, LPTokens) proportional to the share specified by tokens.
ApplyView & view()
beast::Journal const journal
@@ -1188,12 +1195,12 @@ $(document).ready(function() { init_codefold(0); });
Discardable, editable view to a ledger.
Definition Sandbox.h:35
void apply(RawView &to)
Definition Sandbox.h:55
- -
AccountID const account_
Definition Transactor.h:145
-
ApplyView & view()
Definition Transactor.h:161
-
beast::Journal const j_
Definition Transactor.h:143
-
XRPAmount mPriorBalance
Definition Transactor.h:146
-
ApplyContext & ctx_
Definition Transactor.h:141
+ +
AccountID const account_
Definition Transactor.h:147
+
ApplyView & view()
Definition Transactor.h:163
+
beast::Journal const j_
Definition Transactor.h:145
+
XRPAmount mPriorBalance
Definition Transactor.h:148
+
ApplyContext & ctx_
Definition Transactor.h:143
void update(std::shared_ptr< SLE > const &sle) override
Indicate changes to a peeked SLE.
@@ -1230,11 +1237,10 @@ $(document).ready(function() { init_codefold(0); });
TER redeemIOU(ApplyView &view, AccountID const &account, STAmount const &amount, Issue const &issue, beast::Journal j)
Definition View.cpp:2348
constexpr std::uint32_t tfLimitLPToken
Definition TxFlags.h:250
bool ammEnabled(Rules const &)
Return true if required AMM amendments are enabled.
Definition AMMCore.cpp:129
-
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
constexpr std::uint32_t tfOneAssetLPToken
Definition TxFlags.h:249
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No)
Calls static accountSendIOU if saAmount represents Issue.
Definition View.cpp:2174
STAmount getRoundedLPTokens(Rules const &rules, STAmount const &balance, Number const &frac, IsDeposit isDeposit)
Round AMM deposit/withdrawal LPToken amount.
-
static std::optional< STAmount > tokensWithdraw(STAmount const &lpTokens, std::optional< STAmount > const &tokensIn, std::uint32_t flags)
+
static std::optional< STAmount > tokensWithdraw(STAmount const &lpTokens, std::optional< STAmount > const &tokensIn, std::uint32_t flags)
Expected< bool, TER > verifyAndAdjustLPTokenBalance(Sandbox &sb, STAmount const &lpTokens, std::shared_ptr< SLE > &ammSle, AccountID const &account)
Due to rounding, the LPTokenBalance of the last LP might not match the LP's trustline balance.
Definition AMMUtils.cpp:469
bool isFrozen(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer)
Definition View.cpp:247
TER requireAuth(ReadView const &view, Issue const &issue, AccountID const &account, AuthType authType=AuthType::Legacy)
Check if the account lacks required authorization.
Definition View.cpp:2464
@@ -1243,8 +1249,7 @@ $(document).ready(function() { init_codefold(0); });
STAmount ammLPHolds(ReadView const &view, Currency const &cur1, Currency const &cur2, AccountID const &ammAccount, AccountID const &lpAccount, beast::Journal const j)
Get the balance of LP tokens.
Definition AMMUtils.cpp:113
std::tuple< STAmount, std::optional< STAmount >, STAmount > adjustAmountsByLPTokens(STAmount const &amountBalance, STAmount const &amount, std::optional< STAmount > const &amount2, STAmount const &lptAMMBalance, STAmount const &lpTokens, std::uint16_t tfee, IsDeposit isDeposit)
Calls adjustLPTokens() and adjusts deposit or withdraw amounts if the adjusted LP tokens are less tha...
constexpr std::uint32_t tfWithdrawAll
Definition TxFlags.h:245
-
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
-
static STAmount adjustLPTokensIn(Rules const &rules, STAmount const &lptAMMBalance, STAmount const &lpTokensWithdraw, WithdrawAll withdrawAll)
+
static STAmount adjustLPTokensIn(Rules const &rules, STAmount const &lptAMMBalance, STAmount const &lpTokensWithdraw, WithdrawAll withdrawAll)
STAmount ammAssetOut(STAmount const &assetBalance, STAmount const &lptAMMBalance, STAmount const &lpTokens, std::uint16_t tfee)
Calculate asset withdrawal by tokens.
Issue const & noIssue()
Returns an asset specifier that represents no account and currency.
Definition Issue.h:123
@@ -1261,7 +1266,6 @@ $(document).ready(function() { init_codefold(0); });
@ tesSUCCESS
Definition TER.h:244
NotTEC invalidAMMAssetPair(Issue const &issue1, Issue const &issue2, std::optional< std::pair< Issue, Issue > > const &pair=std::nullopt)
Definition AMMCore.cpp:80
-
bool isTesSuccess(TER x) noexcept
Definition TER.h:674
Expected< std::tuple< STAmount, STAmount, STAmount >, TER > ammHolds(ReadView const &view, SLE const &ammSle, std::optional< Issue > const &optIssue1, std::optional< Issue > const &optIssue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool and LP token balances.
Definition AMMUtils.cpp:47
constexpr std::uint32_t tfWithdrawSubTx
Definition TxFlags.h:252
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
@@ -1270,11 +1274,8 @@ $(document).ready(function() { init_codefold(0); });
TERSubset< CanCvtToTER > TER
Definition TER.h:645
STAmount getRoundedAsset(Rules const &rules, STAmount const &balance, A const &frac, IsDeposit isDeposit)
Round AMM equal deposit/withdrawal amount.
Definition AMMHelpers.h:678
Number adjustFracByTokens(Rules const &rules, STAmount const &lptAMMBalance, STAmount const &tokens, Number const &frac)
Find a fraction of tokens after the tokens are adjusted.
-
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:605
@ temMALFORMED
Definition TER.h:87
@ temBAD_AMM_TOKENS
Definition TER.h:129
-
@ temINVALID_FLAG
Definition TER.h:111
-
@ temDISABLED
Definition TER.h:114
T popcount(T... args)
diff --git a/AMMWithdraw_8h_source.html b/AMMWithdraw_8h_source.html index 146bbb65cd..f1083e0a25 100644 --- a/AMMWithdraw_8h_source.html +++ b/AMMWithdraw_8h_source.html @@ -125,154 +125,162 @@ $(document).ready(function() { init_codefold(0); });
77 }
78
-
79 static NotTEC
-
80 preflight(PreflightContext const& ctx);
+
79 static bool
+
81
-
82 static TER
-
83 preclaim(PreclaimContext const& ctx);
+
82 static std::uint32_t
+
84
-
85 TER
-
86 doApply() override;
+
85 static NotTEC
+
86 preflight(PreflightContext const& ctx);
87
- - -
105 Sandbox& view,
-
106 SLE const& ammSle,
-
107 AccountID const account,
-
108 AccountID const& ammAccount,
-
109 STAmount const& amountBalance,
-
110 STAmount const& amount2Balance,
-
111 STAmount const& lptAMMBalance,
-
112 STAmount const& lpTokens,
-
113 STAmount const& lpTokensWithdraw,
-
114 std::uint16_t tfee,
-
115 FreezeHandling freezeHanding,
-
116 WithdrawAll withdrawAll,
-
117 XRPAmount const& priorBalance,
-
118 beast::Journal const& journal);
-
119
- -
137 withdraw(
-
138 Sandbox& view,
-
139 SLE const& ammSle,
-
140 AccountID const& ammAccount,
-
141 AccountID const& account,
-
142 STAmount const& amountBalance,
-
143 STAmount const& amountWithdraw,
-
144 std::optional<STAmount> const& amount2Withdraw,
-
145 STAmount const& lpTokensAMMBalance,
-
146 STAmount const& lpTokensWithdraw,
-
147 std::uint16_t tfee,
-
148 FreezeHandling freezeHandling,
-
149 WithdrawAll withdrawAll,
-
150 XRPAmount const& priorBalance,
-
151 beast::Journal const& journal);
-
152
- - -
155 Sandbox& sb,
-
156 std::shared_ptr<SLE> const ammSle,
-
157 STAmount const& lpTokenBalance,
-
158 Issue const& issue1,
-
159 Issue const& issue2,
-
160 beast::Journal const& journal);
-
161
-
162private:
- - -
165
- -
179 withdraw(
-
180 Sandbox& view,
-
181 SLE const& ammSle,
-
182 AccountID const& ammAccount,
-
183 STAmount const& amountBalance,
-
184 STAmount const& amountWithdraw,
-
185 std::optional<STAmount> const& amount2Withdraw,
-
186 STAmount const& lpTokensAMMBalance,
-
187 STAmount const& lpTokensWithdraw,
-
188 std::uint16_t tfee);
-
189
- - -
205 Sandbox& view,
-
206 SLE const& ammSle,
-
207 AccountID const& ammAccount,
-
208 STAmount const& amountBalance,
-
209 STAmount const& amount2Balance,
-
210 STAmount const& lptAMMBalance,
-
211 STAmount const& lpTokens,
-
212 STAmount const& lpTokensWithdraw,
-
213 std::uint16_t tfee);
-
214
- - -
230 Sandbox& view,
-
231 SLE const& ammSle,
-
232 AccountID const& ammAccount,
-
233 STAmount const& amountBalance,
-
234 STAmount const& amount2Balance,
-
235 STAmount const& lptAMMBalance,
-
236 STAmount const& amount,
-
237 STAmount const& amount2,
-
238 std::uint16_t tfee);
-
239
- - -
252 Sandbox& view,
-
253 SLE const& ammSle,
-
254 AccountID const& ammAccount,
-
255 STAmount const& amountBalance,
-
256 STAmount const& lptAMMBalance,
-
257 STAmount const& amount,
-
258 std::uint16_t tfee);
-
259
- - -
273 Sandbox& view,
-
274 SLE const& ammSle,
-
275 AccountID const& ammAccount,
-
276 STAmount const& amountBalance,
-
277 STAmount const& lptAMMBalance,
-
278 STAmount const& amount,
-
279 STAmount const& lpTokensWithdraw,
-
280 std::uint16_t tfee);
-
281
- - -
295 Sandbox& view,
-
296 SLE const& ammSle,
-
297 AccountID const& ammAccount,
-
298 STAmount const& amountBalance,
-
299 STAmount const& lptAMMBalance,
-
300 STAmount const& amount,
-
301 STAmount const& ePrice,
-
302 std::uint16_t tfee);
-
303
-
305 static WithdrawAll
-
306 isWithdrawAll(STTx const& tx);
-
307};
+
88 static TER
+
89 preclaim(PreclaimContext const& ctx);
+
90
+
91 TER
+
92 doApply() override;
+
93
+ + +
111 Sandbox& view,
+
112 SLE const& ammSle,
+
113 AccountID const account,
+
114 AccountID const& ammAccount,
+
115 STAmount const& amountBalance,
+
116 STAmount const& amount2Balance,
+
117 STAmount const& lptAMMBalance,
+
118 STAmount const& lpTokens,
+
119 STAmount const& lpTokensWithdraw,
+
120 std::uint16_t tfee,
+
121 FreezeHandling freezeHanding,
+
122 WithdrawAll withdrawAll,
+
123 XRPAmount const& priorBalance,
+
124 beast::Journal const& journal);
+
125
+ +
143 withdraw(
+
144 Sandbox& view,
+
145 SLE const& ammSle,
+
146 AccountID const& ammAccount,
+
147 AccountID const& account,
+
148 STAmount const& amountBalance,
+
149 STAmount const& amountWithdraw,
+
150 std::optional<STAmount> const& amount2Withdraw,
+
151 STAmount const& lpTokensAMMBalance,
+
152 STAmount const& lpTokensWithdraw,
+
153 std::uint16_t tfee,
+
154 FreezeHandling freezeHandling,
+
155 WithdrawAll withdrawAll,
+
156 XRPAmount const& priorBalance,
+
157 beast::Journal const& journal);
+
158
+ + +
161 Sandbox& sb,
+
162 std::shared_ptr<SLE> const ammSle,
+
163 STAmount const& lpTokenBalance,
+
164 Issue const& issue1,
+
165 Issue const& issue2,
+
166 beast::Journal const& journal);
+
167
+
168private:
+ + +
171
+ +
185 withdraw(
+
186 Sandbox& view,
+
187 SLE const& ammSle,
+
188 AccountID const& ammAccount,
+
189 STAmount const& amountBalance,
+
190 STAmount const& amountWithdraw,
+
191 std::optional<STAmount> const& amount2Withdraw,
+
192 STAmount const& lpTokensAMMBalance,
+
193 STAmount const& lpTokensWithdraw,
+
194 std::uint16_t tfee);
+
195
+ + +
211 Sandbox& view,
+
212 SLE const& ammSle,
+
213 AccountID const& ammAccount,
+
214 STAmount const& amountBalance,
+
215 STAmount const& amount2Balance,
+
216 STAmount const& lptAMMBalance,
+
217 STAmount const& lpTokens,
+
218 STAmount const& lpTokensWithdraw,
+
219 std::uint16_t tfee);
+
220
+ + +
236 Sandbox& view,
+
237 SLE const& ammSle,
+
238 AccountID const& ammAccount,
+
239 STAmount const& amountBalance,
+
240 STAmount const& amount2Balance,
+
241 STAmount const& lptAMMBalance,
+
242 STAmount const& amount,
+
243 STAmount const& amount2,
+
244 std::uint16_t tfee);
+
245
+ + +
258 Sandbox& view,
+
259 SLE const& ammSle,
+
260 AccountID const& ammAccount,
+
261 STAmount const& amountBalance,
+
262 STAmount const& lptAMMBalance,
+
263 STAmount const& amount,
+
264 std::uint16_t tfee);
+
265
+ + +
279 Sandbox& view,
+
280 SLE const& ammSle,
+
281 AccountID const& ammAccount,
+
282 STAmount const& amountBalance,
+
283 STAmount const& lptAMMBalance,
+
284 STAmount const& amount,
+
285 STAmount const& lpTokensWithdraw,
+
286 std::uint16_t tfee);
+
287
+ + +
301 Sandbox& view,
+
302 SLE const& ammSle,
+
303 AccountID const& ammAccount,
+
304 STAmount const& amountBalance,
+
305 STAmount const& lptAMMBalance,
+
306 STAmount const& amount,
+
307 STAmount const& ePrice,
+
308 std::uint16_t tfee);
+
309
+
311 static WithdrawAll
+
312 isWithdrawAll(STTx const& tx);
+
313};
-
308
-
309} // namespace ripple
-
310
-
311#endif // RIPPLE_TX_AMMWITHDRAW_H_INCLUDED
+
314
+
315} // namespace ripple
+
316
+
317#endif // RIPPLE_TX_AMMWITHDRAW_H_INCLUDED
A generic endpoint for log messages.
Definition Journal.h:60
-
static WithdrawAll isWithdrawAll(STTx const &tx)
Check from the flags if it's withdraw all.
+
static WithdrawAll isWithdrawAll(STTx const &tx)
Check from the flags if it's withdraw all.
+
static bool checkExtraFeatures(PreflightContext const &ctx)
AMMWithdraw(ApplyContext &ctx)
Definition AMMWithdraw.h:75
-
std::pair< TER, STAmount > singleWithdrawEPrice(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &ePrice, std::uint16_t tfee)
Withdraw single asset (Asset1Out, EPrice) with two constraints.
-
std::pair< TER, STAmount > equalWithdrawLimit(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &amount2, std::uint16_t tfee)
Withdraw both assets (Asset1Out, Asset2Out) with the constraints on the maximum amount of each asset ...
-
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > equalWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const account, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokens, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHanding, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Equal-asset withdrawal (LPTokens) of some AMM instance pools shares represented by the number of LPTo...
-
std::pair< TER, bool > applyGuts(Sandbox &view)
-
std::pair< TER, STAmount > singleWithdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, std::uint16_t tfee)
Single asset withdrawal (Asset1Out) equivalent to the amount specified in Asset1Out.
+
std::pair< TER, STAmount > singleWithdrawEPrice(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &ePrice, std::uint16_t tfee)
Withdraw single asset (Asset1Out, EPrice) with two constraints.
+
std::pair< TER, STAmount > equalWithdrawLimit(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &amount2, std::uint16_t tfee)
Withdraw both assets (Asset1Out, Asset2Out) with the constraints on the maximum amount of each asset ...
+
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > equalWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const account, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokens, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHanding, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Equal-asset withdrawal (LPTokens) of some AMM instance pools shares represented by the number of LPTo...
+
std::pair< TER, bool > applyGuts(Sandbox &view)
+
std::pair< TER, STAmount > singleWithdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, std::uint16_t tfee)
Single asset withdrawal (Asset1Out) equivalent to the amount specified in Asset1Out.
static constexpr ConsequencesFactoryType ConsequencesFactory
Definition AMMWithdraw.h:73
-
static std::pair< TER, bool > deleteAMMAccountIfEmpty(Sandbox &sb, std::shared_ptr< SLE > const ammSle, STAmount const &lpTokenBalance, Issue const &issue1, Issue const &issue2, beast::Journal const &journal)
-
static TER preclaim(PreclaimContext const &ctx)
-
static NotTEC preflight(PreflightContext const &ctx)
-
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > withdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, AccountID const &account, STAmount const &amountBalance, STAmount const &amountWithdraw, std::optional< STAmount > const &amount2Withdraw, STAmount const &lpTokensAMMBalance, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHandling, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Withdraw requested assets and token from AMM into LP account.
-
TER doApply() override
-
std::pair< TER, STAmount > singleWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &lpTokensWithdraw, std::uint16_t tfee)
Single asset withdrawal (Asset1Out, LPTokens) proportional to the share specified by tokens.
+
static std::pair< TER, bool > deleteAMMAccountIfEmpty(Sandbox &sb, std::shared_ptr< SLE > const ammSle, STAmount const &lpTokenBalance, Issue const &issue1, Issue const &issue2, beast::Journal const &journal)
+
static TER preclaim(PreclaimContext const &ctx)
+
static NotTEC preflight(PreflightContext const &ctx)
+
static std::tuple< TER, STAmount, STAmount, std::optional< STAmount > > withdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, AccountID const &account, STAmount const &amountBalance, STAmount const &amountWithdraw, std::optional< STAmount > const &amount2Withdraw, STAmount const &lpTokensAMMBalance, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHandling, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)
Withdraw requested assets and token from AMM into LP account.
+
TER doApply() override
+
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
+
std::pair< TER, STAmount > singleWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &lpTokensWithdraw, std::uint16_t tfee)
Single asset withdrawal (Asset1Out, LPTokens) proportional to the share specified by tokens.
State information when applying a tx.
A currency issued by an account.
Definition Issue.h:33
@@ -280,13 +288,13 @@ $(document).ready(function() { init_codefold(0); });
Discardable, editable view to a ledger.
Definition Sandbox.h:35
- - - -
ApplyView & view()
Definition Transactor.h:161
+ + + +
ApplyView & view()
Definition Transactor.h:163
- +
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
WithdrawAll
AMMWithdraw implements AMM withdraw Transactor.
Definition AMMWithdraw.h:68
FreezeHandling
Controls the treatment of frozen account balances.
Definition View.h:77
diff --git a/AMM__test_8cpp_source.html b/AMM__test_8cpp_source.html index 4458a3b3e9..b2195ab666 100644 --- a/AMM__test_8cpp_source.html +++ b/AMM__test_8cpp_source.html @@ -3671,7 +3671,7 @@ $(document).ready(function() { init_codefold(0); });
3572 env.current()->rules(),
3573 tapNONE,
3574 env.journal);
-
3575 auto pf = AMMBid::preflight(pfctx);
+
3575 auto pf = Transactor::invokePreflight<AMMBid>(pfctx);
3576 BEAST_EXPECT(pf == temDISABLED);
3577 env.app().config().features.insert(featureAMM);
3578 }
@@ -3686,7 +3686,7 @@ $(document).ready(function() { init_codefold(0); });
3587 env.current()->rules(),
3588 tapNONE,
3589 env.journal);
-
3590 auto pf = AMMBid::preflight(pfctx);
+
3590 auto pf = Transactor::invokePreflight<AMMBid>(pfctx);
3591 BEAST_EXPECT(pf != tesSUCCESS);
3592 }
3593
@@ -3701,7 +3701,7 @@ $(document).ready(function() { init_codefold(0); });
3602 env.current()->rules(),
3603 tapNONE,
3604 env.journal);
-
3605 auto pf = AMMBid::preflight(pfctx);
+
3605 auto pf = Transactor::invokePreflight<AMMBid>(pfctx);
3606 BEAST_EXPECT(pf == temBAD_AMM_TOKENS);
3607 }
3608 }
diff --git a/AccountObjects__test_8cpp_source.html b/AccountObjects__test_8cpp_source.html index 20632ca6c1..ecc198077b 100644 --- a/AccountObjects__test_8cpp_source.html +++ b/AccountObjects__test_8cpp_source.html @@ -1566,7 +1566,7 @@ $(document).ready(function() { init_codefold(0); });
bool isMember(char const *key) const
Return true if the object has a member named key.
A testsuite class.
Definition suite.h:55
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:155
-
static uint256 createNFTokenID(std::uint16_t flags, std::uint16_t fee, AccountID const &issuer, nft::Taxon taxon, std::uint32_t tokenSeq)
+
static uint256 createNFTokenID(std::uint16_t flags, std::uint16_t fee, AccountID const &issuer, nft::Taxon taxon, std::uint32_t tokenSeq)
diff --git a/AccountSet__test_8cpp_source.html b/AccountSet__test_8cpp_source.html index c8186a67ed..f74dfac63c 100644 --- a/AccountSet__test_8cpp_source.html +++ b/AccountSet__test_8cpp_source.html @@ -102,636 +102,668 @@ $(document).ready(function() { init_codefold(0); });
19
20#include <test/jtx.h>
21
-
22#include <xrpl/protocol/AmountConversions.h>
-
23#include <xrpl/protocol/Feature.h>
-
24#include <xrpl/protocol/Quality.h>
-
25#include <xrpl/protocol/Rate.h>
-
26#include <xrpl/protocol/jss.h>
-
27
-
28namespace ripple {
+
22#include <xrpld/app/tx/apply.h>
+
23
+
24#include <xrpl/protocol/AmountConversions.h>
+
25#include <xrpl/protocol/Feature.h>
+
26#include <xrpl/protocol/Quality.h>
+
27#include <xrpl/protocol/Rate.h>
+
28#include <xrpl/protocol/jss.h>
29
-
- -
31{
-
32public:
-
33 void
-
- -
35 {
-
36 testcase("No AccountSet");
-
37
-
38 using namespace test::jtx;
-
39 Env env(*this);
-
40 Account const alice("alice");
-
41 env.fund(XRP(10000), noripple(alice));
-
42 // ask for the ledger entry - account root, to check its flags
-
43 auto const jrr = env.le(alice);
-
44 BEAST_EXPECT(jrr && jrr->at(sfFlags) == 0u);
-
45 }
+
30namespace ripple {
+
31
+
+ +
33{
+
34public:
+
35 void
+
+ +
37 {
+
38 testcase("No AccountSet");
+
39
+
40 using namespace test::jtx;
+
41 Env env(*this);
+
42 Account const alice("alice");
+
43 env.fund(XRP(10000), noripple(alice));
+
44 // ask for the ledger entry - account root, to check its flags
+
45 auto const jrr = env.le(alice);
+
46 BEAST_EXPECT(jrr && jrr->at(sfFlags) == 0u);
+
47 }
-
46
-
47 void
-
- -
49 {
-
50 testcase("Most Flags");
-
51
-
52 using namespace test::jtx;
-
53 Account const alice("alice");
-
54
-
55 // Test without DepositAuth enabled initially.
-
56 Env env(*this, testable_amendments() - featureDepositAuth);
-
57 env.fund(XRP(10000), noripple(alice));
-
58
-
59 // Give alice a regular key so she can legally set and clear
-
60 // her asfDisableMaster flag.
-
61 Account const alie{"alie", KeyType::secp256k1};
-
62 env(regkey(alice, alie));
-
63 env.close();
-
64
-
65 auto testFlags = [this, &alice, &alie, &env](
- -
67 std::uint32_t const orig_flags = (*env.le(alice))[sfFlags];
-
68 for (std::uint32_t flag{1u};
-
69 flag < std::numeric_limits<std::uint32_t>::digits;
-
70 ++flag)
-
71 {
-
72 if (flag == asfNoFreeze)
-
73 {
-
74 // The asfNoFreeze flag can't be cleared. It is tested
-
75 // elsewhere.
-
76 continue;
-
77 }
-
78
- -
80 {
-
81 // The asfAuthorizedNFTokenMinter flag requires the
-
82 // presence or absence of the sfNFTokenMinter field in
-
83 // the transaction. It is tested elsewhere.
-
84 continue;
-
85 }
-
86
-
87 if (flag == asfDisallowIncomingCheck ||
- - - -
91 {
-
92 // These flags are part of the DisallowIncoming amendment
-
93 // and are tested elsewhere
-
94 continue;
-
95 }
-
96 if (flag == asfAllowTrustLineClawback)
-
97 {
-
98 // The asfAllowTrustLineClawback flag can't be cleared. It
-
99 // is tested elsewhere.
-
100 continue;
-
101 }
-
102 if (flag == asfAllowTrustLineLocking)
-
103 {
-
104 // These flags are part of the AllowTokenLocking amendment
-
105 // and are tested elsewhere
-
106 continue;
-
107 }
-
108
-
109 if (std::find(goodFlags.begin(), goodFlags.end(), flag) !=
-
110 goodFlags.end())
-
111 {
-
112 // Good flag
-
113 env.require(nflags(alice, flag));
-
114 env(fset(alice, flag), sig(alice));
-
115 env.close();
-
116 env.require(flags(alice, flag));
-
117 env(fclear(alice, flag), sig(alie));
-
118 env.close();
-
119 env.require(nflags(alice, flag));
-
120 std::uint32_t const now_flags = (*env.le(alice))[sfFlags];
-
121 BEAST_EXPECT(now_flags == orig_flags);
-
122 }
-
123 else
-
124 {
-
125 // Bad flag
-
126 BEAST_EXPECT((*env.le(alice))[sfFlags] == orig_flags);
-
127 env(fset(alice, flag), sig(alice));
-
128 env.close();
-
129 BEAST_EXPECT((*env.le(alice))[sfFlags] == orig_flags);
-
130 env(fclear(alice, flag), sig(alie));
-
131 env.close();
-
132 BEAST_EXPECT((*env.le(alice))[sfFlags] == orig_flags);
-
133 }
-
134 }
-
135 };
-
136
-
137 // Test with featureDepositAuth disabled.
-
138 testFlags(
- - - - - - -
145
-
146 // Enable featureDepositAuth and retest.
-
147 env.enableFeature(featureDepositAuth);
-
148 env.close();
-
149 testFlags(
- - - - - - - -
157 }
+
48
+
49 void
+
+ +
51 {
+
52 testcase("Most Flags");
+
53
+
54 using namespace test::jtx;
+
55 Account const alice("alice");
+
56
+
57 // Test without DepositAuth enabled initially.
+
58 Env env(*this, testable_amendments() - featureDepositAuth);
+
59 env.fund(XRP(10000), noripple(alice));
+
60
+
61 // Give alice a regular key so she can legally set and clear
+
62 // her asfDisableMaster flag.
+
63 Account const alie{"alie", KeyType::secp256k1};
+
64 env(regkey(alice, alie));
+
65 env.close();
+
66
+
67 auto testFlags = [this, &alice, &alie, &env](
+ +
69 std::uint32_t const orig_flags = (*env.le(alice))[sfFlags];
+
70 for (std::uint32_t flag{1u};
+
71 flag < std::numeric_limits<std::uint32_t>::digits;
+
72 ++flag)
+
73 {
+
74 if (flag == asfNoFreeze)
+
75 {
+
76 // The asfNoFreeze flag can't be cleared. It is tested
+
77 // elsewhere.
+
78 continue;
+
79 }
+
80
+ +
82 {
+
83 // The asfAuthorizedNFTokenMinter flag requires the
+
84 // presence or absence of the sfNFTokenMinter field in
+
85 // the transaction. It is tested elsewhere.
+
86 continue;
+
87 }
+
88
+
89 if (flag == asfDisallowIncomingCheck ||
+ + + +
93 {
+
94 // These flags are part of the DisallowIncoming amendment
+
95 // and are tested elsewhere
+
96 continue;
+
97 }
+
98 if (flag == asfAllowTrustLineClawback)
+
99 {
+
100 // The asfAllowTrustLineClawback flag can't be cleared. It
+
101 // is tested elsewhere.
+
102 continue;
+
103 }
+
104 if (flag == asfAllowTrustLineLocking)
+
105 {
+
106 // These flags are part of the AllowTokenLocking amendment
+
107 // and are tested elsewhere
+
108 continue;
+
109 }
+
110
+
111 if (std::find(goodFlags.begin(), goodFlags.end(), flag) !=
+
112 goodFlags.end())
+
113 {
+
114 // Good flag
+
115 env.require(nflags(alice, flag));
+
116 env(fset(alice, flag), sig(alice));
+
117 env.close();
+
118 env.require(flags(alice, flag));
+
119 env(fclear(alice, flag), sig(alie));
+
120 env.close();
+
121 env.require(nflags(alice, flag));
+
122 std::uint32_t const now_flags = (*env.le(alice))[sfFlags];
+
123 BEAST_EXPECT(now_flags == orig_flags);
+
124 }
+
125 else
+
126 {
+
127 // Bad flag
+
128 BEAST_EXPECT((*env.le(alice))[sfFlags] == orig_flags);
+
129 env(fset(alice, flag), sig(alice));
+
130 env.close();
+
131 BEAST_EXPECT((*env.le(alice))[sfFlags] == orig_flags);
+
132 env(fclear(alice, flag), sig(alie));
+
133 env.close();
+
134 BEAST_EXPECT((*env.le(alice))[sfFlags] == orig_flags);
+
135 }
+
136 }
+
137 };
+
138
+
139 // Test with featureDepositAuth disabled.
+
140 testFlags(
+ + + + + + +
147
+
148 // Enable featureDepositAuth and retest.
+
149 env.enableFeature(featureDepositAuth);
+
150 env.close();
+
151 testFlags(
+ + + + + + + +
159 }
-
158
-
159 void
-
- -
161 {
-
162 testcase("Set and reset AccountTxnID");
-
163
-
164 using namespace test::jtx;
-
165 Env env(*this);
-
166 Account const alice("alice");
-
167 env.fund(XRP(10000), noripple(alice));
-
168
-
169 std::uint32_t const orig_flags = (*env.le(alice))[sfFlags];
+
160
+
161 void
+
+ +
163 {
+
164 testcase("Set and reset AccountTxnID");
+
165
+
166 using namespace test::jtx;
+
167 Env env(*this);
+
168 Account const alice("alice");
+
169 env.fund(XRP(10000), noripple(alice));
170
-
171 // asfAccountTxnID is special and not actually set as a flag,
-
172 // so we check the field presence instead
-
173 BEAST_EXPECT(!env.le(alice)->isFieldPresent(sfAccountTxnID));
-
174 env(fset(alice, asfAccountTxnID), sig(alice));
-
175 BEAST_EXPECT(env.le(alice)->isFieldPresent(sfAccountTxnID));
-
176 env(fclear(alice, asfAccountTxnID));
-
177 BEAST_EXPECT(!env.le(alice)->isFieldPresent(sfAccountTxnID));
-
178 std::uint32_t const now_flags = (*env.le(alice))[sfFlags];
-
179 BEAST_EXPECT(now_flags == orig_flags);
-
180 }
+
171 std::uint32_t const orig_flags = (*env.le(alice))[sfFlags];
+
172
+
173 // asfAccountTxnID is special and not actually set as a flag,
+
174 // so we check the field presence instead
+
175 BEAST_EXPECT(!env.le(alice)->isFieldPresent(sfAccountTxnID));
+
176 env(fset(alice, asfAccountTxnID), sig(alice));
+
177 BEAST_EXPECT(env.le(alice)->isFieldPresent(sfAccountTxnID));
+
178 env(fclear(alice, asfAccountTxnID));
+
179 BEAST_EXPECT(!env.le(alice)->isFieldPresent(sfAccountTxnID));
+
180 std::uint32_t const now_flags = (*env.le(alice))[sfFlags];
+
181 BEAST_EXPECT(now_flags == orig_flags);
+
182 }
-
181
-
182 void
-
- -
184 {
-
185 testcase("Set NoFreeze");
-
186
-
187 using namespace test::jtx;
-
188 Env env(*this);
-
189 Account const alice("alice");
-
190 env.fund(XRP(10000), noripple(alice));
-
191 env.memoize("eric");
-
192 env(regkey(alice, "eric"));
-
193
-
194 env.require(nflags(alice, asfNoFreeze));
-
195 env(fset(alice, asfNoFreeze), sig("eric"), ter(tecNEED_MASTER_KEY));
-
196 env(fset(alice, asfNoFreeze), sig(alice));
-
197 env.require(flags(alice, asfNoFreeze));
-
198 env(fclear(alice, asfNoFreeze), sig(alice));
-
199 // verify flag is still set (clear does not clear in this case)
-
200 env.require(flags(alice, asfNoFreeze));
-
201 }
+
183
+
184 void
+
+ +
186 {
+
187 testcase("Set NoFreeze");
+
188
+
189 using namespace test::jtx;
+
190 Env env(*this);
+
191 Account const alice("alice");
+
192 env.fund(XRP(10000), noripple(alice));
+
193 env.memoize("eric");
+
194 env(regkey(alice, "eric"));
+
195
+
196 env.require(nflags(alice, asfNoFreeze));
+
197 env(fset(alice, asfNoFreeze), sig("eric"), ter(tecNEED_MASTER_KEY));
+
198 env(fset(alice, asfNoFreeze), sig(alice));
+
199 env.require(flags(alice, asfNoFreeze));
+
200 env(fclear(alice, asfNoFreeze), sig(alice));
+
201 // verify flag is still set (clear does not clear in this case)
+
202 env.require(flags(alice, asfNoFreeze));
+
203 }
-
202
-
203 void
-
- -
205 {
-
206 testcase("Domain");
-
207
-
208 using namespace test::jtx;
-
209 Env env(*this);
-
210 Account const alice("alice");
-
211 env.fund(XRP(10000), alice);
-
212 auto jt = noop(alice);
-
213 // The Domain field is represented as the hex string of the lowercase
-
214 // ASCII of the domain. For example, the domain example.com would be
-
215 // represented as "6578616d706c652e636f6d".
-
216 //
-
217 // To remove the Domain field from an account, send an AccountSet with
-
218 // the Domain set to an empty string.
-
219 std::string const domain = "example.com";
-
220 jt[sfDomain.fieldName] = strHex(domain);
-
221 env(jt);
-
222 BEAST_EXPECT((*env.le(alice))[sfDomain] == makeSlice(domain));
-
223
-
224 jt[sfDomain.fieldName] = "";
-
225 env(jt);
-
226 BEAST_EXPECT(!env.le(alice)->isFieldPresent(sfDomain));
-
227
-
228 // The upper limit on the length is 256 bytes
-
229 // (defined as DOMAIN_BYTES_MAX in SetAccount)
-
230 // test the edge cases: 255, 256, 257.
-
231 std::size_t const maxLength = 256;
-
232 for (std::size_t len = maxLength - 1; len <= maxLength + 1; ++len)
-
233 {
-
234 std::string domain2 =
-
235 std::string(len - domain.length() - 1, 'a') + "." + domain;
-
236
-
237 BEAST_EXPECT(domain2.length() == len);
+
204
+
205 void
+
+ +
207 {
+
208 testcase("Domain");
+
209
+
210 using namespace test::jtx;
+
211 Env env(*this);
+
212 Account const alice("alice");
+
213 env.fund(XRP(10000), alice);
+
214 auto jt = noop(alice);
+
215 // The Domain field is represented as the hex string of the lowercase
+
216 // ASCII of the domain. For example, the domain example.com would be
+
217 // represented as "6578616d706c652e636f6d".
+
218 //
+
219 // To remove the Domain field from an account, send an AccountSet with
+
220 // the Domain set to an empty string.
+
221 std::string const domain = "example.com";
+
222 jt[sfDomain.fieldName] = strHex(domain);
+
223 env(jt);
+
224 BEAST_EXPECT((*env.le(alice))[sfDomain] == makeSlice(domain));
+
225
+
226 jt[sfDomain.fieldName] = "";
+
227 env(jt);
+
228 BEAST_EXPECT(!env.le(alice)->isFieldPresent(sfDomain));
+
229
+
230 // The upper limit on the length is 256 bytes
+
231 // (defined as DOMAIN_BYTES_MAX in SetAccount)
+
232 // test the edge cases: 255, 256, 257.
+
233 std::size_t const maxLength = 256;
+
234 for (std::size_t len = maxLength - 1; len <= maxLength + 1; ++len)
+
235 {
+
236 std::string domain2 =
+
237 std::string(len - domain.length() - 1, 'a') + "." + domain;
238
-
239 jt[sfDomain.fieldName] = strHex(domain2);
+
239 BEAST_EXPECT(domain2.length() == len);
240
-
241 if (len <= maxLength)
-
242 {
-
243 env(jt);
-
244 BEAST_EXPECT((*env.le(alice))[sfDomain] == makeSlice(domain2));
-
245 }
-
246 else
-
247 {
-
248 env(jt, ter(telBAD_DOMAIN));
-
249 }
-
250 }
-
251 }
+
241 jt[sfDomain.fieldName] = strHex(domain2);
+
242
+
243 if (len <= maxLength)
+
244 {
+
245 env(jt);
+
246 BEAST_EXPECT((*env.le(alice))[sfDomain] == makeSlice(domain2));
+
247 }
+
248 else
+
249 {
+
250 env(jt, ter(telBAD_DOMAIN));
+
251 }
+
252 }
+
253 }
-
252
-
253 void
-
- -
255 {
-
256 testcase("MessageKey");
-
257
-
258 using namespace test::jtx;
-
259 Env env(*this);
-
260 Account const alice("alice");
-
261 env.fund(XRP(10000), alice);
-
262 auto jt = noop(alice);
-
263
-
264 auto const rkp = randomKeyPair(KeyType::ed25519);
-
265 jt[sfMessageKey.fieldName] = strHex(rkp.first.slice());
-
266 env(jt);
-
267 BEAST_EXPECT(
-
268 strHex((*env.le(alice))[sfMessageKey]) ==
-
269 strHex(rkp.first.slice()));
-
270
-
271 jt[sfMessageKey.fieldName] = "";
-
272 env(jt);
-
273 BEAST_EXPECT(!env.le(alice)->isFieldPresent(sfMessageKey));
-
274
-
275 using namespace std::string_literals;
-
276 jt[sfMessageKey.fieldName] = strHex("NOT_REALLY_A_PUBKEY"s);
-
277 env(jt, ter(telBAD_PUBLIC_KEY));
-
278 }
+
254
+
255 void
+
+ +
257 {
+
258 testcase("MessageKey");
+
259
+
260 using namespace test::jtx;
+
261 Env env(*this);
+
262 Account const alice("alice");
+
263 env.fund(XRP(10000), alice);
+
264 auto jt = noop(alice);
+
265
+
266 auto const rkp = randomKeyPair(KeyType::ed25519);
+
267 jt[sfMessageKey.fieldName] = strHex(rkp.first.slice());
+
268 env(jt);
+
269 BEAST_EXPECT(
+
270 strHex((*env.le(alice))[sfMessageKey]) ==
+
271 strHex(rkp.first.slice()));
+
272
+
273 jt[sfMessageKey.fieldName] = "";
+
274 env(jt);
+
275 BEAST_EXPECT(!env.le(alice)->isFieldPresent(sfMessageKey));
+
276
+
277 using namespace std::string_literals;
+
278 jt[sfMessageKey.fieldName] = strHex("NOT_REALLY_A_PUBKEY"s);
+
279 env(jt, ter(telBAD_PUBLIC_KEY));
+
280 }
-
279
-
280 void
-
- -
282 {
-
283 testcase("WalletID");
-
284
-
285 using namespace test::jtx;
-
286 Env env(*this);
-
287 Account const alice("alice");
-
288 env.fund(XRP(10000), alice);
-
289 auto jt = noop(alice);
-
290
-
291 std::string const locator =
-
292 "9633EC8AF54F16B5286DB1D7B519EF49EEFC050C0C8AC4384F1D88ACD1BFDF05";
-
293 jt[sfWalletLocator.fieldName] = locator;
-
294 env(jt);
-
295 BEAST_EXPECT(to_string((*env.le(alice))[sfWalletLocator]) == locator);
-
296
-
297 jt[sfWalletLocator.fieldName] = "";
-
298 env(jt);
-
299 BEAST_EXPECT(!env.le(alice)->isFieldPresent(sfWalletLocator));
-
300 }
+
281
+
282 void
+
+ +
284 {
+
285 testcase("WalletID");
+
286
+
287 using namespace test::jtx;
+
288 Env env(*this);
+
289 Account const alice("alice");
+
290 env.fund(XRP(10000), alice);
+
291 auto jt = noop(alice);
+
292
+
293 std::string const locator =
+
294 "9633EC8AF54F16B5286DB1D7B519EF49EEFC050C0C8AC4384F1D88ACD1BFDF05";
+
295 jt[sfWalletLocator.fieldName] = locator;
+
296 env(jt);
+
297 BEAST_EXPECT(to_string((*env.le(alice))[sfWalletLocator]) == locator);
+
298
+
299 jt[sfWalletLocator.fieldName] = "";
+
300 env(jt);
+
301 BEAST_EXPECT(!env.le(alice)->isFieldPresent(sfWalletLocator));
+
302 }
-
301
-
302 void
-
- -
304 {
-
305 testcase("EmailHash");
-
306
-
307 using namespace test::jtx;
-
308 Env env(*this);
-
309 Account const alice("alice");
-
310 env.fund(XRP(10000), alice);
-
311 auto jt = noop(alice);
-
312
-
313 std::string const mh("5F31A79367DC3137FADA860C05742EE6");
-
314 jt[sfEmailHash.fieldName] = mh;
-
315 env(jt);
-
316 BEAST_EXPECT(to_string((*env.le(alice))[sfEmailHash]) == mh);
-
317
-
318 jt[sfEmailHash.fieldName] = "";
-
319 env(jt);
-
320 BEAST_EXPECT(!env.le(alice)->isFieldPresent(sfEmailHash));
-
321 }
+
303
+
304 void
+
+ +
306 {
+
307 testcase("EmailHash");
+
308
+
309 using namespace test::jtx;
+
310 Env env(*this);
+
311 Account const alice("alice");
+
312 env.fund(XRP(10000), alice);
+
313 auto jt = noop(alice);
+
314
+
315 std::string const mh("5F31A79367DC3137FADA860C05742EE6");
+
316 jt[sfEmailHash.fieldName] = mh;
+
317 env(jt);
+
318 BEAST_EXPECT(to_string((*env.le(alice))[sfEmailHash]) == mh);
+
319
+
320 jt[sfEmailHash.fieldName] = "";
+
321 env(jt);
+
322 BEAST_EXPECT(!env.le(alice)->isFieldPresent(sfEmailHash));
+
323 }
-
322
-
323 void
-
- -
325 {
-
326 struct test_results
-
327 {
-
328 double set;
-
329 TER code;
-
330 double get;
-
331 };
-
332
-
333 testcase("TransferRate");
+
324
+
325 void
+
+ +
327 {
+
328 struct test_results
+
329 {
+
330 double set;
+
331 TER code;
+
332 double get;
+
333 };
334
-
335 using namespace test::jtx;
-
336 auto doTests = [this](
-
337 FeatureBitset const& features,
- -
339 Env env(*this, features);
-
340
-
341 Account const alice("alice");
-
342 env.fund(XRP(10000), alice);
-
343
-
344 for (auto const& r : testData)
-
345 {
-
346 env(rate(alice, r.set), ter(r.code));
-
347 env.close();
-
348
-
349 // If the field is not present expect the default value
-
350 if (!(*env.le(alice))[~sfTransferRate])
-
351 BEAST_EXPECT(r.get == 1.0);
-
352 else
-
353 BEAST_EXPECT(
-
354 *(*env.le(alice))[~sfTransferRate] ==
-
355 r.get * QUALITY_ONE);
-
356 }
-
357 };
-
358
-
359 doTests(
-
360 testable_amendments(),
-
361 {{1.0, tesSUCCESS, 1.0},
-
362 {1.1, tesSUCCESS, 1.1},
-
363 {2.0, tesSUCCESS, 2.0},
-
364 {2.1, temBAD_TRANSFER_RATE, 2.0},
-
365 {0.0, tesSUCCESS, 1.0},
-
366 {2.0, tesSUCCESS, 2.0},
-
367 {0.9, temBAD_TRANSFER_RATE, 2.0}});
-
368 }
+
335 testcase("TransferRate");
+
336
+
337 using namespace test::jtx;
+
338 auto doTests = [this](
+
339 FeatureBitset const& features,
+ +
341 Env env(*this, features);
+
342
+
343 Account const alice("alice");
+
344 env.fund(XRP(10000), alice);
+
345
+
346 for (auto const& r : testData)
+
347 {
+
348 env(rate(alice, r.set), ter(r.code));
+
349 env.close();
+
350
+
351 // If the field is not present expect the default value
+
352 if (!(*env.le(alice))[~sfTransferRate])
+
353 BEAST_EXPECT(r.get == 1.0);
+
354 else
+
355 BEAST_EXPECT(
+
356 *(*env.le(alice))[~sfTransferRate] ==
+
357 r.get * QUALITY_ONE);
+
358 }
+
359 };
+
360
+
361 doTests(
+
362 testable_amendments(),
+
363 {{1.0, tesSUCCESS, 1.0},
+
364 {1.1, tesSUCCESS, 1.1},
+
365 {2.0, tesSUCCESS, 2.0},
+
366 {2.1, temBAD_TRANSFER_RATE, 2.0},
+
367 {0.0, tesSUCCESS, 1.0},
+
368 {2.0, tesSUCCESS, 2.0},
+
369 {0.9, temBAD_TRANSFER_RATE, 2.0}});
+
370 }
-
369
-
370 void
-
- -
372 {
-
373 testcase("Gateway");
-
374
-
375 using namespace test::jtx;
+
371
+
372 void
+
+ +
374 {
+
375 testcase("Gateway");
376
-
377 Account const alice("alice");
-
378 Account const bob("bob");
-
379 Account const gw("gateway");
-
380 auto const USD = gw["USD"];
-
381
-
382 // Test gateway with a variety of allowed transfer rates
-
383 for (double transferRate = 1.0; transferRate <= 2.0;
-
384 transferRate += 0.03125)
-
385 {
-
386 Env env(*this);
-
387 env.fund(XRP(10000), gw, alice, bob);
-
388 env.close();
-
389 env.trust(USD(10), alice, bob);
+
377 using namespace test::jtx;
+
378
+
379 Account const alice("alice");
+
380 Account const bob("bob");
+
381 Account const gw("gateway");
+
382 auto const USD = gw["USD"];
+
383
+
384 // Test gateway with a variety of allowed transfer rates
+
385 for (double transferRate = 1.0; transferRate <= 2.0;
+
386 transferRate += 0.03125)
+
387 {
+
388 Env env(*this);
+
389 env.fund(XRP(10000), gw, alice, bob);
390 env.close();
-
391 env(rate(gw, transferRate));
+
391 env.trust(USD(10), alice, bob);
392 env.close();
-
393
-
394 auto const amount = USD(1);
-
395 Rate const rate(transferRate * QUALITY_ONE);
-
396 auto const amountWithRate =
-
397 toAmount<STAmount>(multiply(amount.value(), rate));
-
398
-
399 env(pay(gw, alice, USD(10)));
-
400 env.close();
-
401 env(pay(alice, bob, USD(1)), sendmax(USD(10)));
+
393 env(rate(gw, transferRate));
+
394 env.close();
+
395
+
396 auto const amount = USD(1);
+
397 Rate const rate(transferRate * QUALITY_ONE);
+
398 auto const amountWithRate =
+
399 toAmount<STAmount>(multiply(amount.value(), rate));
+
400
+
401 env(pay(gw, alice, USD(10)));
402 env.close();
-
403
-
404 env.require(balance(alice, USD(10) - amountWithRate));
-
405 env.require(balance(bob, USD(1)));
-
406 }
-
407
-
408 // Since fix1201 was enabled on Nov 14 2017 a rate in excess of
-
409 // 2.0 has been blocked by the transactor. But there are a few
-
410 // accounts on the MainNet that have larger-than-currently-allowed
-
411 // TransferRates. We'll bypass the transactor so we can check
-
412 // operation of these legacy TransferRates.
-
413 //
-
414 // Two out-of-bound values are currently in the ledger (March 2020)
-
415 // They are 4.0 and 4.294967295. So those are the values we test.
-
416 for (double transferRate : {4.0, 4.294967295})
-
417 {
-
418 Env env(*this);
-
419 env.fund(XRP(10000), gw, alice, bob);
-
420 env.close();
-
421 env.trust(USD(10), alice, bob);
+
403 env(pay(alice, bob, USD(1)), sendmax(USD(10)));
+
404 env.close();
+
405
+
406 env.require(balance(alice, USD(10) - amountWithRate));
+
407 env.require(balance(bob, USD(1)));
+
408 }
+
409
+
410 // Since fix1201 was enabled on Nov 14 2017 a rate in excess of
+
411 // 2.0 has been blocked by the transactor. But there are a few
+
412 // accounts on the MainNet that have larger-than-currently-allowed
+
413 // TransferRates. We'll bypass the transactor so we can check
+
414 // operation of these legacy TransferRates.
+
415 //
+
416 // Two out-of-bound values are currently in the ledger (March 2020)
+
417 // They are 4.0 and 4.294967295. So those are the values we test.
+
418 for (double transferRate : {4.0, 4.294967295})
+
419 {
+
420 Env env(*this);
+
421 env.fund(XRP(10000), gw, alice, bob);
422 env.close();
-
423
-
424 // We'd like to use transferRate here, but the transactor
-
425 // blocks transfer rates that large. So we use an acceptable
-
426 // transfer rate here and later hack the ledger to replace
-
427 // the acceptable value with an out-of-bounds value.
-
428 env(rate(gw, 2.0));
-
429 env.close();
-
430
-
431 // Because we're hacking the ledger we need the account to have
-
432 // non-zero sfMintedNFTokens and sfBurnedNFTokens fields. This
-
433 // prevents an exception when the AccountRoot template is applied.
-
434 {
-
435 uint256 const nftId0{token::getNextID(env, gw, 0u)};
-
436 env(token::mint(gw, 0u));
-
437 env.close();
-
438
-
439 env(token::burn(gw, nftId0));
-
440 env.close();
-
441 }
-
442
-
443 // Note that we're bypassing almost all of the ledger's safety
-
444 // checks with this modify() call. If you call close() between
-
445 // here and the end of the test all the effort will be lost.
-
446 env.app().openLedger().modify(
-
447 [&gw, transferRate](OpenView& view, beast::Journal j) {
-
448 // Get the account root we want to hijack.
-
449 auto const sle = view.read(keylet::account(gw.id()));
-
450 if (!sle)
-
451 return false; // This would be really surprising!
-
452
-
453 // We'll insert a replacement for the account root
-
454 // with the higher (currently invalid) transfer rate.
-
455 auto replacement = std::make_shared<SLE>(*sle, sle->key());
-
456 (*replacement)[sfTransferRate] =
-
457 static_cast<std::uint32_t>(transferRate * QUALITY_ONE);
-
458 view.rawReplace(replacement);
-
459 return true;
-
460 });
-
461
-
462 auto const amount = USD(1);
-
463 auto const amountWithRate = toAmount<STAmount>(
-
464 multiply(amount.value(), Rate(transferRate * QUALITY_ONE)));
-
465
-
466 env(pay(gw, alice, USD(10)));
-
467 env(pay(alice, bob, amount), sendmax(USD(10)));
-
468
-
469 env.require(balance(alice, USD(10) - amountWithRate));
-
470 env.require(balance(bob, amount));
-
471 }
-
472 }
+
423 env.trust(USD(10), alice, bob);
+
424 env.close();
+
425
+
426 // We'd like to use transferRate here, but the transactor
+
427 // blocks transfer rates that large. So we use an acceptable
+
428 // transfer rate here and later hack the ledger to replace
+
429 // the acceptable value with an out-of-bounds value.
+
430 env(rate(gw, 2.0));
+
431 env.close();
+
432
+
433 // Because we're hacking the ledger we need the account to have
+
434 // non-zero sfMintedNFTokens and sfBurnedNFTokens fields. This
+
435 // prevents an exception when the AccountRoot template is applied.
+
436 {
+
437 uint256 const nftId0{token::getNextID(env, gw, 0u)};
+
438 env(token::mint(gw, 0u));
+
439 env.close();
+
440
+
441 env(token::burn(gw, nftId0));
+
442 env.close();
+
443 }
+
444
+
445 // Note that we're bypassing almost all of the ledger's safety
+
446 // checks with this modify() call. If you call close() between
+
447 // here and the end of the test all the effort will be lost.
+
448 env.app().openLedger().modify(
+
449 [&gw, transferRate](OpenView& view, beast::Journal j) {
+
450 // Get the account root we want to hijack.
+
451 auto const sle = view.read(keylet::account(gw.id()));
+
452 if (!sle)
+
453 return false; // This would be really surprising!
+
454
+
455 // We'll insert a replacement for the account root
+
456 // with the higher (currently invalid) transfer rate.
+
457 auto replacement = std::make_shared<SLE>(*sle, sle->key());
+
458 (*replacement)[sfTransferRate] =
+
459 static_cast<std::uint32_t>(transferRate * QUALITY_ONE);
+
460 view.rawReplace(replacement);
+
461 return true;
+
462 });
+
463
+
464 auto const amount = USD(1);
+
465 auto const amountWithRate = toAmount<STAmount>(
+
466 multiply(amount.value(), Rate(transferRate * QUALITY_ONE)));
+
467
+
468 env(pay(gw, alice, USD(10)));
+
469 env(pay(alice, bob, amount), sendmax(USD(10)));
+
470
+
471 env.require(balance(alice, USD(10) - amountWithRate));
+
472 env.require(balance(bob, amount));
+
473 }
+
474 }
-
473
-
474 void
-
- -
476 {
-
477 testcase("Bad inputs");
-
478
-
479 using namespace test::jtx;
-
480 Env env(*this);
-
481 Account const alice("alice");
-
482 env.fund(XRP(10000), alice);
-
483
-
484 auto jt = fset(alice, asfDisallowXRP);
-
485 jt[jss::ClearFlag] = asfDisallowXRP;
-
486 env(jt, ter(temINVALID_FLAG));
-
487
-
488 jt = fset(alice, asfRequireAuth);
-
489 jt[jss::ClearFlag] = asfRequireAuth;
-
490 env(jt, ter(temINVALID_FLAG));
-
491
-
492 jt = fset(alice, asfRequireDest);
-
493 jt[jss::ClearFlag] = asfRequireDest;
-
494 env(jt, ter(temINVALID_FLAG));
-
495
-
496 jt = fset(alice, asfDisallowXRP);
-
497 jt[sfFlags.fieldName] = tfAllowXRP;
-
498 env(jt, ter(temINVALID_FLAG));
-
499
-
500 jt = fset(alice, asfRequireAuth);
-
501 jt[sfFlags.fieldName] = tfOptionalAuth;
-
502 env(jt, ter(temINVALID_FLAG));
-
503
-
504 jt = fset(alice, asfRequireDest);
-
505 jt[sfFlags.fieldName] = tfOptionalDestTag;
-
506 env(jt, ter(temINVALID_FLAG));
-
507
-
508 jt = fset(alice, asfRequireDest);
-
509 jt[sfFlags.fieldName] = tfAccountSetMask;
-
510 env(jt, ter(temINVALID_FLAG));
-
511
-
512 env(fset(alice, asfDisableMaster),
-
513 sig(alice),
- -
515 }
+
475
+
476 void
+
+ +
478 {
+
479 testcase("Bad inputs");
+
480
+
481 using namespace test::jtx;
+
482 Env env(*this);
+
483 Account const alice("alice");
+
484 env.fund(XRP(10000), alice);
+
485
+
486 auto jt = fset(alice, asfDisallowXRP);
+
487 jt[jss::ClearFlag] = asfDisallowXRP;
+
488 env(jt, ter(temINVALID_FLAG));
+
489
+
490 jt = fset(alice, asfRequireAuth);
+
491 jt[jss::ClearFlag] = asfRequireAuth;
+
492 env(jt, ter(temINVALID_FLAG));
+
493
+
494 jt = fset(alice, asfRequireDest);
+
495 jt[jss::ClearFlag] = asfRequireDest;
+
496 env(jt, ter(temINVALID_FLAG));
+
497
+
498 jt = fset(alice, asfDisallowXRP);
+
499 jt[sfFlags.fieldName] = tfAllowXRP;
+
500 env(jt, ter(temINVALID_FLAG));
+
501
+
502 jt = fset(alice, asfRequireAuth);
+
503 jt[sfFlags.fieldName] = tfOptionalAuth;
+
504 env(jt, ter(temINVALID_FLAG));
+
505
+
506 jt = fset(alice, asfRequireDest);
+
507 jt[sfFlags.fieldName] = tfOptionalDestTag;
+
508 env(jt, ter(temINVALID_FLAG));
+
509
+
510 jt = fset(alice, asfRequireDest);
+
511 jt[sfFlags.fieldName] = tfAccountSetMask;
+
512 env(jt, ter(temINVALID_FLAG));
+
513
+
514 env(fset(alice, asfDisableMaster),
+
515 sig(alice),
+ +
517 }
-
516
-
517 void
-
- -
519 {
-
520 testcase("Require auth");
-
521
-
522 using namespace test::jtx;
-
523 Env env(*this);
-
524 Account const alice("alice");
-
525 Account const bob("bob");
-
526
-
527 env.fund(XRP(10000), alice);
-
528 env.close();
-
529
-
530 // alice should have an empty directory.
-
531 BEAST_EXPECT(dirIsEmpty(*env.closed(), keylet::ownerDir(alice)));
-
532
-
533 // Give alice a signer list, then there will be stuff in the directory.
-
534 env(signers(alice, 1, {{bob, 1}}));
-
535 env.close();
-
536 BEAST_EXPECT(!dirIsEmpty(*env.closed(), keylet::ownerDir(alice)));
-
537
-
538 env(fset(alice, asfRequireAuth), ter(tecOWNERS));
+
518
+
519 void
+
+ +
521 {
+
522 testcase("Require auth");
+
523
+
524 using namespace test::jtx;
+
525 Env env(*this);
+
526 Account const alice("alice");
+
527 Account const bob("bob");
+
528
+
529 env.fund(XRP(10000), alice);
+
530 env.close();
+
531
+
532 // alice should have an empty directory.
+
533 BEAST_EXPECT(dirIsEmpty(*env.closed(), keylet::ownerDir(alice)));
+
534
+
535 // Give alice a signer list, then there will be stuff in the directory.
+
536 env(signers(alice, 1, {{bob, 1}}));
+
537 env.close();
+
538 BEAST_EXPECT(!dirIsEmpty(*env.closed(), keylet::ownerDir(alice)));
539
-
540 // Remove the signer list. After that asfRequireAuth should succeed.
-
541 env(signers(alice, test::jtx::none));
-
542 env.close();
-
543 BEAST_EXPECT(dirIsEmpty(*env.closed(), keylet::ownerDir(alice)));
-
544
-
545 env(fset(alice, asfRequireAuth));
-
546 }
+
540 env(fset(alice, asfRequireAuth), ter(tecOWNERS));
+
541
+
542 // Remove the signer list. After that asfRequireAuth should succeed.
+
543 env(signers(alice, test::jtx::none));
+
544 env.close();
+
545 BEAST_EXPECT(dirIsEmpty(*env.closed(), keylet::ownerDir(alice)));
+
546
+
547 env(fset(alice, asfRequireAuth));
+
548 }
-
547
-
548 void
-
- -
550 {
-
551 using namespace test::jtx;
-
552 Env env(*this);
-
553 Account const alice("alice");
-
554
-
555 env.fund(XRP(10000), alice);
-
556 env.close();
-
557
-
558 std::uint32_t const ticketSeq{env.seq(alice) + 1};
-
559 env(ticket::create(alice, 1));
-
560 env.close();
-
561 env.require(owners(alice, 1), tickets(alice, 1));
-
562
-
563 // Try using a ticket that alice doesn't have.
-
564 env(noop(alice), ticket::use(ticketSeq + 1), ter(terPRE_TICKET));
-
565 env.close();
-
566 env.require(owners(alice, 1), tickets(alice, 1));
-
567
-
568 // Actually use alice's ticket. Note that if a transaction consumes
-
569 // a ticket then the account's sequence number does not advance.
-
570 std::uint32_t const aliceSeq{env.seq(alice)};
-
571 env(noop(alice), ticket::use(ticketSeq));
-
572 env.close();
-
573 env.require(owners(alice, 0), tickets(alice, 0));
-
574 BEAST_EXPECT(aliceSeq == env.seq(alice));
-
575
-
576 // Try re-using a ticket that alice already used.
-
577 env(noop(alice), ticket::use(ticketSeq), ter(tefNO_TICKET));
-
578 env.close();
-
579 }
-
-
580
-
581 void
-
-
582 run() override
-
583 {
- - - - -
588 testDomain();
-
589 testGateway();
- -
591 testWalletID();
- - - - -
596 testTicket();
-
597 }
-
-
598};
+
549
+
550 void
+
+ +
552 {
+
553 using namespace test::jtx;
+
554 Env env(*this);
+
555 Account const alice("alice");
+
556
+
557 env.fund(XRP(10000), alice);
+
558 env.close();
+
559
+
560 std::uint32_t const ticketSeq{env.seq(alice) + 1};
+
561 env(ticket::create(alice, 1));
+
562 env.close();
+
563 env.require(owners(alice, 1), tickets(alice, 1));
+
564
+
565 // Try using a ticket that alice doesn't have.
+
566 env(noop(alice), ticket::use(ticketSeq + 1), ter(terPRE_TICKET));
+
567 env.close();
+
568 env.require(owners(alice, 1), tickets(alice, 1));
+
569
+
570 // Actually use alice's ticket. Note that if a transaction consumes
+
571 // a ticket then the account's sequence number does not advance.
+
572 std::uint32_t const aliceSeq{env.seq(alice)};
+
573 env(noop(alice), ticket::use(ticketSeq));
+
574 env.close();
+
575 env.require(owners(alice, 0), tickets(alice, 0));
+
576 BEAST_EXPECT(aliceSeq == env.seq(alice));
+
577
+
578 // Try re-using a ticket that alice already used.
+
579 env(noop(alice), ticket::use(ticketSeq), ter(tefNO_TICKET));
+
580 env.close();
+
581 }
+
582
+
583 void
+
+ +
585 {
+
586 using namespace test::jtx;
+
587 testcase("Bad signing key");
+
588 Env env(*this);
+
589 Account const alice("alice");
+
590
+
591 env.fund(XRP(10000), alice);
+
592 env.close();
+
593
+
594 auto jtx = env.jt(noop("alice"), ter(temBAD_SIGNATURE));
+
595 if (!BEAST_EXPECT(jtx.stx))
+
596 return;
+
597 auto stx = std::make_shared<STTx>(*jtx.stx);
+
598 stx->at(sfSigningPubKey) = makeSlice(std::string("badkey"));
599
-
600BEAST_DEFINE_TESTSUITE_PRIO(AccountSet, rpc, ripple, 1);
-
601
-
602} // namespace ripple
+
600 env.app().openLedger().modify([&](OpenView& view, beast::Journal j) {
+
601 auto const result =
+
602 ripple::apply(env.app(), view, *stx, tapNONE, j);
+
603 BEAST_EXPECT(result.ter == temBAD_SIGNATURE);
+
604 BEAST_EXPECT(!result.applied);
+
605 return result.applied;
+
606 });
+
607 }
+
+
608
+
609 void
+
+
610 run() override
+
611 {
+ + + + +
616 testDomain();
+
617 testGateway();
+ +
619 testWalletID();
+ + + + +
624 testTicket();
+ +
626 }
+
+
627};
+
+
628
+
629BEAST_DEFINE_TESTSUITE_PRIO(AccountSet, rpc, ripple, 1);
+
630
+
631} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:60
A testsuite class.
Definition suite.h:55
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:155
- - - - - - - - - - - - - -
void run() override
Runs the suite.
- + + + + + + + + + + + + + +
void run() override
Runs the suite.
+ +
Writable ledger view that accumulates state and tx changes.
Definition OpenView.h:65
std::shared_ptr< SLE const > read(Keylet const &k) const override
Return the state item associated with a key.
Definition OpenView.cpp:169
@@ -779,17 +811,20 @@ $(document).ready(function() { init_codefold(0); });
@ tecNO_ALTERNATIVE_KEY
Definition TER.h:296
@ tesSUCCESS
Definition TER.h:244
constexpr std::uint32_t tfOptionalAuth
Definition TxFlags.h:69
+
ApplyResult apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
Definition apply.cpp:148
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
constexpr std::uint32_t asfDisallowIncomingPayChan
Definition TxFlags.h:92
T get(Section const &section, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
constexpr std::uint32_t asfAllowTrustLineClawback
Definition TxFlags.h:94
+
@ tapNONE
Definition ApplyView.h:31
constexpr std::uint32_t asfRequireAuth
Definition TxFlags.h:78
@ terPRE_TICKET
Definition TER.h:226
constexpr std::uint32_t asfDisallowXRP
Definition TxFlags.h:79
@ temINVALID_FLAG
Definition TER.h:111
@ temBAD_TRANSFER_RATE
Definition TER.h:107
+
@ temBAD_SIGNATURE
Definition TER.h:105
T length(T... args)
Represents a transfer rate.
Definition Rate.h:40
diff --git a/ApplyContext_8cpp_source.html b/ApplyContext_8cpp_source.html index 4d26dd05d9..fa10b24361 100644 --- a/ApplyContext_8cpp_source.html +++ b/ApplyContext_8cpp_source.html @@ -299,7 +299,7 @@ $(document).ready(function() { init_codefold(0); });
@ tapDRY_RUN
Definition ApplyView.h:49
@ tapBATCH
Definition ApplyView.h:45
-
bool isTecClaim(TER x) noexcept
Definition TER.h:680
+
bool isTecClaim(TER x) noexcept
Definition TER.h:681
T has_value(T... args)
diff --git a/Batch_8cpp_source.html b/Batch_8cpp_source.html index fb42da3c5c..520946bc36 100644 --- a/Batch_8cpp_source.html +++ b/Batch_8cpp_source.html @@ -229,296 +229,304 @@ $(document).ready(function() { init_codefold(0); });
165}
166
-
200NotTEC
-
- -
202{
-
203 if (!ctx.rules.enabled(featureBatch))
-
204 return temDISABLED;
-
205
-
206 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
-
207 return ret;
-
208
+ +
+ +
169{
+
170 return tfBatchMask;
+
171}
+
+
172
+
206NotTEC
+
+ +
208{
209 auto const parentBatchId = ctx.tx.getTransactionID();
-
210 auto const outerAccount = ctx.tx.getAccountID(sfAccount);
-
211 auto const flags = ctx.tx.getFlags();
-
212
-
213 if (flags & tfBatchMask)
-
214 {
-
215 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]:"
-
216 << "invalid flags.";
-
217 return temINVALID_FLAG;
-
218 }
-
219
-
220 if (std::popcount(
-
221 flags &
- +
210 auto const flags = ctx.tx.getFlags();
+
211
+
212 if (std::popcount(
+
213 flags &
+ +
215 {
+
216 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]:"
+
217 << "too many flags.";
+
218 return temINVALID_FLAG;
+
219 }
+
220
+
221 auto const& rawTxns = ctx.tx.getFieldArray(sfRawTransactions);
+
222 if (rawTxns.size() <= 1)
223 {
224 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]:"
-
225 << "too many flags.";
-
226 return temINVALID_FLAG;
+
225 << "txns array must have at least 2 entries.";
+
226 return temARRAY_EMPTY;
227 }
228
-
229 auto const& rawTxns = ctx.tx.getFieldArray(sfRawTransactions);
-
230 if (rawTxns.size() <= 1)
-
231 {
-
232 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]:"
-
233 << "txns array must have at least 2 entries.";
-
234 return temARRAY_EMPTY;
-
235 }
-
236
-
237 if (rawTxns.size() > maxBatchTxCount)
-
238 {
-
239 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]:"
-
240 << "txns array exceeds 8 entries.";
-
241 return temARRAY_TOO_LARGE;
-
242 }
-
243
-
244 // Validation Inner Batch Txns
-
245 std::unordered_set<AccountID> requiredSigners;
-
246 std::unordered_set<uint256> uniqueHashes;
- -
248 accountSeqTicket;
-
249 for (STObject rb : rawTxns)
-
250 {
-
251 STTx const stx = STTx{std::move(rb)};
-
252 auto const hash = stx.getTransactionID();
-
253 if (!uniqueHashes.emplace(hash).second)
-
254 {
-
255 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
-
256 << "duplicate Txn found. "
-
257 << "txID: " << hash;
-
258 return temREDUNDANT;
-
259 }
-
260
-
261 if (stx.getFieldU16(sfTransactionType) == ttBATCH)
-
262 {
-
263 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
-
264 << "batch cannot have an inner batch txn. "
-
265 << "txID: " << hash;
-
266 return temINVALID;
+
229 if (rawTxns.size() > maxBatchTxCount)
+
230 {
+
231 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]:"
+
232 << "txns array exceeds 8 entries.";
+
233 return temARRAY_TOO_LARGE;
+
234 }
+
235
+
236 // Validation Inner Batch Txns
+
237 std::unordered_set<uint256> uniqueHashes;
+ +
239 accountSeqTicket;
+
240 for (STObject rb : rawTxns)
+
241 {
+
242 STTx const stx = STTx{std::move(rb)};
+
243 auto const hash = stx.getTransactionID();
+
244 if (!uniqueHashes.emplace(hash).second)
+
245 {
+
246 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
+
247 << "duplicate Txn found. "
+
248 << "txID: " << hash;
+
249 return temREDUNDANT;
+
250 }
+
251
+
252 if (stx.getFieldU16(sfTransactionType) == ttBATCH)
+
253 {
+
254 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
+
255 << "batch cannot have an inner batch txn. "
+
256 << "txID: " << hash;
+
257 return temINVALID;
+
258 }
+
259
+
260 if (!(stx.getFlags() & tfInnerBatchTxn))
+
261 {
+
262 JLOG(ctx.j.debug())
+
263 << "BatchTrace[" << parentBatchId << "]: "
+
264 << "inner txn must have the tfInnerBatchTxn flag. "
+
265 << "txID: " << hash;
+
266 return temINVALID_FLAG;
267 }
268
-
269 if (!(stx.getFlags() & tfInnerBatchTxn))
+
269 if (stx.isFieldPresent(sfTxnSignature))
270 {
-
271 JLOG(ctx.j.debug())
-
272 << "BatchTrace[" << parentBatchId << "]: "
-
273 << "inner txn must have the tfInnerBatchTxn flag. "
-
274 << "txID: " << hash;
-
275 return temINVALID_FLAG;
-
276 }
-
277
-
278 if (stx.isFieldPresent(sfTxnSignature))
-
279 {
-
280 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
-
281 << "inner txn cannot include TxnSignature. "
-
282 << "txID: " << hash;
-
283 return temBAD_SIGNATURE;
-
284 }
-
285
-
286 if (stx.isFieldPresent(sfSigners))
-
287 {
-
288 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
-
289 << "inner txn cannot include Signers. "
-
290 << "txID: " << hash;
-
291 return temBAD_SIGNER;
-
292 }
-
293
-
294 if (!stx.getSigningPubKey().empty())
-
295 {
-
296 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
-
297 << "inner txn SigningPubKey must be empty. "
-
298 << "txID: " << hash;
-
299 return temBAD_REGKEY;
-
300 }
-
301
-
302 auto const innerAccount = stx.getAccountID(sfAccount);
-
303 if (auto const preflightResult = ripple::preflight(
-
304 ctx.app, ctx.rules, parentBatchId, stx, tapBATCH, ctx.j);
-
305 preflightResult.ter != tesSUCCESS)
-
306 {
-
307 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
-
308 << "inner txn preflight failed: "
-
309 << transHuman(preflightResult.ter) << " "
-
310 << "txID: " << hash;
- -
312 }
-
313
-
314 // Check that the fee is zero
-
315 if (auto const fee = stx.getFieldAmount(sfFee);
-
316 !fee.native() || fee.xrp() != beast::zero)
-
317 {
-
318 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
-
319 << "inner txn must have a fee of 0. "
-
320 << "txID: " << hash;
-
321 return temBAD_FEE;
-
322 }
-
323
-
324 // Check that Sequence and TicketSequence are not both present
-
325 if (stx.isFieldPresent(sfTicketSequence) &&
-
326 stx.getFieldU32(sfSequence) != 0)
-
327 {
-
328 JLOG(ctx.j.debug())
-
329 << "BatchTrace[" << parentBatchId << "]: "
-
330 << "inner txn must have exactly one of Sequence and "
-
331 "TicketSequence. "
-
332 << "txID: " << hash;
-
333 return temSEQ_AND_TICKET;
-
334 }
-
335
-
336 // Verify that either Sequence or TicketSequence is present
-
337 if (!stx.isFieldPresent(sfTicketSequence) &&
-
338 stx.getFieldU32(sfSequence) == 0)
-
339 {
-
340 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
-
341 << "inner txn must have either Sequence or "
-
342 "TicketSequence. "
-
343 << "txID: " << hash;
-
344 return temSEQ_AND_TICKET;
-
345 }
-
346
-
347 // Duplicate sequence and ticket checks
-
348 if (flags & (tfAllOrNothing | tfUntilFailure))
-
349 {
-
350 if (auto const seq = stx.getFieldU32(sfSequence); seq != 0)
-
351 {
-
352 if (!accountSeqTicket[innerAccount].insert(seq).second)
-
353 {
-
354 JLOG(ctx.j.debug())
-
355 << "BatchTrace[" << parentBatchId << "]: "
-
356 << "duplicate sequence found: "
-
357 << "txID: " << hash;
-
358 return temREDUNDANT;
-
359 }
-
360 }
-
361
-
362 if (stx.isFieldPresent(sfTicketSequence))
-
363 {
-
364 if (auto const ticket = stx.getFieldU32(sfTicketSequence);
-
365 !accountSeqTicket[innerAccount].insert(ticket).second)
-
366 {
-
367 JLOG(ctx.j.debug())
-
368 << "BatchTrace[" << parentBatchId << "]: "
-
369 << "duplicate ticket found: "
-
370 << "txID: " << hash;
-
371 return temREDUNDANT;
-
372 }
-
373 }
-
374 }
-
375
-
376 // If the inner account is the same as the outer account, do not add the
-
377 // inner account to the required signers set.
-
378 if (innerAccount != outerAccount)
-
379 requiredSigners.insert(innerAccount);
-
380 }
-
381
-
382 // LCOV_EXCL_START
-
383 if (auto const ret = preflight2(ctx); !isTesSuccess(ret))
-
384 return ret;
-
385 // LCOV_EXCL_STOP
-
386
-
387 // Validation Batch Signers
- -
389 if (ctx.tx.isFieldPresent(sfBatchSigners))
-
390 {
-
391 STArray const& signers = ctx.tx.getFieldArray(sfBatchSigners);
-
392
-
393 // Check that the batch signers array is not too large.
-
394 if (signers.size() > maxBatchTxCount)
-
395 {
-
396 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
-
397 << "signers array exceeds 8 entries.";
-
398 return temARRAY_TOO_LARGE;
-
399 }
-
400
-
401 // Add batch signers to the set to ensure all signer accounts are
-
402 // unique. Meanwhile, remove signer accounts from the set of inner
-
403 // transaction accounts (`requiredSigners`). By the end of the loop,
-
404 // `requiredSigners` should be empty, indicating that all inner
-
405 // accounts are matched with signers.
-
406 for (auto const& signer : signers)
-
407 {
-
408 AccountID const signerAccount = signer.getAccountID(sfAccount);
-
409 if (signerAccount == outerAccount)
-
410 {
-
411 JLOG(ctx.j.debug())
-
412 << "BatchTrace[" << parentBatchId << "]: "
-
413 << "signer cannot be the outer account: " << signerAccount;
-
414 return temBAD_SIGNER;
-
415 }
-
416
-
417 if (!batchSigners.insert(signerAccount).second)
-
418 {
-
419 JLOG(ctx.j.debug())
-
420 << "BatchTrace[" << parentBatchId << "]: "
-
421 << "duplicate signer found: " << signerAccount;
-
422 return temREDUNDANT;
-
423 }
-
424
-
425 // Check that the batch signer is in the required signers set.
-
426 // Remove it if it does, as it can be crossed off the list.
-
427 if (requiredSigners.erase(signerAccount) == 0)
-
428 {
-
429 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
-
430 << "no account signature for inner txn.";
-
431 return temBAD_SIGNER;
-
432 }
-
433 }
-
434
-
435 // Check the batch signers signatures.
-
436 auto const sigResult = ctx.tx.checkBatchSign(
- -
438
-
439 if (!sigResult)
-
440 {
-
441 JLOG(ctx.j.debug())
-
442 << "BatchTrace[" << parentBatchId << "]: "
-
443 << "invalid batch txn signature: " << sigResult.error();
-
444 return temBAD_SIGNATURE;
-
445 }
-
446 }
-
447
-
448 if (!requiredSigners.empty())
-
449 {
-
450 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
-
451 << "invalid batch signers.";
-
452 return temBAD_SIGNER;
-
453 }
-
454 return tesSUCCESS;
-
455}
+
271 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
+
272 << "inner txn cannot include TxnSignature. "
+
273 << "txID: " << hash;
+
274 return temBAD_SIGNATURE;
+
275 }
+
276
+
277 if (stx.isFieldPresent(sfSigners))
+
278 {
+
279 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
+
280 << "inner txn cannot include Signers. "
+
281 << "txID: " << hash;
+
282 return temBAD_SIGNER;
+
283 }
+
284
+
285 if (!stx.getSigningPubKey().empty())
+
286 {
+
287 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
+
288 << "inner txn SigningPubKey must be empty. "
+
289 << "txID: " << hash;
+
290 return temBAD_REGKEY;
+
291 }
+
292
+
293 auto const innerAccount = stx.getAccountID(sfAccount);
+
294 if (auto const preflightResult = ripple::preflight(
+
295 ctx.app, ctx.rules, parentBatchId, stx, tapBATCH, ctx.j);
+
296 preflightResult.ter != tesSUCCESS)
+
297 {
+
298 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
+
299 << "inner txn preflight failed: "
+
300 << transHuman(preflightResult.ter) << " "
+
301 << "txID: " << hash;
+ +
303 }
+
304
+
305 // Check that the fee is zero
+
306 if (auto const fee = stx.getFieldAmount(sfFee);
+
307 !fee.native() || fee.xrp() != beast::zero)
+
308 {
+
309 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
+
310 << "inner txn must have a fee of 0. "
+
311 << "txID: " << hash;
+
312 return temBAD_FEE;
+
313 }
+
314
+
315 // Check that Sequence and TicketSequence are not both present
+
316 if (stx.isFieldPresent(sfTicketSequence) &&
+
317 stx.getFieldU32(sfSequence) != 0)
+
318 {
+
319 JLOG(ctx.j.debug())
+
320 << "BatchTrace[" << parentBatchId << "]: "
+
321 << "inner txn must have exactly one of Sequence and "
+
322 "TicketSequence. "
+
323 << "txID: " << hash;
+
324 return temSEQ_AND_TICKET;
+
325 }
+
326
+
327 // Verify that either Sequence or TicketSequence is present
+
328 if (!stx.isFieldPresent(sfTicketSequence) &&
+
329 stx.getFieldU32(sfSequence) == 0)
+
330 {
+
331 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
+
332 << "inner txn must have either Sequence or "
+
333 "TicketSequence. "
+
334 << "txID: " << hash;
+
335 return temSEQ_AND_TICKET;
+
336 }
+
337
+
338 // Duplicate sequence and ticket checks
+
339 if (flags & (tfAllOrNothing | tfUntilFailure))
+
340 {
+
341 if (auto const seq = stx.getFieldU32(sfSequence); seq != 0)
+
342 {
+
343 if (!accountSeqTicket[innerAccount].insert(seq).second)
+
344 {
+
345 JLOG(ctx.j.debug())
+
346 << "BatchTrace[" << parentBatchId << "]: "
+
347 << "duplicate sequence found: "
+
348 << "txID: " << hash;
+
349 return temREDUNDANT;
+
350 }
+
351 }
+
352
+
353 if (stx.isFieldPresent(sfTicketSequence))
+
354 {
+
355 if (auto const ticket = stx.getFieldU32(sfTicketSequence);
+
356 !accountSeqTicket[innerAccount].insert(ticket).second)
+
357 {
+
358 JLOG(ctx.j.debug())
+
359 << "BatchTrace[" << parentBatchId << "]: "
+
360 << "duplicate ticket found: "
+
361 << "txID: " << hash;
+
362 return temREDUNDANT;
+
363 }
+
364 }
+
365 }
+
366 }
+
367
+
368 return tesSUCCESS;
+
369}
-
456
-
474NotTEC
-
- -
476{
-
477 if (auto ret = Transactor::checkSign(ctx); !isTesSuccess(ret))
-
478 return ret;
-
479
-
480 if (auto ret = Transactor::checkBatchSign(ctx); !isTesSuccess(ret))
+
370
+
371NotTEC
+
+ +
373{
+
374 auto const parentBatchId = ctx.tx.getTransactionID();
+
375 auto const outerAccount = ctx.tx.getAccountID(sfAccount);
+
376 auto const& rawTxns = ctx.tx.getFieldArray(sfRawTransactions);
+
377
+
378 // Build the signers list
+
379 std::unordered_set<AccountID> requiredSigners;
+
380 for (STObject const& rb : rawTxns)
+
381 {
+
382 auto const innerAccount = rb.getAccountID(sfAccount);
+
383
+
384 // If the inner account is the same as the outer account, do not add the
+
385 // inner account to the required signers set.
+
386 if (innerAccount != outerAccount)
+
387 requiredSigners.insert(innerAccount);
+
388 }
+
389
+
390 // Validation Batch Signers
+ +
392 if (ctx.tx.isFieldPresent(sfBatchSigners))
+
393 {
+
394 STArray const& signers = ctx.tx.getFieldArray(sfBatchSigners);
+
395
+
396 // Check that the batch signers array is not too large.
+
397 if (signers.size() > maxBatchTxCount)
+
398 {
+
399 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
+
400 << "signers array exceeds 8 entries.";
+
401 return temARRAY_TOO_LARGE;
+
402 }
+
403
+
404 // Add batch signers to the set to ensure all signer accounts are
+
405 // unique. Meanwhile, remove signer accounts from the set of inner
+
406 // transaction accounts (`requiredSigners`). By the end of the loop,
+
407 // `requiredSigners` should be empty, indicating that all inner
+
408 // accounts are matched with signers.
+
409 for (auto const& signer : signers)
+
410 {
+
411 AccountID const signerAccount = signer.getAccountID(sfAccount);
+
412 if (signerAccount == outerAccount)
+
413 {
+
414 JLOG(ctx.j.debug())
+
415 << "BatchTrace[" << parentBatchId << "]: "
+
416 << "signer cannot be the outer account: " << signerAccount;
+
417 return temBAD_SIGNER;
+
418 }
+
419
+
420 if (!batchSigners.insert(signerAccount).second)
+
421 {
+
422 JLOG(ctx.j.debug())
+
423 << "BatchTrace[" << parentBatchId << "]: "
+
424 << "duplicate signer found: " << signerAccount;
+
425 return temREDUNDANT;
+
426 }
+
427
+
428 // Check that the batch signer is in the required signers set.
+
429 // Remove it if it does, as it can be crossed off the list.
+
430 if (requiredSigners.erase(signerAccount) == 0)
+
431 {
+
432 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
+
433 << "no account signature for inner txn.";
+
434 return temBAD_SIGNER;
+
435 }
+
436 }
+
437
+
438 // Check the batch signers signatures.
+
439 auto const sigResult = ctx.tx.checkBatchSign(
+ +
441
+
442 if (!sigResult)
+
443 {
+
444 JLOG(ctx.j.debug())
+
445 << "BatchTrace[" << parentBatchId << "]: "
+
446 << "invalid batch txn signature: " << sigResult.error();
+
447 return temBAD_SIGNATURE;
+
448 }
+
449 }
+
450
+
451 if (!requiredSigners.empty())
+
452 {
+
453 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
+
454 << "invalid batch signers.";
+
455 return temBAD_SIGNER;
+
456 }
+
457 return tesSUCCESS;
+
458}
+
+
459
+
477NotTEC
+
+ +
479{
+
480 if (auto ret = Transactor::checkSign(ctx); !isTesSuccess(ret))
481 return ret;
482
-
483 return tesSUCCESS;
-
484}
-
+
483 if (auto ret = Transactor::checkBatchSign(ctx); !isTesSuccess(ret))
+
484 return ret;
485
-
496TER
-
- -
498{
-
499 return tesSUCCESS;
-
500}
+
486 return tesSUCCESS;
+
487}
-
501
-
502} // namespace ripple
+
488
+
499TER
+
+ +
501{
+
502 return tesSUCCESS;
+
503}
+
+
504
+
505} // namespace ripple
Stream debug() const
Definition Journal.h:328
-
TER doApply() override
Applies the outer batch transaction.
Definition Batch.cpp:497
-
static NotTEC preflight(PreflightContext const &ctx)
Performs preflight validation checks for a Batch transaction.
Definition Batch.cpp:201
-
static NotTEC checkSign(PreclaimContext const &ctx)
Checks the validity of signatures for a batch transaction.
Definition Batch.cpp:475
+
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
Definition Batch.cpp:168
+
TER doApply() override
Applies the outer batch transaction.
Definition Batch.cpp:500
+
static NotTEC preflight(PreflightContext const &ctx)
Performs preflight validation checks for a Batch transaction.
Definition Batch.cpp:207
+
static NotTEC preflightSigValidated(PreflightContext const &ctx)
Definition Batch.cpp:372
+
static NotTEC checkSign(PreclaimContext const &ctx)
Checks the validity of signatures for a batch transaction.
Definition Batch.cpp:478
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Calculates the total base fee for a batch transaction.
Definition Batch.cpp:54
A view into a ledger.
Definition ReadView.h:51
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
-
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:130
AccountID getAccountID(SField const &field) const
Definition STObject.cpp:657
@@ -535,10 +543,10 @@ $(document).ready(function() { init_codefold(0); });
uint256 getTransactionID() const
Definition STTx.h:219
Expected< void, std::string > checkBatchSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const &rules) const
Definition STTx.cpp:269
-
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
-
static NotTEC checkSign(PreclaimContext const &ctx)
-
ApplyView & view()
Definition Transactor.h:161
-
static NotTEC checkBatchSign(PreclaimContext const &ctx)
+
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
+
static NotTEC checkSign(PreclaimContext const &ctx)
+
ApplyView & view()
Definition Transactor.h:163
+
static NotTEC checkBatchSign(PreclaimContext const &ctx)
T emplace(T... args)
@@ -556,9 +564,7 @@ $(document).ready(function() { init_codefold(0); });
constexpr std::uint32_t tfIndependent
Definition TxFlags.h:279
XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Compute only the expected base fee for a transaction.
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
-
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
constexpr std::uint32_t tfUntilFailure
Definition TxFlags.h:278
-
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
beast::Journal debugLog()
Returns a debug journal.
Definition Log.cpp:468
@ tesSUCCESS
Definition TER.h:244
bool isTesSuccess(TER x) noexcept
Definition TER.h:674
@@ -575,7 +581,6 @@ $(document).ready(function() { init_codefold(0); });
@ temINVALID_FLAG
Definition TER.h:111
@ temARRAY_EMPTY
Definition TER.h:140
@ temARRAY_TOO_LARGE
Definition TER.h:141
-
@ temDISABLED
Definition TER.h:114
@ temBAD_SIGNATURE
Definition TER.h:105
T popcount(T... args)
XRPAmount base
diff --git a/CancelCheck_8cpp_source.html b/CancelCheck_8cpp_source.html index b1eb3d892e..84017cc6d2 100644 --- a/CancelCheck_8cpp_source.html +++ b/CancelCheck_8cpp_source.html @@ -116,147 +116,122 @@ $(document).ready(function() { init_codefold(0); });
34{
-
35 if (!ctx.rules.enabled(featureChecks))
-
36 return temDISABLED;
+
35 return tesSUCCESS;
+
36}
+
37
-
38 NotTEC const ret{preflight1(ctx)};
-
39 if (!isTesSuccess(ret))
-
40 return ret;
-
41
-
42 if (ctx.tx.getFlags() & tfUniversalMask)
+
38TER
+
+ +
40{
+
41 auto const sleCheck = ctx.view.read(keylet::check(ctx.tx[sfCheckID]));
+
42 if (!sleCheck)
43 {
-
44 // There are no flags (other than universal) for CreateCheck yet.
-
45 JLOG(ctx.j.warn()) << "Malformed transaction: Invalid flags set.";
-
46 return temINVALID_FLAG;
-
47 }
-
48
-
49 return preflight2(ctx);
-
50}
-
+
44 JLOG(ctx.j.warn()) << "Check does not exist.";
+
45 return tecNO_ENTRY;
+
46 }
+
47
+
48 using duration = NetClock::duration;
+
49 using timepoint = NetClock::time_point;
+
50 auto const optExpiry = (*sleCheck)[~sfExpiration];
51
-
52TER
-
- -
54{
-
55 auto const sleCheck = ctx.view.read(keylet::check(ctx.tx[sfCheckID]));
-
56 if (!sleCheck)
-
57 {
-
58 JLOG(ctx.j.warn()) << "Check does not exist.";
-
59 return tecNO_ENTRY;
-
60 }
-
61
-
62 using duration = NetClock::duration;
-
63 using timepoint = NetClock::time_point;
-
64 auto const optExpiry = (*sleCheck)[~sfExpiration];
-
65
-
66 // Expiration is defined in terms of the close time of the parent
-
67 // ledger, because we definitively know the time that it closed but
-
68 // we do not know the closing time of the ledger that is under
-
69 // construction.
-
70 if (!optExpiry ||
-
71 (ctx.view.parentCloseTime() < timepoint{duration{*optExpiry}}))
-
72 {
-
73 // If the check is not yet expired, then only the creator or the
-
74 // destination may cancel the check.
-
75 AccountID const acctId{ctx.tx[sfAccount]};
-
76 if (acctId != (*sleCheck)[sfAccount] &&
-
77 acctId != (*sleCheck)[sfDestination])
-
78 {
-
79 JLOG(ctx.j.warn()) << "Check is not expired and canceler is "
-
80 "neither check source nor destination.";
-
81 return tecNO_PERMISSION;
-
82 }
-
83 }
-
84 return tesSUCCESS;
-
85}
+
52 // Expiration is defined in terms of the close time of the parent
+
53 // ledger, because we definitively know the time that it closed but
+
54 // we do not know the closing time of the ledger that is under
+
55 // construction.
+
56 if (!optExpiry ||
+
57 (ctx.view.parentCloseTime() < timepoint{duration{*optExpiry}}))
+
58 {
+
59 // If the check is not yet expired, then only the creator or the
+
60 // destination may cancel the check.
+
61 AccountID const acctId{ctx.tx[sfAccount]};
+
62 if (acctId != (*sleCheck)[sfAccount] &&
+
63 acctId != (*sleCheck)[sfDestination])
+
64 {
+
65 JLOG(ctx.j.warn()) << "Check is not expired and canceler is "
+
66 "neither check source nor destination.";
+
67 return tecNO_PERMISSION;
+
68 }
+
69 }
+
70 return tesSUCCESS;
+
71}
-
86
-
87TER
-
-
88CancelCheck::doApply()
-
89{
-
90 auto const sleCheck = view().peek(keylet::check(ctx_.tx[sfCheckID]));
-
91 if (!sleCheck)
-
92 {
-
93 // Error should have been caught in preclaim.
-
94 JLOG(j_.warn()) << "Check does not exist.";
-
95 return tecNO_ENTRY;
-
96 }
-
97
-
98 AccountID const srcId{sleCheck->getAccountID(sfAccount)};
-
99 AccountID const dstId{sleCheck->getAccountID(sfDestination)};
-
100 auto viewJ = ctx_.app.journal("View");
-
101
-
102 // If the check is not written to self (and it shouldn't be), remove the
-
103 // check from the destination account root.
-
104 if (srcId != dstId)
-
105 {
-
106 std::uint64_t const page{(*sleCheck)[sfDestinationNode]};
-
107 if (!view().dirRemove(
-
108 keylet::ownerDir(dstId), page, sleCheck->key(), true))
-
109 {
-
110 JLOG(j_.fatal()) << "Unable to delete check from destination.";
-
111 return tefBAD_LEDGER;
-
112 }
-
113 }
-
114 {
-
115 std::uint64_t const page{(*sleCheck)[sfOwnerNode]};
-
116 if (!view().dirRemove(
-
117 keylet::ownerDir(srcId), page, sleCheck->key(), true))
-
118 {
-
119 JLOG(j_.fatal()) << "Unable to delete check from owner.";
-
120 return tefBAD_LEDGER;
-
121 }
-
122 }
-
123
-
124 // If we succeeded, update the check owner's reserve.
-
125 auto const sleSrc = view().peek(keylet::account(srcId));
-
126 adjustOwnerCount(view(), sleSrc, -1, viewJ);
-
127
-
128 // Remove check from ledger.
-
129 view().erase(sleCheck);
-
130 return tesSUCCESS;
-
131}
+
72
+
73TER
+
+
74CancelCheck::doApply()
+
75{
+
76 auto const sleCheck = view().peek(keylet::check(ctx_.tx[sfCheckID]));
+
77 if (!sleCheck)
+
78 {
+
79 // Error should have been caught in preclaim.
+
80 JLOG(j_.warn()) << "Check does not exist.";
+
81 return tecNO_ENTRY;
+
82 }
+
83
+
84 AccountID const srcId{sleCheck->getAccountID(sfAccount)};
+
85 AccountID const dstId{sleCheck->getAccountID(sfDestination)};
+
86 auto viewJ = ctx_.app.journal("View");
+
87
+
88 // If the check is not written to self (and it shouldn't be), remove the
+
89 // check from the destination account root.
+
90 if (srcId != dstId)
+
91 {
+
92 std::uint64_t const page{(*sleCheck)[sfDestinationNode]};
+
93 if (!view().dirRemove(
+
94 keylet::ownerDir(dstId), page, sleCheck->key(), true))
+
95 {
+
96 JLOG(j_.fatal()) << "Unable to delete check from destination.";
+
97 return tefBAD_LEDGER;
+
98 }
+
99 }
+
100 {
+
101 std::uint64_t const page{(*sleCheck)[sfOwnerNode]};
+
102 if (!view().dirRemove(
+
103 keylet::ownerDir(srcId), page, sleCheck->key(), true))
+
104 {
+
105 JLOG(j_.fatal()) << "Unable to delete check from owner.";
+
106 return tefBAD_LEDGER;
+
107 }
+
108 }
+
109
+
110 // If we succeeded, update the check owner's reserve.
+
111 auto const sleSrc = view().peek(keylet::account(srcId));
+
112 adjustOwnerCount(view(), sleSrc, -1, viewJ);
+
113
+
114 // Remove check from ledger.
+
115 view().erase(sleCheck);
+
116 return tesSUCCESS;
+
117}
-
132
-
133} // namespace ripple
+
118
+
119} // namespace ripple
Stream fatal() const
Definition Journal.h:352
Stream warn() const
Definition Journal.h:340
-
static TER preclaim(PreclaimContext const &ctx)
+
static TER preclaim(PreclaimContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
std::chrono::time_point< NetClock > time_point
Definition chrono.h:69
std::chrono::duration< rep, period > duration
Definition chrono.h:68
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
NetClock::time_point parentCloseTime() const
Returns the close time of the previous ledger.
Definition ReadView.h:111
-
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:130
-
std::uint32_t getFlags() const
Definition STObject.cpp:537
- +
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Definition Indexes.cpp:336
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
void adjustOwnerCount(ApplyView &view, std::shared_ptr< SLE > const &sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
Definition View.cpp:1029
-
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
@ tefBAD_LEDGER
Definition TER.h:170
-
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
@ tecNO_ENTRY
Definition TER.h:306
@ tecNO_PERMISSION
Definition TER.h:305
@ tesSUCCESS
Definition TER.h:244
-
bool isTesSuccess(TER x) noexcept
Definition TER.h:674
-
constexpr std::uint32_t tfUniversalMask
Definition TxFlags.h:63
TERSubset< CanCvtToTER > TER
Definition TER.h:645
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:605
-
@ temINVALID_FLAG
Definition TER.h:111
-
@ temDISABLED
Definition TER.h:114
uint256 key
Definition Keylet.h:40
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:80
ReadView const & view
Definition Transactor.h:83
beast::Journal const j
Definition Transactor.h:88
State information when preflighting a tx.
Definition Transactor.h:35
- -
beast::Journal const j
Definition Transactor.h:42
-
@@ -471,7 +530,7 @@ Static Private Member Functions

Implements ripple::Transactor.

-

Definition at line 125 of file AMMClawback.cpp.

+

Definition at line 123 of file AMMClawback.cpp.

@@ -499,7 +558,7 @@ Static Private Member Functions
-

Definition at line 137 of file AMMClawback.cpp.

+

Definition at line 135 of file AMMClawback.cpp.

@@ -593,7 +652,7 @@ Static Private Member Functions
Returns
-

Definition at line 253 of file AMMClawback.cpp.

+

Definition at line 251 of file AMMClawback.cpp.

@@ -622,7 +681,7 @@ Static Private Member Functions

Process the transaction.

-

Definition at line 1064 of file Transactor.cpp.

+

Definition at line 1145 of file Transactor.cpp.

@@ -649,7 +708,7 @@ Static Private Member Functions
-

Definition at line 161 of file Transactor.h.

+

Definition at line 163 of file Transactor.h.

@@ -676,7 +735,7 @@ Static Private Member Functions
-

Definition at line 167 of file Transactor.h.

+

Definition at line 169 of file Transactor.h.

@@ -720,7 +779,7 @@ Static Private Member Functions
-

Definition at line 361 of file Transactor.cpp.

+

Definition at line 442 of file Transactor.cpp.

@@ -748,7 +807,7 @@ Static Private Member Functions
-

Definition at line 433 of file Transactor.cpp.

+

Definition at line 514 of file Transactor.cpp.

@@ -786,7 +845,7 @@ Static Private Member Functions
-

Definition at line 261 of file Transactor.cpp.

+

Definition at line 342 of file Transactor.cpp.

@@ -814,7 +873,7 @@ Static Private Member Functions
-

Definition at line 581 of file Transactor.cpp.

+

Definition at line 662 of file Transactor.cpp.

@@ -842,7 +901,7 @@ Static Private Member Functions
-

Definition at line 638 of file Transactor.cpp.

+

Definition at line 719 of file Transactor.cpp.

@@ -880,7 +939,95 @@ Static Private Member Functions
-

Definition at line 233 of file Transactor.cpp.

+

Definition at line 293 of file Transactor.cpp.

+ +
+
+ +

◆ invokePreflight() [1/3]

+ +
+
+
+template<class T >
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
+ +

Definition at line 391 of file Transactor.h.

+ +
+
+ +

◆ invokePreflight() [2/3]

+ +
+
+
+template<>
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
+ +

Definition at line 37 of file Change.cpp.

+ +
+
+ +

◆ invokePreflight() [3/3]

+ +
+
+
+template<>
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
@@ -918,7 +1065,7 @@ Static Private Member Functions
-

Definition at line 217 of file Transactor.cpp.

+

Definition at line 277 of file Transactor.cpp.

@@ -968,7 +1115,7 @@ Static Private Member Functions
-

Definition at line 482 of file Transactor.cpp.

+

Definition at line 563 of file Transactor.cpp.

@@ -995,7 +1142,7 @@ Static Private Member Functions
-

Definition at line 544 of file Transactor.cpp.

+

Definition at line 625 of file Transactor.cpp.

@@ -1024,7 +1171,7 @@ Static Private Member Functions

Reimplemented in ripple::Change, and ripple::SetSignerList.

-

Definition at line 536 of file Transactor.cpp.

+

Definition at line 617 of file Transactor.cpp.

@@ -1091,7 +1238,231 @@ Static Private Member Functions -

Definition at line 251 of file Transactor.cpp.

+

Definition at line 332 of file Transactor.cpp.

+ +
+
+ +

◆ calculateOwnerReserveFee()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
XRPAmount ripple::Transactor::calculateOwnerReserveFee (ReadView const & view,
STTx const & tx 
)
+
+staticprotectedinherited
+
+ +

Definition at line 312 of file Transactor.cpp.

+ +
+
+ +

◆ checkExtraFeatures()

+ +
+
+ + + + + +
+ + + + + + + + +
bool ripple::Transactor::checkExtraFeatures (PreflightContext const & ctx)
+
+staticprotectedinherited
+
+ +

Definition at line 355 of file Transactor.h.

+ +
+
+ +

◆ preflightSigValidated()

+ +
+
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::preflightSigValidated (PreflightContext const & ctx)
+
+staticprotectedinherited
+
+ +

Definition at line 271 of file Transactor.cpp.

+ +
+
+ +

◆ validDataLength()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validDataLength (std::optional< Slice > const & slice,
std::size_t maxLength 
)
+
+staticprotectedinherited
+
+ +

Definition at line 255 of file Transactor.cpp.

+ +
+
+ +

◆ validNumericRange() [1/2]

+ +
+
+
+template<class T >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validNumericRange (std::optional< T > value,
max,
min = {} 
)
+
+staticprotectedinherited
+
+ +

Definition at line 418 of file Transactor.h.

+ +
+
+ +

◆ validNumericRange() [2/2]

+ +
+
+
+template<class T , class Unit >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validNumericRange (std::optional< T > value,
unit::ValueUnit< Unit, T > max,
unit::ValueUnit< Unit, T > min = {} 
)
+
+staticprotectedinherited
+
+ +

Definition at line 427 of file Transactor.h.

@@ -1128,7 +1499,7 @@ Static Private Member Functions
Returns
A pair containing the transaction result and the actual fee charged.
-

Definition at line 1002 of file Transactor.cpp.

+

Definition at line 1083 of file Transactor.cpp.

@@ -1156,7 +1527,7 @@ Static Private Member Functions
-

Definition at line 463 of file Transactor.cpp.

+

Definition at line 544 of file Transactor.cpp.

@@ -1183,7 +1554,7 @@ Static Private Member Functions
-

Definition at line 326 of file Transactor.cpp.

+

Definition at line 407 of file Transactor.cpp.

@@ -1239,7 +1610,7 @@ Static Private Member Functions
-

Definition at line 685 of file Transactor.cpp.

+

Definition at line 766 of file Transactor.cpp.

@@ -1295,7 +1666,7 @@ Static Private Member Functions
-

Definition at line 746 of file Transactor.cpp.

+

Definition at line 827 of file Transactor.cpp.

@@ -1323,7 +1694,80 @@ Static Private Member Functions
-

Definition at line 1057 of file Transactor.cpp.

+

Definition at line 1138 of file Transactor.cpp.

+ +
+ + +

◆ preflight1()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
NotTEC ripple::Transactor::preflight1 (PreflightContext const & ctx,
std::uint32_t flagMask 
)
+
+staticprivateinherited
+
+ +

Performs early sanity checks on the account and fee fields.

+

(And passes flagMask to preflight0)

+

Do not try to call preflight1 from preflight() in derived classes. See the description of invokePreflight for details.

+ +

Definition at line 163 of file Transactor.cpp.

+ +
+
+ +

◆ preflight2()

+ +
+
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::preflight2 (PreflightContext const & ctx)
+
+staticprivateinherited
+
+ +

Checks whether the signature appears valid.

+

Do not try to call preflight2 from preflight() in derived classes. See the description of invokePreflight for details.

+ +

Definition at line 226 of file Transactor.cpp.

@@ -1372,7 +1816,7 @@ Static Private Member Functions
-

Definition at line 141 of file Transactor.h.

+

Definition at line 143 of file Transactor.h.

@@ -1396,7 +1840,7 @@ Static Private Member Functions
-

Definition at line 142 of file Transactor.h.

+

Definition at line 144 of file Transactor.h.

@@ -1420,7 +1864,7 @@ Static Private Member Functions
-

Definition at line 143 of file Transactor.h.

+

Definition at line 145 of file Transactor.h.

@@ -1444,7 +1888,7 @@ Static Private Member Functions
-

Definition at line 145 of file Transactor.h.

+

Definition at line 147 of file Transactor.h.

@@ -1468,7 +1912,7 @@ Static Private Member Functions
-

Definition at line 146 of file Transactor.h.

+

Definition at line 148 of file Transactor.h.

@@ -1492,7 +1936,7 @@ Static Private Member Functions
-

Definition at line 147 of file Transactor.h.

+

Definition at line 149 of file Transactor.h.

diff --git a/classripple_1_1AMMCreate-members.html b/classripple_1_1AMMCreate-members.html index 477b7da4de..b47ce2483c 100644 --- a/classripple_1_1AMMCreate-members.html +++ b/classripple_1_1AMMCreate-members.html @@ -84,7 +84,9 @@ $(function() { apply()ripple::Transactorprotected Blocker enum valueripple::Transactor calculateBaseFee(ReadView const &view, STTx const &tx)ripple::AMMCreatestatic - checkBatchSign(PreclaimContext const &ctx)ripple::Transactorstatic + calculateOwnerReserveFee(ReadView const &view, STTx const &tx)ripple::Transactorprotectedstatic + checkBatchSign(PreclaimContext const &ctx)ripple::Transactorstatic + checkExtraFeatures(PreflightContext const &ctx)ripple::AMMCreatestatic checkFee(PreclaimContext const &ctx, XRPAmount baseFee)ripple::Transactorstatic checkMultiSign(ReadView const &view, AccountID const &idAccount, STArray const &txSigners, ApplyFlags const &flags, beast::Journal j)ripple::Transactorprivatestatic checkPermission(ReadView const &view, STTx const &tx)ripple::Transactorstatic @@ -98,6 +100,10 @@ $(function() { ctx_ripple::Transactorprotected Custom enum valueripple::Transactor doApply() overrideripple::AMMCreatevirtual + getFlagsMask(PreflightContext const &ctx)ripple::Transactorprotectedstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic j_ripple::Transactorprotected minimumFee(Application &app, XRPAmount baseFee, Fees const &fees, ApplyFlags flags)ripple::Transactorprotectedstatic mPriorBalanceripple::Transactorprotected @@ -109,12 +115,18 @@ $(function() { preclaim(PreclaimContext const &ctx)ripple::AMMCreatestatic preCompute()ripple::Transactorprotectedvirtual preflight(PreflightContext const &ctx)ripple::AMMCreatestatic - reset(XRPAmount fee)ripple::Transactorprivate - sink_ripple::Transactorprotected - ticketDelete(ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)ripple::Transactorstatic - Transactor(Transactor const &)=deleteripple::Transactorprotected - Transactor(ApplyContext &ctx)ripple::Transactorexplicitprotected - trapTransaction(uint256) constripple::Transactorprivate + preflight1(PreflightContext const &ctx, std::uint32_t flagMask)ripple::Transactorprivatestatic + preflight2(PreflightContext const &ctx)ripple::Transactorprivatestatic + preflightSigValidated(PreflightContext const &ctx)ripple::Transactorprotectedstatic + reset(XRPAmount fee)ripple::Transactorprivate + sink_ripple::Transactorprotected + ticketDelete(ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)ripple::Transactorstatic + Transactor(Transactor const &)=deleteripple::Transactorprotected + Transactor(ApplyContext &ctx)ripple::Transactorexplicitprotected + trapTransaction(uint256) constripple::Transactorprivate + validDataLength(std::optional< Slice > const &slice, std::size_t maxLength)ripple::Transactorprotectedstatic + validNumericRange(std::optional< T > value, T max, T min={})ripple::Transactorprotectedstatic + validNumericRange(std::optional< T > value, unit::ValueUnit< Unit, T > max, unit::ValueUnit< Unit, T > min={})ripple::Transactorprotectedstatic view()ripple::Transactor view() constripple::Transactor ~Transactor()=defaultripple::Transactorprotectedvirtual diff --git a/classripple_1_1AMMCreate.html b/classripple_1_1AMMCreate.html index 01dec4f181..81bc488f02 100644 --- a/classripple_1_1AMMCreate.html +++ b/classripple_1_1AMMCreate.html @@ -253,6 +253,8 @@ Public Member Functions + + @@ -269,6 +271,15 @@ Static Public Member Functions + + + + + + + + + @@ -291,6 +302,20 @@ Static Protected Member Functions + + + + + + + + + + + + + +

Static Public Member Functions

static bool checkExtraFeatures (PreflightContext const &ctx)
 
static NotTEC preflight (PreflightContext const &ctx)
 
static XRPAmount calculateBaseFee (ReadView const &view, STTx const &tx)
 
static NotTEC checkBatchSign (PreclaimContext const &ctx)
 
template<class T >
static NotTEC invokePreflight (PreflightContext const &ctx)
 
template<>
NotTEC invokePreflight (PreflightContext const &ctx)
 
template<>
NotTEC invokePreflight (PreflightContext const &ctx)
 
static TER checkPermission (ReadView const &view, STTx const &tx)
 
static TER ticketDelete (ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)
static XRPAmount minimumFee (Application &app, XRPAmount baseFee, Fees const &fees, ApplyFlags flags)
 Compute the minimum fee required to process a transaction with a given baseFee based on the current server load.
 
static XRPAmount calculateOwnerReserveFee (ReadView const &view, STTx const &tx)
 
static std::uint32_t getFlagsMask (PreflightContext const &ctx)
 
static NotTEC preflightSigValidated (PreflightContext const &ctx)
 
static bool validDataLength (std::optional< Slice > const &slice, std::size_t maxLength)
 
template<class T >
static bool validNumericRange (std::optional< T > value, T max, T min={})
 
template<class T , class Unit >
static bool validNumericRange (std::optional< T > value, unit::ValueUnit< Unit, T > max, unit::ValueUnit< Unit, T > min={})
 
@@ -325,6 +350,12 @@ Static Private Member Functions + + + + + +

Protected Attributes

 
static NotTEC checkMultiSign (ReadView const &view, AccountID const &idAccount, STArray const &txSigners, ApplyFlags const &flags, beast::Journal j)
 
static NotTEC preflight1 (PreflightContext const &ctx, std::uint32_t flagMask)
 Performs early sanity checks on the account and fee fields.
 
static NotTEC preflight2 (PreflightContext const &ctx)
 Checks whether the signature appears valid.
 

Detailed Description

AMMCreate implements Automatic Market Maker(AMM) creation Transactor.

@@ -357,7 +388,7 @@ Static Private Member Functions Custom  -

Definition at line 155 of file Transactor.h.

+

Definition at line 157 of file Transactor.h.

@@ -391,6 +422,34 @@ Static Private Member Functions

Member Function Documentation

+ +

◆ checkExtraFeatures()

+ +
+
+ + + + + +
+ + + + + + + + +
bool ripple::AMMCreate::checkExtraFeatures (PreflightContext const & ctx)
+
+static
+
+ +

Definition at line 35 of file AMMCreate.cpp.

+ +
+

◆ preflight()

@@ -415,7 +474,7 @@ Static Private Member Functions
-

Definition at line 35 of file AMMCreate.cpp.

+

Definition at line 41 of file AMMCreate.cpp.

@@ -453,7 +512,7 @@ Static Private Member Functions
-

Definition at line 81 of file AMMCreate.cpp.

+

Definition at line 75 of file AMMCreate.cpp.

@@ -481,7 +540,7 @@ Static Private Member Functions
-

Definition at line 88 of file AMMCreate.cpp.

+

Definition at line 82 of file AMMCreate.cpp.

@@ -512,7 +571,7 @@ Static Private Member Functions

Implements ripple::Transactor.

-

Definition at line 345 of file AMMCreate.cpp.

+

Definition at line 339 of file AMMCreate.cpp.

@@ -541,7 +600,7 @@ Static Private Member Functions

Process the transaction.

-

Definition at line 1064 of file Transactor.cpp.

+

Definition at line 1145 of file Transactor.cpp.

@@ -568,7 +627,7 @@ Static Private Member Functions
-

Definition at line 161 of file Transactor.h.

+

Definition at line 163 of file Transactor.h.

@@ -595,7 +654,7 @@ Static Private Member Functions
-

Definition at line 167 of file Transactor.h.

+

Definition at line 169 of file Transactor.h.

@@ -639,7 +698,7 @@ Static Private Member Functions
-

Definition at line 361 of file Transactor.cpp.

+

Definition at line 442 of file Transactor.cpp.

@@ -667,7 +726,7 @@ Static Private Member Functions
-

Definition at line 433 of file Transactor.cpp.

+

Definition at line 514 of file Transactor.cpp.

@@ -705,7 +764,7 @@ Static Private Member Functions
-

Definition at line 261 of file Transactor.cpp.

+

Definition at line 342 of file Transactor.cpp.

@@ -733,7 +792,7 @@ Static Private Member Functions
-

Definition at line 581 of file Transactor.cpp.

+

Definition at line 662 of file Transactor.cpp.

@@ -761,7 +820,95 @@ Static Private Member Functions
-

Definition at line 638 of file Transactor.cpp.

+

Definition at line 719 of file Transactor.cpp.

+ +
+ + +

◆ invokePreflight() [1/3]

+ +
+
+
+template<class T >
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
+ +

Definition at line 391 of file Transactor.h.

+ +
+
+ +

◆ invokePreflight() [2/3]

+ +
+
+
+template<>
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
+ +

Definition at line 37 of file Change.cpp.

+ +
+
+ +

◆ invokePreflight() [3/3]

+ +
+
+
+template<>
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
@@ -799,7 +946,7 @@ Static Private Member Functions
-

Definition at line 217 of file Transactor.cpp.

+

Definition at line 277 of file Transactor.cpp.

@@ -849,7 +996,7 @@ Static Private Member Functions
-

Definition at line 482 of file Transactor.cpp.

+

Definition at line 563 of file Transactor.cpp.

@@ -876,7 +1023,7 @@ Static Private Member Functions
-

Definition at line 544 of file Transactor.cpp.

+

Definition at line 625 of file Transactor.cpp.

@@ -905,7 +1052,7 @@ Static Private Member Functions

Reimplemented in ripple::Change, and ripple::SetSignerList.

-

Definition at line 536 of file Transactor.cpp.

+

Definition at line 617 of file Transactor.cpp.

@@ -972,7 +1119,231 @@ Static Private Member Functions -

Definition at line 251 of file Transactor.cpp.

+

Definition at line 332 of file Transactor.cpp.

+ + + + +

◆ calculateOwnerReserveFee()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
XRPAmount ripple::Transactor::calculateOwnerReserveFee (ReadView const & view,
STTx const & tx 
)
+
+staticprotectedinherited
+
+ +

Definition at line 312 of file Transactor.cpp.

+ +
+
+ +

◆ getFlagsMask()

+ +
+
+ + + + + +
+ + + + + + + + +
std::uint32_t ripple::Transactor::getFlagsMask (PreflightContext const & ctx)
+
+staticprotectedinherited
+
+ +

Definition at line 265 of file Transactor.cpp.

+ +
+
+ +

◆ preflightSigValidated()

+ +
+
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::preflightSigValidated (PreflightContext const & ctx)
+
+staticprotectedinherited
+
+ +

Definition at line 271 of file Transactor.cpp.

+ +
+
+ +

◆ validDataLength()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validDataLength (std::optional< Slice > const & slice,
std::size_t maxLength 
)
+
+staticprotectedinherited
+
+ +

Definition at line 255 of file Transactor.cpp.

+ +
+
+ +

◆ validNumericRange() [1/2]

+ +
+
+
+template<class T >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validNumericRange (std::optional< T > value,
max,
min = {} 
)
+
+staticprotectedinherited
+
+ +

Definition at line 418 of file Transactor.h.

+ +
+
+ +

◆ validNumericRange() [2/2]

+ +
+
+
+template<class T , class Unit >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validNumericRange (std::optional< T > value,
unit::ValueUnit< Unit, T > max,
unit::ValueUnit< Unit, T > min = {} 
)
+
+staticprotectedinherited
+
+ +

Definition at line 427 of file Transactor.h.

@@ -1009,7 +1380,7 @@ Static Private Member Functions
Returns
A pair containing the transaction result and the actual fee charged.
-

Definition at line 1002 of file Transactor.cpp.

+

Definition at line 1083 of file Transactor.cpp.

@@ -1037,7 +1408,7 @@ Static Private Member Functions
-

Definition at line 463 of file Transactor.cpp.

+

Definition at line 544 of file Transactor.cpp.

@@ -1064,7 +1435,7 @@ Static Private Member Functions
-

Definition at line 326 of file Transactor.cpp.

+

Definition at line 407 of file Transactor.cpp.

@@ -1120,7 +1491,7 @@ Static Private Member Functions
-

Definition at line 685 of file Transactor.cpp.

+

Definition at line 766 of file Transactor.cpp.

@@ -1176,7 +1547,7 @@ Static Private Member Functions
-

Definition at line 746 of file Transactor.cpp.

+

Definition at line 827 of file Transactor.cpp.

@@ -1204,7 +1575,80 @@ Static Private Member Functions
-

Definition at line 1057 of file Transactor.cpp.

+

Definition at line 1138 of file Transactor.cpp.

+ +
+ + +

◆ preflight1()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
NotTEC ripple::Transactor::preflight1 (PreflightContext const & ctx,
std::uint32_t flagMask 
)
+
+staticprivateinherited
+
+ +

Performs early sanity checks on the account and fee fields.

+

(And passes flagMask to preflight0)

+

Do not try to call preflight1 from preflight() in derived classes. See the description of invokePreflight for details.

+ +

Definition at line 163 of file Transactor.cpp.

+ +
+
+ +

◆ preflight2()

+ +
+
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::preflight2 (PreflightContext const & ctx)
+
+staticprivateinherited
+
+ +

Checks whether the signature appears valid.

+

Do not try to call preflight2 from preflight() in derived classes. See the description of invokePreflight for details.

+ +

Definition at line 226 of file Transactor.cpp.

@@ -1253,7 +1697,7 @@ Static Private Member Functions
-

Definition at line 141 of file Transactor.h.

+

Definition at line 143 of file Transactor.h.

@@ -1277,7 +1721,7 @@ Static Private Member Functions
-

Definition at line 142 of file Transactor.h.

+

Definition at line 144 of file Transactor.h.

@@ -1301,7 +1745,7 @@ Static Private Member Functions
-

Definition at line 143 of file Transactor.h.

+

Definition at line 145 of file Transactor.h.

@@ -1325,7 +1769,7 @@ Static Private Member Functions
-

Definition at line 145 of file Transactor.h.

+

Definition at line 147 of file Transactor.h.

@@ -1349,7 +1793,7 @@ Static Private Member Functions
-

Definition at line 146 of file Transactor.h.

+

Definition at line 148 of file Transactor.h.

@@ -1373,7 +1817,7 @@ Static Private Member Functions
-

Definition at line 147 of file Transactor.h.

+

Definition at line 149 of file Transactor.h.

diff --git a/classripple_1_1AMMDelete-members.html b/classripple_1_1AMMDelete-members.html index fbe32dd065..869c80157d 100644 --- a/classripple_1_1AMMDelete-members.html +++ b/classripple_1_1AMMDelete-members.html @@ -84,7 +84,9 @@ $(function() { apply()ripple::Transactorprotected Blocker enum valueripple::Transactor calculateBaseFee(ReadView const &view, STTx const &tx)ripple::Transactorstatic - checkBatchSign(PreclaimContext const &ctx)ripple::Transactorstatic + calculateOwnerReserveFee(ReadView const &view, STTx const &tx)ripple::Transactorprotectedstatic + checkBatchSign(PreclaimContext const &ctx)ripple::Transactorstatic + checkExtraFeatures(PreflightContext const &ctx)ripple::AMMDeletestatic checkFee(PreclaimContext const &ctx, XRPAmount baseFee)ripple::Transactorstatic checkMultiSign(ReadView const &view, AccountID const &idAccount, STArray const &txSigners, ApplyFlags const &flags, beast::Journal j)ripple::Transactorprivatestatic checkPermission(ReadView const &view, STTx const &tx)ripple::Transactorstatic @@ -98,6 +100,10 @@ $(function() { ctx_ripple::Transactorprotected Custom enum valueripple::Transactor doApply() overrideripple::AMMDeletevirtual + getFlagsMask(PreflightContext const &ctx)ripple::Transactorprotectedstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic j_ripple::Transactorprotected minimumFee(Application &app, XRPAmount baseFee, Fees const &fees, ApplyFlags flags)ripple::Transactorprotectedstatic mPriorBalanceripple::Transactorprotected @@ -109,12 +115,18 @@ $(function() { preclaim(PreclaimContext const &ctx)ripple::AMMDeletestatic preCompute()ripple::Transactorprotectedvirtual preflight(PreflightContext const &ctx)ripple::AMMDeletestatic - reset(XRPAmount fee)ripple::Transactorprivate - sink_ripple::Transactorprotected - ticketDelete(ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)ripple::Transactorstatic - Transactor(Transactor const &)=deleteripple::Transactorprotected - Transactor(ApplyContext &ctx)ripple::Transactorexplicitprotected - trapTransaction(uint256) constripple::Transactorprivate + preflight1(PreflightContext const &ctx, std::uint32_t flagMask)ripple::Transactorprivatestatic + preflight2(PreflightContext const &ctx)ripple::Transactorprivatestatic + preflightSigValidated(PreflightContext const &ctx)ripple::Transactorprotectedstatic + reset(XRPAmount fee)ripple::Transactorprivate + sink_ripple::Transactorprotected + ticketDelete(ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)ripple::Transactorstatic + Transactor(Transactor const &)=deleteripple::Transactorprotected + Transactor(ApplyContext &ctx)ripple::Transactorexplicitprotected + trapTransaction(uint256) constripple::Transactorprivate + validDataLength(std::optional< Slice > const &slice, std::size_t maxLength)ripple::Transactorprotectedstatic + validNumericRange(std::optional< T > value, T max, T min={})ripple::Transactorprotectedstatic + validNumericRange(std::optional< T > value, unit::ValueUnit< Unit, T > max, unit::ValueUnit< Unit, T > min={})ripple::Transactorprotectedstatic view()ripple::Transactor view() constripple::Transactor ~Transactor()=defaultripple::Transactorprotectedvirtual diff --git a/classripple_1_1AMMDelete.html b/classripple_1_1AMMDelete.html index 722929c14f..e060a20adc 100644 --- a/classripple_1_1AMMDelete.html +++ b/classripple_1_1AMMDelete.html @@ -252,6 +252,8 @@ Public Member Functions + + @@ -268,6 +270,15 @@ Static Public Member Functions + + + + + + + + + @@ -290,6 +301,20 @@ Static Protected Member Functions + + + + + + + + + + + + + +

Static Public Member Functions

static bool checkExtraFeatures (PreflightContext const &ctx)
 
static NotTEC preflight (PreflightContext const &ctx)
 
static TER preclaim (PreclaimContext const &ctx)
 
static XRPAmount calculateBaseFee (ReadView const &view, STTx const &tx)
 
template<class T >
static NotTEC invokePreflight (PreflightContext const &ctx)
 
template<>
NotTEC invokePreflight (PreflightContext const &ctx)
 
template<>
NotTEC invokePreflight (PreflightContext const &ctx)
 
static TER checkPermission (ReadView const &view, STTx const &tx)
 
static TER ticketDelete (ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)
static XRPAmount minimumFee (Application &app, XRPAmount baseFee, Fees const &fees, ApplyFlags flags)
 Compute the minimum fee required to process a transaction with a given baseFee based on the current server load.
 
static XRPAmount calculateOwnerReserveFee (ReadView const &view, STTx const &tx)
 
static std::uint32_t getFlagsMask (PreflightContext const &ctx)
 
static NotTEC preflightSigValidated (PreflightContext const &ctx)
 
static bool validDataLength (std::optional< Slice > const &slice, std::size_t maxLength)
 
template<class T >
static bool validNumericRange (std::optional< T > value, T max, T min={})
 
template<class T , class Unit >
static bool validNumericRange (std::optional< T > value, unit::ValueUnit< Unit, T > max, unit::ValueUnit< Unit, T > min={})
 
@@ -324,6 +349,12 @@ Static Private Member Functions + + + + + +

Protected Attributes

 
static NotTEC checkMultiSign (ReadView const &view, AccountID const &idAccount, STArray const &txSigners, ApplyFlags const &flags, beast::Journal j)
 
static NotTEC preflight1 (PreflightContext const &ctx, std::uint32_t flagMask)
 Performs early sanity checks on the account and fee fields.
 
static NotTEC preflight2 (PreflightContext const &ctx)
 Checks whether the signature appears valid.
 

Detailed Description

AMMDelete implements AMM delete transactor.

@@ -356,7 +387,7 @@ Static Private Member Functions Custom  -

Definition at line 155 of file Transactor.h.

+

Definition at line 157 of file Transactor.h.

@@ -390,6 +421,34 @@ Static Private Member Functions

Member Function Documentation

+ +

◆ checkExtraFeatures()

+ +
+
+ + + + + +
+ + + + + + + + +
bool ripple::AMMDelete::checkExtraFeatures (PreflightContext const & ctx)
+
+static
+
+ +

Definition at line 31 of file AMMDelete.cpp.

+ +
+

◆ preflight()

@@ -414,7 +473,7 @@ Static Private Member Functions
-

Definition at line 31 of file AMMDelete.cpp.

+

Definition at line 37 of file AMMDelete.cpp.

@@ -442,7 +501,7 @@ Static Private Member Functions
-

Definition at line 49 of file AMMDelete.cpp.

+

Definition at line 43 of file AMMDelete.cpp.

@@ -471,7 +530,7 @@ Static Private Member Functions

Implements ripple::Transactor.

-

Definition at line 67 of file AMMDelete.cpp.

+

Definition at line 61 of file AMMDelete.cpp.

@@ -500,7 +559,7 @@ Static Private Member Functions

Process the transaction.

-

Definition at line 1064 of file Transactor.cpp.

+

Definition at line 1145 of file Transactor.cpp.

@@ -527,7 +586,7 @@ Static Private Member Functions
-

Definition at line 161 of file Transactor.h.

+

Definition at line 163 of file Transactor.h.

@@ -554,7 +613,7 @@ Static Private Member Functions
-

Definition at line 167 of file Transactor.h.

+

Definition at line 169 of file Transactor.h.

@@ -598,7 +657,7 @@ Static Private Member Functions
-

Definition at line 361 of file Transactor.cpp.

+

Definition at line 442 of file Transactor.cpp.

@@ -626,7 +685,7 @@ Static Private Member Functions
-

Definition at line 433 of file Transactor.cpp.

+

Definition at line 514 of file Transactor.cpp.

@@ -664,7 +723,7 @@ Static Private Member Functions
-

Definition at line 261 of file Transactor.cpp.

+

Definition at line 342 of file Transactor.cpp.

@@ -692,7 +751,7 @@ Static Private Member Functions
-

Definition at line 581 of file Transactor.cpp.

+

Definition at line 662 of file Transactor.cpp.

@@ -720,7 +779,7 @@ Static Private Member Functions
-

Definition at line 638 of file Transactor.cpp.

+

Definition at line 719 of file Transactor.cpp.

@@ -758,7 +817,95 @@ Static Private Member Functions
-

Definition at line 233 of file Transactor.cpp.

+

Definition at line 293 of file Transactor.cpp.

+ +
+ + +

◆ invokePreflight() [1/3]

+ +
+
+
+template<class T >
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
+ +

Definition at line 391 of file Transactor.h.

+ +
+
+ +

◆ invokePreflight() [2/3]

+ +
+
+
+template<>
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
+ +

Definition at line 37 of file Change.cpp.

+ +
+
+ +

◆ invokePreflight() [3/3]

+ +
+
+
+template<>
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
@@ -796,7 +943,7 @@ Static Private Member Functions
-

Definition at line 217 of file Transactor.cpp.

+

Definition at line 277 of file Transactor.cpp.

@@ -846,7 +993,7 @@ Static Private Member Functions
-

Definition at line 482 of file Transactor.cpp.

+

Definition at line 563 of file Transactor.cpp.

@@ -873,7 +1020,7 @@ Static Private Member Functions
-

Definition at line 544 of file Transactor.cpp.

+

Definition at line 625 of file Transactor.cpp.

@@ -902,7 +1049,7 @@ Static Private Member Functions

Reimplemented in ripple::Change, and ripple::SetSignerList.

-

Definition at line 536 of file Transactor.cpp.

+

Definition at line 617 of file Transactor.cpp.

@@ -969,7 +1116,231 @@ Static Private Member Functions -

Definition at line 251 of file Transactor.cpp.

+

Definition at line 332 of file Transactor.cpp.

+ + + + +

◆ calculateOwnerReserveFee()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
XRPAmount ripple::Transactor::calculateOwnerReserveFee (ReadView const & view,
STTx const & tx 
)
+
+staticprotectedinherited
+
+ +

Definition at line 312 of file Transactor.cpp.

+ +
+
+ +

◆ getFlagsMask()

+ +
+
+ + + + + +
+ + + + + + + + +
std::uint32_t ripple::Transactor::getFlagsMask (PreflightContext const & ctx)
+
+staticprotectedinherited
+
+ +

Definition at line 265 of file Transactor.cpp.

+ +
+
+ +

◆ preflightSigValidated()

+ +
+
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::preflightSigValidated (PreflightContext const & ctx)
+
+staticprotectedinherited
+
+ +

Definition at line 271 of file Transactor.cpp.

+ +
+
+ +

◆ validDataLength()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validDataLength (std::optional< Slice > const & slice,
std::size_t maxLength 
)
+
+staticprotectedinherited
+
+ +

Definition at line 255 of file Transactor.cpp.

+ +
+
+ +

◆ validNumericRange() [1/2]

+ +
+
+
+template<class T >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validNumericRange (std::optional< T > value,
max,
min = {} 
)
+
+staticprotectedinherited
+
+ +

Definition at line 418 of file Transactor.h.

+ +
+
+ +

◆ validNumericRange() [2/2]

+ +
+
+
+template<class T , class Unit >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validNumericRange (std::optional< T > value,
unit::ValueUnit< Unit, T > max,
unit::ValueUnit< Unit, T > min = {} 
)
+
+staticprotectedinherited
+
+ +

Definition at line 427 of file Transactor.h.

@@ -1006,7 +1377,7 @@ Static Private Member Functions
Returns
A pair containing the transaction result and the actual fee charged.
-

Definition at line 1002 of file Transactor.cpp.

+

Definition at line 1083 of file Transactor.cpp.

@@ -1034,7 +1405,7 @@ Static Private Member Functions
-

Definition at line 463 of file Transactor.cpp.

+

Definition at line 544 of file Transactor.cpp.

@@ -1061,7 +1432,7 @@ Static Private Member Functions
-

Definition at line 326 of file Transactor.cpp.

+

Definition at line 407 of file Transactor.cpp.

@@ -1117,7 +1488,7 @@ Static Private Member Functions
-

Definition at line 685 of file Transactor.cpp.

+

Definition at line 766 of file Transactor.cpp.

@@ -1173,7 +1544,7 @@ Static Private Member Functions
-

Definition at line 746 of file Transactor.cpp.

+

Definition at line 827 of file Transactor.cpp.

@@ -1201,7 +1572,80 @@ Static Private Member Functions
-

Definition at line 1057 of file Transactor.cpp.

+

Definition at line 1138 of file Transactor.cpp.

+ +
+ + +

◆ preflight1()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
NotTEC ripple::Transactor::preflight1 (PreflightContext const & ctx,
std::uint32_t flagMask 
)
+
+staticprivateinherited
+
+ +

Performs early sanity checks on the account and fee fields.

+

(And passes flagMask to preflight0)

+

Do not try to call preflight1 from preflight() in derived classes. See the description of invokePreflight for details.

+ +

Definition at line 163 of file Transactor.cpp.

+ +
+
+ +

◆ preflight2()

+ +
+
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::preflight2 (PreflightContext const & ctx)
+
+staticprivateinherited
+
+ +

Checks whether the signature appears valid.

+

Do not try to call preflight2 from preflight() in derived classes. See the description of invokePreflight for details.

+ +

Definition at line 226 of file Transactor.cpp.

@@ -1250,7 +1694,7 @@ Static Private Member Functions
-

Definition at line 141 of file Transactor.h.

+

Definition at line 143 of file Transactor.h.

@@ -1274,7 +1718,7 @@ Static Private Member Functions
-

Definition at line 142 of file Transactor.h.

+

Definition at line 144 of file Transactor.h.

@@ -1298,7 +1742,7 @@ Static Private Member Functions
-

Definition at line 143 of file Transactor.h.

+

Definition at line 145 of file Transactor.h.

@@ -1322,7 +1766,7 @@ Static Private Member Functions
-

Definition at line 145 of file Transactor.h.

+

Definition at line 147 of file Transactor.h.

@@ -1346,7 +1790,7 @@ Static Private Member Functions
-

Definition at line 146 of file Transactor.h.

+

Definition at line 148 of file Transactor.h.

@@ -1370,7 +1814,7 @@ Static Private Member Functions
-

Definition at line 147 of file Transactor.h.

+

Definition at line 149 of file Transactor.h.

diff --git a/classripple_1_1AMMDeposit-members.html b/classripple_1_1AMMDeposit-members.html index 151f40a57f..d52139c76c 100644 --- a/classripple_1_1AMMDeposit-members.html +++ b/classripple_1_1AMMDeposit-members.html @@ -85,7 +85,9 @@ $(function() { applyGuts(Sandbox &view)ripple::AMMDepositprivate Blocker enum valueripple::Transactor calculateBaseFee(ReadView const &view, STTx const &tx)ripple::Transactorstatic - checkBatchSign(PreclaimContext const &ctx)ripple::Transactorstatic + calculateOwnerReserveFee(ReadView const &view, STTx const &tx)ripple::Transactorprotectedstatic + checkBatchSign(PreclaimContext const &ctx)ripple::Transactorstatic + checkExtraFeatures(PreflightContext const &ctx)ripple::AMMDepositstatic checkFee(PreclaimContext const &ctx, XRPAmount baseFee)ripple::Transactorstatic checkMultiSign(ReadView const &view, AccountID const &idAccount, STArray const &txSigners, ApplyFlags const &flags, beast::Journal j)ripple::Transactorprivatestatic checkPermission(ReadView const &view, STTx const &tx)ripple::Transactorstatic @@ -103,6 +105,10 @@ $(function() { equalDepositInEmptyState(Sandbox &view, AccountID const &ammAccount, STAmount const &amount, STAmount const &amount2, Issue const &lptIssue, std::uint16_t tfee)ripple::AMMDepositprivate equalDepositLimit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &amount2, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)ripple::AMMDepositprivate equalDepositTokens(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::optional< STAmount > const &depositMin, std::optional< STAmount > const &deposit2Min, std::uint16_t tfee)ripple::AMMDepositprivate + getFlagsMask(PreflightContext const &ctx)ripple::AMMDepositstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic j_ripple::Transactorprotected minimumFee(Application &app, XRPAmount baseFee, Fees const &fees, ApplyFlags flags)ripple::Transactorprotectedstatic mPriorBalanceripple::Transactorprotected @@ -114,15 +120,21 @@ $(function() { preclaim(PreclaimContext const &ctx)ripple::AMMDepositstatic preCompute()ripple::Transactorprotectedvirtual preflight(PreflightContext const &ctx)ripple::AMMDepositstatic - reset(XRPAmount fee)ripple::Transactorprivate - singleDeposit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)ripple::AMMDepositprivate - singleDepositEPrice(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &ePrice, std::uint16_t tfee)ripple::AMMDepositprivate - singleDepositTokens(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::uint16_t tfee)ripple::AMMDepositprivate - sink_ripple::Transactorprotected - ticketDelete(ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)ripple::Transactorstatic - Transactor(Transactor const &)=deleteripple::Transactorprotected - Transactor(ApplyContext &ctx)ripple::Transactorexplicitprotected - trapTransaction(uint256) constripple::Transactorprivate + preflight1(PreflightContext const &ctx, std::uint32_t flagMask)ripple::Transactorprivatestatic + preflight2(PreflightContext const &ctx)ripple::Transactorprivatestatic + preflightSigValidated(PreflightContext const &ctx)ripple::Transactorprotectedstatic + reset(XRPAmount fee)ripple::Transactorprivate + singleDeposit(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, std::optional< STAmount > const &lpTokensDepositMin, std::uint16_t tfee)ripple::AMMDepositprivate + singleDepositEPrice(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &ePrice, std::uint16_t tfee)ripple::AMMDepositprivate + singleDepositTokens(Sandbox &view, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount, STAmount const &lptAMMBalance, STAmount const &lpTokensDeposit, std::uint16_t tfee)ripple::AMMDepositprivate + sink_ripple::Transactorprotected + ticketDelete(ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)ripple::Transactorstatic + Transactor(Transactor const &)=deleteripple::Transactorprotected + Transactor(ApplyContext &ctx)ripple::Transactorexplicitprotected + trapTransaction(uint256) constripple::Transactorprivate + validDataLength(std::optional< Slice > const &slice, std::size_t maxLength)ripple::Transactorprotectedstatic + validNumericRange(std::optional< T > value, T max, T min={})ripple::Transactorprotectedstatic + validNumericRange(std::optional< T > value, unit::ValueUnit< Unit, T > max, unit::ValueUnit< Unit, T > min={})ripple::Transactorprotectedstatic view()ripple::Transactor view() constripple::Transactor ~Transactor()=defaultripple::Transactorprotectedvirtual diff --git a/classripple_1_1AMMDeposit.html b/classripple_1_1AMMDeposit.html index 17703fe3c0..64656d12a3 100644 --- a/classripple_1_1AMMDeposit.html +++ b/classripple_1_1AMMDeposit.html @@ -252,6 +252,10 @@ Public Member Functions + + + + @@ -268,6 +272,15 @@ Static Public Member Functions + + + + + + + + + @@ -290,6 +303,18 @@ Static Protected Member Functions + + + + + + + + + + + +

Static Public Member Functions

static bool checkExtraFeatures (PreflightContext const &ctx)
 
static std::uint32_t getFlagsMask (PreflightContext const &ctx)
 
static NotTEC preflight (PreflightContext const &ctx)
 
static TER preclaim (PreclaimContext const &ctx)
 
static XRPAmount calculateBaseFee (ReadView const &view, STTx const &tx)
 
template<class T >
static NotTEC invokePreflight (PreflightContext const &ctx)
 
template<>
NotTEC invokePreflight (PreflightContext const &ctx)
 
template<>
NotTEC invokePreflight (PreflightContext const &ctx)
 
static TER checkPermission (ReadView const &view, STTx const &tx)
 
static TER ticketDelete (ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)
static XRPAmount minimumFee (Application &app, XRPAmount baseFee, Fees const &fees, ApplyFlags flags)
 Compute the minimum fee required to process a transaction with a given baseFee based on the current server load.
 
static XRPAmount calculateOwnerReserveFee (ReadView const &view, STTx const &tx)
 
static NotTEC preflightSigValidated (PreflightContext const &ctx)
 
static bool validDataLength (std::optional< Slice > const &slice, std::size_t maxLength)
 
template<class T >
static bool validNumericRange (std::optional< T > value, T max, T min={})
 
template<class T , class Unit >
static bool validNumericRange (std::optional< T > value, unit::ValueUnit< Unit, T > max, unit::ValueUnit< Unit, T > min={})
 
@@ -347,6 +372,12 @@ Static Private Member Functions + + + + + +

Protected Attributes

 
static NotTEC checkMultiSign (ReadView const &view, AccountID const &idAccount, STArray const &txSigners, ApplyFlags const &flags, beast::Journal j)
 
static NotTEC preflight1 (PreflightContext const &ctx, std::uint32_t flagMask)
 Performs early sanity checks on the account and fee fields.
 
static NotTEC preflight2 (PreflightContext const &ctx)
 Checks whether the signature appears valid.
 

Detailed Description

AMMDeposit implements AMM deposit Transactor.

@@ -379,7 +410,7 @@ Static Private Member Functions Custom  -

Definition at line 155 of file Transactor.h.

+

Definition at line 157 of file Transactor.h.

@@ -413,6 +444,62 @@ Static Private Member Functions

Member Function Documentation

+ +

◆ checkExtraFeatures()

+ +
+
+ + + + + +
+ + + + + + + + +
bool ripple::AMMDeposit::checkExtraFeatures (PreflightContext const & ctx)
+
+static
+
+ +

Definition at line 33 of file AMMDeposit.cpp.

+ +
+
+ +

◆ getFlagsMask()

+ +
+
+ + + + + +
+ + + + + + + + +
std::uint32_t ripple::AMMDeposit::getFlagsMask (PreflightContext const & ctx)
+
+static
+
+ +

Definition at line 39 of file AMMDeposit.cpp.

+ +
+

◆ preflight()

@@ -437,7 +524,7 @@ Static Private Member Functions
-

Definition at line 33 of file AMMDeposit.cpp.

+

Definition at line 46 of file AMMDeposit.cpp.

@@ -465,7 +552,7 @@ Static Private Member Functions
-

Definition at line 166 of file AMMDeposit.cpp.

+

Definition at line 168 of file AMMDeposit.cpp.

@@ -494,7 +581,7 @@ Static Private Member Functions

Implements ripple::Transactor.

-

Definition at line 483 of file AMMDeposit.cpp.

+

Definition at line 485 of file AMMDeposit.cpp.

@@ -522,7 +609,7 @@ Static Private Member Functions
-

Definition at line 368 of file AMMDeposit.cpp.

+

Definition at line 370 of file AMMDeposit.cpp.

@@ -633,7 +720,7 @@ Static Private Member Functions
Returns
-

Definition at line 497 of file AMMDeposit.cpp.

+

Definition at line 499 of file AMMDeposit.cpp.

@@ -731,7 +818,7 @@ Static Private Member Functions
Returns
-

Definition at line 643 of file AMMDeposit.cpp.

+

Definition at line 645 of file AMMDeposit.cpp.

@@ -830,7 +917,7 @@ Static Private Member Functions
Returns

a = (t/T) * A (1) b = (t/T) * B (2) where A,B: current pool composition T: current balance of outstanding LPTokens a: balance of asset A being added b: balance of asset B being added t: balance of LPTokens issued to LP after a successful transaction Use equation 1 to compute the amount of t, given the amount in Asset1In. Let this be Z Use equation 2 to compute the amount of asset2, given t~Z. Let the computed amount of asset2 be X. If X <= amount in Asset2In: The amount of asset1 to be deposited is the one specified in Asset1In The amount of asset2 to be deposited is X The amount of LPTokens to be issued is Z If X > amount in Asset2In: Use equation 2 to compute , given the amount in Asset2In. Let this be W Use equation 1 to compute the amount of asset1, given t~W from above. Let the computed amount of asset1 be Y If Y <= amount in Asset1In: The amount of asset1 to be deposited is Y The amount of asset2 to be deposited is the one specified in Asset2In The amount of LPTokens to be issued is W else, failed transaction

-

Definition at line 719 of file AMMDeposit.cpp.

+

Definition at line 721 of file AMMDeposit.cpp.

@@ -915,7 +1002,7 @@ Static Private Member Functions
Returns

t = T * (b / B - x) / (1 + x) (3) where f1 = (1 - 0.5 * tfee) / (1 - tfee) x = sqrt(f1**2 + b / (B * (1 - tfee)) - f1 Use equation 3

See also
singleDeposit to compute amount of LPTokens to be issued, given the amount in Asset1In.
-

Definition at line 796 of file AMMDeposit.cpp.

+

Definition at line 798 of file AMMDeposit.cpp.

@@ -1000,7 +1087,7 @@ Static Private Member Functions
Returns

Use equation 4 to compute the amount of asset1 to be deposited, given t represented by amount of LPTokens. Equation 4 solves equation 3

See also
singleDeposit for b. Fail if b exceeds specified Max amount to deposit.
-

Definition at line 843 of file AMMDeposit.cpp.

+

Definition at line 845 of file AMMDeposit.cpp.

@@ -1087,7 +1174,7 @@ Static Private Member Functions
singleDeposit & III and the given EPrice to compute the following two variables: The amount of asset1 in. Let this be Q The amount of LPTokens out. Let this be W The amount of asset1 to be deposited is Q The amount of LPTokens to be issued is W
-

Definition at line 901 of file AMMDeposit.cpp.

+

Definition at line 903 of file AMMDeposit.cpp.

@@ -1162,7 +1249,7 @@ Static Private Member Functions
Returns
-

Definition at line 1006 of file AMMDeposit.cpp.

+

Definition at line 1008 of file AMMDeposit.cpp.

@@ -1191,7 +1278,7 @@ Static Private Member Functions

Process the transaction.

-

Definition at line 1064 of file Transactor.cpp.

+

Definition at line 1145 of file Transactor.cpp.

@@ -1218,7 +1305,7 @@ Static Private Member Functions
-

Definition at line 161 of file Transactor.h.

+

Definition at line 163 of file Transactor.h.

@@ -1245,7 +1332,7 @@ Static Private Member Functions
-

Definition at line 167 of file Transactor.h.

+

Definition at line 169 of file Transactor.h.

@@ -1289,7 +1376,7 @@ Static Private Member Functions
-

Definition at line 361 of file Transactor.cpp.

+

Definition at line 442 of file Transactor.cpp.

@@ -1317,7 +1404,7 @@ Static Private Member Functions
-

Definition at line 433 of file Transactor.cpp.

+

Definition at line 514 of file Transactor.cpp.

@@ -1355,7 +1442,7 @@ Static Private Member Functions
-

Definition at line 261 of file Transactor.cpp.

+

Definition at line 342 of file Transactor.cpp.

@@ -1383,7 +1470,7 @@ Static Private Member Functions
-

Definition at line 581 of file Transactor.cpp.

+

Definition at line 662 of file Transactor.cpp.

@@ -1411,7 +1498,7 @@ Static Private Member Functions
-

Definition at line 638 of file Transactor.cpp.

+

Definition at line 719 of file Transactor.cpp.

@@ -1449,7 +1536,95 @@ Static Private Member Functions
-

Definition at line 233 of file Transactor.cpp.

+

Definition at line 293 of file Transactor.cpp.

+ +
+ + +

◆ invokePreflight() [1/3]

+ +
+
+
+template<class T >
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
+ +

Definition at line 391 of file Transactor.h.

+ +
+
+ +

◆ invokePreflight() [2/3]

+ +
+
+
+template<>
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
+ +

Definition at line 37 of file Change.cpp.

+ +
+
+ +

◆ invokePreflight() [3/3]

+ +
+
+
+template<>
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
@@ -1487,7 +1662,7 @@ Static Private Member Functions
-

Definition at line 217 of file Transactor.cpp.

+

Definition at line 277 of file Transactor.cpp.

@@ -1537,7 +1712,7 @@ Static Private Member Functions
-

Definition at line 482 of file Transactor.cpp.

+

Definition at line 563 of file Transactor.cpp.

@@ -1564,7 +1739,7 @@ Static Private Member Functions
-

Definition at line 544 of file Transactor.cpp.

+

Definition at line 625 of file Transactor.cpp.

@@ -1593,7 +1768,7 @@ Static Private Member Functions

Reimplemented in ripple::Change, and ripple::SetSignerList.

-

Definition at line 536 of file Transactor.cpp.

+

Definition at line 617 of file Transactor.cpp.

@@ -1660,7 +1835,203 @@ Static Private Member Functions -

Definition at line 251 of file Transactor.cpp.

+

Definition at line 332 of file Transactor.cpp.

+ + + + +

◆ calculateOwnerReserveFee()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
XRPAmount ripple::Transactor::calculateOwnerReserveFee (ReadView const & view,
STTx const & tx 
)
+
+staticprotectedinherited
+
+ +

Definition at line 312 of file Transactor.cpp.

+ +
+
+ +

◆ preflightSigValidated()

+ +
+
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::preflightSigValidated (PreflightContext const & ctx)
+
+staticprotectedinherited
+
+ +

Definition at line 271 of file Transactor.cpp.

+ +
+
+ +

◆ validDataLength()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validDataLength (std::optional< Slice > const & slice,
std::size_t maxLength 
)
+
+staticprotectedinherited
+
+ +

Definition at line 255 of file Transactor.cpp.

+ +
+
+ +

◆ validNumericRange() [1/2]

+ +
+
+
+template<class T >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validNumericRange (std::optional< T > value,
max,
min = {} 
)
+
+staticprotectedinherited
+
+ +

Definition at line 418 of file Transactor.h.

+ +
+
+ +

◆ validNumericRange() [2/2]

+ +
+
+
+template<class T , class Unit >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validNumericRange (std::optional< T > value,
unit::ValueUnit< Unit, T > max,
unit::ValueUnit< Unit, T > min = {} 
)
+
+staticprotectedinherited
+
+ +

Definition at line 427 of file Transactor.h.

@@ -1697,7 +2068,7 @@ Static Private Member Functions
Returns
A pair containing the transaction result and the actual fee charged.
-

Definition at line 1002 of file Transactor.cpp.

+

Definition at line 1083 of file Transactor.cpp.

@@ -1725,7 +2096,7 @@ Static Private Member Functions
-

Definition at line 463 of file Transactor.cpp.

+

Definition at line 544 of file Transactor.cpp.

@@ -1752,7 +2123,7 @@ Static Private Member Functions
-

Definition at line 326 of file Transactor.cpp.

+

Definition at line 407 of file Transactor.cpp.

@@ -1808,7 +2179,7 @@ Static Private Member Functions
-

Definition at line 685 of file Transactor.cpp.

+

Definition at line 766 of file Transactor.cpp.

@@ -1864,7 +2235,7 @@ Static Private Member Functions
-

Definition at line 746 of file Transactor.cpp.

+

Definition at line 827 of file Transactor.cpp.

@@ -1892,7 +2263,80 @@ Static Private Member Functions
-

Definition at line 1057 of file Transactor.cpp.

+

Definition at line 1138 of file Transactor.cpp.

+ +
+ + +

◆ preflight1()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
NotTEC ripple::Transactor::preflight1 (PreflightContext const & ctx,
std::uint32_t flagMask 
)
+
+staticprivateinherited
+
+ +

Performs early sanity checks on the account and fee fields.

+

(And passes flagMask to preflight0)

+

Do not try to call preflight1 from preflight() in derived classes. See the description of invokePreflight for details.

+ +

Definition at line 163 of file Transactor.cpp.

+ +
+
+ +

◆ preflight2()

+ +
+
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::preflight2 (PreflightContext const & ctx)
+
+staticprivateinherited
+
+ +

Checks whether the signature appears valid.

+

Do not try to call preflight2 from preflight() in derived classes. See the description of invokePreflight for details.

+ +

Definition at line 226 of file Transactor.cpp.

@@ -1941,7 +2385,7 @@ Static Private Member Functions
-

Definition at line 141 of file Transactor.h.

+

Definition at line 143 of file Transactor.h.

@@ -1965,7 +2409,7 @@ Static Private Member Functions
-

Definition at line 142 of file Transactor.h.

+

Definition at line 144 of file Transactor.h.

@@ -1989,7 +2433,7 @@ Static Private Member Functions
-

Definition at line 143 of file Transactor.h.

+

Definition at line 145 of file Transactor.h.

@@ -2013,7 +2457,7 @@ Static Private Member Functions
-

Definition at line 145 of file Transactor.h.

+

Definition at line 147 of file Transactor.h.

@@ -2037,7 +2481,7 @@ Static Private Member Functions
-

Definition at line 146 of file Transactor.h.

+

Definition at line 148 of file Transactor.h.

@@ -2061,7 +2505,7 @@ Static Private Member Functions
-

Definition at line 147 of file Transactor.h.

+

Definition at line 149 of file Transactor.h.

diff --git a/classripple_1_1AMMVote-members.html b/classripple_1_1AMMVote-members.html index a7df7ce853..7afc45c090 100644 --- a/classripple_1_1AMMVote-members.html +++ b/classripple_1_1AMMVote-members.html @@ -84,7 +84,9 @@ $(function() { apply()ripple::Transactorprotected Blocker enum valueripple::Transactor calculateBaseFee(ReadView const &view, STTx const &tx)ripple::Transactorstatic - checkBatchSign(PreclaimContext const &ctx)ripple::Transactorstatic + calculateOwnerReserveFee(ReadView const &view, STTx const &tx)ripple::Transactorprotectedstatic + checkBatchSign(PreclaimContext const &ctx)ripple::Transactorstatic + checkExtraFeatures(PreflightContext const &ctx)ripple::AMMVotestatic checkFee(PreclaimContext const &ctx, XRPAmount baseFee)ripple::Transactorstatic checkMultiSign(ReadView const &view, AccountID const &idAccount, STArray const &txSigners, ApplyFlags const &flags, beast::Journal j)ripple::Transactorprivatestatic checkPermission(ReadView const &view, STTx const &tx)ripple::Transactorstatic @@ -98,6 +100,10 @@ $(function() { ctx_ripple::Transactorprotected Custom enum valueripple::Transactor doApply() overrideripple::AMMVotevirtual + getFlagsMask(PreflightContext const &ctx)ripple::Transactorprotectedstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic j_ripple::Transactorprotected minimumFee(Application &app, XRPAmount baseFee, Fees const &fees, ApplyFlags flags)ripple::Transactorprotectedstatic mPriorBalanceripple::Transactorprotected @@ -109,12 +115,18 @@ $(function() { preclaim(PreclaimContext const &ctx)ripple::AMMVotestatic preCompute()ripple::Transactorprotectedvirtual preflight(PreflightContext const &ctx)ripple::AMMVotestatic - reset(XRPAmount fee)ripple::Transactorprivate - sink_ripple::Transactorprotected - ticketDelete(ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)ripple::Transactorstatic - Transactor(Transactor const &)=deleteripple::Transactorprotected - Transactor(ApplyContext &ctx)ripple::Transactorexplicitprotected - trapTransaction(uint256) constripple::Transactorprivate + preflight1(PreflightContext const &ctx, std::uint32_t flagMask)ripple::Transactorprivatestatic + preflight2(PreflightContext const &ctx)ripple::Transactorprivatestatic + preflightSigValidated(PreflightContext const &ctx)ripple::Transactorprotectedstatic + reset(XRPAmount fee)ripple::Transactorprivate + sink_ripple::Transactorprotected + ticketDelete(ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)ripple::Transactorstatic + Transactor(Transactor const &)=deleteripple::Transactorprotected + Transactor(ApplyContext &ctx)ripple::Transactorexplicitprotected + trapTransaction(uint256) constripple::Transactorprivate + validDataLength(std::optional< Slice > const &slice, std::size_t maxLength)ripple::Transactorprotectedstatic + validNumericRange(std::optional< T > value, T max, T min={})ripple::Transactorprotectedstatic + validNumericRange(std::optional< T > value, unit::ValueUnit< Unit, T > max, unit::ValueUnit< Unit, T > min={})ripple::Transactorprotectedstatic view()ripple::Transactor view() constripple::Transactor ~Transactor()=defaultripple::Transactorprotectedvirtual diff --git a/classripple_1_1AMMVote.html b/classripple_1_1AMMVote.html index de15c351c9..e14e9c2c00 100644 --- a/classripple_1_1AMMVote.html +++ b/classripple_1_1AMMVote.html @@ -252,6 +252,8 @@ Public Member Functions + + @@ -268,6 +270,15 @@ Static Public Member Functions + + + + + + + + + @@ -290,6 +301,20 @@ Static Protected Member Functions + + + + + + + + + + + + + +

Static Public Member Functions

static bool checkExtraFeatures (PreflightContext const &ctx)
 
static NotTEC preflight (PreflightContext const &ctx)
 
static TER preclaim (PreclaimContext const &ctx)
 
static XRPAmount calculateBaseFee (ReadView const &view, STTx const &tx)
 
template<class T >
static NotTEC invokePreflight (PreflightContext const &ctx)
 
template<>
NotTEC invokePreflight (PreflightContext const &ctx)
 
template<>
NotTEC invokePreflight (PreflightContext const &ctx)
 
static TER checkPermission (ReadView const &view, STTx const &tx)
 
static TER ticketDelete (ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)
static XRPAmount minimumFee (Application &app, XRPAmount baseFee, Fees const &fees, ApplyFlags flags)
 Compute the minimum fee required to process a transaction with a given baseFee based on the current server load.
 
static XRPAmount calculateOwnerReserveFee (ReadView const &view, STTx const &tx)
 
static std::uint32_t getFlagsMask (PreflightContext const &ctx)
 
static NotTEC preflightSigValidated (PreflightContext const &ctx)
 
static bool validDataLength (std::optional< Slice > const &slice, std::size_t maxLength)
 
template<class T >
static bool validNumericRange (std::optional< T > value, T max, T min={})
 
template<class T , class Unit >
static bool validNumericRange (std::optional< T > value, unit::ValueUnit< Unit, T > max, unit::ValueUnit< Unit, T > min={})
 
@@ -324,6 +349,12 @@ Static Private Member Functions + + + + + +

Protected Attributes

 
static NotTEC checkMultiSign (ReadView const &view, AccountID const &idAccount, STArray const &txSigners, ApplyFlags const &flags, beast::Journal j)
 
static NotTEC preflight1 (PreflightContext const &ctx, std::uint32_t flagMask)
 Performs early sanity checks on the account and fee fields.
 
static NotTEC preflight2 (PreflightContext const &ctx)
 Checks whether the signature appears valid.
 

Detailed Description

AMMVote implements AMM vote Transactor.

@@ -364,7 +395,7 @@ Static Private Member Functions Custom  -

Definition at line 155 of file Transactor.h.

+

Definition at line 157 of file Transactor.h.

@@ -398,6 +429,34 @@ Static Private Member Functions

Member Function Documentation

+ +

◆ checkExtraFeatures()

+ +
+
+ + + + + +
+ + + + + + + + +
bool ripple::AMMVote::checkExtraFeatures (PreflightContext const & ctx)
+
+static
+
+ +

Definition at line 31 of file AMMVote.cpp.

+ +
+

◆ preflight()

@@ -422,7 +481,7 @@ Static Private Member Functions
-

Definition at line 31 of file AMMVote.cpp.

+

Definition at line 37 of file AMMVote.cpp.

@@ -450,7 +509,7 @@ Static Private Member Functions
-

Definition at line 62 of file AMMVote.cpp.

+

Definition at line 56 of file AMMVote.cpp.

@@ -479,7 +538,7 @@ Static Private Member Functions

Implements ripple::Transactor.

-

Definition at line 239 of file AMMVote.cpp.

+

Definition at line 233 of file AMMVote.cpp.

@@ -508,7 +567,7 @@ Static Private Member Functions

Process the transaction.

-

Definition at line 1064 of file Transactor.cpp.

+

Definition at line 1145 of file Transactor.cpp.

@@ -535,7 +594,7 @@ Static Private Member Functions
-

Definition at line 161 of file Transactor.h.

+

Definition at line 163 of file Transactor.h.

@@ -562,7 +621,7 @@ Static Private Member Functions
-

Definition at line 167 of file Transactor.h.

+

Definition at line 169 of file Transactor.h.

@@ -606,7 +665,7 @@ Static Private Member Functions
-

Definition at line 361 of file Transactor.cpp.

+

Definition at line 442 of file Transactor.cpp.

@@ -634,7 +693,7 @@ Static Private Member Functions
-

Definition at line 433 of file Transactor.cpp.

+

Definition at line 514 of file Transactor.cpp.

@@ -672,7 +731,7 @@ Static Private Member Functions
-

Definition at line 261 of file Transactor.cpp.

+

Definition at line 342 of file Transactor.cpp.

@@ -700,7 +759,7 @@ Static Private Member Functions
-

Definition at line 581 of file Transactor.cpp.

+

Definition at line 662 of file Transactor.cpp.

@@ -728,7 +787,7 @@ Static Private Member Functions
-

Definition at line 638 of file Transactor.cpp.

+

Definition at line 719 of file Transactor.cpp.

@@ -766,7 +825,95 @@ Static Private Member Functions
-

Definition at line 233 of file Transactor.cpp.

+

Definition at line 293 of file Transactor.cpp.

+ +
+ + +

◆ invokePreflight() [1/3]

+ +
+
+
+template<class T >
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
+ +

Definition at line 391 of file Transactor.h.

+ +
+
+ +

◆ invokePreflight() [2/3]

+ +
+
+
+template<>
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
+ +

Definition at line 37 of file Change.cpp.

+ +
+
+ +

◆ invokePreflight() [3/3]

+ +
+
+
+template<>
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
@@ -804,7 +951,7 @@ Static Private Member Functions
-

Definition at line 217 of file Transactor.cpp.

+

Definition at line 277 of file Transactor.cpp.

@@ -854,7 +1001,7 @@ Static Private Member Functions
-

Definition at line 482 of file Transactor.cpp.

+

Definition at line 563 of file Transactor.cpp.

@@ -881,7 +1028,7 @@ Static Private Member Functions
-

Definition at line 544 of file Transactor.cpp.

+

Definition at line 625 of file Transactor.cpp.

@@ -910,7 +1057,7 @@ Static Private Member Functions

Reimplemented in ripple::Change, and ripple::SetSignerList.

-

Definition at line 536 of file Transactor.cpp.

+

Definition at line 617 of file Transactor.cpp.

@@ -977,7 +1124,231 @@ Static Private Member Functions -

Definition at line 251 of file Transactor.cpp.

+

Definition at line 332 of file Transactor.cpp.

+ + + + +

◆ calculateOwnerReserveFee()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
XRPAmount ripple::Transactor::calculateOwnerReserveFee (ReadView const & view,
STTx const & tx 
)
+
+staticprotectedinherited
+
+ +

Definition at line 312 of file Transactor.cpp.

+ +
+
+ +

◆ getFlagsMask()

+ +
+
+ + + + + +
+ + + + + + + + +
std::uint32_t ripple::Transactor::getFlagsMask (PreflightContext const & ctx)
+
+staticprotectedinherited
+
+ +

Definition at line 265 of file Transactor.cpp.

+ +
+
+ +

◆ preflightSigValidated()

+ +
+
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::preflightSigValidated (PreflightContext const & ctx)
+
+staticprotectedinherited
+
+ +

Definition at line 271 of file Transactor.cpp.

+ +
+
+ +

◆ validDataLength()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validDataLength (std::optional< Slice > const & slice,
std::size_t maxLength 
)
+
+staticprotectedinherited
+
+ +

Definition at line 255 of file Transactor.cpp.

+ +
+
+ +

◆ validNumericRange() [1/2]

+ +
+
+
+template<class T >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validNumericRange (std::optional< T > value,
max,
min = {} 
)
+
+staticprotectedinherited
+
+ +

Definition at line 418 of file Transactor.h.

+ +
+
+ +

◆ validNumericRange() [2/2]

+ +
+
+
+template<class T , class Unit >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validNumericRange (std::optional< T > value,
unit::ValueUnit< Unit, T > max,
unit::ValueUnit< Unit, T > min = {} 
)
+
+staticprotectedinherited
+
+ +

Definition at line 427 of file Transactor.h.

@@ -1014,7 +1385,7 @@ Static Private Member Functions
Returns
A pair containing the transaction result and the actual fee charged.
-

Definition at line 1002 of file Transactor.cpp.

+

Definition at line 1083 of file Transactor.cpp.

@@ -1042,7 +1413,7 @@ Static Private Member Functions
-

Definition at line 463 of file Transactor.cpp.

+

Definition at line 544 of file Transactor.cpp.

@@ -1069,7 +1440,7 @@ Static Private Member Functions
-

Definition at line 326 of file Transactor.cpp.

+

Definition at line 407 of file Transactor.cpp.

@@ -1125,7 +1496,7 @@ Static Private Member Functions
-

Definition at line 685 of file Transactor.cpp.

+

Definition at line 766 of file Transactor.cpp.

@@ -1181,7 +1552,7 @@ Static Private Member Functions
-

Definition at line 746 of file Transactor.cpp.

+

Definition at line 827 of file Transactor.cpp.

@@ -1209,7 +1580,80 @@ Static Private Member Functions
-

Definition at line 1057 of file Transactor.cpp.

+

Definition at line 1138 of file Transactor.cpp.

+ +
+ + +

◆ preflight1()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
NotTEC ripple::Transactor::preflight1 (PreflightContext const & ctx,
std::uint32_t flagMask 
)
+
+staticprivateinherited
+
+ +

Performs early sanity checks on the account and fee fields.

+

(And passes flagMask to preflight0)

+

Do not try to call preflight1 from preflight() in derived classes. See the description of invokePreflight for details.

+ +

Definition at line 163 of file Transactor.cpp.

+ +
+
+ +

◆ preflight2()

+ +
+
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::preflight2 (PreflightContext const & ctx)
+
+staticprivateinherited
+
+ +

Checks whether the signature appears valid.

+

Do not try to call preflight2 from preflight() in derived classes. See the description of invokePreflight for details.

+ +

Definition at line 226 of file Transactor.cpp.

@@ -1258,7 +1702,7 @@ Static Private Member Functions
-

Definition at line 141 of file Transactor.h.

+

Definition at line 143 of file Transactor.h.

@@ -1282,7 +1726,7 @@ Static Private Member Functions
-

Definition at line 142 of file Transactor.h.

+

Definition at line 144 of file Transactor.h.

@@ -1306,7 +1750,7 @@ Static Private Member Functions
-

Definition at line 143 of file Transactor.h.

+

Definition at line 145 of file Transactor.h.

@@ -1330,7 +1774,7 @@ Static Private Member Functions
-

Definition at line 145 of file Transactor.h.

+

Definition at line 147 of file Transactor.h.

@@ -1354,7 +1798,7 @@ Static Private Member Functions
-

Definition at line 146 of file Transactor.h.

+

Definition at line 148 of file Transactor.h.

@@ -1378,7 +1822,7 @@ Static Private Member Functions
-

Definition at line 147 of file Transactor.h.

+

Definition at line 149 of file Transactor.h.

diff --git a/classripple_1_1AMMWithdraw-members.html b/classripple_1_1AMMWithdraw-members.html index 65a930fd40..86e3d501cd 100644 --- a/classripple_1_1AMMWithdraw-members.html +++ b/classripple_1_1AMMWithdraw-members.html @@ -85,7 +85,9 @@ $(function() { applyGuts(Sandbox &view)ripple::AMMWithdrawprivate Blocker enum valueripple::Transactor calculateBaseFee(ReadView const &view, STTx const &tx)ripple::Transactorstatic - checkBatchSign(PreclaimContext const &ctx)ripple::Transactorstatic + calculateOwnerReserveFee(ReadView const &view, STTx const &tx)ripple::Transactorprotectedstatic + checkBatchSign(PreclaimContext const &ctx)ripple::Transactorstatic + checkExtraFeatures(PreflightContext const &ctx)ripple::AMMWithdrawstatic checkFee(PreclaimContext const &ctx, XRPAmount baseFee)ripple::Transactorstatic checkMultiSign(ReadView const &view, AccountID const &idAccount, STArray const &txSigners, ApplyFlags const &flags, beast::Journal j)ripple::Transactorprivatestatic checkPermission(ReadView const &view, STTx const &tx)ripple::Transactorstatic @@ -103,6 +105,10 @@ $(function() { equalWithdrawLimit(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &amount2, std::uint16_t tfee)ripple::AMMWithdrawprivate equalWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const account, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokens, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHanding, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)ripple::AMMWithdrawstatic equalWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &amount2Balance, STAmount const &lptAMMBalance, STAmount const &lpTokens, STAmount const &lpTokensWithdraw, std::uint16_t tfee)ripple::AMMWithdrawprivate + getFlagsMask(PreflightContext const &ctx)ripple::AMMWithdrawstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic + invokePreflight(PreflightContext const &ctx)ripple::Transactorstatic isWithdrawAll(STTx const &tx)ripple::AMMWithdrawprivatestatic j_ripple::Transactorprotected minimumFee(Application &app, XRPAmount baseFee, Fees const &fees, ApplyFlags flags)ripple::Transactorprotectedstatic @@ -115,15 +121,21 @@ $(function() { preclaim(PreclaimContext const &ctx)ripple::AMMWithdrawstatic preCompute()ripple::Transactorprotectedvirtual preflight(PreflightContext const &ctx)ripple::AMMWithdrawstatic - reset(XRPAmount fee)ripple::Transactorprivate - singleWithdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, std::uint16_t tfee)ripple::AMMWithdrawprivate - singleWithdrawEPrice(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &ePrice, std::uint16_t tfee)ripple::AMMWithdrawprivate - singleWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &lpTokensWithdraw, std::uint16_t tfee)ripple::AMMWithdrawprivate - sink_ripple::Transactorprotected - ticketDelete(ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)ripple::Transactorstatic - Transactor(Transactor const &)=deleteripple::Transactorprotected - Transactor(ApplyContext &ctx)ripple::Transactorexplicitprotected - trapTransaction(uint256) constripple::Transactorprivate + preflight1(PreflightContext const &ctx, std::uint32_t flagMask)ripple::Transactorprivatestatic + preflight2(PreflightContext const &ctx)ripple::Transactorprivatestatic + preflightSigValidated(PreflightContext const &ctx)ripple::Transactorprotectedstatic + reset(XRPAmount fee)ripple::Transactorprivate + singleWithdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, std::uint16_t tfee)ripple::AMMWithdrawprivate + singleWithdrawEPrice(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &ePrice, std::uint16_t tfee)ripple::AMMWithdrawprivate + singleWithdrawTokens(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, STAmount const &amountBalance, STAmount const &lptAMMBalance, STAmount const &amount, STAmount const &lpTokensWithdraw, std::uint16_t tfee)ripple::AMMWithdrawprivate + sink_ripple::Transactorprotected + ticketDelete(ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)ripple::Transactorstatic + Transactor(Transactor const &)=deleteripple::Transactorprotected + Transactor(ApplyContext &ctx)ripple::Transactorexplicitprotected + trapTransaction(uint256) constripple::Transactorprivate + validDataLength(std::optional< Slice > const &slice, std::size_t maxLength)ripple::Transactorprotectedstatic + validNumericRange(std::optional< T > value, T max, T min={})ripple::Transactorprotectedstatic + validNumericRange(std::optional< T > value, unit::ValueUnit< Unit, T > max, unit::ValueUnit< Unit, T > min={})ripple::Transactorprotectedstatic view()ripple::Transactor view() constripple::Transactor withdraw(Sandbox &view, SLE const &ammSle, AccountID const &ammAccount, AccountID const &account, STAmount const &amountBalance, STAmount const &amountWithdraw, std::optional< STAmount > const &amount2Withdraw, STAmount const &lpTokensAMMBalance, STAmount const &lpTokensWithdraw, std::uint16_t tfee, FreezeHandling freezeHandling, WithdrawAll withdrawAll, XRPAmount const &priorBalance, beast::Journal const &journal)ripple::AMMWithdrawstatic diff --git a/classripple_1_1AMMWithdraw.html b/classripple_1_1AMMWithdraw.html index 4b77b09238..5963082999 100644 --- a/classripple_1_1AMMWithdraw.html +++ b/classripple_1_1AMMWithdraw.html @@ -249,6 +249,10 @@ Public Member Functions + + + + @@ -273,6 +277,15 @@ Static Public Member Functions + + + + + + + + + @@ -295,6 +308,18 @@ Static Protected Member Functions + + + + + + + + + + + +

Static Public Member Functions

static bool checkExtraFeatures (PreflightContext const &ctx)
 
static std::uint32_t getFlagsMask (PreflightContext const &ctx)
 
static NotTEC preflight (PreflightContext const &ctx)
 
static TER preclaim (PreclaimContext const &ctx)
 
static XRPAmount calculateBaseFee (ReadView const &view, STTx const &tx)
 
template<class T >
static NotTEC invokePreflight (PreflightContext const &ctx)
 
template<>
NotTEC invokePreflight (PreflightContext const &ctx)
 
template<>
NotTEC invokePreflight (PreflightContext const &ctx)
 
static TER checkPermission (ReadView const &view, STTx const &tx)
 
static TER ticketDelete (ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)
static XRPAmount minimumFee (Application &app, XRPAmount baseFee, Fees const &fees, ApplyFlags flags)
 Compute the minimum fee required to process a transaction with a given baseFee based on the current server load.
 
static XRPAmount calculateOwnerReserveFee (ReadView const &view, STTx const &tx)
 
static NotTEC preflightSigValidated (PreflightContext const &ctx)
 
static bool validDataLength (std::optional< Slice > const &slice, std::size_t maxLength)
 
template<class T >
static bool validNumericRange (std::optional< T > value, T max, T min={})
 
template<class T , class Unit >
static bool validNumericRange (std::optional< T > value, unit::ValueUnit< Unit, T > max, unit::ValueUnit< Unit, T > min={})
 
@@ -352,6 +377,12 @@ Static Private Member Functions + + + + + +

Protected Attributes

 
static NotTEC checkMultiSign (ReadView const &view, AccountID const &idAccount, STArray const &txSigners, ApplyFlags const &flags, beast::Journal j)
 
static NotTEC preflight1 (PreflightContext const &ctx, std::uint32_t flagMask)
 Performs early sanity checks on the account and fee fields.
 
static NotTEC preflight2 (PreflightContext const &ctx)
 Checks whether the signature appears valid.
 

Detailed Description

@@ -382,7 +413,7 @@ Static Private Member Functions Custom  -

Definition at line 155 of file Transactor.h.

+

Definition at line 157 of file Transactor.h.

@@ -416,6 +447,62 @@ Static Private Member Functions

Member Function Documentation

+ +

◆ checkExtraFeatures()

+ +
+
+ + + + + +
+ + + + + + + + +
bool ripple::AMMWithdraw::checkExtraFeatures (PreflightContext const & ctx)
+
+static
+
+ +

Definition at line 32 of file AMMWithdraw.cpp.

+ +
+
+ +

◆ getFlagsMask()

+ +
+
+ + + + + +
+ + + + + + + + +
std::uint32_t ripple::AMMWithdraw::getFlagsMask (PreflightContext const & ctx)
+
+static
+
+ +

Definition at line 38 of file AMMWithdraw.cpp.

+ +
+

◆ preflight()

@@ -440,7 +527,7 @@ Static Private Member Functions
-

Definition at line 32 of file AMMWithdraw.cpp.

+

Definition at line 44 of file AMMWithdraw.cpp.

@@ -468,7 +555,7 @@ Static Private Member Functions
-

Definition at line 168 of file AMMWithdraw.cpp.

+

Definition at line 169 of file AMMWithdraw.cpp.

@@ -497,7 +584,7 @@ Static Private Member Functions

Implements ripple::Transactor.

-

Definition at line 422 of file AMMWithdraw.cpp.

+

Definition at line 423 of file AMMWithdraw.cpp.

@@ -626,7 +713,7 @@ Static Private Member Functions
Returns
-

Definition at line 750 of file AMMWithdraw.cpp.

+

Definition at line 751 of file AMMWithdraw.cpp.

@@ -755,7 +842,7 @@ Static Private Member Functions
Returns
-

Definition at line 468 of file AMMWithdraw.cpp.

+

Definition at line 469 of file AMMWithdraw.cpp.

@@ -817,7 +904,7 @@ Static Private Member Functions
-

Definition at line 719 of file AMMWithdraw.cpp.

+

Definition at line 720 of file AMMWithdraw.cpp.

@@ -845,7 +932,7 @@ Static Private Member Functions
-

Definition at line 292 of file AMMWithdraw.cpp.

+

Definition at line 293 of file AMMWithdraw.cpp.

@@ -941,7 +1028,7 @@ Static Private Member Functions
Returns
-

Definition at line 436 of file AMMWithdraw.cpp.

+

Definition at line 437 of file AMMWithdraw.cpp.

@@ -1038,7 +1125,7 @@ Static Private Member Functions
Returns
-

Definition at line 686 of file AMMWithdraw.cpp.

+

Definition at line 687 of file AMMWithdraw.cpp.

@@ -1136,7 +1223,7 @@ Static Private Member Functions
Returns

a = (t/T) * A (5) b = (t/T) * B (6) where A,B: current pool composition T: current balance of outstanding LPTokens a: balance of asset A being withdrawn b: balance of asset B being withdrawn t: balance of LPTokens issued to LP after a successful transaction Use equation 5 to compute t, given the amount in Asset1Out. Let this be Z Use equation 6 to compute the amount of asset2, given Z. Let the computed amount of asset2 be X If X <= amount in Asset2Out: The amount of asset1 to be withdrawn is the one specified in Asset1Out The amount of asset2 to be withdrawn is X The amount of LPTokens redeemed is Z If X> amount in Asset2Out: Use equation 5 to compute t, given the amount in Asset2Out. Let this be Q Use equation 6 to compute the amount of asset1, given Q. Let the computed amount of asset1 be W The amount of asset2 to be withdrawn is the one specified in Asset2Out The amount of asset1 to be withdrawn is W The amount of LPTokens redeemed is Q

-

Definition at line 858 of file AMMWithdraw.cpp.

+

Definition at line 859 of file AMMWithdraw.cpp.

@@ -1220,7 +1307,7 @@ Static Private Member Functions
Returns

t = T * (c - sqrt(c**2 - 4*R))/2 where R = b/B, c = R*fee + 2 - fee Use equation 7 to compute the t, given the amount in Asset1Out.

-

Definition at line 933 of file AMMWithdraw.cpp.

+

Definition at line 934 of file AMMWithdraw.cpp.

@@ -1311,7 +1398,7 @@ Static Private Member Functions
Returns

Use equation 8 to compute the amount of asset1, given the redeemed t represented by LPTokens. Let this be Y. If (amount exists for Asset1Out & Y >= amount in Asset1Out) || (amount field does not exist for Asset1Out): The amount of asset out is Y The amount of LPTokens redeemed is LPTokens Equation 8 solves equation 7

See also
singleWithdraw for b.
-

Definition at line 982 of file AMMWithdraw.cpp.

+

Definition at line 983 of file AMMWithdraw.cpp.

@@ -1402,7 +1489,7 @@ Static Private Member Functions
Returns

a. amount of asset1 if specified (not 0) in Asset1Out specifies the minimum amount of asset1 that the trader is willing to withdraw. b. The effective price of asset traded out does not exceed the amount specified in EPrice The effective price (EP) of a trade is defined as the ratio of the tokens the trader sold or swapped in (Token B) and the token they got in return or swapped out (Token A). EP(B/A) = b/a (III) b = B * (t1**2 + t1*(f - 2))/(t1*f - 1) (8) where t1 = t/T Use equations 8 & III and amount in EPrice to compute the two variables: asset in as LPTokens. Let this be X asset out as that in Asset1Out. Let this be Y If (amount exists for Asset1Out & Y >= amount in Asset1Out) || (amount field does not exist for Asset1Out): The amount of assetOut is given by Y The amount of LPTokens is given by X

-

Definition at line 1036 of file AMMWithdraw.cpp.

+

Definition at line 1037 of file AMMWithdraw.cpp.

@@ -1432,7 +1519,7 @@ Static Private Member Functions

Check from the flags if it's withdraw all.

-

Definition at line 1097 of file AMMWithdraw.cpp.

+

Definition at line 1098 of file AMMWithdraw.cpp.

@@ -1461,7 +1548,7 @@ Static Private Member Functions

Process the transaction.

-

Definition at line 1064 of file Transactor.cpp.

+

Definition at line 1145 of file Transactor.cpp.

@@ -1488,7 +1575,7 @@ Static Private Member Functions
-

Definition at line 161 of file Transactor.h.

+

Definition at line 163 of file Transactor.h.

@@ -1515,7 +1602,7 @@ Static Private Member Functions
-

Definition at line 167 of file Transactor.h.

+

Definition at line 169 of file Transactor.h.

@@ -1559,7 +1646,7 @@ Static Private Member Functions
-

Definition at line 361 of file Transactor.cpp.

+

Definition at line 442 of file Transactor.cpp.

@@ -1587,7 +1674,7 @@ Static Private Member Functions
-

Definition at line 433 of file Transactor.cpp.

+

Definition at line 514 of file Transactor.cpp.

@@ -1625,7 +1712,7 @@ Static Private Member Functions
-

Definition at line 261 of file Transactor.cpp.

+

Definition at line 342 of file Transactor.cpp.

@@ -1653,7 +1740,7 @@ Static Private Member Functions
-

Definition at line 581 of file Transactor.cpp.

+

Definition at line 662 of file Transactor.cpp.

@@ -1681,7 +1768,7 @@ Static Private Member Functions
-

Definition at line 638 of file Transactor.cpp.

+

Definition at line 719 of file Transactor.cpp.

@@ -1719,7 +1806,95 @@ Static Private Member Functions
-

Definition at line 233 of file Transactor.cpp.

+

Definition at line 293 of file Transactor.cpp.

+ +
+ + +

◆ invokePreflight() [1/3]

+ +
+
+
+template<class T >
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
+ +

Definition at line 391 of file Transactor.h.

+ +
+
+ +

◆ invokePreflight() [2/3]

+ +
+
+
+template<>
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
+ +

Definition at line 37 of file Change.cpp.

+ +
+
+ +

◆ invokePreflight() [3/3]

+ +
+
+
+template<>
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::invokePreflight (PreflightContext const & ctx)
+
+staticinherited
+
@@ -1757,7 +1932,7 @@ Static Private Member Functions
-

Definition at line 217 of file Transactor.cpp.

+

Definition at line 277 of file Transactor.cpp.

@@ -1807,7 +1982,7 @@ Static Private Member Functions
-

Definition at line 482 of file Transactor.cpp.

+

Definition at line 563 of file Transactor.cpp.

@@ -1834,7 +2009,7 @@ Static Private Member Functions
-

Definition at line 544 of file Transactor.cpp.

+

Definition at line 625 of file Transactor.cpp.

@@ -1863,7 +2038,7 @@ Static Private Member Functions

Reimplemented in ripple::Change, and ripple::SetSignerList.

-

Definition at line 536 of file Transactor.cpp.

+

Definition at line 617 of file Transactor.cpp.

@@ -1930,7 +2105,203 @@ Static Private Member Functions -

Definition at line 251 of file Transactor.cpp.

+

Definition at line 332 of file Transactor.cpp.

+ + + + +

◆ calculateOwnerReserveFee()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
XRPAmount ripple::Transactor::calculateOwnerReserveFee (ReadView const & view,
STTx const & tx 
)
+
+staticprotectedinherited
+
+ +

Definition at line 312 of file Transactor.cpp.

+ +
+
+ +

◆ preflightSigValidated()

+ +
+
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::preflightSigValidated (PreflightContext const & ctx)
+
+staticprotectedinherited
+
+ +

Definition at line 271 of file Transactor.cpp.

+ +
+
+ +

◆ validDataLength()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validDataLength (std::optional< Slice > const & slice,
std::size_t maxLength 
)
+
+staticprotectedinherited
+
+ +

Definition at line 255 of file Transactor.cpp.

+ +
+
+ +

◆ validNumericRange() [1/2]

+ +
+
+
+template<class T >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validNumericRange (std::optional< T > value,
max,
min = {} 
)
+
+staticprotectedinherited
+
+ +

Definition at line 418 of file Transactor.h.

+ +
+
+ +

◆ validNumericRange() [2/2]

+ +
+
+
+template<class T , class Unit >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool ripple::Transactor::validNumericRange (std::optional< T > value,
unit::ValueUnit< Unit, T > max,
unit::ValueUnit< Unit, T > min = {} 
)
+
+staticprotectedinherited
+
+ +

Definition at line 427 of file Transactor.h.

@@ -1967,7 +2338,7 @@ Static Private Member Functions
Returns
A pair containing the transaction result and the actual fee charged.
-

Definition at line 1002 of file Transactor.cpp.

+

Definition at line 1083 of file Transactor.cpp.

@@ -1995,7 +2366,7 @@ Static Private Member Functions
-

Definition at line 463 of file Transactor.cpp.

+

Definition at line 544 of file Transactor.cpp.

@@ -2022,7 +2393,7 @@ Static Private Member Functions
-

Definition at line 326 of file Transactor.cpp.

+

Definition at line 407 of file Transactor.cpp.

@@ -2078,7 +2449,7 @@ Static Private Member Functions
-

Definition at line 685 of file Transactor.cpp.

+

Definition at line 766 of file Transactor.cpp.

@@ -2134,7 +2505,7 @@ Static Private Member Functions
-

Definition at line 746 of file Transactor.cpp.

+

Definition at line 827 of file Transactor.cpp.

@@ -2162,7 +2533,80 @@ Static Private Member Functions
-

Definition at line 1057 of file Transactor.cpp.

+

Definition at line 1138 of file Transactor.cpp.

+ +
+ + +

◆ preflight1()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
NotTEC ripple::Transactor::preflight1 (PreflightContext const & ctx,
std::uint32_t flagMask 
)
+
+staticprivateinherited
+
+ +

Performs early sanity checks on the account and fee fields.

+

(And passes flagMask to preflight0)

+

Do not try to call preflight1 from preflight() in derived classes. See the description of invokePreflight for details.

+ +

Definition at line 163 of file Transactor.cpp.

+ +
+
+ +

◆ preflight2()

+ +
+
+ + + + + +
+ + + + + + + + +
NotTEC ripple::Transactor::preflight2 (PreflightContext const & ctx)
+
+staticprivateinherited
+
+ +

Checks whether the signature appears valid.

+

Do not try to call preflight2 from preflight() in derived classes. See the description of invokePreflight for details.

+ +

Definition at line 226 of file Transactor.cpp.

@@ -2211,7 +2655,7 @@ Static Private Member Functions
-

Definition at line 141 of file Transactor.h.

+

Definition at line 143 of file Transactor.h.

@@ -2235,7 +2679,7 @@ Static Private Member Functions
-

Definition at line 142 of file Transactor.h.

+

Definition at line 144 of file Transactor.h.

@@ -2259,7 +2703,7 @@ Static Private Member Functions
-

Definition at line 143 of file Transactor.h.

+

Definition at line 145 of file Transactor.h.

@@ -2283,7 +2727,7 @@ Static Private Member Functions
-

Definition at line 145 of file Transactor.h.

+

Definition at line 147 of file Transactor.h.

@@ -2307,7 +2751,7 @@ Static Private Member Functions
-

Definition at line 146 of file Transactor.h.

+

Definition at line 148 of file Transactor.h.

@@ -2331,7 +2775,7 @@ Static Private Member Functions
-

Definition at line 147 of file Transactor.h.

+

Definition at line 149 of file Transactor.h.

diff --git a/classripple_1_1AccountSet__test-members.html b/classripple_1_1AccountSet__test-members.html index 4af535523f..233508d35e 100644 --- a/classripple_1_1AccountSet__test-members.html +++ b/classripple_1_1AccountSet__test-members.html @@ -103,25 +103,26 @@ $(function() { suite()beast::unit_test::suite suite(suite const &)=deletebeast::unit_test::suite testBadInputs()ripple::AccountSet_test - testcasebeast::unit_test::suite - testDomain()ripple::AccountSet_test - testEmailHash()ripple::AccountSet_test - testGateway()ripple::AccountSet_test - testMessageKey()ripple::AccountSet_test - testMostFlags()ripple::AccountSet_test - testNullAccountSet()ripple::AccountSet_test - testRequireAuthWithDir()ripple::AccountSet_test - testSetAndResetAccountTxnID()ripple::AccountSet_test - testSetNoFreeze()ripple::AccountSet_test - testTicket()ripple::AccountSet_test - testTransferRate()ripple::AccountSet_test - testWalletID()ripple::AccountSet_test - this_suite()beast::unit_test::suitestatic - unexcept(F &&f, String const &reason)beast::unit_test::suite - unexcept(F &&f)beast::unit_test::suite - unexpected(Condition shouldBeFalse, String const &reason)beast::unit_test::suite - unexpected(Condition shouldBeFalse)beast::unit_test::suite - ~suite()=defaultbeast::unit_test::suitevirtual + testBadSigningKey()ripple::AccountSet_test + testcasebeast::unit_test::suite + testDomain()ripple::AccountSet_test + testEmailHash()ripple::AccountSet_test + testGateway()ripple::AccountSet_test + testMessageKey()ripple::AccountSet_test + testMostFlags()ripple::AccountSet_test + testNullAccountSet()ripple::AccountSet_test + testRequireAuthWithDir()ripple::AccountSet_test + testSetAndResetAccountTxnID()ripple::AccountSet_test + testSetNoFreeze()ripple::AccountSet_test + testTicket()ripple::AccountSet_test + testTransferRate()ripple::AccountSet_test + testWalletID()ripple::AccountSet_test + this_suite()beast::unit_test::suitestatic + unexcept(F &&f, String const &reason)beast::unit_test::suite + unexcept(F &&f)beast::unit_test::suite + unexpected(Condition shouldBeFalse, String const &reason)beast::unit_test::suite + unexpected(Condition shouldBeFalse)beast::unit_test::suite + ~suite()=defaultbeast::unit_test::suitevirtual