refactor EscrowCreate

This commit is contained in:
Mayukha Vadari
2026-03-22 20:01:18 -07:00
parent 1a822da112
commit e7e48d9bb1
12 changed files with 301 additions and 90 deletions

View File

@@ -28,6 +28,32 @@ public:
return issuance_;
}
MPTIssue
getMptIssue() const
{
return issuance_.getMptIssue();
}
[[nodiscard]] TER
checkSpendable(
STAmount const& amount,
FreezeHandling zeroIfFrozen,
AuthHandling zeroIfUnauthorized,
beast::Journal j) const override
{
STAmount const spendableAmount = accountHolds(zeroIfFrozen, zeroIfUnauthorized, j);
// If the balance is less than or equal to 0, return tecINSUFFICIENT_FUNDS
if (spendableAmount <= beast::zero)
return tecINSUFFICIENT_FUNDS;
// If the spendable amount is less than the amount, return tecINSUFFICIENT_FUNDS
if (!canSubtract(spendableAmount, amount))
return tecINSUFFICIENT_FUNDS;
return tesSUCCESS;
}
protected:
MPTokenIssuance const& issuance_;
};

View File

@@ -46,7 +46,7 @@ public:
}
AccountID const&
getIssuer() const
getIssuer() const override
{
return mptIssue_.getIssuer();
}
@@ -127,6 +127,12 @@ public:
[[nodiscard]] bool
canClawback() const override;
[[nodiscard]] bool
canEscrow() const override
{
return sle_->isFlag(lsfMPTCanEscrow);
}
[[nodiscard]] bool
requiresAuth() const override;
@@ -135,6 +141,8 @@ public:
{
if (!exists())
return tecOBJECT_NOT_FOUND;
if (sle_->getAccountID(sfIssuer) != mptIssue_.getIssuer())
return tecINTERNAL;
return tesSUCCESS;
}
@@ -144,6 +152,17 @@ public:
return readView_.exists(keylet::mptoken(mptID_, holder));
}
[[nodiscard]] TER
checkHolder(AccountID const& holder) const override
{
if (!hasHolder(holder))
return tecOBJECT_NOT_FOUND;
return tesSUCCESS;
}
[[nodiscard]] std::unique_ptr<TokenHolderBase>
getHolder(AccountID const& holder) const override;
STAmount
accountHolds(
AccountID const& account,

View File

@@ -38,6 +38,42 @@ public:
return iouToken_;
}
[[nodiscard]] TER
checkSpendable(
STAmount const& amount,
FreezeHandling zeroIfFrozen,
AuthHandling zeroIfUnauthorized,
beast::Journal j) const override
{
STAmount const balance = (*sle_)[sfBalance];
AccountID const& issuer = iouToken_.getIssuer();
// If balance is positive, issuer must have higher address than account
if (balance > beast::zero && issuer < holder_)
return tecNO_PERMISSION; // LCOV_EXCL_LINE
// If balance is negative, issuer must have lower address than account
if (balance < beast::zero && issuer > holder_)
return tecNO_PERMISSION; // LCOV_EXCL_LINE
STAmount const spendableAmount = accountHolds(zeroIfFrozen, zeroIfUnauthorized, j);
// If the balance is less than or equal to 0, return tecINSUFFICIENT_FUNDS
if (spendableAmount <= beast::zero)
return tecINSUFFICIENT_FUNDS;
// If the spendable amount is less than the amount, return
// tecINSUFFICIENT_FUNDS
if (spendableAmount < amount)
return tecINSUFFICIENT_FUNDS;
// If the amount is not addable to the balance, return tecPRECISION_LOSS
if (!canAdd(spendableAmount, amount))
return tecPRECISION_LOSS;
return tesSUCCESS;
}
protected:
IOUToken const& iouToken_;
};

View File

@@ -38,7 +38,7 @@ public:
}
[[nodiscard]] AccountID const&
getIssuer() const
getIssuer() const override
{
return issuer_;
}
@@ -129,6 +129,12 @@ public:
[[nodiscard]] bool
canClawback() const override;
[[nodiscard]] bool
canEscrow() const override
{
return issuerAccount_->isFlag(lsfAllowTrustLineLocking);
}
[[nodiscard]] bool
requiresAuth() const override;
@@ -146,6 +152,17 @@ public:
return readView_.exists(keylet::line(issuer_, holder, currency_));
}
[[nodiscard]] TER
checkHolder(AccountID const& holder) const override
{
if (!hasHolder(holder))
return tecNO_LINE;
return tesSUCCESS;
}
[[nodiscard]] std::unique_ptr<TokenHolderBase>
getHolder(AccountID const& holder) const override;
protected:
Issue const issue_;
AccountID const issuer_;

View File

@@ -44,15 +44,14 @@ enum class WaiveTransferFee : bool { No = false, Yes };
*/
enum class AuthType { StrongAuth, WeakAuth, Legacy };
//------------------------------------------------------------------------------
//
// Freeze checking (Asset-based dispatchers)
//
//------------------------------------------------------------------------------
class TokenHolderBase;
class TokenBase : public virtual ReadOnlySLE
{
public:
[[nodiscard]] virtual AccountID const&
getIssuer() const = 0;
[[nodiscard]] virtual bool
isGlobalFrozen() const = 0;
@@ -153,6 +152,9 @@ public:
[[nodiscard]] virtual bool
canClawback() const = 0;
[[nodiscard]] virtual bool
canEscrow() const = 0;
/** Check if the token requires authorization for holders.
* For IOUs, checks lsfRequireAuth on issuer's AccountRoot.
* For MPTs, checks lsfMPTRequireAuth on the issuance.
@@ -166,6 +168,12 @@ public:
[[nodiscard]] virtual bool
hasHolder(AccountID const& holder) const = 0;
[[nodiscard]] virtual TER
checkHolder(AccountID const& holder) const = 0;
[[nodiscard]] virtual std::unique_ptr<TokenHolderBase>
getHolder(AccountID const& holder) const = 0;
protected:
TokenBase(ReadView const& view, std::shared_ptr<SLE const> sle) : ReadOnlySLE(sle, view)
{

View File

@@ -88,6 +88,13 @@ public:
holder_, zeroIfFrozen, zeroIfUnauthorized, j, includeFullBalance);
}
[[nodiscard]] virtual TER
checkSpendable(
STAmount const& amount,
FreezeHandling zeroIfFrozen,
AuthHandling zeroIfUnauthorized,
beast::Journal j) const = 0;
[[nodiscard]] TER
requireAuth(AuthType authType = AuthType::Legacy, int depth = 0) const
{

View File

@@ -11,6 +11,7 @@
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STBase.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/protocol/json_get_or_throw.h>
@@ -739,6 +740,9 @@ canAdd(STAmount const& amt1, STAmount const& amt2);
bool
canSubtract(STAmount const& amt1, STAmount const& amt2);
NotTEC
checkAmount(STAmount const& amount);
} // namespace xrpl
//------------------------------------------------------------------------------