diff --git a/docs/_snippets/common-links.md b/docs/_snippets/common-links.md index c4368a1..907a6b4 100644 --- a/docs/_snippets/common-links.md +++ b/docs/_snippets/common-links.md @@ -1,4 +1,5 @@ [ACCOUNT_ZERO]: https://xrpl.org/docs/concepts/accounts/addresses#special-addresses +[AccountID]: https://xrpl.org/docs/references/protocol/binary-format/#accountid-fields [AccountDelete]: https://xrpl.org/docs/references/protocol/transactions/types/accountdelete [Address]: https://xrpl.org/docs/references/protocol/data-types/basic-data-types#addresses [amendment]: https://xrpl.org/docs/concepts/networks-and-servers/amendments @@ -6,6 +7,7 @@ [common ledger entry fields]: https://xrpl.org/docs/references/protocol/ledger-data/common-fields/ [credentials]: https://xrpl.org/docs/concepts/decentralized-storage/credentials [EscrowFinish]: https://xrpl.org/docs/references/protocol/transactions/types/escrowfinish +[`flags` field]: https://xrpl.org/docs/references/protocol/transactions/common-fields#flags-field [Hash]: https://xrpl.org/docs/references/protocol/data-types/basic-data-types#hashes [Internal Type]: https://xrpl.org/docs/references/protocol/binary-format/ [ledger entry ID]: https://xrpl.org/docs/references/protocol/ledger-data/common-fields/ @@ -14,6 +16,9 @@ [ledger index]: https://xrpl.org/docs/references/protocol/data-types/basic-data-types/#ledger-index [PaymentChannelClaim]: https://xrpl.org/docs/references/protocol/transactions/types/paymentchannelclaim [Payment]: https://xrpl.org/docs/references/protocol/transactions/types/payment +[PermissionedDomain entry]: /docs/xls-80d-permissioned-domains/permissioneddomain.md +[PermissionedDomainSet transaction]: /docs/xls-80d-permissioned-domains/permissioneddomainset.md +[PermissionedDomainDelete transaction]: /docs/xls-80d-permissioned-domains/permissioneddomaindelete.md [reserve requirement]: https://xrpl.org/docs/concepts/accounts/reserves [seconds since the Ripple Epoch]: https://xrpl.org/docs/references/protocol/data-types/basic-data-types#specifying-time [SHA-512Half]: https://xrpl.org/docs/references/protocol/data-types/basic-data-types#hashes @@ -21,12 +26,8 @@ [standard format]: https://xrpl.org/docs/references/http-websocket-apis/api-conventions/response-formatting/ [transaction result codes]: https://xrpl.org/docs/references/protocol/transactions/transaction-results [universal error types]: https://xrpl.org/docs/references/http-websocket-apis/api-conventions/error-formatting#universal-errors - -[PermissionedDomain entry]: /docs/xls-80d-permissioned-domains/permissioneddomain.md -[PermissionedDomainSet transaction]: /docs/xls-80d-permissioned-domains/permissioneddomainset.md -[PermissionedDomainDelete transaction]: /docs/xls-80d-permissioned-domains/permissioneddomaindelete.md -[PermissionedDomains amendment]: /docs/xls-80d-permissioned-domains/index.page.tsx -[Single Asset Vault amendment]: https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0065d-single-asset-vault - +[Lending Protocol amendment]: https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0066d-lending-protocol [PermissionedDEX amendment]: /docs/xls-81d-permissioned-dexes/index.page.tsx +[PermissionedDomains amendment]: /docs/xls-80d-permissioned-domains/index.page.tsx +[Single Asset Vault amendment]: https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0065-single-asset-vault diff --git a/docs/xls-66d-lending-protocol/concepts/lending-protocol-diagram.svg b/docs/xls-66d-lending-protocol/concepts/lending-protocol-diagram.svg new file mode 100644 index 0000000..dbec030 --- /dev/null +++ b/docs/xls-66d-lending-protocol/concepts/lending-protocol-diagram.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/xls-66d-lending-protocol/concepts/lending-protocol.md b/docs/xls-66d-lending-protocol/concepts/lending-protocol.md new file mode 100644 index 0000000..be6917c --- /dev/null +++ b/docs/xls-66d-lending-protocol/concepts/lending-protocol.md @@ -0,0 +1,198 @@ +--- +seo: + description: The XRPL Lending Protocol enables on-chain, uncollateralized fixed-term loans. +labels: + - Decentralized Finance + - Lending Protocol +--- +# Lending Protocol + +The Lending Protocol is an XRP Ledger DeFi primitive that enables on-chain, fixed-term, uncollateralized loans using pooled funds from a [Single Asset Vault](https://opensource.ripple.com/docs/xls-65d-single-asset-vault). The protocol is highly configurable, enabling loan brokers to easily tune risk appetite, depostitor protections, and economic incentives. + +The implementation relies on off-chain underwriting and risk management to assess the creditworthiness of borrowers, but offers peer-to-peer loans without intermediaries like banks or financial institutions. First-loss capital protection is used to help offset losses from loan defaults. + +The current implementation of the lending protocol doesn't include automated on-chain collateral and liquidation management, instead focusing on on-chain credit origination. + +To ensure compliance needs are met, asset issuers can [claw back](https://xrpl.org/docs/references/protocol/transactions/types/clawback) funds from the vault associated with the lending protocol. Issuers can also [freeze](https://xrpl.org/docs/concepts/tokens/fungible-tokens/freezes) individual accounts or issue a global freeze. + +## Protocol Flow + +There are three parties involved in the process of creating a loan: + +- **Loan Brokers**: Create asset vaults and manage associated loans. +- **Depositors**: Add assets to vaults. +- **Borrowers**: Receive loans, making repayments as defined by their loan terms. + +[{% inline-svg file="./lending-protocol-diagram.svg" /%}](./lending-protocol-diagram.svg "Diagram: The lifecycle of a loan.") + +The lifecycle of a loan is as follows: + +1. A loan broker creates a vault. +2. Depositors add assets to the vault. +3. (Optional) The loan broker deposits first-loss capital. +4. A loan broker and borrower create a loan, defining the terms of the loan, and the requested principal (excluding fees) is transferred to the borrower. +5. If payments are missed, the loan enters a grace period. Once the grace period expires, the loan broker has the option to default the loan. +6. The loan is deleted when matured or defaulted. +7. (Optional) The loan broker can withdraw first-loss capital. +8. After all loans are paid, the loan broker can delete the `LoanBroker` ledger entry, and then the corresponding `Vault` ledger entry. + + +## Accounting + +### Risk Management + +#### First-Loss Capital + +First-Loss Capital is an optional mechanism to mitigate the risks associated with lending. To protect investors' assets, a loan broker can deposit assets as first-loss capital, which acts as a buffer in the event of loan defaults. The first-loss capital is placed into the vault to cover a percentage of losses from missed payments. + +Three parameters control the First-Loss Capital: + +- `CoverAvailable`: The total amount of cover deposited by the lending protocol owner. +- `CoverRateMinimum`: The percentage of debt that must be covered by `CoverAvailable`. +- `CoverRateLiquidation`: The maximum percentage of the minimum required cover _(DebtTotal x CoverRateMinimum)_ that will be placed in the asset vault to cover a loan default. + +Whenever the available cover falls below the minimum required: + +- The loan broker can't issue new loans. +- The loan broker can't receive fees. All fees are added to the First-Loss Capital to cover the deficit. + +Below is an example of how first-loss capital is used to cover a loan default: + +``` +** Initial States ** + +-- Vault -- +AssetsTotal = 100,090 Tokens +AssetsAvailable = 99,000 Tokens +SharesTotal = 100,000 Tokens + +-- Lending Protocol -- +DebtTotal = 1,090 Tokens +CoverRateMinimum = 0.1 (10%) +CoverRateLiquidation = 0.1 (10%) +CoverAvailable = 1,000 Tokens + +-- Loan -- +AssetsAvailable = 500 Tokens +PrincipleOutstanding = 1,000 Tokens +InterestOutstanding = 90 Tokens + + +# First-Loss Capital liquidation maths + +DefaultAmount = PrincipleOutstanding + InterestOutstanding - AssetsAvailable + = 1,000 + 90 - 500 + = 590 + +# The amount of the default that the first-loss capital scheme will cover +DefaultCovered = min((DebtTotal x CoverRateMinimum) x CoverRateLiquidation, DefaultAmount) + = min((1,090 * 0.1) * 0.1, 1,090) = min(10.9, 590) + = 10.9 Tokens + +Loss = DefaultAmount - DefaultCovered + = 590 - 10.9 + = 579.1 Tokens + +FundsReturned = DefaultCovered + AssetsAvailable + = 10.9 + 500 + = 510.9 + +# Note: Loss + FundsReturned MUST be equal to PrincipleOutstanding + InterestOutstanding + +** State Changes ** + +-- Vault -- +AssetsTotal = AssetsTotal - Loss + = 100,090 - 579.1 + = 99,510.9 Tokens + +AssetsAvailable = AssetsAvailable + FundsReturned + = 99,000 + 510.9 + = 99,510.9 Tokens + +SharesTotal = (UNCHANGED) + +-- Lending Protocol -- +DebtTotal = DebtTotal - PrincipleOutstanding + InterestOutstanding + = 1,090 - (1,000 + 90) + = 0 Tokens + +CoverAvailable = CoverAvailable - DefaultCovered + = 1,000 - 10.9 + = 989.1 Tokens +``` + +#### Impairment + +If the loan broker discovers a borrower can't make an upcoming payment, impairment allows the loan broker to register a "paper loss" with the vault. The impairment mechanism moves the due date of the next payment to the time the loan is impaired, allowing the loan to default more quickly. However, if the borrower makes a payment before that date, the impairment status is automatically cleared. + + +### Compliance + +#### Clawback + +Issuers (trust line token or MPT, not XRP) can claw back funds from First-Loss Capital. To ensure there is always a minimum amount of capital available to protect depositors, issuers can't claw back the entire available amount. Instead, they can claw back up to a minimum amount of First-Loss Capital that the loan broker must maintain for the lending protocol; the minimum amount is calculated as `LoanBroker.DebtTotal * LoanBroker.CoverRateMinimum`. + +#### Freeze + +Freezing is a mechanism by which an asset issuer (trust line token or MPT, not XRP) prevents an account from sending their issued asset. _Deep freeze_ takes this a step further by preventing an account from sending _and_ receiving issued assets. Issuers can also enact a _global freeze_, which prevents everyone from sending or receiving their issued asset. + +{% admonition type="info" name="Note" %} +In all freeze scenarios, assets can be sent back to the issuer. +{% /admonition %} + +If a borrower has their account frozen or deep frozen, they can't make loan payments. This doesn't absolve a borrower of their repayment obligations, and they will eventually default on their loan. + +Freezing a borrower's account won't affect a loan broker's functions, but it will prevent them from receiving any lending protocol fees. However, issuers can freeze a loan broker's _pseudo-account_ and prevent the loan broker from creating new loans; existing loans won't be affected. A deep freeze on a loan broker's _pseudo-account_ also prevents loans from being repaid. + + +### Interest Rates + +There are three interest rates associated with a loan: + +- **Interest Rate**: The regular interest rate based on the principal amount. It is the cost of borrowing funds. +- **Late Interest Rate**: A higher interest rate charged for a late payment. +- **Full Payment Rate**: An interest rate charged for repaying the total loan early. + + +### Fees + +The lending protocol charges a number of fees that the loan broker can configure. The protocol won't charge these fees if the loan broker hasn't deposited enough first-loss capital. + +- **Management Fee**: This is a percentage of interest charged by the loan broker. Vault depositors pay this fee. +- **Loan Origination Fee**: A fee paid to the loan broker, taken from the principal amount loaned out. +- **Loan Service Fee**: A fee charged on top of each loan payment. +- **Late Payment Fee**: A fee paid on top of a late payment. +- **Early Payment Fee**: A fee paid on top of an early payment. + + +## Loan Payment Processing + +Loan payments are evaluated and processed around three criteria: amount, timing, and specified flags. The combination of these criteria determine how funds are applied to the loan's principal, interest, and associated fees. + +Each payment consists of three components: + +- **Principal**: The portion that reduces the outstanding loan principle. +- **Interest**: The portion that covers the cost of borrowing for the period. +- **Fees**: The portion that covers any applicable service fees, management fees, late payment fees, or other charges. + +When the loan payment is submitted, the lending protocol then checks these parameters: + +- **Timing**: Is the payment on time or late? +- **Amount**: Does the payment amount meet the minimum required amount, or exceed it? + +Based on the timing and transaction flags, the lending protocol processes the payment as one of four types: + +- **On-Time Payments**: If the payment is on-time, it's further classified into these payment scenarios: + - **Sequential Periodic Payments**: The payment is applied to as many complete payment cycles as possible; cycles are calculated as the amount due each payment period (including fees). + - **Overpayments**: After all possible cycles are fully paid, any remaining amount is treated as an overpayment and applied to the principal. This type of payment requires the `lsfLoanOverpayment` flag to be enabled on the `Loan` ledger entry, as well as the `tfLoanOverpayment` flag to be enabled on the `LoanPay` transaction. If these flags are missing, the excess amount is ignored. + - **Full Early Repayment**: The payment has the `tfLoanFullPayment` flag set, and the amount covers the remainder of the loan (including fees). +- **Late Payments**: The payment is late on a payment cycle. Late payments must be for an exact amount, calculated as: + + `totalDue = periodicPayment + loanServiceFee + latePaymentFee + latePaymentInterest` + + Overpayments aren't permitted on late payments; any excess amount is ignored. + +{% admonition type="info" name="Note" %} +In scenarios where excess payment amounts are "ignored", the transaction succeeds, but the borrower is only charged on the expected amount. +{% /admonition %} diff --git a/docs/xls-66d-lending-protocol/index.page.tsx b/docs/xls-66d-lending-protocol/index.page.tsx new file mode 100644 index 0000000..2f0aef6 --- /dev/null +++ b/docs/xls-66d-lending-protocol/index.page.tsx @@ -0,0 +1,106 @@ +import * as React from "react"; +import { + LandingContainer, + LandingLayout, + FeatureHeader, + FeatureContent +} from "../../components/landing"; +import { AmendmentTracker } from "../../components/AmendmentTracker"; +import { Button } from "@redocly/theme"; +import { Card } from "@redocly/theme/markdoc/components/Cards/Card"; +import { Cards } from "@redocly/theme/markdoc/components/Cards/Cards"; + +export const frontmatter = { + seo: { + title: "XLS-66d Lending Protocol", + description: "An XRP Ledger DeFi primitive that enables loans from a Single Asset Vault." + }, +}; + +export default function Page() { + const KEY_DATE_EVENTS = [ + "XLS Spec Live", + "Available to Test on Devnet", + "Open for Voting on Mainnet", + "Vote Consensus" + ]; + + const [keyDates, setKeyDates] = React.useState( + KEY_DATE_EVENTS.map(event => ({ date: "🔄 Loading...", event })) + ); + + const handleKeyDatesUpdate = React.useCallback((newKeyDates: any[]) => { + setKeyDates(newKeyDates); + }, []); + + return ( + + + + + + + + + + +

