mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
fix(AMM): prevent orphaned objects, inconsistent ledger state: (#4626)
When an AMM account is deleted, the owner directory entries must be
deleted in order to ensure consistent ledger state.
* When deleting AMM account:
* Clean up AMM owner dir, linking AMM account and AMM object
* Delete trust lines to AMM
* Disallow `CheckCreate` to AMM accounts
* AMM cannot cash a check
* Constrain entries in AuthAccounts array to be accounts
* AuthAccounts is an array of objects for the AMMBid transaction
* SetTrust (TrustSet): Allow on AMM only for LP tokens
* If the destination is an AMM account and the trust line doesn't
exist, then:
* If the asset is not the AMM LP token, then fail the tx with
`tecNO_PERMISSION`
* If the AMM is in empty state, then fail the tx with `tecAMM_EMPTY`
* This disallows trustlines to AMM in empty state
* Add AMMID to AMM root account
* Remove lsfAMM flag and use sfAMMID instead
* Remove owner dir entry for ltAMM
* Add `AMMDelete` transaction type to handle amortized deletion
* Limit number of trust lines to delete on final withdraw + AMMDelete
* Put AMM in empty state when LPTokens is 0 upon final withdraw
* Add `tfTwoAssetIfEmpty` deposit option in AMM empty state
* Fail all AMM transactions in AMM empty state except special deposit
* Add `tecINCOMPLETE` to indicate that not all AMM trust lines are
deleted (i.e. partial deletion)
* This is handled in Transactor similar to deleted offers
* Fail AMMDelete with `tecINTERNAL` if AMM root account is nullptr
* Don't validate for invalid asset pair in AMMDelete
* AMMWithdraw deletes AMM trust lines and AMM account/object only if the
number of trust lines is less than max
* Current `maxDeletableAMMTrustLines` = 512
* Check no directory left after AMM trust lines are deleted
* Enable partial trustline deletion in AMMWithdraw
* Add `tecAMM_NOT_EMPTY` to fail any transaction that expects an AMM in
empty state
* Clawback considerations
* Disallow clawback out of AMM account
* Disallow AMM create if issuer can claw back
This patch applies to the AMM implementation in #4294.
Acknowledgements:
Richard Holland and Nik Bougalis for responsibly disclosing this issue.
Bug Bounties and Responsible Disclosures:
We welcome reviews of the project code and urge researchers to
responsibly disclose any issues they may find.
To report a bug, please send a detailed report to:
bugs@xrpl.org
Signed-off-by: Manoj Doshi <mdoshi@ripple.com>
This commit is contained in:
committed by
Manoj Doshi
parent
5530a0b665
commit
58f7aecb0b
@@ -62,8 +62,10 @@ AMM::AMM(
|
||||
, creatorAccount_(account)
|
||||
, asset1_(asset1)
|
||||
, asset2_(asset2)
|
||||
, ammID_(keylet::amm(asset1_.issue(), asset2_.issue()).key)
|
||||
, initialLPTokens_(initialTokens(asset1, asset2))
|
||||
, log_(log)
|
||||
, doClose_(true)
|
||||
, lastPurchasePrice_(0)
|
||||
, bidMin_()
|
||||
, bidMax_()
|
||||
@@ -382,6 +384,7 @@ AMM::deposit(
|
||||
flags,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
ter);
|
||||
}
|
||||
|
||||
@@ -404,6 +407,7 @@ AMM::deposit(
|
||||
flags,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
ter);
|
||||
}
|
||||
|
||||
@@ -417,6 +421,7 @@ AMM::deposit(
|
||||
std::optional<std::uint32_t> const& flags,
|
||||
std::optional<std::pair<Issue, Issue>> const& assets,
|
||||
std::optional<jtx::seq> const& seq,
|
||||
std::optional<std::uint16_t> const& tfee,
|
||||
std::optional<ter> const& ter)
|
||||
{
|
||||
Json::Value jv;
|
||||
@@ -428,6 +433,8 @@ AMM::deposit(
|
||||
asset2In->setJson(jv[jss::Amount2]);
|
||||
if (maxEP)
|
||||
maxEP->setJson(jv[jss::EPrice]);
|
||||
if (tfee)
|
||||
jv[jss::TradingFee] = *tfee;
|
||||
std::uint32_t jvflags = 0;
|
||||
if (flags)
|
||||
jvflags = *flags;
|
||||
@@ -671,7 +678,8 @@ AMM::submit(
|
||||
env_(jv, *ter);
|
||||
else
|
||||
env_(jv);
|
||||
env_.close();
|
||||
if (doClose_)
|
||||
env_.close();
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -697,6 +705,18 @@ AMM::expectAuctionSlot(auto&& cb) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
AMM::ammDelete(AccountID const& deleter, std::optional<ter> const& ter)
|
||||
{
|
||||
Json::Value jv;
|
||||
jv[jss::Account] = to_string(deleter);
|
||||
setTokens(jv);
|
||||
jv[jss::TransactionType] = jss::AMMDelete;
|
||||
if (fee_ != 0)
|
||||
jv[jss::Fee] = std::to_string(fee_);
|
||||
submit(jv, std::nullopt, ter);
|
||||
}
|
||||
|
||||
namespace amm {
|
||||
Json::Value
|
||||
trust(AccountID const& account, STAmount const& amount, std::uint32_t flags)
|
||||
|
||||
@@ -27,22 +27,6 @@ namespace jtx {
|
||||
|
||||
namespace check {
|
||||
|
||||
// Create a check.
|
||||
Json::Value
|
||||
create(
|
||||
jtx::Account const& account,
|
||||
jtx::Account const& dest,
|
||||
STAmount const& sendMax)
|
||||
{
|
||||
Json::Value jv;
|
||||
jv[sfAccount.jsonName] = account.human();
|
||||
jv[sfSendMax.jsonName] = sendMax.getJson(JsonOptions::none);
|
||||
jv[sfDestination.jsonName] = dest.human();
|
||||
jv[sfTransactionType.jsonName] = jss::CheckCreate;
|
||||
jv[sfFlags.jsonName] = tfUniversal;
|
||||
return jv;
|
||||
}
|
||||
|
||||
// Cash a check requiring that a specific amount be delivered.
|
||||
Json::Value
|
||||
cash(jtx::Account const& dest, uint256 const& checkId, STAmount const& amount)
|
||||
|
||||
Reference in New Issue
Block a user