Skip to content

Commit

Permalink
featureTokenEscrow
Browse files Browse the repository at this point in the history
  • Loading branch information
dangell7 committed Feb 12, 2025
1 parent a079bac commit 67fa360
Show file tree
Hide file tree
Showing 19 changed files with 3,874 additions and 112 deletions.
2 changes: 1 addition & 1 deletion include/xrpl/protocol/Feature.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,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 = 88;
static constexpr std::size_t numFeatures = 89;

/** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated
Expand Down
3 changes: 2 additions & 1 deletion include/xrpl/protocol/LedgerFormats.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ enum LedgerSpecificFlags {
0x10000000, // True, reject new paychans
lsfDisallowIncomingTrustline =
0x20000000, // True, reject new trustlines (only if no issued assets)
// 0x40000000 is available
lsfAllowTokenLocking =
0x40000000, // True, enable token locking
lsfAllowTrustLineClawback =
0x80000000, // True, enable clawback

Expand Down
42 changes: 42 additions & 0 deletions include/xrpl/protocol/STAmount.h
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,48 @@ isXRP(STAmount const& amount)
return amount.native();
}

/** returns true if adding or subtracting results in less than or equal to
* 0.01% precision loss **/
inline bool
isAddable(STAmount const& amt1, STAmount const& amt2)
{
// special case: adding anything to zero is always fine
if (amt1 == beast::zero || amt2 == beast::zero)
return true;

// special case: adding two xrp amounts together.
// this is just an overflow check
if (isXRP(amt1) && isXRP(amt2))
{
XRPAmount A = (amt1.signum() == -1 ? -(amt1.xrp()) : amt1.xrp());
XRPAmount B = (amt2.signum() == -1 ? -(amt2.xrp()) : amt2.xrp());

XRPAmount finalAmt = A + B;
return (finalAmt >= A && finalAmt >= B);
}

static const STAmount one{IOUAmount{1, 0}, noIssue()};
static const STAmount maxLoss{IOUAmount{1, -4}, noIssue()};

STAmount A = amt1;
STAmount B = amt2;

if (isXRP(A))
A = STAmount{IOUAmount{A.xrp().drops(), -6}, noIssue()};

if (isXRP(B))
B = STAmount{IOUAmount{B.xrp().drops(), -6}, noIssue()};

A.setIssue(noIssue());
B.setIssue(noIssue());

STAmount lhs = divide((A - B) + B, A, noIssue()) - one;
STAmount rhs = divide((B - A) + A, B, noIssue()) - one;

return ((rhs.negative() ? -rhs : rhs) + (lhs.negative() ? -lhs : lhs)) <=
maxLoss;
}

// Since `canonicalize` does not have access to a ledger, this is needed to put
// the low-level routine stAmountCanonicalize on an amendment switch. Only
// transactions need to use this switchover. Outside of a transaction it's safe
Expand Down
1 change: 1 addition & 0 deletions include/xrpl/protocol/TER.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ enum TECcodes : TERUnderlyingType {
tecARRAY_TOO_LARGE = 191,
tecLOCKED = 192,
tecBAD_CREDENTIALS = 193,
tecPRECISION_LOSS = 194,
};

//------------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions include/xrpl/protocol/TxFlags.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ constexpr std::uint32_t asfDisallowIncomingCheck = 13;
constexpr std::uint32_t asfDisallowIncomingPayChan = 14;
constexpr std::uint32_t asfDisallowIncomingTrustline = 15;
constexpr std::uint32_t asfAllowTrustLineClawback = 16;
constexpr std::uint32_t asfAllowTokenLocking = 17;

// OfferCreate flags:
constexpr std::uint32_t tfPassive = 0x00010000;
Expand Down
1 change: 1 addition & 0 deletions include/xrpl/protocol/detail/features.macro
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
// If you add an amendment here, then do not forget to increment `numFeatures`
// in include/xrpl/protocol/Feature.h.

XRPL_FEATURE(TokenEscrow, Supported::yes, VoteBehavior::DefaultNo)
// Check flags in Credential transactions
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (FrozenLPTokenTransfer, Supported::yes, VoteBehavior::DefaultNo)
Expand Down
2 changes: 2 additions & 0 deletions include/xrpl/protocol/detail/ledger_entries.macro
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ LEDGER_ENTRY(ltESCROW, 0x0075, Escrow, escrow, ({
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
{sfDestinationNode, soeOPTIONAL},
{sfTransferRate, soeOPTIONAL},
{sfIssuerNode, soeOPTIONAL},
}))

/** A ledger object describing a single unidirectional XRP payment channel.
Expand Down
2 changes: 1 addition & 1 deletion include/xrpl/protocol/detail/transactions.macro
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ TRANSACTION(ttPAYMENT, 0, Payment, ({
/** This transaction type creates an escrow object. */
TRANSACTION(ttESCROW_CREATE, 1, EscrowCreate, ({
{sfDestination, soeREQUIRED},
{sfAmount, soeREQUIRED},
{sfAmount, soeREQUIRED, soeMPTSupported},
{sfCondition, soeOPTIONAL},
{sfCancelAfter, soeOPTIONAL},
{sfFinishAfter, soeOPTIONAL},
Expand Down
1 change: 1 addition & 0 deletions src/libxrpl/protocol/TER.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ transResults()
MAKE_ERROR(tecARRAY_TOO_LARGE, "Array is too large."),
MAKE_ERROR(tecLOCKED, "Fund is locked."),
MAKE_ERROR(tecBAD_CREDENTIALS, "Bad credentials."),
MAKE_ERROR(tecPRECISION_LOSS, "The amounts used by the transaction cannot interact."),

MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),
Expand Down
28 changes: 28 additions & 0 deletions src/test/app/AccountDelete_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,34 @@ class AccountDelete_test : public beast::unit_test::suite
jv[sfOfferSequence.jsonName] = seq;
return jv;
};

bool const withTokenEscrow =
env.current()->rules().enabled(featureTokenEscrow);
if (withTokenEscrow)
{
Account const carol("carol");
auto const USD = gw["USD"];
env.fund(XRP(100000), carol);
env(fset(gw, asfAllowTokenLocking));
env.close();
env.trust(USD(10000), carol);
env.close();
env(pay(gw, carol, USD(100)));
env.close();

std::uint32_t const escrowSeq{env.seq(carol)};
env(escrowCreate(carol, becky, USD(1), env.now() + 2s));
env.close();

env(acctdelete(gw, becky),
fee(acctDelFee),
ter(tecHAS_OBLIGATIONS));
env.close();

env(escrowCancel(becky, carol, escrowSeq));
env.close();
}

env(escrowCancel(becky, alice, escrowSeq));
env.close();

Expand Down
Loading

0 comments on commit 67fa360

Please sign in to comment.