+ Technical spec for the feature outlining requirements, design, + and implementation details. +

+ +
+ + +

+ Explore key concepts, find detailed references, and follow + step-by-step tutorials. +

+ +
+
+ + +

+ An overview of the feature and why it matters to developers, explained in our blog post. +

+ +
+ +

+ The security audit performed by third-party security experts, including a link to the full, detailed security audit report. +

+ +
+
+
+
+ ); +} diff --git a/docs/xls-66d-lending-protocol/reference/ledger-data/loan.md b/docs/xls-66d-lending-protocol/reference/ledger-data/loan.md new file mode 100644 index 0000000..576ca2d --- /dev/null +++ b/docs/xls-66d-lending-protocol/reference/ledger-data/loan.md @@ -0,0 +1,120 @@ +--- +seo: + description: A Loan ledger entry represents the terms of a loan between a borrower and loan issuer. +labels: + - Decentralized Finance + - Lending Protocol +--- + +# Loan + +A `Loan` ledger entry defines the state of an on-chain loan agreement between a _Loan Broker_ and a _Borrower_. It contains all the details of the loan, such as fees and interest rates. You can create a `Loan` ledger entry with the [`LoanSet`](../transactions/loanset.md) transaction. + +The `Loan` ledger entry is tracked in two [Owner Directories](https://xrpl.org/directorynode.html): +1. The owner directory of the _Borrower_ on the loan. +2. The owner directory of the `LoanBroker` pseudo-account. + +_(Requires the [Lending Protocol amendment][] {% not-enabled /%})_ + + +## Example {% $frontmatter.seo.title %} JSON + +```json +{ + "LedgerEntryType": "Loan", + "LedgerIndex": "E123F4567890ABCDE123F4567890ABCDEF1234567890ABCDEF1234567890ABCD", + "Flags": "0", + "PreviousTxnID": "9A8765B4321CDE987654321CDE987654321CDE987654321CDE987654321CDE98", + "PreviousTxnLgrSeq": 12345678, + "LoanSequence": 1, + "OwnerNode": 2, + "LoanBrokerNode": 1, + "LoanBrokerID": "ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890", + "Borrower": "rEXAMPLE9AbCdEfGhIjKlMnOpQrStUvWxYz", + "LoanOriginationFee": 100, + "LoanServiceFee": 10, + "LatePaymentFee": 5, + "ClosePaymentFee": 20, + "OverpaymentFee": 5, + "InterestRate": 500, + "LateInterestRate": 1000, + "CloseInterestRate": 200, + "OverpaymentInterestRate": 5, + "StartDate": 1234567890, + "PaymentInterval": 2592000, + "GracePeriod": 604800, + "PreviousPaymentDueDate": 1234587890, + "NextPaymentDueDate": 1234597890, + "PaymentRemaining": 12, + "PrincipalOutstanding": 10000, + "TotalValueOutstanding": 12000, + "ManagementFeeOutstanding": 2000, + "PeriodicPayment": 1000 +} +``` + +## {% $frontmatter.seo.title %} Fields + +In addition to the [common ledger entry fields][], {% code-page-name /%} entries have the following fields: + +| Name | JSON Type | Internal Type | Required? | Description | +| :-------------------- | :-------- | :------------ | :-------- | :-----------| +| `PreviousTxnID` | String | Hash256 | Yes | Identifies the transaction ID that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The sequence of the ledger that contains the transaction that most recently modified this object. | +| `LoanSequence` | Number | UInt32 | Yes | The sequence number of the loan. | +| `OwnerNode` | Number | UInt64 | Yes | Identifies the page where this item is referenced in the owner's directory. | +| `LoanBrokerNode` | Number | UInt64 | Yes | Identifies the page where this item is referenced in the `LoanBroker` owner directory. | +| `LoanBrokerID` | String | Hash256 | Yes | The ID of the _Loan Broker_ associated with this loan. | +| `Borrower` | String | AccountID | Yes | The account address of the _Borrower_. | +| `LoanOriginationFee` | Number | Number | Yes | The amount paid to the _Loan Broker_, taken from the principal loan at creation. | +| `LoanServiceFee` | Number | Number | Yes | The amount paid to the _Loan Broker_ with each loan payment. | +| `LatePaymentFee` | Number | Number | Yes | The amount paid to the _Loan Broker_ for each late payment. | +| `ClosePaymentFee` | Number | Number | Yes | The amount paid to the _Loan Broker_ when a full early payment is made. | +| `OverpaymentFee` | Number | UInt32 | Yes | The fee charged on overpayments, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. | +| `InterestRate` | Number | UInt32 | Yes | The annualized interest rate of the loan, in 1/10th basis points. | +| `LateInterestRate` | Number | UInt32 | Yes | The premium added to the interest rate for late payments, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. | +| `CloseInterestRate` | Number | UInt32 | Yes | The interest rate charged for repaying the loan early, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. | +| `OverpaymentInterestRate` | Number | UInt32 | Yes | The interest rate charged on overpayments, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. | +| `StartDate` | Number | UInt32 | Yes | The timestamp of when the loan started, in [seconds since the Ripple Epoch][]. | +| `PaymentInterval` | Number | UInt32 | Yes | The number of seconds between loan payments. | +| `GracePeriod` | Number | UInt32 | Yes | The number of seconds after a loan payment is due before the loan defaults. | +| `PreviousPaymentDueDate` | Number | UInt32 | Yes | The timestamp of when the previous payment was made, in [seconds since the Ripple Epoch][]. | +| `NextPaymentDueDate` | Number | UInt32 | Yes | The timestamp of when the next payment is due, in [seconds since the Ripple Epoch][]. | +| `PaymentRemaining` | Number | UInt32 | Yes | The number of payments remaining on the loan. | +| `PrincipalOutstanding` | Number | Number | Yes | The principal amount still owed on the loan. | +| `TotalValueOutstanding` | Number | Number | Yes | The total amount owed on the loan, including remaining principal and fees. | +| `ManagementFeeOutstanding` | Number | Number | Yes | The remaining management fee owed to the loan broker. | +| `PeriodicPayment` | Number | Number | Yes | The amount due for each payment interval. | +| `LoanScale` | Number | Int32 | No | The scale factor that ensures all computed amounts are rounded to the same number of decimal places. It is based on the total loan value at creation time. | + +{% admonition type="info" name="Note" %} +When the loan broker discovers that the borrower can't make an upcoming payment, they can impair the loan to register a "paper loss" with the vault. The impairment mechanism moves up the `NextPaymentDueDate` to the time the loan is impaired, allowing the loan to default quicker. However, if the borrower makes a payment in the subsequent `GracePeriod`, the impairment status is removed. +{% /admonition %} + + +## {% $frontmatter.seo.title %} Flags + +{% code-page-name /%} entries can have the following flags: + +| Field Name | Hex Value | Decimal Value | Description | +|:---------------------|:-------------|:--------------|:------------| +| `lsfLoanDefault` | `0x00010000` | `65536` | Indicates the loan is defaulted. | +| `lsfLoanImpaired` | `0x00020000` | `131072` | Indicates the loan is impaired. | +| `lsfLoanOverpayment` | `0x00040000` | `262144` | Indicates the loan supports overpayments. | + + +## {% $frontmatter.seo.title %} Reserve + +`Loan` entries incur one owner reserve from the borrower. + + +## {% $frontmatter.seo.title %} ID Format + +The ID of a `Loan` ledger entry is the [SHA-512Half][] of the following values, concatenated in order: + +- The `Loan` space key `0x004C`. +- The [AccountID][] of the Borrower account. +- The `LoanBrokerID` of the associated `LoanBroker` ledger entry. +- The `LoanSequence` number of the `LoanBroker` ledger entry. + +{% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/xls-66d-lending-protocol/reference/ledger-data/loanbroker.md b/docs/xls-66d-lending-protocol/reference/ledger-data/loanbroker.md new file mode 100644 index 0000000..0b00581 --- /dev/null +++ b/docs/xls-66d-lending-protocol/reference/ledger-data/loanbroker.md @@ -0,0 +1,91 @@ +--- +seo: + description: A LoanBroker ledger entry represents the configuration and state of a lending protocol instance. +labels: + - Decentralized Finance + - Lending Protocol +--- +# LoanBroker + +A `LoanBroker` ledger entry defines the configuration and state of a lending protocol instance. It tracks details such as fees and first-loss capital cover. You can create a `LoanBroker` object with the [`LoanBrokerSet`](../transactions/loanbrokerset.md) transaction. + +The `LoanBroker` entry is tracked in an [Owner Directory](https://xrpl.org/directorynode.html) owned by the account that submitted the `LoanBrokerSet` transaction. To facilitate lookup, it is also tracked in the `OwnerDirectory` of the associated vault's _pseudo-account_. + +{% admonition type="info" name="Note" %} +The lending protocol uses the pseudo-account of the associated `Vault` entry to hold the first-loss capital. +{% /admonition %} + +_(Requires the [Lending Protocol amendment][] {% not-enabled /%})_ + +## Example {% $frontmatter.seo.title %} JSON + +```json +{ + "LedgerEntryType": "LoanBroker", + "LedgerIndex": "E123F4567890ABCDE123F4567890ABCDEF1234567890ABCDEF1234567890ABCD", + "Flags": "0", + "PreviousTxnID": "9A8765B4321CDE987654321CDE987654321CDE987654321CDE987654321CDE98", + "PreviousTxnLgrSeq": 12345678, + "Sequence": 1, + "LoanSequence": 2, + "OwnerNode": 2, + "VaultNode": 1, + "VaultID": "ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890", + "Account": "rBROKER9AbCdEfGhIjKlMnOpQrStUvWxYz", + "Owner": "rEXAMPLE9AbCdEfGhIjKlMnOpQrStUvWxYz", + "Data": "5468697320697320617262697472617279206D657461646174612061626F757420746865206C6F616E62726F6B65722E", + "ManagementFeeRate": 100, + "OwnerCount": 3, + "DebtTotal": 50000, + "DebtMaximum": 100000, + "CoverAvailable": 10000, + "CoverRateMinimum": 1000, + "CoverRateLiquidation": 500 +} +``` + + +## {% $frontmatter.seo.title %} Fields + +In addition to the [common ledger entry fields][], {% code-page-name /%} entries have the following fields: + +| Name | JSON Type | Internal Type | Required? | Description | +| :-------------------- | :-------- | :------------ | :-------- | :-----------| +| `PreviousTxnID` | String | Hash256 | Yes | Identifies the transaction ID that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The sequence of the ledger that contains the transaction that most recently modified this object. | +| `Sequence` | Number | UInt32 | Yes | The transaction sequence number that created the LoanBroker. | +| `LoanSequence` | Number | UInt32 | Yes | A sequential identifier for `Loan` ledger entires, incremented each time a new loan is created by this `LoanBroker`. | +| `OwnerNode` | Number | UInt64 | Yes | Identifies the page where this item is referenced in the owner's directory. | +| `VaultNode` | Number | UInt64 | Yes | Identifies the page where this item is referenced in the `Vault` pseudo-account owner's directory. | +| `VaultID` | String | Hash256 | Yes | The ID of the vault that provides the loaned assets. | +| `Account` | String | AccountID | Yes | The address of the `LoanBroker` pseudo-account. | +| `Owner` | String | AccountID | Yes | The account address of the vault owner. | +| `Data` | String | Blob | No | Arbitrary metadata about the vault. Limited to 256 bytes. | +| `ManagementFeeRate` | Number | UInt16 | No | The fee charged by the lending protocol, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. | +| `OwnerCount` | Number | UInt32 | Yes | The number of active loans issued by the LoanBroker. | +| `DebtTotal` | Number | Number | Yes | The total asset amount the protocol owes the vault, including interest. | +| `DebtMaximum` | Number | Number | Yes | The maximum amount the protocol can owe the vault. The default value of `0` means there is no limit to the debt. | +| `CoverAvailable` | Number | Number | Yes | The total amount of first-loss capital deposited into the lending protocol. | +| `CoverRateMinimum` | Number | UInt32 | Yes | The 1/10th basis point of the `DebtTotal` that the first-loss capital must cover. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. | +| `CoverRateLiquidation`| Number | UInt12 | Yes | The 1/10th basis point of minimum required first-loss capital that is moved to an asset vault to cover a loan default. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. | + + +## {% $frontmatter.seo.title %} Flags + +There are no flags defined for {% code-page-name /%} ledger entries. + + +## {% $frontmatter.seo.title %} Reserve + +`Loan` entries incur one owner reserve from the account that creates it. + + +## {% $frontmatter.seo.title %} ID Format + +The ID of a `LoanBroker` entry is the [SHA512-Half][] of the following values, concatenated in order: + +- The `LoanBroker` space key `0x006C`. +- The [AccountID][] of the account submitting the `LoanBrokerSet` transaction. +- The transaction `Sequence` number. If the transaction used a [Ticket][], the `TicketSequence` value is used instead. + +{% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/xls-66d-lending-protocol/reference/transactions/loanbrokercoverclawback.md b/docs/xls-66d-lending-protocol/reference/transactions/loanbrokercoverclawback.md new file mode 100644 index 0000000..1b6f8df --- /dev/null +++ b/docs/xls-66d-lending-protocol/reference/transactions/loanbrokercoverclawback.md @@ -0,0 +1,60 @@ +--- +seo: + description: Claw back first-loss capital from a `LoanBroker` ledger entry. +labels: + - Transactions + - Lending Protocol +--- +# LoanBrokerCoverClawback +[[Source]](https://github.com/XRPLF/rippled/blob/ximinez/lending-XLS-66/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp "Source") + +The `LoanBrokerCoverClawback` transaction claws back first-loss capital from a `LoanBroker` ledger entry. The transaction can only be submitted by the issuer of the asset used in the lending protocol, and can't clawback an amount that would cause the available first-loss capital to drop below the minimum amount defined by the `LoanBroker.CoverRateMinimum` value. + +_(Requires the [Lending Protocol amendment][] {% not-enabled /%})_ + + +## Example {% $frontmatter.seo.title %} JSON + +```json +{ + "TransactionType": "LoanBrokerCoverClawback", + "Account": "rEXAMPLE9AbCdEfGhIjKlMnOpQrStUvWxYz", + "Fee": "12", + "Flags": 0, + "LastLedgerSequence": 7108682, + "Sequence": 8, + "LoanBrokerID": "E123F4567890ABCDE123F4567890ABCDEF1234567890ABCDEF1234567890ABCD", + "Amount": { + "currency": "USD", + "issuer": "rIssuer1234567890abcdef1234567890abcdef", + "value": "1000" + } +} +``` + + +## {% $frontmatter.seo.title %} Fields + +In addition to the [common fields][], {% code-page-name /%} transactions use the following fields: + +| Field Name | JSON Type | Internal Type | Required? | Description | +|:-------------- |:----------|:--------------|:----------|:------------| +| `LoanBrokerID` | String | Hash256 | No | The ID of the `LoanBroker` ledger entry to clawback first-loss capital. Must be provided if `Amount` is an MPT, or `Amount` is an IOU and the specified `issuer` matches the `Account` submitting the transaction. | +| `Amount` | Object | Amount | No | The amount of first-loss capital to claw back. If the value is `0` or empty, claw back all assets down to the minimum cover (`DebtTotal * CoverRateMinimum`). | + + +## Error Cases + +Besides errors that can occur for all transactions, {% code-page-name /%} transactions can result in the following [transaction result codes][]: + +| Error Code | Description | +| :----------------------- | :----------------------------------| +| `temINVALID` | - The transaction is missing the `LoanBrokerID` and `Amount` fields.
- `LoanBrokerID` is invalid.
- `Amount` is an MPT and `LoanBrokerID` is missing.
- Amount is an IOU and its `issuer` matches `Account`. | +| `temBAD_AMOUNT` | - `Amount` is less than or equal to zero.
- `Amount` specifies the native XRP. | +| `tecNO_ENTRY` | - The `LoanBroker` ledger entry doesn't exist, or the asset `issuer` doesn't exist. | +| `tecNO_PERMISSION` | - The asset doesn't support clawback, or the asset can't be frozen.
- The transaction is attempting to clawback native XRP.
- The `Account` isn't the asset issuer. | +| `tecWRONG_ASSET` | The specified asset to clawback doesn't match the asset in the lending protocol vault. | +| `tecINTERNAL` | The balance of the trust line doesn't match the `CoverAvailable` field. | +| `tecINSUFFICIENT_FUNDS` | Clawing back the specified `Amount` puts the available cover below the minimum required. You can also receive this error if the issuer of the asset has frozen the account or placed a global freeze. | + +{% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/xls-66d-lending-protocol/reference/transactions/loanbrokercoverdeposit.md b/docs/xls-66d-lending-protocol/reference/transactions/loanbrokercoverdeposit.md new file mode 100644 index 0000000..c3c015a --- /dev/null +++ b/docs/xls-66d-lending-protocol/reference/transactions/loanbrokercoverdeposit.md @@ -0,0 +1,61 @@ +--- +seo: + description: Deposits first-loss capital into a `LoanBroker` ledger entry. +labels: + - Transactions + - Lending Protocol +--- +# LoanBrokerCoverDeposit +[[Source]](https://github.com/XRPLF/rippled/blob/ximinez/lending-XLS-66/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp "Source") + +Deposits first-loss capital into a `LoanBroker` ledger entry to provide protection for vault depositors. + +Only the owner of the associated `LoanBroker` entry can initiate this transaction. + +_(Requires the [Lending Protocol amendment][] {% not-enabled /%})_ + + +## Example {% $frontmatter.seo.title %} JSON + +```json +{ + "TransactionType": "LoanBrokerCoverDeposit", + "Account": "rEXAMPLE9AbCdEfGhIjKlMnOpQrStUvWxYz", + "Fee": "12", + "Flags": 0, + "LastLedgerSequence": 7108682, + "Sequence": 8, + "LoanBrokerID": "E123F4567890ABCDE123F4567890ABCDEF1234567890ABCDEF1234567890ABCD", + "Amount": { + "currency": "USD", + "issuer": "rIssuer1234567890abcdef1234567890abcdef", + "value": "1000" + } +} +``` + + +## {% $frontmatter.seo.title %} Fields + +In addition to the [common fields][], {% code-page-name /%} transactions use the following fields: + +| Field Name | JSON Type | Internal Type | Required? | Description | +|:-------------- |:----------|:--------------|:----------|:------------| +| `LoanBrokerID` | String | Hash256 | Yes | The ID of the `LoanBroker` ledger entry to deposit the first-loss capital. | +| `Amount` | Object | Amount | Yes | The amount of first-loss capital to deposit. | + + +## Error Cases + +Besides errors that can occur for all transactions, {% code-page-name /%} transactions can result in the following [transaction result codes][]: + +| Error Code | Description | +| :----------------------- | :----------------------------------| +| `temINVALID` | The `LoanBrokerID` field is invalid. | +| `temBAD_AMOUNT` | The `Amount` field is less than or equal to zero. | +| `tecNO_ENTRY` | The `LoanBroker` ledger entry doesn't exist. | +| `tecNO_PERMISSION` | The account sending the transaction isn't the owner of the `LoanBroker` ledger entry. | +| `tecWRONG_ASSET` | The asset being deposited doesn't match the asset in the `LoanBroker` vault. | +| `tecINSUFFICIENT_FUNDS` | The account depositing first-loss capital doesn't hold enough of the asset. You can also receive this error if the issuer of the asset has frozen the account or placed a global freeze. | + +{% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/xls-66d-lending-protocol/reference/transactions/loanbrokercoverwithdraw.md b/docs/xls-66d-lending-protocol/reference/transactions/loanbrokercoverwithdraw.md new file mode 100644 index 0000000..c50ed94 --- /dev/null +++ b/docs/xls-66d-lending-protocol/reference/transactions/loanbrokercoverwithdraw.md @@ -0,0 +1,66 @@ +--- +seo: + description: Withdraws first-loss capital from a `LoanBroker` ledger entry. +labels: + - Transactions + - Lending Protocol +--- +# LoanBrokerCoverWithdraw +[[Source]](https://github.com/XRPLF/rippled/blob/ximinez/lending-XLS-66/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp "Source") + +Withdraws first-loss capital from a `LoanBroker` ledger entry. + +Only the owner of the associated `LoanBroker` entry can initiate this transaction. + +_(Requires the [Lending Protocol amendment][] {% not-enabled /%})_ + + +## Example {% $frontmatter.seo.title %} JSON + +```json +{ + "TransactionType": "LoanBrokerCoverWithdraw", + "Account": "rEXAMPLE9AbCdEfGhIjKlMnOpQrStUvWxYz", + "Fee": "12", + "Flags": 0, + "LastLedgerSequence": 7108682, + "Sequence": 8, + "LoanBrokerID": "E123F4567890ABCDE123F4567890ABCDEF1234567890ABCDEF1234567890ABCD", + "Amount": { + "currency": "USD", + "issuer": "rIssuer1234567890abcdef1234567890abcdef", + "value": "1000" + } +} +``` + + +## {% $frontmatter.seo.title %} Fields + +In addition to the [common fields][], {% code-page-name /%} transactions use the following fields: + +| Field Name | JSON Type | Internal Type | Required? | Description | +|:-------------- |:----------|:-------------|:----------|:------------| +| `LoanBrokerID` | String | Hash256 | Yes | The ID of the `LoanBroker` ledger entry to withdraw from. | +| `Amount` | Object | Amount | Yes | The amount of first-loss capital to withdraw. | +| `Destination` | String | AccountID | No | An account to receive the assets. | + + +## Error Cases + +Besides errors that can occur for all transactions, {% code-page-name /%} transactions can result in the following [transaction result codes][]: + +| Error Code | Description | +| :------------------------ | :----------------------------------| +| `temINVALID` | The `LoanBrokerID` field is invalid. | +| `temBAD_AMOUNT` | The amount to withdraw is lass than or equal to `0`. | +| `temMALFORMED` | The `Destination` account is empty or `0`. You can also receive this error if the destination tag is set, but `Destination` isn't. | +| `tecNO_ENTRY` | The specified `LoanBroker` ledger entry doesn't exist. | +| `tecWRONG_ASSET` | The withdrawal asset doesn't match the asset in the vault. | +| `tecNO_DST` | The `Destination` provided doesn't exist on the ledger. | +| `tecDST_TAG_NEEDED` | The `Destination` account requires a destination tag. | +| `tecINSUFFICIENT_FUNDS` | There isn't enough first-loss capital to withdraw. You can also receive this error if the issuer of the asset has frozen the account or placed a global freeze. | +| `tecNO_PERMISSION` | The account sending the transaction isn't the owner of the `LoanBroker` ledger entry. | +| `tecPATH_DRY` | The XRP Ledger failed to send the funds to the `Destination`. | + +{% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/xls-66d-lending-protocol/reference/transactions/loanbrokerdelete.md b/docs/xls-66d-lending-protocol/reference/transactions/loanbrokerdelete.md new file mode 100644 index 0000000..1af25f8 --- /dev/null +++ b/docs/xls-66d-lending-protocol/reference/transactions/loanbrokerdelete.md @@ -0,0 +1,50 @@ +--- +seo: + description: Deletes a `LoanBroker` ledger entry. +labels: + - Transactions + - Lending Protocol +--- +# LoanBrokerDelete +[[Source]](https://github.com/XRPLF/rippled/blob/ximinez/lending-XLS-66/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp "Source") + +Deletes a `LoanBroker` ledger entry. Only the owner of the `LoanBroker` entry can delete it. + +_(Requires the [Lending Protocol amendment][] {% not-enabled /%})_ + + +## Example {% $frontmatter.seo.title %} JSON + +```json +{ + "TransactionType": "LoanBrokerDelete", + "Account": "rEXAMPLE9AbCdEfGhIjKlMnOpQrStUvWxYz", + "Fee": "12", + "Flags": 0, + "LastLedgerSequence": 7108682, + "Sequence": 8, + "LoanBrokerID": "E123F4567890ABCDE123F4567890ABCDEF1234567890ABCDEF1234567890ABCD" +} +``` + + +## {% $frontmatter.seo.title %} Fields + +In addition to the [common fields][], {% code-page-name /%} transactions use the following fields: + +| Field Name | JSON Type | Internal Type | Required? | Description | +|:-------------- |:----------|:--------------|:----------|:------------| +| `LoanBrokerID` | String | Hash256 | Yes | The ID of the `LoanBroker` ledger entry to delete. | + + +## Error Cases + +Besides errors that can occur for all transactions, {% code-page-name /%} transactions can result in the following [transaction result codes][]: + +| Error Code | Description | +| :--------------------| :----------------------------------| +| `tecNO_ENTRY` | The `LoanBroker` ledger entry specified doesn't exist. | +| `tec_NO_PERMISSION` | The transaction submitter is not the owner of the `LoanBroker` ledger entry. | +| `tecHAS_OBLIGATIONS` | The `OwnerCount` field is greater than zero (active loans exist). This error can also occur if the loan broker's pseudo-account has a balance, owns other ledger entries, or has an owner directory. | + +{% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/xls-66d-lending-protocol/reference/transactions/loanbrokerset.md b/docs/xls-66d-lending-protocol/reference/transactions/loanbrokerset.md new file mode 100644 index 0000000..d82b747 --- /dev/null +++ b/docs/xls-66d-lending-protocol/reference/transactions/loanbrokerset.md @@ -0,0 +1,65 @@ +--- +seo: + description: Creates or updates an existing `LoanBroker` ledger entry. +labels: + - Transactions + - Lending Protocol +--- +# LoanBrokerSet +[[Source]](https://github.com/XRPLF/rippled/blob/ximinez/lending-XLS-66/src/xrpld/app/tx/detail/LoanBrokerSet.cpp "Source") + +Creates or updates a `LoanBroker` ledger entry, configuring protocol parameters and associating it with a `Vault`. + +Only the owner of the associated vault can initiate this transaction. + +_(Requires the [Lending Protocol amendment][] {% not-enabled /%})_ + +## Example {% $frontmatter.seo.title %} JSON + +```json +{ + "TransactionType": "LoanBrokerSet", + "Account": "rEXAMPLE9AbCdEfGhIjKlMnOpQrStUvWxYz", + "Fee": "12", + "Flags": 0, + "LastLedgerSequence": 7108682, + "Sequence": 8, + "VaultID": "ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890", + "LoanBrokerID": "E123F4567890ABCDE123F4567890ABCDEF1234567890ABCDEF1234567890ABCD", + "Data": "5468697320697320617262697472617279206D657461646174612061626F757420746865206C6F616E62726F6B65722E", + "ManagementFeeRate": 100, + "DebtMaximum": 100000, + "CoverRateMinimum": 1000, + "CoverRateLiquidation": 500 +} +``` + +## {% $frontmatter.seo.title %} Fields + +In addition to the [common fields][], {% code-page-name /%} transactions use the following fields: + +| Field Name | JSON Type | Internal Type | Required? | Description | +|:-----------------------|:----------|:--------------|:----------|:------------| +| `VaultID` | String | Hash256 | Yes | The ID of the vault that the lending protocol will use to access liquidity. | +| `LoanBrokerID` | String | Hash256 | No | The loan broker ID that the transaction is modifying. | +| `Data` | String | Blob | No | Arbitrary metadata in hex format--limited to 256 bytes. | +| `ManagementFeeRate` | Number | UInt16 | No | The 1/10th basis point fee charged by the lending protocol owner. Valid values range from `0` to `10000`. | +| `DebtMaximum` | Number | Number | No | The maximum amount the protocol can owe the vault. The default value of `0` means there is no limit to the debt. Must be a positive value. | +| `CoverRateMinimum` | Number | UInt32 | No | The 1/10th basis point `DebtTotal` that the first-loss capital must cover. Valid values range from `0` to `100000`. | +| `CoverRateLiquidation` | Number | UInt32 | No | The 1/10th basis point of minimum required first-loss capital that is moved to an asset vault to cover a loan default. Valid values range from `0` to `100000`. | + +When this transaction modifies an existing `LoanBroker` ledger entry, you can only modify `Flags`, `Data`, and `DebtMaximum`. + + +## Error Cases + +Besides errors that can occur for all transactions, {% code-page-name /%} transactions can result in the following [transaction result codes][]: + +| Error Code | Description | +|:--------------------------|:-----------------------------------| +| `temINVALID` | The transaction is trying to modify a fixed field. You can only update the values for `Flags`, `Data`, or `DebtMaximum`. | +| `tecNO_PERMISSION` | The account submitting the transaction doesn't own the associated `Vault` ledger entry. You can also receive this error if the transaction tries to modify the `VaultID` of an existing `LoanBroker` ledger entry. | +| `tecNO_ENTRY` | A `LoanBroker` entry with the specified ID does not exist. You can also receive this if the specified `VaultID` doesn't exist. | +| `tecINSUFFICIENT_RESERVE` | The owner's account doesn't have enough to cover the reserve requirement for the new `LoanBroker` ledger entry. | + +{% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/xls-66d-lending-protocol/reference/transactions/loandelete.md b/docs/xls-66d-lending-protocol/reference/transactions/loandelete.md new file mode 100644 index 0000000..956ba08 --- /dev/null +++ b/docs/xls-66d-lending-protocol/reference/transactions/loandelete.md @@ -0,0 +1,50 @@ +--- +seo: + description: Delete a `Loan` ledger entry. +labels: + - Transactions + - Lending Protocol +--- +# LoanDelete +[[Source]](https://github.com/XRPLF/rippled/blob/ximinez/lending-XLS-66/src/xrpld/app/tx/detail/LoanDelete.cpp "Source") + +Deletes a `Loan` ledger entry. Only the loan broker or borrower can submit this transaction. + +_(Requires the [Lending Protocol amendment][] {% not-enabled /%})_ + +## Example {% $frontmatter.seo.title %} JSON + +```json +{ + "TransactionType": "LoanDelete", + "Account": "rEXAMPLE9AbCdEfGhIjKlMnOpQrStUvWxYz", + "Fee": "12", + "Flags": 0, + "LastLedgerSequence": 7108682, + "Sequence": 8, + "LoanID": "E123F4567890ABCDE123F4567890ABCDEF1234567890ABCDEF1234567890ABCD" +} +``` + + +## {% $frontmatter.seo.title %} Fields + +In addition to the [common fields][], {% code-page-name /%} transactions use the following fields: + +| Field Name | JSON Type | Internal Type | Required? | Description | +|:-------------- |:----------|:--------------|:----------|:------------| +| `LoanID` | String | Hash256 | Yes | The ID of the `Loan` ledger entry to delete. | + + +## Error Cases + +Besides errors that can occur for all transactions, {% code-page-name /%} transactions can result in the following [transaction result codes][]: + +| Error Code | Description | +|:---------------------|:------------| +| `temINVALID` | The `LoanID` is missing or set to zero. | +| `tecNO_ENTRY` | The loan specified by `LoanID` doesn't exist. | +| `tecHAS_OBLIGATIONS` | The loan can't be deleted because it still has outstanding payments due. | +| `tecNO_PERMISSION` | The account submitting the transaction is neither the borrower of the `Loan` ledger entry nor the owner of the `LoanBroker` ledger entry. | + +{% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/xls-66d-lending-protocol/reference/transactions/loanmanage.md b/docs/xls-66d-lending-protocol/reference/transactions/loanmanage.md new file mode 100644 index 0000000..47c75e9 --- /dev/null +++ b/docs/xls-66d-lending-protocol/reference/transactions/loanmanage.md @@ -0,0 +1,67 @@ +--- +seo: + description: Manages the state of a loan, including defaulting, impairing, or unimpairing a loan. +labels: + - Transactions + - Lending Protocol +--- +# LoanManage +[[Source]](https://github.com/XRPLF/rippled/blob/ximinez/lending-XLS-66/src/xrpld/app/tx/detail/LoanManage.cpp "Source") + +Manages the state of a `Loan` ledger entry, including defaulting, impairing, or unimpairing a loan. + +Only the `LoanBroker` ledger entry owner can initiate this transaction. + +_(Requires the [Lending Protocol amendment][] {% not-enabled /%})_ + + +## Example {% $frontmatter.seo.title %} JSON + +```json +{ + "TransactionType": "LoanManage", + "Account": "rEXAMPLE9AbCdEfGhIjKlMnOpQrStUvWxYz", + "Fee": "12", + "Flags": 65536, + "LastLedgerSequence": 7108682, + "Sequence": 8, + "LoanID": "E123F4567890ABCDE123F4567890ABCDEF1234567890ABCDEF1234567890ABCD" +} +``` + + +## {% $frontmatter.seo.title %} Fields + +In addition to the [common fields][], {% code-page-name /%} transactions use the following fields: + +| Field Name | JSON Type | Internal Type | Required? | Description | +|:-------------- |:----------|:-------------|:----------|:------------| +| `LoanID` | String | Hash256 | Yes | The ID of the `Loan` ledger entry to manage. | +| `Flags` | String | UInt32 | No | The flag to modify the loan. | + + +## {% $frontmatter.seo.title %} Flags + +Transactions of the {% code-page-name /%} type support additional values in the [`flags` field], as follows: + +| Field Name | Hex Value | Decimal Value | Description | +|:----------------|:-------------|:--------------|:------------| +| `tfLoanDefault` | `0x00010000` | `65536` | Indicates the loan should be defaulted. | +| `tfLoanImpair` | `0x00020000` | `131072` | Indicates the the loan should be impaired. | +| `tfLoanUnimpair`| `0x00040000` | `262144` | Indicates the the loan should be unimpaired. | + + +## Error Cases + +Besides errors that can occur for all transactions, {% code-page-name /%} transactions can result in the following [transaction result codes][]: + +| Error Code | Description | +| :------------------ | :----------------------------------| +| `temINVALID` | the `LoanID` field is missing or set to zero. | +| `temINVALID_FLAG` | Multiple management flags have been set. Only one can be set at a time. | +| `tecNO_ENTRY` | The loan specified by `LoanID` doesn't exist. | +| `tecNO_PERMISSION` | - The transaction is attempting to modify a defaulted loan, or a fully paid loan.
- The transaction is attempting to change the loan's impairment status to the one it already has. | +| `tecTOO_SOON` | The loan can't be marked as defaulted before its payment due date and grace period have passed. | +| `tecLIMIT_EXCEEDED` | Marking the loan as impaired creates a loss greater than the vault's oustanding assets, which would put the vault in an invalid state. | + +{% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/xls-66d-lending-protocol/reference/transactions/loanpay.md b/docs/xls-66d-lending-protocol/reference/transactions/loanpay.md new file mode 100644 index 0000000..d1f5939 --- /dev/null +++ b/docs/xls-66d-lending-protocol/reference/transactions/loanpay.md @@ -0,0 +1,76 @@ +--- +seo: + description: Make a payment on an active loan. +labels: + - Transactions + - Lending Protocol +--- +# LoanPay +[[Source]](https://github.com/XRPLF/rippled/blob/ximinez/lending-XLS-66/src/xrpld/app/tx/detail/LoanPay.cpp "Source") + +Makes a payment on an active loan. Only the borrower on the loan can make payments, and payments must meet the minimum amount required for that period. + +_(Requires the [Lending Protocol amendment][] {% not-enabled /%})_ + +A loan payment has four types, depending on the amount and timing of the payment: + +- **Regular Payment**: A payment made on time, where the payment size and schedule are calculated with a standard [amortization formula](https://en.wikipedia.org/wiki/Amortization_calculator). +- **Late Payment**: A payment made after the `NextPaymentDueDate` in the `Loan` ledger entry. Late payments include a `LatePaymentFee` and `LateInterestRate`. +- **Early Full Payment**: A payment that covers the outstanding principal of the loan. A `CloseInterestRate` is charged on the outstanding principal. +- **Overpayment**: A payment that exceeds the required minimum payment amount. + +To see how loan payment transactions are calculated, see [transaction pseudo-code](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0066-lending-protocol#3244-transaction-pseudo-code). + + +## Example {% $frontmatter.seo.title %} JSON + +```json +{ + "TransactionType": "LoanPay", + "Account": "rBORROWER9AbCdEfGhIjKlMnOpQrStUvWxYz", + "Fee": "12", + "Flags": 0, + "LoanID": "ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890", + "Amount": 1000, + "Sequence": 10, + "LastLedgerSequence": 7108701 +} +``` + + +## {% $frontmatter.seo.title %} Fields + +In addition to the [common fields][], {% code-page-name /%} transactions use the following fields: + +| Field Name | JSON Type | Internal Type | Required? | Description | +|:--------------- |:----------|:-------------|:----------|:------------| +| `LoanID` | String | Hash256 | Yes | The ID of the `Loan` ledger entry to repay. | +| `Amount` | Number | Amount | Yes | The amount to pay toward the loan. | + + +## {% $frontmatter.seo.title %} Flags + +Transactions of the {% code-page-name /%} type support additional values in the [`flags` field], as follows: + +| Flag Name | Hex Value | Decimal Value | Description | +|:----------|:----------|:--------------|:------------| +| `tfLoanOverpayment` | `0x00010000` | 65536 | Indicates that the remaining payment amount should be treated as an overpayment. | +| `tfLoanFullPayment` | `0x00020000` | 131072 | Indicates that the borrower is making a full early repayment. | + + +## Error Cases + +Besides errors that can occur for all transactions, {% code-page-name /%} transactions can result in the following [transaction result codes][]: + +| Error Code | Description | +|:-----------|:------------| +| `temINVALID` | The `LoanID` field is missing or set to zero. | +| `temBAD_AMOUNT` | The `Amount` field must specify a positive value. | +| `tecNO_ENTRY` | The loan specified by `LoanID` doesn't exist. | +| `tecNO_PERMISSION` | The account submitting the transaction isn't the borrower on the loan. | +| `tecTOO_SOON` | The loan hasn't started yet. | +| `tecKILLED` | The loan is already fully paid. | +| `tecWRONG_ASSET` | The asset specified by `Amount` doesn't match the asset of the loan. | +| `tecFROZEN` | The borrower's account is frozen for the specified asset, or the loan broker's pseudo-account is deep-frozen and can't receive funds. | + +{% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/xls-66d-lending-protocol/reference/transactions/loanset.md b/docs/xls-66d-lending-protocol/reference/transactions/loanset.md new file mode 100644 index 0000000..dc94d1c --- /dev/null +++ b/docs/xls-66d-lending-protocol/reference/transactions/loanset.md @@ -0,0 +1,122 @@ +--- +seo: + description: Creates a new `Loan` ledger entry to represent a loan agreement between a Loan Broker and Borrower. +labels: + - Transactions + - Lending Protocol +--- +# LoanSet +[[Source]](https://github.com/XRPLF/rippled/blob/ximinez/lending-XLS-66/src/xrpld/app/tx/detail/LoanSet.cpp "Source") + +Creates a new `Loan` ledger entry, representing a loan agreement between a _Loan Broker_ and _Borrower_. + +The `LoanSet` transaction is a mutual agreement between the _Loan Broker_ and _Borrower_, and must be signed by both parties. The following multi-signature flow can be initiated by either party: + +1. The borrower or loan broker creates the transaction with the preagreed terms of the loan. They sign the transaction and set the `SigningPubKey`, `TxnSignature`, `Signers`, `Account`, `Fee`, `Sequence`, and `Counterparty` fields. +2. The counterparty verifies the loan terms and signature before signing and submitting the transaction. + +_(Requires the [Lending Protocol amendment][] {% not-enabled /%})_ + + +## Example {% $frontmatter.seo.title %} JSON + +```json +{ + "TransactionType": "LoanSet", + "Account": "rEXAMPLE9AbCdEfGhIjKlMnOpQrStUvWxYz", + "Fee": "12", + "Flags": 0, + "LastLedgerSequence": 7108682, + "Sequence": 8, + "Data": "546869732069732061726269747261727920646174612061626F757420746865206C6F616E2E", + "Counterparty": "rCOUNTER9AbCdEfGhIjKlMnOpQrStUvWxYz", + "LoanOriginationFee": 100, + "LoanServiceFee": 10, + "LatePaymentFee": 5, + "ClosePaymentFee": 20, + "OverpaymentFee": 5, + "InterestRate": 500, + "LateInterestRate": 1000, + "CloseInterestRate": 200, + "OverpaymentInterestRate": 5, + "PrincipalRequested": 10000, + "PaymentTotal": 12, + "PaymentInterval": 2592000, + "GracePeriod": 604800, + "SigningPubKey": "03C040CAC1E164B0E385D31E41447FE6B8960E0D202811CFDA08B55BA29E08C6B0", + "TxnSignature": "30440220549D359F792E155D20B5E8B3423F0F844CCF7C86986EB85BE482908A55A7157D02207B464FFE57E75D9693BAC445540CF078E9E0B6452C917DE4D66F27918D32A170", + "hash": "831EEFF19C980FC348E984625FE41AEB27301B0B072D4239A980E78B86B2515C" +} +``` + + +## {% $frontmatter.seo.title %} Fields + +In addition to the [common fields][], {% code-page-name /%} transactions use the following fields: + +| Field Name | JSON Type | Internal Type | Required? | Description | +|:--------------------------|:----------|:--------------|:----------|:------------| +| `LoanBrokerID` | String | Hash256 | Yes | The ID of the `LoanBroker` ledger entry. | +| `Flags` | String | UInt32 | No | Flags for the loan. | +| `Data` | String | Blob | No | Arbitrary metadata in hex format (max 256 bytes). | +| `Counterparty` | String | AccountID | No | The address of the counterparty of the loan. | +| `LoanOriginationFee` | Number | Number | No | The amount paid to the `LoanBroker` owner when the loan is created. | +| `LoanServiceFee` | Number | Number | No | The amount paid to the `LoanBroker` owner with each loan payment. | +| `LatePaymentFee` | Number | Number | No | The amount paid to the `LoanBroker` owner for late payments. | +| `ClosePaymentFee` | Number | Number | No | The amount paid to the `LoanBroker` owner for early full repayment. | +| `OverpaymentFee` | Number | UInt32 | No | A fee charged on overpayments, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. | +| `InterestRate` | Number | UInt32 | No | The annualized interest rate of the loan, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. | +| `LateInterestRate` | Number | UInt32 | No | A premium added to the interest rate for late payments, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. | +| `CloseInterestRate` | Number | UInt32 | No | A fee charged for repaying the loan early, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. | +| `OverpaymentInterestRate` | Number | UInt32 | No | The interest rate charged on overpayments, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. | +| `PrincipalRequested` | Number | Number | Yes | The principal loan amount requested by the borrower. | +| `PaymentTotal` | Number | UInt32 | No | The total number of payments to be made against the loan. | +| `PaymentInterval` | Number | UInt32 | No | The number of seconds between loan payments. | +| `GracePeriod` | Number | UInt32 | No | The number of seconds after the loan's payment due date when it can be defaulted. | +| `SigningPubKey` | String | Blob | Yes | The public key used to verify the validity of the first signer's signature. | +| `TxnSignature` | String | Blob | Yes | The hex encoding of the digital signature for the first signing. | +| `hash` | String | Hash256 | Yes | The unique identifying hash of the partially-signed transaction. | + +### CounterpartySignature Fields + +An inner object that contains the signatures of the counterparty of the transaction. The object contains the following fields: + +| Field Name | JSON Type | Internal Type | Required? | Description | +|:----------------|:----------|:--------------|:----------|:------------| +| `SigningPubKey` | String | STBlob | No | The public key used to verify the validity of the signature. | +| `Signature` | String | STBlob | No | The signature over all signing fields. | +| `Signers` | List | STArray | No | An array of transaction signatures from the counterparty. | + +The final transaction must include either: +- Both the `SigningPubKey` and `TxnSignature` fields. +- The `Signers` field. + +{% admonition type="info" name="Note" %} +This field isn't included in the `LoanSet` JSON, instead it's added to the stored transaction metadata after the counterparty submits the fully signed `LoanSet` transaction. +{% /admonition %} + + +## {% $frontmatter.seo.title %} Flags + +Transactions of the {% code-page-name /%} type support additional values in the [`flags` field], as follows: + +| Flag Name | Hex Value | Decimal Value | Description | +|:----------|:----------|:--------------|:------------| +| `tfLoanOverpayment` | `0x00010000` | 65536 | Indicates that the loan supports overpayments. | + + +## Error Cases + +Besides errors that can occur for all transactions, {% code-page-name /%} transactions can result in the following [transaction result codes][]: + +| Error Code | Description | +|:--------------------------|:-----------------------------------| +| `temBAD_SIGNER` | - The transaction is missing a `CounterpartySignature` field.
- This transaction is part of a `Batch` transaction, but didn't specify a `Counterparty`. | +| `temINVALID` | One or more of the numeric fields are outside their valid ranges. For example, the `GracePeriod` can't be longer than the `PaymentInterval`. | +| `tecNO_ENTRY` | The `LoanBroker` doesn't exist. | +| `tecNO_PERMISSION` | Neither the transaction sender's `Account` or the `Counterparty` field owns the associated `LoanBroker` ledger entry. | +| `tecINSUFFICIENT_FUNDS` | - The `Vault` associated with the `LoanBroker` doesn't have enough assets to fund the loan.
- The `LoanBroker` ledger entry doesn't have enough first-loss capital to meet the minimum coverage requirement for the new total debt. | +| `tecLIMIT_EXCEEDED` | The requested loan would cause the `LoanBroker` ledger entry to exceed it's maximum allowed debt. | +| `tecINSUFFICIENT_RESERVE` | The borrower's account doesn't have enough XRP to meet the reserve requirements. | + +{% raw-partial file="/docs/_snippets/common-links.md" /%} diff --git a/docs/xls-66d-lending-protocol/reference/transactions/updated-transactions.md b/docs/xls-66d-lending-protocol/reference/transactions/updated-transactions.md new file mode 100644 index 0000000..b4f85ae --- /dev/null +++ b/docs/xls-66d-lending-protocol/reference/transactions/updated-transactions.md @@ -0,0 +1,15 @@ +--- +seo: + description: The Lending Protocol updates the sign, sign_for, and submit commands with an additional field. +labels: + - Transactions + - Lending Protocol +--- +# Updated Transactions + +The Lending Protocol updates the [`sign`](https://xrpl.org/docs/references/http-websocket-apis/admin-api-methods/signing-methods/sign), [`sign_for`](https://xrpl.org/docs/references/http-websocket-apis/admin-api-methods/signing-methods/sign_for), and [`submit`](https://xrpl.org/docs/references/http-websocket-apis/public-api-methods/transaction-methods/submit) commands with a new `signature_target` field. + + +| `Field` | Type | Required? | Description | +|:-------------------|:--------|:----------|:------------| +| `signature_target` | String | No | Specifies where in the transaction metadata the signature information should be stored. Currently, the only valid value is `CounterpartySignature`. | diff --git a/docs/xls-66d-lending-protocol/use-cases/institutional-credit-facilities.md b/docs/xls-66d-lending-protocol/use-cases/institutional-credit-facilities.md new file mode 100644 index 0000000..26e0e1b --- /dev/null +++ b/docs/xls-66d-lending-protocol/use-cases/institutional-credit-facilities.md @@ -0,0 +1,68 @@ +--- +seo: + description: The XRPL's Lending Protocol, combined with Single Asset Vaults, Credentials, and Permissioned Domains, enable institutional credit facilities. +labels: + - Decentralized Finance + - Lending Protocol +--- +# Institutional Credit Facilities + +Financial institutions need efficient ways to provide credit facilities while maintaining regulatory compliance. Traditional uncollateralized lending faces challenges with liquidity management, credit assessment, and operational efficiency. The XRPL's Lending Protocol, combined with Single Asset Vaults, Credentials, and Permissioned Domains, provides a solution for institutional credit facilities. + + +## Background: Challenges with traditional credit facilities + +Institutional lending typically involves multiple challenges in the current financial system: + +1. **Liquidity Management**: Capital inefficiently distributed across multiple lending pools, which makes it difficult to source at low cost. +2. **Credit Assessment**: Complex verification and management of institutional creditworthiness +3. **Settlement Delays**: Multi-day settlement cycles for loan disbursement and repayment +4. **Operational Overhead**: Manual processing of loan documentation and approvals +5. **Regulatory Compliance**: Resource-intensive KYC and reporting requirements + + +## Solution: Lending on the XRPL + +The XRPL lending protocol addresses these challenges through: + + +### Efficient Liquidity Pooling + +- You can create Single Asset Vaults to aggregate lender assets into unified pools and programmatically loan those assets out. The following scenario is difficult to achieve in TradFi because you would have to manage deposits across multiple banks, conduct KYC on each user, handle repayments, and absorb the costs of inefficient rails and transaction fees. Single Asset Vaults provide benefits to all participants in the lending protocol: + - **Depositors** gain access to larger lending markets by aggregating deposits with other small-sized depositors. This lets them participate in loans they normally wouldn’t be able to in tradfi scenarios which require far more capital. This enables them to earn yield on otherwise idle assets. + - **Lenders** can source from these vaults cheaply and and quickly, capitalizing on the spread. + - **Borrowers** gain access to reliable liquidity. +- Single Asset Vaults automate liquidity management, handling deposits and redemptions through a sophisticated exchange algorithm that: + - Converts deposits into shares for vault depositors. + - Manages redemptions back into assets. + - Dynamically adjusts exchange rates to reflect true vault value when interest from loans are paid back into the vault. +- Single Asset Vaults support multiple asset types (XRP, Trust Line Tokens such as RLUSD, or Multi-purpose Tokens). + + +### Regulatory Compliance + +- Accounts on the XRPL can be vetted by a trusted credential issuer. Credentials can be issued and revoked, based around relevant criteria, such as credit score. +- Permissioned Domains act as a gateway, limiting who can access the credit facilities, based on accepted credentials you define. +- All credential and loan info is transparent on the XRPL, which makes compliance reporting and monitoring simpler and tamper-proof. + + +### Streamlined Credit Operations + +- You can reduce the overhead of managing loans by programmatically setting the terms of loans with the Lending Protocol, which then handles loan disbursements and repayments. +- The Lending Protocol utilizes uncollateralized loans, but the design is simple and flexible enough for you to add additional logic on top of the primitive. For example, if you need collateralized loans, you can utilize on-chain custodians. +- Built-in first-loss capital features automatically protect against asset losses from defaults. + + +## Implementation Steps + +1. Set Up Credential System + - Select or become a credential issuer. + - Define required credentials for borrowers. + - Set up Permissioned Domains to protect your lending protocol and stay compliant with regulations. +2. Configure Asset Vaults + - Set up vaults for different lending assets + - Define public/private access parameters + - Establish vault management policies +3. Deploy Lending Protocol + - Configure lending parameters and terms + - Set up monitoring and reporting systems diff --git a/index.page.tsx b/index.page.tsx index 90ff56d..b1f3ffb 100644 --- a/index.page.tsx +++ b/index.page.tsx @@ -30,6 +30,13 @@ export default function Page() { + +

The XRPL-native lending protocol offers on-chain, fixed-term loans, utilizing pooled funds from single-asset vaults.

+ +
+

A single asset vault is an XRP Ledger primitive that aggregates assets from multiple depositors and makes them available to other on-chain protocols.