Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions include/xrpl/ledger/helpers/CouponHelpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#pragma once

#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/TER.h>

#include <cstdint>

namespace xrpl {

/**
* Settle a holder's accrued coupons on their MPToken.
*
* Adds units * (AccruedPerUnit - CouponIndex) to CouponAccrued, rounded
* once downward to the coupon asset, then advances CouponIndex to
* AccruedPerUnit. Units are MPTAmount + LockedAmount. Increments the
* schedule's ClaimantCount when CouponAccrued becomes non-zero on a
* holder that had none. The caller must view.update() both entries on
* tesSUCCESS.
*/
[[nodiscard]] TER
couponSettleMPToken(SLE::ref schedule, SLE::ref mptoken, beast::Journal j);

/**
* Settle a holder against the schedule of the issuance their MPToken
* belongs to, if that issuance carries lsfMPTCouponSchedule. Does
* nothing when the flag is clear, which is the case for every issuance
* without a coupon schedule.
*
* This is the entry point called from the MPT unit-change helpers.
*/
[[nodiscard]] TER
couponSettleIfScheduled(
ApplyView& view,
SLE::const_ref issuance,
SLE::ref mptoken,
beast::Journal j);

/**
* The units a holder is credited for: MPTAmount + LockedAmount.
*/
[[nodiscard]] std::uint64_t
couponHolderUnits(SLE::const_ref mptoken);

} // namespace xrpl
9 changes: 9 additions & 0 deletions include/xrpl/protocol/Indexes.h
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,15 @@ loan(uint256 const& key)
return {ltLOAN, key};
}

Keylet
couponSchedule(uint192 const& mptIssuanceID) noexcept;

inline Keylet
couponSchedule(uint256 const& scheduleKey)
{
return {ltCOUPON_SCHEDULE, scheduleKey};
}

Keylet
permissionedDomain(AccountID const& account, SeqProxy const& seq) noexcept;

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 @@ -188,7 +188,8 @@ enum LedgerEntryType : std::uint16_t {
LSF_FLAG(lsfMPTCanTrade, 0x00000010) \
LSF_FLAG(lsfMPTCanTransfer, 0x00000020) \
LSF_FLAG(lsfMPTCanClawback, 0x00000040) \
LSF_FLAG(lsfMPTCanHoldConfidentialBalance, 0x00000080)) \
LSF_FLAG(lsfMPTCanHoldConfidentialBalance, 0x00000080) \
LSF_FLAG(lsfMPTCouponSchedule, 0x00000100)) \
\
LEDGER_OBJECT(MPToken, \
LSF_FLAG2(lsfMPTLocked, 0x00000001) \
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 @@ -15,6 +15,7 @@
// Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order.

XRPL_FEATURE(CouponPayments, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(SmartEscrow, Supported::No, VoteBehavior::DefaultNo)
XRPL_FEATURE(LendingProtocolV1_2, Supported::No, VoteBehavior::DefaultNo)
XRPL_FIX (Cleanup3_5_0, Supported::Yes, VoteBehavior::DefaultNo)
Expand Down
29 changes: 29 additions & 0 deletions include/xrpl/protocol/detail/ledger_entries.macro
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,8 @@ LEDGER_ENTRY(ltMPTOKEN, 0x007f, MPToken, mptoken, ({
{sfIssuerEncryptedBalance, SoeOptional},
{sfAuditorEncryptedBalance, SoeOptional},
{sfHolderEncryptionKey, SoeOptional},
{sfCouponAccrued, SoeOptional},
{sfCouponIndex, SoeOptional},
}))

/** A ledger object which tracks Oracle
Expand Down Expand Up @@ -634,6 +636,33 @@ LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({
{sfLoanScale, SoeDefault},
}))

/** A ledger object representing a bond coupon schedule: the issuer's
standing offer of fixed periodic coupon payments per unit of a bond
asset, in a settlement asset. One schedule per (Account, BondAsset).

\sa keylet::couponSchedule
*/
LEDGER_ENTRY(ltCOUPON_SCHEDULE, 0x0091, CouponSchedule, coupon_schedule, ({
{sfPreviousTxnID, SoeRequired},
{sfPreviousTxnLgrSeq, SoeRequired},
{sfOwnerNode, SoeRequired},
{sfOwner, SoeRequired},
{sfAccount, SoeRequired},
{sfMPTokenIssuanceID, SoeRequired},
{sfCouponAsset, SoeRequired},
{sfAccruedPerUnit, SoeDefault},
{sfPoolAmount, SoeDefault},
{sfClaimantCount, SoeDefault},
{sfCouponCount, SoeDefault},
{sfLastCouponTime, SoeOptional},
{sfCouponAmount, SoeOptional},
{sfCouponInterval, SoeOptional},
{sfFirstCouponTime, SoeOptional},
{sfExpiration, SoeOptional},
{sfCallNoticePeriod, SoeOptional},
{sfEarliestCallTime, SoeOptional},
}))

/** A ledger object representing a sponsorship.
\sa keylet::sponsorship
*/
Expand Down
13 changes: 13 additions & 0 deletions include/xrpl/protocol/detail/sfields.macro
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,13 @@ TYPED_SFIELD(sfBytecodeSizeLimit, UINT32, 82)
TYPED_SFIELD(sfGasPrice, UINT32, 83)
TYPED_SFIELD(sfGas, UINT32, 84)
TYPED_SFIELD(sfGasUsed, UINT32, 85)
TYPED_SFIELD(sfCouponInterval, UINT32, 86)
TYPED_SFIELD(sfFirstCouponTime, UINT32, 87)
TYPED_SFIELD(sfCallNoticePeriod, UINT32, 88)
TYPED_SFIELD(sfEarliestCallTime, UINT32, 89)
TYPED_SFIELD(sfLastCouponTime, UINT32, 90)
TYPED_SFIELD(sfClaimantCount, UINT32, 91)
TYPED_SFIELD(sfCouponCount, UINT32, 92)

// 64-bit integers (common)
TYPED_SFIELD(sfIndexNext, UINT64, 1)
Expand Down Expand Up @@ -282,6 +289,11 @@ TYPED_SFIELD(sfLPTokenBalance, AMOUNT, 31)
TYPED_SFIELD(sfFeeAmount, AMOUNT, 32)
TYPED_SFIELD(sfMaxFee, AMOUNT, 33)
TYPED_SFIELD(sfFeeAmountDelta, AMOUNT, 34)
TYPED_SFIELD(sfCouponAmount, AMOUNT, 35)
TYPED_SFIELD(sfAccruedPerUnit, AMOUNT, 36)
TYPED_SFIELD(sfPoolAmount, AMOUNT, 37)
TYPED_SFIELD(sfCouponAccrued, AMOUNT, 38)
TYPED_SFIELD(sfCouponIndex, AMOUNT, 39)

// variable length (common)
TYPED_SFIELD(sfPublicKey, VL, 1)
Expand Down Expand Up @@ -380,6 +392,7 @@ TYPED_SFIELD(sfLockingChainIssue, ISSUE, 1)
TYPED_SFIELD(sfIssuingChainIssue, ISSUE, 2)
TYPED_SFIELD(sfAsset, ISSUE, 3)
TYPED_SFIELD(sfAsset2, ISSUE, 4)
TYPED_SFIELD(sfCouponAsset, ISSUE, 5)

// bridge
TYPED_SFIELD(sfXChainBridge, XCHAIN_BRIDGE, 1)
Expand Down
79 changes: 79 additions & 0 deletions include/xrpl/protocol/detail/transactions.macro
Original file line number Diff line number Diff line change
Expand Up @@ -1134,6 +1134,85 @@ TRANSACTION(ttSPONSORSHIP_SET, 91, SponsorshipSet,
{sfRemainingOwnerCountDelta, SoeOptional},
}))

