Skip to content

Commit

Permalink
invar 1
Browse files Browse the repository at this point in the history
  • Loading branch information
shawnxie999 committed Apr 8, 2024
1 parent c88166e commit 683598d
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 2 deletions.
69 changes: 69 additions & 0 deletions src/ripple/app/tx/impl/InvariantCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <ripple/protocol/SystemParameters.h>
#include <ripple/protocol/TxFormats.h>
#include <ripple/protocol/nftPageMask.h>
#include <ripple/app/misc/AMMHelpers.h>

namespace ripple {

Expand Down Expand Up @@ -800,4 +801,72 @@ ValidClawback::finalize(
return true;
}

void
AMMPoolChecks::visitEntry(
bool,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after)
{
if (after && after->getType() == ltRIPPLE_STATE)
{
trustlineAccts_.emplace_back(after->getFieldAmount(sfHighLimit).getIssuer());
trustlineAccts_.emplace_back(after->getFieldAmount(sfLowLimit).getIssuer());
}

if (after && after->getType() == ltAMM)
ammPools_.emplace_back(std::make_pair((*after)[sfAsset], (*after)[sfAsset2]));
}

bool
AMMPoolChecks::finalize(
STTx const& tx,
TER const result,
XRPAmount const,
ReadView const& view,
beast::Journal const& j)
{
if (!view.rules().enabled(fixAMMInvariants))
return true;

auto getAssetBalance = [&](AccountID const& ammAccount, Issue const& issue) -> STAmount {
if(isXRP(issue.currency))
return view.read(keylet::account(ammAccount))->getFieldAmount(sfBalance);

auto const trustlineSle = view.read(keylet::line(issue.account, ammAccount, issue.currency));
STAmount amount = trustlineSle->getFieldAmount(sfBalance);
if (amount.negative()) amount.negate();

return amount;
};

// auto isAmmAcct = [&](STObject const& sleAcct) -> bool {
// if (sleAcct.isFieldPresent(sfAMMID))
// return true;

// return false;
// }

if (tx.getTxnType() == ttAMM_CREATE && result == tesSUCCESS)
{
if (ammPools_.size() != 1){
JLOG(j.fatal()) << "Invariant failed: only one AMM object can be created.";
return false;
}

auto const ammSle = view.read(keylet::amm(ammPools_[0].first, ammPools_[0].second));
if (!ammSle)
return false;

auto const lptBalance = (*ammSle)[sfLPTokenBalance];
auto const asset1Balance = getAssetBalance((*ammSle)[sfAccount], (*ammSle)[sfAsset]);
auto const asset2Balance = getAssetBalance((*ammSle)[sfAccount], (*ammSle)[sfAsset2]);

if (ammLPTokens(asset1Balance, asset2Balance, lptBalance.issue()) != lptBalance){
JLOG(j.fatal()) << "Invariant failed: LPTokenBalance does not equal to the product of the sqrt of each asset.";
return false;
}
}
return true;
}

} // namespace ripple
24 changes: 23 additions & 1 deletion src/ripple/app/tx/impl/InvariantCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,27 @@ class ValidClawback
beast::Journal const&);
};

class AMMPoolChecks
{
std::vector<AccountID> trustlineAccts_;
std::vector<std::pair<Issue, Issue>> ammPools_;

public:
void
visitEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&);

bool
finalize(
STTx const&,
TER const,
XRPAmount const,
ReadView const&,
beast::Journal const&);
};

// additional invariant checks can be declared above and then added to this
// tuple
using InvariantChecks = std::tuple<
Expand All @@ -432,7 +453,8 @@ using InvariantChecks = std::tuple<
ValidNewAccountRoot,
ValidNFTokenPage,
NFTokenCountTracking,
ValidClawback>;
ValidClawback,
AMMPoolChecks>;

/**
* @brief get a tuple of all invariant checks
Expand Down
3 changes: 2 additions & 1 deletion src/ripple/protocol/Feature.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ namespace detail {
// Feature.cpp. Because it's only used to reserve storage, and determine how
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
// the actual number of amendments. A LogicError on startup will verify this.
static constexpr std::size_t numFeatures = 71;
static constexpr std::size_t numFeatures = 72;

/** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated
Expand Down Expand Up @@ -358,6 +358,7 @@ extern uint256 const fixAMMOverflowOffer;
extern uint256 const featurePriceOracle;
extern uint256 const fixEmptyDID;
extern uint256 const fixXChainRewardRounding;
extern uint256 const fixAMMInvariants;

} // namespace ripple

Expand Down
1 change: 1 addition & 0 deletions src/ripple/protocol/impl/Feature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ REGISTER_FIX (fixAMMOverflowOffer, Supported::yes, VoteBehavior::De
REGISTER_FEATURE(PriceOracle, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX (fixEmptyDID, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX (fixXChainRewardRounding, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX (fixAMMInvariants, Supported::yes, VoteBehavior::DefaultNo);

// The following amendments are obsolete, but must remain supported
// because they could potentially get enabled.
Expand Down

0 comments on commit 683598d

Please sign in to comment.