/** This transaction creates a coupon schedule for a bond asset. */
#if TRANSACTION_INCLUDE
# include <xrpl/tx/transactors/coupon/CouponScheduleCreate.h>
#endif
TRANSACTION(ttCOUPON_SCHEDULE_CREATE, 92, CouponScheduleCreate,
({
.delegable = Delegation::NotDelegable,
.amendment = featureCouponPayments,
}),
({
{sfMPTokenIssuanceID, SoeRequired},
{sfCouponAsset, SoeRequired, SoeMptSupported},
{sfCouponAmount, SoeOptional, SoeMptSupported},
{sfCouponInterval, SoeOptional},
{sfFirstCouponTime, SoeOptional},
{sfExpiration, SoeOptional},
{sfCallNoticePeriod, SoeOptional},
{sfEarliestCallTime, SoeOptional},
}))

/** This transaction exercises the issuer's call option on a callable
coupon schedule by shortening its Expiration. */
#if TRANSACTION_INCLUDE
# include <xrpl/tx/transactors/coupon/CouponScheduleSet.h>
#endif
TRANSACTION(ttCOUPON_SCHEDULE_SET, 93, CouponScheduleSet,
({
.delegable = Delegation::NotDelegable,
.amendment = featureCouponPayments,
}),
({
{sfMPTokenIssuanceID, SoeRequired},
{sfExpiration, SoeRequired},
}))

/** This transaction deletes an empty coupon schedule. */
#if TRANSACTION_INCLUDE
# include <xrpl/tx/transactors/coupon/CouponScheduleDelete.h>
#endif
TRANSACTION(ttCOUPON_SCHEDULE_DELETE, 94, CouponScheduleDelete,
({
.delegable = Delegation::NotDelegable,
.amendment = featureCouponPayments,
}),
({
{sfMPTokenIssuanceID, SoeRequired},
}))

/** This transaction claims settled coupons, delivered from the
schedule's pool. */
#if TRANSACTION_INCLUDE
# include <xrpl/tx/transactors/coupon/CouponClaim.h>
#endif
TRANSACTION(ttCOUPON_CLAIM, 95, CouponClaim,
({
.delegable = Delegation::Delegable,
.amendment = featureCouponPayments,
}),
({
{sfMPTokenIssuanceID, SoeRequired},
{sfAmount, SoeOptional, SoeMptSupported},
}))

/** This transaction declares a coupon: it moves the coupon amount from the
payer's spendable balance into the schedule's pool and advances the
per-unit accumulator. Codes 95 and 96 are retired and not reused. */
#if TRANSACTION_INCLUDE
# include <xrpl/tx/transactors/coupon/CouponPay.h>
#endif
TRANSACTION(ttCOUPON_PAY, 96, CouponPay,
({
.delegable = Delegation::NotDelegable,
.amendment = featureCouponPayments,
}),
({
{sfMPTokenIssuanceID, SoeRequired},
{sfAmount, SoeRequired, SoeMptSupported},
}))

/** This system-generated transaction type is used to update the status of the various amendments.

For details, see: https://xrpl.org/amendments.html
Expand Down
1 change: 1 addition & 0 deletions include/xrpl/protocol/jss.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ JSS(load_factor_local); // out: NetworkOPs
JSS(load_factor_net); // out: NetworkOPs
JSS(load_factor_server); // out: NetworkOPs
JSS(load_fee); // out: LoadFeeTrackImp, NetworkOPs
JSS(coupon_schedule_id); // in: LedgerEntry
JSS(loan_broker_id); // in: LedgerEntry
JSS(loan_seq); // in: LedgerEntry
JSS(local); // out: resource/Logic.h
Expand Down
Loading