XRP LedgerのLending Protocol
はじめに
この記事はXLS-66dとして提案されているLending Protocolを紹介するものです。
この提案はまだ確定しているものではないため、今後変更される可能性があります。
Lending Protocol
概要
分散型金融(DeFi)レンディングは、ブロックチェーンエコシステム内における変革的な力です。銀行や金融機関などの仲介者を必要としないピアツーピアの代替手段を提供することで、従来の金融サービスに革命をもたらします。その核心において、DeFiレンディングプラットフォームはユーザーがデジタル資産を直接貸借できるようにし、金融包摂、透明性、効率性を促進します。
この提案は、XRP Ledgerネイティブのレンディングプロトコルの基本的な機能を導入します。このプロトコルは、プールされた資金を利用し、利息が発生するローンの事前設定された条件で、シンプルなオンチェーンの無担保固定期間ローンを提供します。本設計は、借り手の信用力を評価するためのオフチェーンの引受と信用リスク管理に依存しています。ただし、First-Loss Capital保護スキームがローンのデフォルト時の損失の一部を吸収します。
このバージョンでは、意図的に自動化されたオンチェーン担保と清算管理の複雑なメカニズムをスキップしています。代わりに、オンチェーン信用創造のための機能と必須コンポーネントに焦点を当てています。したがって、主要な設計原則は、将来的に追加の複雑な機能の導入を可能にする柔軟性と再利用性です。
1. はじめに
1.1 概要
レンディングプロトコルは、1人以上の預金者から資産を提供するためにVaultオンチェーンオブジェクトを使用します。Loan Brokerはレンディングプロトコルと関連するVaultの管理を担当します。VaultのオーナーとLoan Brokerは同じアカウントである必要がありますが、これは将来変更される可能性があります。
この仕様は、LoanBrokerとLoanという2つの新しいレジャーエントリを導入します。LoanBrokerオブジェクトは、手数料やFirst-Loss Capitalカバーなど、レンディングプロトコル固有の詳細を捕捉します。さらに、Vaultから取得した資金を追跡します。Loanオブジェクトは、Loan BrokerとBorrower間のローン契約を捕捉します。
この仕様は、以下のトランザクションを導入します。
-
LoanBrokerSet: 新しいLoanBrokerオブジェクトを作成するトランザクション -
LoanBrokerDelete: 既存のLoanBrokerオブジェクトを削除するトランザクション -
LoanBrokerCoverDeposit: First-Loss Capitalを預け入れるトランザクション -
LoanBrokerCoverWithdraw: First-Loss Capitalを引き出すトランザクション -
LoanSet: 新しいLoanオブジェクトを作成するトランザクション -
LoanDelete: 既存のLoanオブジェクトを削除するトランザクション -
LoanManage: 既存のLoanを管理するトランザクション -
LoanDraw:Loan資金を引き出すトランザクション -
LoanPay:Loanの支払いを行うトランザクション
レンディングプロトコルのフローは以下の通りです。
- Loan Brokerが
Vaultレジャーエントリを作成します - Loan Brokerが
LoanBrokerSetトランザクションでLoanBrokerレジャーエントリを作成します - 預金者が
Vaultに資産を預け入れます - オプションで、Loan Brokerが
LoanBrokerCoverDepositトランザクションでLoanBrokerにFirst-Loss Capitalを預け入れます - Loan BrokerとBorrowerが
LoanSetトランザクションでLoanオブジェクトを作成します - Borrowerは
LoanDrawトランザクションで資金を引き出し、LoanPayで支払いを行うことができます - BorrowerがLoanの支払いを怠った場合、Loan Brokerは
LoanManageトランザクションを使用してLoanをデフォルトにできます - Loanが満期(またはデフォルト)になると、BorrowerまたはLoan Brokerは
LoanDeleteトランザクションを使用してそれを削除できます - オプションで、Loan Brokerは
LoanBrokerCoverWithdrawトランザクションを使用してFirst-Loss Capitalを引き出すことができます - すべての
Loanオブジェクトが削除されると、Loan BrokerはLoanBrokerDeleteトランザクションでLoanBrokerオブジェクトを削除できます - すべての
LoanBrokerオブジェクトが削除されると、Loan BrokerはVaultオブジェクトを削除できます
1.2 コンプライアンス機能
1.2.1 Clawback
Clawbackは、資産発行者(IOUまたはMPTのみ)が資金を回収するメカニズムです。これはVaultで実行でき、レンディングプロトコルでは実行できません。
1.2.2 Freeze
Freezeは、資産発行者(IOUまたはMPTのみ)がAccountを凍結し、そのアカウントによる該当資産の送受信をブロックする機能です。さらに、発行者はGlobal Freezeを実施でき、こは該当資産保有者全員の送受信をブロックします。単一アカウントへのFreezeとGlobal Freezeの両方において、資産は発行者に対して送信できることに注意してください。
発行者がBorrowerのアカウントをFreezeした場合、Borrowerはローンの支払いや資金の引き出しができません。Freezeされたアカウントであっても、ローンを返済する義務は免除されません。
Loan BrokerのアカウントがFreezeされた場合、Brokerはローン手数料を受け取れません。新しいローンを作成でき、既存のローンは影響を受けません。ただし、Loan BrokerはFirst-Loss Capitalの預け入れや引き出しができません。
最後に、Global Freezeでの正確な動作はまだ定義されていません。TBD
1.3 リスク管理
リスク管理は、レンディングに関連するリスクを軽減するメカニズムを含みます。投資家の資産を保護するために、オプションのFirst-Loss Capital保護スキームを導入しました。このスキームでは、Loan Brokerがローンデフォルト時の損失をカバーするために部分的に清算できる資金を預け入れる必要があります。必要なFirst-Loss Capitalの額は、Vaultに対する総債務の割合です。デフォルト時には、最低必要カバー率に基づいてFirst-Loss Capitalの一部が清算されます。清算された資本は損失の一部をカバーするためにVaultに戻されます。
1.4 金利
ローンに関連する3つの基本的な金利があります。
-
Interest Rate: 元本に基づく通常の金利。これは資金を借りるコストです。 -
Late Interest Rate: 支払い遅延に対して課される高い金利。 -
Full Payment Rate: ローン全額を早期返済する場合に課される金利。
1.5 手数料
レンディングプロトコルは、Loan Brokerが設定できる複数の手数料を課します。Loan Brokerが十分なFirst-Loss Capitalを預け入れていない場合、プロトコルは手数料を課しません。
-
Management Fee: これはLoan Brokerが設定できる手数料で、ローンの利息に対して計算されます。これはVaultの預金者に送信される利息から差し引かれます。本質的に、借り手は全利息を支払いますが、その利息が預金者に到達する前にLoan Brokerがその一部を取ります。 -
Loan Origination Fee: ローンの発行に対して支払われる手数料。 -
Loan Service Fee: 各ローン支払いに対して支払われる手数料。 -
Late Payment Fee: 遅延支払いに対して支払われる手数料。 -
Early Payment Fee: 早期支払いに対して支払われる手数料。
1.6 用語
1.6.1 用語
-
Fixed-Term Loan: 既知の終了日と定期的な支払いスケジュールを持つローンの一種。 -
Principal: 借りた元本の合計額。利息やその他の手数料を除く。 -
Interest: 資産を借りるコスト。ローンの元本に対して計算される利息。借り手は時間とともにLenderに支払います。 -
Drawdown: ローンの作成後、借り手がローン資金の一部または全部をアクセスするプロセス。 -
Default: 借り手がローンの義務を履行しないこと。例えば、支払いを遅らせること。 -
First-Loss Capital: デフォルト時にVault預金者が損失を被ることを防ぐための資金。 -
Term: 借り手がローンを返済する期間。 -
Amortization: 定期的な支払いで、利息と元本を時間とともに返済するプロセス。 -
Repayment Schedule: 借り手がローンを返済するタイミングと金額を定めた計画。 -
Grace Period: ローンの期限後、Loan Brokerがローンをデフォルトにできる期間。
1.6.2 人物
-
LoanBroker: ローンを発行するエンティティ。 -
Borrower: 資金を借りるアカウント。
1.7 システム図
+-----------------+ +-----------------+ +-----------------+
| Depositor | | LoanBroker | | Borrower |
| AccountRoot | | AccountRoot | | AccountRoot |
|-----------------| |-----------------| |-----------------|
| Owner Directory | | Owner Directory | | Owner Directory |
+-----------------+ +-----------------+ +-----------------+
^ | | |
| Reserve ____________Reserve____________ Reserve
Account | | | |
| V V V V
+-----------------+ +-----------------+ +-----------------+ +-----------------+
| | | |1 N| |1 N| |
| MPToken | | Vault |--------->| LoanBroker |--------->| Loan |
| | | | |-----------------| | |
+-----------------+ +-----------------+ | Owner Directory | +-----------------+
| ^ +-----------------+ ^
Issuance | ___________ ____________^ |_________Link_________|
| | Account |
V ^ | ^
+-----------------+ | +-----------------+ |
| Share | | | Pseudo-Account | |
| MPTokenIssuance |<------Issuer------| -----| AccountRoot | |
| | |_Link_|-----------------|_Link_|
+-----------------+ | Owner Directory |
+-----------------+
2. レジャーエントリ
2.1. LoanBrokerレジャーエントリ
LoanBrokerオブジェクトはレンディングプロトコルの属性を捕捉します。
2.1.1 オブジェクト識別子
LoanBrokerオブジェクトのキーは、以下の値を順番に連結したSHA512-Halfの結果です。
-
LoanBrokerスペースキー0x006C(小文字のl) -
LoanBrokerSetトランザクションを送信するアカウント(つまりLender)のAccountID - トランザクションの
Sequence番号。トランザクションがTicketを使用した場合は、TicketSequence値を使用します。
2.1.2 フィールド
LoanBrokerオブジェクトには以下のフィールドがあります。
| フィールド名 | 変更可能? | 必須? | JSONの型 | 内部の型 | デフォルト値 | 説明 |
|---|---|---|---|---|---|---|
LedgerEntryType |
N/A |
✅ | 文字列 |
UINT16 |
TODO | レジャーオブジェクトのタイプ。 |
LedgerIndex |
N/A |
✅ | 文字列 |
UINT16 |
N/A |
レジャーオブジェクトの識別子。 |
Flags |
Yes |
✅ | 文字列 |
UINT32 |
0 | レジャーオブジェクトのフラグ。 |
PreviousTxnID |
N/A |
✅ | 文字列 |
HASH256 |
N/A |
このオブジェクトを最後に変更したトランザクションのID。 |
PreviousTxnLgrSeq |
N/A |
✅ | 数値 |
UINT32 |
N/A |
このオブジェクトを最後に変更したトランザクションが含まれるレジャーのシーケンス。 |
Sequence |
N/A |
✅ | 数値 |
UINT32 |
N/A |
このオブジェクトを作成したトランザクションのシーケンス番号。 |
OwnerNode |
N/A |
✅ | 数値 |
UINT64 |
N/A |
このオブジェクトが所有者のディレクトリで参照されるページを識別します。 |
VaultID |
No |
✅ | 文字列 |
HASH256 |
N/A |
このレンディングプロトコルインスタンスに関連するVaultオブジェクトのID。 |
Owner |
No |
✅ | 文字列 |
AccountID |
N/A |
Loan Brokerのアドレス。 |
Data |
Yes |
string |
BLOB |
None | Loan Brokerに関する任意のメタデータ。最大256バイト | |
ManagementFeeRate |
No |
number |
UINT16 |
0 | レンディングプロトコルが課す1/10ベースポイント単位の手数料。 有効な値は0から10000までの範囲。値1は1/10ベースポイントまたは0.001%に相当します. | |
OwnerCount |
N/A |
✅ | number |
UINT32 |
0 | Loan Brokerが発行したアクティブなローンの数。 |
DebtTotal |
N/A |
✅ | number |
NUMBER |
0 | レンディングプロトコルがVaultに負う債務の総額。利息を含む。 |
DebtMaximum |
Yes |
✅ | number |
NUMBER |
0 | レンディングプロトコルがVaultに負うことができる最大債務。デフォルト値の0は債務の制限がないことを意味します。 |
CoverAvailable |
N/A |
✅ | number |
NUMBER |
0 | レンディングプロトコルに預け入れられたFirst-Loss Capitalの総額。 |
CoverRateMinimum |
No |
✅ | number |
UINT16 |
0 | ローンデフォルトをカバーするためにFirst-Loss Capitalが必要なDebtTotalの1/10ベースポイント。有効な値は0から100000までの範囲。値1は1/10ベースポイントまたは0.001%に相当します。 |
CoverRateLiquidation |
No |
✅ | number |
UINT16 |
0 | ローンデフォルトをカバーするためにFirst-Loss Capitalが清算される必要なDebtTotalの1/10ベースポイント。有効な値は0から100000までの範囲。値1は1/10ベースポイントまたは0.001%に相当します。 |
2.1.3 LoanBroker pseudo-account
レンディングプロトコルは、First-Loss Capitalを保持するために関連するVaultオブジェクトの pseudo-account を使用します。
2.1.4 所有権
レンディングプロトコルオブジェクトはledgerに保存され、LoanBrokerSetトランザクションを送信するアカウントが所有する所有者ディレクトリで追跡されます。さらに、このオブジェクトは pseudo-account のOwnerDirectoryでも追跡されます。
LoanBrokerは、LoanBrokerオブジェクトがアクティブなローンがある間に削除されることを防ぎ、将来のRPCエンドポイントのために、関連するLoanオブジェクトの追跡を必要とします。したがって、LoanBrokerには関連する所有者ディレクトリオブジェクトがあります。
DirectoryNodeオブジェクトのRootIndexは、以下の値を順番に連結したSHA512-Halfの結果です。
-
OwnerDirectoryスペースキー0x004F LoanBrokerID
2.1.5 準備金
LoanBrokerオブジェクトは、作成するアカウントに対して1つの所有者準備金を必要とします。
2.1.6 会計
レンディングプロトコルは、DebtTotalフィールドで関連するVaultに対する債務を追跡します。これは、Vaultから取得した元本額と支払うべき利息を捕捉し、すべての手数料は除外します。DebtMaximumフィールドは、レンディングプロトコルが負うことができる最大債務を制御します。Lenderがローンを発行するたびに、DebtTotalはローンの元本と利息(手数料を除く)だけ増加します。DebtTotalがDebtMaximumを超えることになるようなローンを発行することはできません。
例
例1: # ローンの発行 #
** 初期状態 **
-- Vault --
AssetsTotal = 100,000 トークン
AssetsAvailable = 100,000 トークン
SharesTotal = 100,000 シェア
-- レンディングプロトコル --
DebtTotal = 0
# レンディングプロトコルが利息に対して課す手数料
ManagementFeeRate = 0.1 (10%)
# Lenderが以下のローンを発行
-- Loan --
LoanPrincipal = 1,000 トークン
LoanInterestRate = 0.1 (10%)
# 簡略化
LoanInterest = LoanPrincipal x LoanInterestRate
= 100 トークン
** 状態変更 **
-- Vault --
# Vaultの潜在的価値を増加
AssetsTotal = AssetsTotal + ((LoanInterest - (LoanInterest x ManagementFeeRate)))
= 100,000 + (100 - (100 x 0.1)) = 100,000 + 90
= 100,090 トークン
# Vaultの利用可能資産を減少
AssetsAvailable = AssetsAvailable - LoanPrincipal
= 100,000 - 1,000
= 99,000 トークン
SharesTotal = (変更なし)
-- レンディングプロトコル --
# レンディングプロトコルの債務を増加
DebtTotal = DebtTotal + LoanPrincipal + (LoanInterest - (LoanInterest x ManagementFeeRate))
= 0 + 1,000 + (100 - (100 x 0.1)) = 1,000 + 90
= 1,090 トークン
---------------------------------------------------------------------------------------------------
例2: # ローンの支払い #
** 初期状態 **
-- Vault --
AssetsTotal = 100,090 トークン
AssetsAvailable = 99,000 トークン
SharesTotal = 100,000 シェア
-- レンディングプロトコル --
DebtTotal = 1,090 トークン
# レンディングプロトコルが利息に対して課す手数料
ManagementFeeRate = 0.1 (10%)
-- Loan --
LoanPrincipal = 1,000 トークン
LoanInterestRate = 0.1 (10%)
# 簡略化
LoanPayments = 2
# 簡略化
LoanInterest = LoanPrincipal x LoanInterestRate
= 100 トークン
# Borrowerが単一の支払いを行う
PaymentAmount = 550 トークン
PaymentPrincipalPortion = 500 トークン
PaymentInterestPortion = 50 トークン
** 状態変更 **
-- Vault --
AssetsTotal = (変更なし)
# Vaultの利用可能資産を増加
AssetsAvailable = AssetsAvailable + PaymentPrincipalPortion + (PaymentInterestPortion - (PaymentInterestPortion x ManagementFeeRate))
= 99,000 + 500 + (50 - (50 x 0.1))
= 99,545 トークン
SharesTotal = (変更なし)
-- レンディングプロトコル --
# レンディングプロトコルの債務を減少
DebtTotal = DebtTotal - PaymentPrincipalAmount - (PaymentInterestPortion - (PaymentInterestPortion x ManagementFeeRate))
= 1,090 - 500 - (50 - (50 x 0.1))
= 545 トークン
2.1.7 First-Loss Capital
First-Loss Capitalは、ローンデフォルト時にVault預金者が損失を被ることを防ぐための任意の機能です。First-Loss Capitalは損失の一部を吸収します。以下のパラメータがFirst-Loss Capitalを制御します。
-
CoverAvailable- レンディングプロトコルオーナーが預け入れたカバーの総額 -
CoverRateMinimum-CoverAvailableがDebtTotalをカバーしなければならない割合 -
CoverRateLiquidation- ローンデフォルトをカバーするために清算される最低必要カバー( )の最大割合DebtTotal \times CoverRateMinimum
利用可能なカバーが必要最低カバーを下回った場合、2つの結果が発生します。
- Lenderは新しいローンを発行できません
- Lenderは手数料を受け取れません。借り手の手数料は無視され(つまり、借り手はローン支払い手数料を支払う必要がない)、管理手数料はその代わりにVaultに預け入れられます
例
例1: ローンデフォルト
** 初期状態 **
-- Vault --
AssetsTotal = 100,090 トークン
AssetsAvailable = 99,000 トークン
SharesTotal = 100,000 トークン
-- レンディングプロトコル --
DebtTotal = 1,090 トークン
CoverRateMinimum = 0.1 (10%)
CoverRateLiquidation = 0.1 (10%)
CoverAvailable = 1,000 トークン
-- Loan --
DefaultAmount = 1,090 トークン
# First-Loss Capital清算の計算
# First-Loss Capitalスキームがカバーするデフォルト額
DefaultCovered = min((DebtTotal x CoverRateMinimum) x CoverRateLiquidation, DefaultAmount)
= min((1,090 * 0.1) * 0.1, 1,090) = min(10.9, 1,090)
= 10.9 トークン
DefaultRemaining = DefaultAmount - DefaultCovered
= 1,090 - 10.9
= 1,079.1 トークン
** 状態変更 **
-- Vault --
AssetsTotal = AssetsTotal - DefaultRemaining
= 100,090 - 1,079.1
= 99,010.9 トークン
AssetsAvailable = AssetsAvailable + DefaultCovered
= 99,000 + 10.9
= 99,010.9 トークン
SharesTotal = (変更なし)
-- レンディングプロトコル --
DebtTotal = DebtTotal - DefaultAmount
= 1,090 - 1,090
= 0 トークン
CoverAvailable = CoverAvailable - DefaultCovered
= 1,000 - 10.9
= 989.1 トークン
2.2. Loanレジャーエントリ
Loanレジャーエントリは、オンチェーン上の様々なローン条件を捕捉します。これはBorrowerとローン発行者間の契約です。
2.2.1 オブジェクト識別子
LoanIDは以下のように計算されます。
- 以下の値の
SHA512-Halfを計算。
2.2.2 フィールド
| フィールド名 | 変更可能? | 必須? | JSONタイプ | 内部タイプ | デフォルト値 | 説明 |
|---|---|---|---|---|---|---|
LedgerEntryType |
N/A |
✅ | 文字列 |
UINT16 |
TODO | Ledgerオブジェクトタイプ |
LedgerIndex |
N/A |
✅ | 文字列 |
UINT16 |
N/A |
Ledgerオブジェクト識別子 |
Flags |
Yes |
文字列 |
UINT32 |
0 | Ledgerオブジェクトフラグ | |
PreviousTxnID |
N/A |
✅ | 文字列 |
HASH256 |
N/A |
このオブジェクトを最後に変更したトランザクションのID |
PreviousTxnLgrSeq |
N/A |
✅ | 数値 |
UINT32 |
N/A |
このオブジェクトを最後に変更したトランザクションを含むledgerのシーケンス |
Sequence |
N/A |
✅ | 数値 |
UINT32 |
N/A |
ローンを作成したトランザクションのシーケンス番号 |
OwnerNode |
N/A |
✅ | 数値 |
UINT64 |
N/A |
このアイテムがオーナーのディレクトリで参照されているページを識別 |
LoanBrokerID |
No |
✅ | 文字列 |
HASH256 |
N/A |
このLoanインスタンスに関連するLoanBrokerのID |
Borrower |
No |
✅ | 文字列 |
AccountID |
N/A |
借り手アカウントのアドレス |
LoanOriginationFee |
No |
✅ | 数値 |
NUMBER |
N/A |
ローン作成時にLoanBroker.Ownerに支払われる名目資金額 |
LoanServiceFee |
No |
✅ | 数値 |
NUMBER |
N/A |
各ローン支払いと共にLoanBroker.Ownerに支払われる名目資金額 |
LatePaymentFee |
No |
✅ | 数値 |
NUMBER |
N/A |
支払いが遅延した場合にLoanBroker.Ownerに支払われる名目資金額 |
ClosePaymentFee |
No |
✅ | 数値 |
NUMBER |
N/A |
全額支払いが行われた場合にLoanBroker.Ownerに支払われる名目資金額 |
OveraymentFee |
No |
✅ | 数値 |
NUMBER |
N/A |
過払い金に対する1/100ベーシスポイント単位の手数料。有効な値は0から100000(0~100%)です。 |
InterestRate |
No |
✅ | 数値 |
UINT16 |
N/A |
1/10ベーシスポイント単位のローンの年換算金利 |
LateInterestRate |
No |
✅ | 数値 |
UINT16 |
N/A |
遅延支払いに対する1/10ベーシスポイント単位の金利 |
CloseInterestRate |
No |
✅ | 数値 |
UINT16 |
N/A |
早期返済に対する1/10ベーシスポイント単位の金利 |
OverpaymentInterestRate |
No |
✅ | 数値 |
UINT16 |
N/A |
超過支払いに対する1/10ベーシスポイント単位の金利 |
StartDate |
No |
✅ | 数値 |
UINT32 |
N/A |
ローン開始時のリップルエポック |
PaymentInterval |
No |
✅ | 数値 |
UINT32 |
N/A |
ローン支払い間隔の秒数 |
GracePeriod |
No |
✅ | 数値 |
UINT32 |
N/A |
支払い期限後の秒数 |
PreviousPaymentDate |
N/A |
✅ | 数値 |
UINT32 |
0 |
前回の支払い時のリップルエポック |
NextPaymentDueDate |
N/A |
✅ | 数値 |
UINT32 |
LoanSet.StartDate + LoanSet.PaymentInterval |
次回の支払い期限のリップルエポック |
PaymentsRemaining |
N/A |
✅ | 数値 |
UINT32 |
LoanSet.PaymentsTotal |
残りの支払い回数 |
AssetsAvailable |
N/A |
✅ | 数値 |
NUMBER |
LoanSet.[PrincipalRequested - LoanOriginationFee] |
ローンで利用可能な資産額 |
PrincipalOutstanding |
No |
✅ | 数値 |
NUMBER |
LoanSet.PrincipalRequested |
借り手が要求した元本額 |
2.2.2.1 フラグ
Loanオブジェクトは以下のフラグをサポートします。
| フラグ名 | フラグ値 | 変更可能? | 説明 |
|---|---|---|---|
lsfLoanDefault |
0x0001 |
No |
設定されている場合、ローンがデフォルトになったことを示します。 |
lsfLoanImpaired |
0x0002 |
Yes |
設定されている場合、ローンが債務不履行になったことを示します。 |
lsfLoanOverpayment |
0x0003 |
No |
設定されている場合、ローンが超過支払いをサポートしていることを示します。 |
2.2.3 所有権
Loanオブジェクトはレジャーに保存され、Borrowerの所有者ディレクトリに追跡されます。
さらに、LoanBrokerからLoanオブジェクトの検索を容易にするため、オブジェクトはLoanBrokerオブジェクトに関連するOwnerDirectoryにも追跡されます。
2.2.4 準備金
LoanオブジェクトはBorrowerの準備金を1つ消費します。
2.2.5 債務不履行
LoanBrokerが借り手が次回の支払いを行えないことを発見した場合、債務不履行によりLoanBrokerはVaultに"含み損"を登録できます。債務不履行メカニズムは次回の支払い期限をローンが債務不履行になった時間に移動し、ローンをより迅速に債務不履行にすることができます。ただし、借り手が支払いを行った場合、債務不履行の状態は自動的にクリアされます。
3. トランザクション
3.1. LoanBrokerトランザクション
このセクションではLoanBrokerレジャーエントリに関連するトランザクションを指定します。
3.1.1 LoanBrokerSet
このトランザクションは新しいLoanBrokerオブジェクトを作成するか、既存のものを更新します。
| フィールド名 | Required? | JSONタイプ | 内部タイプ | デフォルト値 | 説明 |
|---|---|---|---|---|---|
TransactionType |
✅ | 文字列 |
UINT16 |
TODO | トランザクションタイプ |
VaultID |
✅ | 文字列 |
HASH256 |
N/A |
ローンプロトコルが流動性にアクセスするために使用するVault ID |
LoanBrokerID |
文字列 |
HASH256 |
N/A |
トランザクションが変更するLoanBroker ID | |
Flags |
文字列 |
UINT32 |
0 | ローンプロトコルのフラグ | |
Data |
文字列 |
BLOB |
None | 16進数形式の任意のメタデータ。フィールドは256バイトに制限されています。 | |
ManagementFeeRate |
数値 |
UINT16 |
0 | ローンプロトコルオーナーが課金する1/10ベーシスポイントの手数料。有効な値は0から10000(0~100%)です。 | |
DebtMaximum |
数値 |
NUMBER |
0 | ローンプロトコルがVaultに負うことができる最大額。デフォルト値の0は債務の上限がないことを意味します。 | |
CoverRateMinimum |
数値 |
UINT16 |
0 | First-Loss Capitalが債務をカバーするために必要な1/10ベーシスポイントの比率。有効な値は0から100000(0~100%)です。 | |
CoverRateLiquidation |
数値 |
UINT16 |
0 | ローン債務不履行をカバーするためにFirst-Loss Capitalが清算される必要がある1/10ベーシスポイントの比率。有効な値は0から100000(0~100%)です。 |
3.1.1.1 失敗条件
-
LoanBrokerIDが指定されていない場合:-
VaultIDで指定されたVaultオブジェクトがレジャー上に存在しない。
-
-
送信者の
AccountRoot.Account != Vault(VaultID).Owner。 -
LoanBrokerIDが指定されている場合:-
LoanBrokerIDで指定されたLoanBrokerオブジェクトがレジャー上に存在しない。 - 送信者の
AccountRoot.Account != LoanBroker(LoanBrokerID).Owner. - 送信者が固定フィールドを変更しようとしている。
-
-
フィールドのいずれかが無効である。
3.1.1.2 状態変更
-
LoanBrokerIDが指定されていない場合:- 送信者の
OwnerDirectoryにLoanBrokerIDを追加。 - ローンプロトコルの
Vaultの_pseudo-account_のOwnerDirectoryにLoanBrokerIDを追加。
- 送信者の
-
If
LoanBrokerIDis specified:- Update appropriate fields.
3.1.1.3 不変条件
TBD
3.1.2 LoanBrokerDelete
| フィールド名 | 必須? | JSONの型 | 内部の型 | デフォルト値 | 説明 |
|---|---|---|---|---|---|
TransactionType |
✅ | string |
UINT16 |
TODO | トランザクションタイプ. |
LoanBrokerID |
string |
HASH256 |
N/A |
トランザクションが削除するLoanBrokerID. |
3.1.2.1 失敗条件
-
LoanBrokerIDで指定されたLoanBrokerオブジェクトがレジャー上に存在しない。 -
送信者の
AccountRoot.Account != LoanBroker(LoanBrokerID).Owner. -
OwnerCountが0より大きい。 -
CoverAvailableが0より大きい。
3.1.2.2 状態変更
- 送信者の
OwnerDirectoryからLoanBrokerIDを削除。 - ローンプロトコルの
Vaultの_pseudo-account_のOwnerDirectoryからLoanBrokerIDを削除。 -
LoanBrokerオブジェクトに関連するOwnerDirectoryを削除。
3.1.2.3 不変条件
TBD
3.1.3 LoanBrokerCoverDeposit
このトランザクションはLoanBrokerのCoverAvailableを増加させます。
| フィールド名 | 必須? | JSONの型 | 内部の型 | デフォルト値 | 説明 |
|---|---|---|---|---|---|
TransactionType |
✅ | 文字列 |
UINT16 |
TODO | トランザクションタイプ. |
LoanBrokerID |
✅ | 文字列 |
HASH256 |
N/A |
First-Loss Capitalを預けるLoanBrokerID. |
Amount |
✅ | オブジェクト |
NUMBER |
0 | First-Loss Capitalの金額. |
3.1.3.1 失敗条件
-
LoanBrokerIDで指定されたLoanBrokerオブジェクトがレジャー上に存在しない。 -
送信者の
AccountRoot.Account != LoanBroker(LoanBrokerID).Owner.-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetがIOUの場合- 送信者のアカウントと資産の
IssuerのRippleStateオブジェクトにlsfLowFreezeまたはlsfHighFreezeフラグが設定されている。 -
IssuerのAccountRootオブジェクトにlsfGlobalFreezeフラグが設定されている。 - トラストラインの
BalanceがAmountより小さい。
- 送信者のアカウントと資産の
-
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetがMPTの場合- 送信者の
AccountRootのMPTokenオブジェクトにVault(LoanBroker(LoanBrokerID).VaultID).Assetが設定されている。-
lsfMPTLockedフラグが設定されている。 -
MPTAmountがAmountより小さい。
-
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetのMPTokenIssuanceオブジェクトにlsfMPTLockedフラグが設定されている。
- 送信者の
3.1.3.2 状態変更
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetがXRPの場合-
擬似アカウント
AccountRootのBalanceフィールドをAmount増加。 - 送信者の
AccountRootのBalanceフィールドをAmount減少。
-
擬似アカウント
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetがIOUの場合-
擬似アカウント
AccountRootとIssuerのAccountRootのRippleStateバランスをAmount増加。 - 送信者の
AccountRootとIssuerのAccountRootのRippleStateバランスをAmount減少。
-
擬似アカウント
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetがMPTの場合-
擬似アカウント
MPTokenオブジェクトのMPTAmountフィールドをAmount増加。 - 送信者の
MPTokenオブジェクトのMPTAmountフィールドをAmount減少。
-
擬似アカウント
-
LoanBroker.CoverAvailableをAmount増加。
3.1.3.3 不変条件
TBD
3.1.4 LoanBrokerCoverWithdraw
LoanBrokerCoverWithdrawトランザクションはLoanBrokerからFirst-Loss Capitalを引き出します。
| フィールド名 | 必須? | JSONの型 | 内部の型 | デフォルト値 | 説明 |
|---|---|---|---|---|---|
TransactionType |
✅ | 文字列 |
UINT16 |
TODO | トランザクションタイプ. |
LoanBrokerID |
✅ | 文字列 |
HASH256 |
N/A |
First-Loss Capitalを引き出すLoanBrokerID. |
Amount |
✅ | オブジェクト |
NUMBER |
0 | 引き出す資産の金額。 |
3.1.4.1 失敗条件
-
LoanBrokerIDで指定されたLoanBrokerオブジェクトがレジャー上に存在しない。 -
送信者の
AccountRoot.Account != LoanBroker(LoanBrokerID).Owner. -
Vault(LoanBroker(LoanBrokerID).VaultID).AssetがIOUの場合- 送信者のアカウントと資産の
IssuerのRippleStateオブジェクトにlsfLowFreezeまたはlsfHighFreezeフラグが設定されている。 -
IssuerのAccountRootオブジェクトにlsfGlobalFreezeフラグが設定されている。
- 送信者のアカウントと資産の
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetがMPTの場合- 送信者の
AccountRootのMPTokenオブジェクトにVault(LoanBroker(LoanBrokerID).VaultID).Assetが設定されている。-
lsfMPTLockedフラグが設定されている。
-
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetのMPTokenIssuanceオブジェクトにlsfMPTLockedフラグが設定されている。
- 送信者の
-
送信者が資産を引き出そうとしているが、資産が
Vaultの資産と一致しない。 -
LoanBroker.CoverAvailable<Amount.
3.1.4.2 状態変更
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetがXRPの場合-
擬似アカウント
AccountRootのBalanceフィールドをAmount減少。 - 送信者の
AccountRootのBalanceフィールドをAmount増加。
-
擬似アカウント
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetがIOUの場合-
擬似アカウント
AccountRootとIssuerのAccountRootのRippleState残高をAmount減少。 - 送信者の
AccountRootとIssuerのAccountRootのRippleState残高をAmount増加。
-
擬似アカウント
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetがMPTの場合-
擬似アカウント
MPTokenオブジェクトのMPTAmountフィールドをAmount減少。 - 送信者の
MPTokenオブジェクトのMPTAmountフィールドをAmount増加。
-
擬似アカウント
-
LoanBroker.CoverAvailableをAmount減少。
3.2. Loanトランザクション
このセクションではLoanレジャーエントリーに関連するトランザクションを指定します。
3.2.1 LoanSetトランザクション
このトランザクションは新しいLoanオブジェクトを作成します。
| フィールド名 | 必須? | JSONの型 | 内部の型 | デフォルト値 | 説明 |
|---|---|---|---|---|---|
TransactionType |
✅ | string |
UINT16 |
TODO | トランザクションタイプ. |
LoanBrokerID |
✅ | string |
HASH256 |
N/A |
ローンブローカーID. |
Flags |
string |
UINT32 |
0 | ローンのフラグ. | |
Data |
string |
BLOB |
None | ローンのメタデータ. | |
Borrower |
✅ | string |
AccountID |
N/A |
ローンの借り手のアドレス. |
LoanOriginationFee |
number |
NUMBER |
0 | ローン作成時にローンブローカーに支払われる名目上の資金額. | |
LoanServiceFee |
number |
NUMBER |
0 | ローンの支払いごとにローンブローカーに支払われる名目上の資金額. | |
LatePaymentFee |
number |
NUMBER |
0 | ローンの支払いが遅れた場合にローンブローカーに支払われる名目上の資金額. | |
ClosePaymentFee |
number |
NUMBER |
0 | ローンの早期全額返済時にローンブローカーに支払われる名目上の資金額. | |
InterestRate |
number |
UINT16 |
0 | ベーシス・ポイントで表したローンの年換算金利。 | |
LateInterestRate |
number |
UINT16 |
0 | ベーシスポイント単位で、支払遅延に対する金利に上乗せされるプレミアム。有効な値は0~10000です。(0-100%) | |
CloseInterestRate |
number |
UINT16 |
0 | ベーシスポイント単位で、早期全額返済時に課される手数料。有効な値は0~100000です。(0-100%) | |
PrincipalRequested |
✅ | number |
NUMBER |
N/A |
借り手が要求した元本額。 |
StartDate |
✅ | number |
UINT32 |
N/A |
リップルエポックで表されるローン開始のタイムスタンプ。 |
PaymentsTotal |
number |
UINT32 |
1 | ローンの支払い回数。 | |
PaymentInterval |
number |
UINT32 |
60 | ローンの支払い間隔(秒)。 | |
GracePeriod |
number |
UINT32 |
60 | ローンの支払い期限日からデフォルトになるまでの猶予期間(秒)。 | |
Lender |
✅ | object |
STObject |
N/A |
トランザクション上の貸し手の署名を含む内部オブジェクト。 |
3.2.1.1 Flags
| Flag名 | Flag値 | 説明 |
|---|---|---|
tfLoanOverpayment |
0x0001 |
Vaultが超過支払いをサポートすることを示します。 |
3.2.1.2 Lender
トランザクションに対するLenderの署名を含む内部オブジェクトです。このオブジェクトに含まれるフィールドは以下の通りです。
| フィールド名 | 必須? | JSONの型 | 内部の型 | デフォルト値 | 説明 |
|---|---|---|---|---|---|
SigningPubKey |
✅ | 文字列 |
STBlob |
N/A |
署名の有効性を検証するために使用される公開鍵。 |
Signature |
✅ | 文字列 |
STBlob |
N/A |
BorrowerのSignatureを含むすべての署名フィールドに対する署名。 |
Signers |
✅ | リスト |
STArray |
N/A |
このトランザクションの承認を示すLoanBroker.Ownerの署名者からのトランザクション署名の配列。 |
最終的なトランザクションにはSignatureまたはSignersのいずれかが含まれている必要があります。
Signersフィールドが必要な場合、処理が必要な追加の署名により、マルチ署名の追加手数料と同様にトランザクションの合計手数料が増加します。最小手数料は
署名に対する合計手数料の計算は
このフィールドは署名フィールドではありません(トランザクション署名には含まれませんが、SignatureまたはSignersフィールドは保存されたトランザクションに含まれます)。
3.2.1.3 マルチシグ
LoanSetトランザクションは、ローンを作成するためのBorrowerとLoanBroke.Owner間の相互合意です。そのため、LoanSetトランザクションは両当事者によって署名される必要があります。マルチシグのフローは以下の通りです。
-
Borrowerが事前に合意されたローン条件で新しいトランザクションを作成し、署名します。 -
LenderがBorrowerの署名を含むすべての署名フィールドに署名します。
3.2.1.4 失敗条件
-
指定された
LoanBrokerIDを持つLoanBrokerオブジェクトがレジャー上に存在しない。 -
送信者の
AccountRoot.Account != LoanBroker(LoanBrokerID).Owner。 -
Lender.Signatureが無効。 -
Vault(LoanBroker(LoanBrokerID).VaultID).AssetがIOUの場合- 送信者アカウントと資産の
Issuer間のtrustlineがfreezeされている。 -
IssuerのAccountRootオブジェクトにlsfGlobalFreezeフラグが設定されている。
- 送信者アカウントと資産の
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetがMPTの場合- 送信者の
AccountRootのVault(LoanBroker(LoanBrokerID).VaultID).Assetに対するMPTokenオブジェクト-
lsfMPTLockedフラグが設定されている。
-
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetのMPTokenIssuanceオブジェクトにlsfMPTLockedフラグが設定されている。
- 送信者の
-
tfDefault、tfImpair、tfUnimpairフラグのいずれかが設定されている。 -
BorrowerのAccountRootオブジェクトが存在しない。 -
PaymentIntervalが60秒未満。 -
GracePeriodがPaymentIntervalより大きい。 -
Loan.StartDate < CurrentTime。 -
Vault内の資産が不足
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetsAvailable<Loan.PrincipalRequested。
-
-
LoanBrokerの最大債務を超過
-
LoanBroker(LoanBrokerID).DebtMaximum<LoanBroker(LoanBrokerID).DebtTotal + Loan.PrincipalRequested
-
-
First-Loss Capitalが不足
-
LoanBroker(LoanBrokerID).CoverAvailable<(LoanBroker(LoanBrokerID).DebtTotal + Loan.PrincipalRequested) x LoanBroker(LoanBrokerID).CoverRateMinimum
-
3.2.1.5 状態変更
-
ローン資産が
IOUの場合-
IssuerとBorrower間にTrustlineが存在しない場合は作成。
-
-
ローン資産が
MPTの場合-
BorrowerのMPTokenオブジェクトが存在しない場合は作成。
-
-
Vault(LoanBroker(LoanBrokerID).VaultID)オブジェクトの状態変更-
Vault内の利用可能な資産を減少
-
Vault.AssetsAvailable -= Loan.PrincipalRequested。
-
-
Vaultの総価値を増加
-
Vault.AssetsTotal += LoanInterest - (LoanInterest x LoanBroker.ManagementFeeRate)(LoanInterestはローンの総利息)。
-
-
-
LoanBroker(LoanBrokerID)オブジェクトの変更-
LoanBroker.DebtTotal += Loan.PrincipalRequested + (LoanInterest - (LoanInterest x LoanBroker.ManagementFeeRate) -
LoanBroker.OwnerCount += 1 -
LoanBrokerのDirectoryNodeが存在しない場合は作成。-
DirectoryNode.IndexesにLoanIDを追加。
-
-
3.2.1.4 不変条件
TBD
3.2.2 LoanDeleteトランザクション
このトランザクションは既存のLoanオブジェクトを削除します。
| フィールド名 | 必須? | JSONの型 | 内部の型 | デフォルト値 | 説明 |
|---|---|---|---|---|---|
TransactionType |
✅ | 文字列 |
UINT16 |
TODO | トランザクションタイプ。 |
LoanID |
✅ | 文字列 |
HASH256 |
N/A |
削除するLoanオブジェクトのID。 |
3.2.2.1 失敗条件
- 指定された
LoanIDを持つLoanオブジェクトがレジャー上に存在しない。 -
LoanDeleteを送信するアカウントがLoanBroker.OwnerまたはLoan.Borrowerではない。 - ローンがアクティブ
Loan.PaymentsRemaining > 0
3.2.2.2 状態変更
-
LoanBrokerに関連付けられたOwner DirectoryからLoanIDを削除。 LoanBroker.OwnerCount -= 1-
Loanオブジェクトを削除。 - 準備金をBorrowerに返還。
3.2.3 LoanManageトランザクション
| フィールド名 | 必須? | JSONの型 | 内部の型 | デフォルト値 | 説明 |
|---|---|---|---|---|---|
TransactionType |
✅ | 文字列 |
UINT16 |
TODO | トランザクションタイプ。 |
LoanID |
✅ | 文字列 |
HASH256 |
N/A |
更新するLoanオブジェクトのID。 |
Flags |
文字列 |
UINT32 |
0 | ローンのフラグを指定。 |
3.2.3.1 Flags
| Flag名 | Flag値 | 説明 |
|---|---|---|
tfLoanDefault |
0x0001 |
ローンをデフォルト状態にすることを示す。 |
tfLoanImpair |
0x0002 |
ローンを債務不履行状態にすることを示す。 |
tfLoanUnimpair |
0x0003 |
ローンの債務不履行状態を解除することを示す。 |
3.2.3.1 失敗条件
-
指定された
LoanIDを持つLoanオブジェクトがレジャー上に存在しない。 -
トランザクションを送信する
AccountがLoanBroker.Ownerではない。 -
ローンオブジェクトに
lsfLoanDefaultフラグが設定されている。ローンがデフォルトになると、変更できない。 -
Loan(LoanID).Flags == lsfLoanImpairedかつtfLoanImpairフラグが提供されている。 -
Loan.PaymentsRemaining == 0 -
tfDefaultフラグが指定され、かつ-
CurrentTime<Loan.NextPaymentDueDate + Loan.GracePeriod
-
3.2.3.2 状態変更
-
tfDefaultフラグが指定されている場合-
First-Loss Capitalがカバーするデフォルト額を計算
- デフォルト値は、Borrowerが未請求の資金を除く、未払いの元本と利息の合計。
-
DefaultAmount = (Loan.PrincipalOutstanding + Loan.InterestOutstanding) - Loan.AssetsAvailable。
-
- First-Loss Capitalをデフォルト値に適用
DefaultCovered = min((LoanBroker(Loan.LoanBrokerID).DebtTotal x LoanBroker(Loan.LoanBrokerID).CoverRateMinimum) x LoanBroker(Loan.LoanBrokerID).CoverRateLiquidation, DefaultAmount)
DefaultAmount -= DefaultCovered
- デフォルト値は、Borrowerが未請求の資金を除く、未払いの元本と利息の合計。
-
Vaultオブジェクトを更新- Vaultの総価値を減少
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetsTotal -= DefaultAmount。
-
- Vaultの利用可能な資産を清算されたFirst-Loss Capitalと未請求の資金額分増加
-
Vault(LoanBroker(LoanBrokerID).VaultID).AssetsAvailable += DefaultCovered + Loan.AssetsAvailable。
-
- Vaultの総価値を減少
-
-
LoanBrokerオブジェクトを更新- LoanBrokerの債務を減少
LoanBroker(LoanBrokerID).DebtTotal -=Loan.PrincipalOutstanding + Loan.InterestOutstanding + Loan.AssetsAvailable
- 利用可能なFirst-Loss Capitalカバーを減少
LoanBroker(LoanBrokerID).CoverAvailable -= DefaultCovered
- アクティブなローン数を減少
LoanBroker(LoanBrokerID).OwnerCount -= 1
- LoanBrokerの債務を減少
-
Loanオブジェクトを更新Loan(LoanID).Flags = lsfLoanDefaultLoan(LoanID).PaymentsRemaining = 0Loan(LoanID).AssetsAvailable = 0Loan(LoanID).PrincipalOutstanding = 0
-
tfLoanImpairフラグが指定されている場合-
Vaultオブジェクトを更新("含み損"を設定)-
Vault(LoanBroker(LoanBrokerID).VaultID).LossUnrealized += Loan.PrincipalOutstanding + TotalInterestOutstanding()(未払い利息の合計の計算方法については3.2.5.1. 支払いタイプセクションを参照)
-
-
Loanオブジェクトを更新Loan(LoanID).Flags = lsfLoanImpaired-
currentTime < Loan(LoanID).NextPaymentDueDateの場合(ローン支払いがまだ遅延していない場合)-
Loan(LoanID).NextPaymentDueDate = currentTime(次回支払い期限を現在時刻に移動)
-
-
-
tfLoanUnimpairフラグが指定されている場合-
Vaultオブジェクトを更新("含み損"をクリア) -
Vault(LoanBroker(LoanBrokerID).VaultID).LossUnrealized -= Loan.PrincipalOutstanding + TotalInterestOutstanding()(未払い利息の合計の計算方法については3.2.5.1. 支払いタイプセクションを参照) -
Loanオブジェクトを更新-
Loan(LoanID).Flags = 0 -
Loan(LoanID).PreviousPaymentDate + Loan(LoanID).PaymentInterval > currentTimeの場合(支払い期間内にローンの債務不履行が解除された場合)Loan(LoanID).NextPaymentDueDate = Loan(LoanID).PreviousPaymentDate + Loan(LoanID).PaymentInterval
-
Loan(LoanID).PreviousPaymentDate + Loan(LoanID).PaymentInterval < currentTimeの場合(元の支払い期限後にローンの債務不履行が解除された場合)Loan(LoanID).NextPaymentDueDate = currentTime + Loan(LoanID).PaymentInterval
-
-
3.2.3.3 不変条件
TBD
3.2.4 LoanDrawトランザクション
Borrowerがローンから資金を引き出すためにLoanDrawトランザクションを送信します。
| フィールド名 | 必須? | JSONの型 | 内部の型 | デフォルト値 | 説明 |
|---|---|---|---|---|---|
TransactionType |
✅ | 文字列 |
UINT16 |
TODO | トランザクションタイプ。 |
LoanID |
✅ | 文字列 |
HASH256 |
N/A |
引き出し元のLoanオブジェクトのID。 |
Amount |
✅ | 数値 |
NUMBER |
N/A |
引き出す資金額。 |
3.2.4.1 失敗条件
-
指定された
LoanIDを持つLoanオブジェクトがレジャー上に存在しない。 -
送信者の
AccountRoot.AccountがLoan.Borrowerではない。 -
ローンが開始していない
Loan.StartDate > CurrentTime
-
資産が不足している
-
Loan.AssetsAvailable<Amount
-
-
LoanにlsfLoanImpairedまたはlsfLoanDefaultフラグが設定されている。 -
Vault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).AssetがIOUの場合- 送信者アカウントと資産の
Issuer間のtrustlineがfreezeされている。 -
IssuerのAccountRootオブジェクトにlsfGlobalFreezeフラグが設定されている。
- 送信者アカウントと資産の
-
Vault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).AssetがMPTの場合- 送信者の
AccountRootのVault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).Assetに対するMPTokenオブジェクト-
lsfMPTLockedフラグが設定されている。
-
-
Vault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).AssetのMPTokenIssuanceオブジェクトにlsfMPTLockedフラグが設定されている。
- 送信者の
-
Borrowerが支払いを遅延CurrentTime > Loan.NextPaymentDueDate
3.2.4.2 状態変更
-
Vault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).AssetがXRPの場合- pseudo-account
AccountRootのBalanceフィールドをAmount分減少。 - 送信者の
AccountRootのBalanceフィールドをAmount分増加。
- pseudo-account
-
Vault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).AssetがIOUの場合- pseudo-account
AccountRootとIssuerAccountRoot間のRippleState残高をAmount分減少。 - 送信者の
AccountRootとIssuerAccountRoot間のRippleState残高をAmount分増加。
- pseudo-account
-
Vault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).AssetがMPTの場合-
Vault.Assetに対するpseudo-accountMPTokenオブジェクトのMPToken.MPTAmountをAmount分減少。 -
Vault.Assetに対する送信者のMPTokenオブジェクトのMPToken.MPTAmountをAmount分増加。
-
-
Loan.AssetsAvailableをAmount分減少。
3.2.4.3 不変条件
TBD
3.2.5 LoanPayトランザクション
Borrowerがローンの支払いを行うためにLoanPayトランザクションを送信します。
| フィールド名 | 必須? | JSONの型 | 内部の型 | デフォルト値 | 説明 |
|---|---|---|---|---|---|
TransactionType |
✅ | 文字列 |
UINT16 |
TODO | トランザクションタイプ。 |
LoanID |
✅ | 文字列 |
HASH256 |
N/A |
支払い対象のLoanオブジェクトのID。 |
Amount |
✅ | 数値 |
NUMBER |
N/A |
支払う資金額。 |
3.2.5.1 支払いタイプ
ローン支払いには4つのタイプがあります。
-
標準償却計算式で計算された支払い額とスケジュールに従って期限内に行われる通常支払い。
-
netxPaymentDueDate後にBorrowerが行う 遅延 支払い。遅延支払いにはLatePaymentFeeとLateInterestRateが含まれます。 -
Borrowerが未払い元本を支払う早期 全額 支払い。未払い元本に対して
CloseInterestRateが課されます。 -
借り手が必要最低支払額を超える支払いを行う超過支払い。
支払いの金額とタイミングによって支払いのタイプが決定されます。Loan.NextPaymentDueDate以前に行われる支払いは通常支払いとなり、標準償却計算に従います。この日付以降に行われる支払いは遅延支払いとみなされます。
以下の図は、支払われた金額に基づいて支払いがどのように処理されるかを示しています。
拒否 超過支払い 超過支払い 超過支払い 請求なし
|------------|---------------|---------------|---------------|-------------|
定期/遅延 定期 定期 全額
支払い額 支払い額 支払い額 支払い額
I II N - 1 支払い額
必要最低支払額は、借り手がNextPaymentDueDate以前に支払いを行うか、遅延するかによって決定されます。必要最低額を下回る支払いは拒否されます。借り手は単一のLoanPayトランザクションで複数のローン支払いを行うことができます。例えば、定期支払い額が400トークンで、借り手が900トークンの支払いを行った場合、その支払いは2回分の定期支払いとして扱われ、NextPaymentDueDateは2支払い期間分前進し、残りの100トークンは超過支払いとなります。
Loan Brokerと借り手が超過支払いを許可することに合意している場合、定期支払い額を超える金額は超過支払いとして扱われます。ただし、超過支払いがサポートされていない場合、超過額は請求されず、借り手の元に残ります。
各支払いは、principal(元本)、interest(利息)、fee(手数料)の3つの部分で構成されます。principalはローンの元本に対して支払われる金額、interestはローンの利息部分、feeはprincipalとinterestに加えて借り手が支払う手数料部分です。
3.2.5.1.1 通常支払い
定期支払い額は、元利均等返済の支払い公式を使用して計算されます。
ここで、定期利率は支払い期間ごとに課される利率です。
principalとinterestの部分は次のように導出できます。
3.2.5.1.2 遅延支払い
借り手がNextPaymentDueDate以降に支払いを行う場合、名目遅延支払い手数料と、未払い期間の延滞額に対して課される追加利息を支払う必要があります。計算式は以下の通りです。
延滞期間に対して特別な遅延支払い利率が適用されます。
遅延支払いはLoanSetトランザクションでVault価値を増加させる際に計算された利息よりも多くの利息を支払います。したがって、Vault.AssetsTotalで捕捉されるVaultの総価値を再計算する必要があります。
PeriodicPayment()関数がprincipalPeriodicとinterestPeriodicに分割された予想定期支払い額を返すと仮定します。さらに、遅延支払い計算式を実装するLatePayment()関数を仮定します。この関数は、上記の計算式を使用して計算されたprincipalLateとinterestLateに分割された遅延支払いを返します。principalPeriodic == principalLateおよびinterestLate > interestPeriodicは支払いが遅延した場合にのみ使用されることに注意してください。それ以外の場合は、interestLate == interestPeriodicとなります。
valueChange >= 0であることに注意してください。
3.2.5.1.3 ローン超過支払い
-
と\mathcal{P} をそれぞれローンの総元本と未払い元本とします。\mathcal{p} -
と\mathcal{I} をそれぞれ\mathcal{i} と\mathcal{P} から計算された総利息と未払い利息とします。\mathcal{p}
3.2.5.1.4 早期全額返済
借り手は、全額返済に必要な総額を提出することで、ローンを早期に完済することができます。この金額は、残高、発生利息、期限前返済ペナルティ、および期限前返済手数料の合計です。
早期完済時点までの発生利息は以下のように計算されます。
最後に、Lenderはローンの早期返済に対して期限前返済ペナルティを課すことができ、これは以下のように計算されます。
早期返済はLoanSetトランザクションでVault価値を増加させる際に計算された利息よりも少ない利息を支払います。したがって、Vault.AssetsTotalで捕捉されるVaultの価値は早期返済後に再計算する必要があります。
ローンのprincipalOutstandingとinterestOutstandingを返すCurrentValue()関数を仮定します。さらに、全額返済の計算を実装するClosePayment()関数を仮定します。この関数はprincipalとinterestに分割された支払うべき全額返済額を返します。
早期全額返済の価値変更は以下のように計算されます。
valueChange <= 0となることに注意してください。これは早期返済がローンの総価値を減少させるためです。
3.2.5.1.5 管理手数料の計算
LoanBroker管理手数料はローンの利息部分に対して課され、ローン作成時にローンの総価値から差し引かれます。ただし、手数料は実際にはローン支払い時にのみ課されます。早期支払いや遅延支払いは、総利息の価値を減少または増加させることでローンの総価値を変更します。したがって、早期、遅延、または超過支払いが行われた場合、管理手数料を更新する必要があります。
管理手数料を更新するには、早期または遅延支払いを実行した後の新しい総利息に基づいて、新しい総管理手数料を計算する必要があります。そのため、支払いが行われる前のローン価値と、支払い後の新しい価値を捕捉する必要があります。
計算のために、以下の変数を仮定します。
-
と\mathcal{P} をそれぞれローンの総元本と未払い元本とします。\mathcal{p} -
と\mathcal{I} をそれぞれ\mathcal{i} と\mathcal{P} から計算された総利息と未払い利息とします。\mathcal{p} -
と\mathcal{V} をそれぞれローンの総価値と未払い価値とします。\mathcal{v} および\mathcal{V} = \mathcal{P} + \mathcal{I} です。\mathcal{v} = \mathcal{p} + \mathcal{i} - 最後に、
をLoan Brokerの管理手数料率とします。\mathcal{m}
総管理手数料は以下のように計算されます。
これまでに支払われた管理手数料を以下のように計算します。
最後に、管理手数料の変更を以下のように計算します。
上記の計算は以下のように簡略化できます。
管理手数料の変更が負の場合、ローンの価値は減少し、したがってLoan Brokerの債務も減少します。
直感的に、負の手数料変更は手数料を返還する必要があることを示唆し、これによってloan brokerの債務が増加します。
対照的に、管理手数料の変更が正の場合、ローンの価値は増加し、さらなる手数料を債務から差し引く必要があります。
直感的に、正の手数料変更は支払われる利息の増加により追加の手数料を支払う必要があることを示唆します。
LoanBrokerの債務は以下のように更新されます。
3.2.5.2 トランザクションの疑似コード
以下はローン支払いトランザクションを処理するための疑似コードです。
function make_payment(amount, current_time) -> (principal_paid, interest_paid, value_change, fee_paid):
if loan.payments_remaining is 0 || loan.principal_outstanding is 0 {
return "loan complete" error
}
// 支払いが遅延している場合
if loan.next_payment_due_date < current_time {
let late_payment = loan.compute_late_payment(current_time)
if amount < late_payment {
return "insufficient amount paid" error
}
loan.payments_remaining -= 1
loan.principal_outstanding -= late_payment.principal
loan.last_payment_date = loan.next_payment_due_date
loan.next_payment_due_date = loan.next_payment_due_date + loan.payment_interval
let periodic_payment = loan.compute_periodic_payment()
// 遅延支払いはローンの価値を定期支払いと遅延支払いの利息の差分だけ増加させる
return (late_payment.principal, late_payment.interest, late_payment.interest - periodic_payment.interest, loan.late_payment_fee)
}
let full_payment = loan.compute_full_payment(current_time)
// 支払額が全額返済額以上で、かつ1回以上の支払いが残っている場合は
// 全額返済を行う
if amount >= full_payment && loan.payments_remaining > 1 {
loan.payments_remaining = 0
loan.principal_outstanding = 0
// 全額返済はローンの価値を支払われた利息と予想される未払い利息の差分だけ減少させる
return (full_payment.principal, full_payment.interest, full_payment.interest - loan.compute_current_value().interest, full_payment.fee)
}
// 支払いが遅延でもなく全額返済でもない場合は定期支払い
let periodic_payment = loan.compute_periodic_payment()
let full_periodic_payments = floor(amount / periodic_payment)
if full_periodic_payments < 1 {
return "insufficient amount paid" error
}
loan.payments_remaining -= full_periodic_payments
loan.next_payment_due_date = loan.next_payment_due_date + loan.payment_interval * full_periodic_payments
loan.last_payment_date = loan.next_payment_due_date - loan.payment_interval
let total_principal_paid = 0
let total_interest_paid = 0
let loan_value_change = 0
let total_fee_paid = loan.service_fee * full_periodic_payments
while full_periodic_payments > 0 {
total_principal_paid += periodic_payment.principal
total_interest_paid += periodic_payment.interest
periodic_payment = loan.compute_periodic_payment()
full_periodic_payments -= 1
}
loan.principal_outstanding -= total_principal_paid
let overpayment = min(loan.principal_outstanding, amount % periodic_payment)
if overpayment > 0 && is_set(lsfOverPayment) {
let interest_portion = overpayment * loan.overpayment_interest_rate
let fee_portion = overpayment * loan.overpayment_fee
let remainder = overpayment - interest_portion - fee_portion
total_principal_paid += remainder
total_interest_paid += interest_portion
total_fee_paid += fee_portion
let current_value = loan.compute_current_value()
loan.principal_outstanding -= remainder
let new_value = loan.compute_current_value()
loan_value_change = (new_value.interest - current_value.interest) + interest_portion
}
return (total_principal_paid, total_interest_paid, loan_value_change, total_fee_paid)
}
3.2.5.3 失敗条件
-
指定された
LoanIDを持つLoanオブジェクトがledger上に存在しない。 -
ローンがまだ開始していない:
Loan.StartDate > CurrentTime。 -
トランザクション送信者の
AccountRoot.AccountがLoan.Borrowerと等しくない。 -
Loan.PaymentsRemainingまたはLoan.PrincipalOutstandingが0。 -
Vault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).AssetがIOUの場合- 送信者アカウントと資産の
Issuer間のトラストラインがフリーズされている。 -
IssuerのAccountRootオブジェクトにlsfGlobalFreezeフラグが設定されている。
- 送信者アカウントと資産の
-
Vault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).AssetがMPTの場合- 送信者の
AccountRootのVault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).Assetに対するMPTokenオブジェクト-
lsfMPTLockedフラグが設定されている。
-
-
Vault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).AssetのMPTokenIssuanceオブジェクトにlsfMPTLockedフラグが設定されている。
- 送信者の
-
CurrentTime > Loan.NextPaymentDueDateかつAmount<LatePaymentAmount() -
CurrentTime <= Loan.NextPaymentDueDateかつAmount<PeriodicPaymentAmount()
3.2.5.4 状態変更
支払いがprincipal、interest、feeに分割され、totalDue = principal + interest + feeと仮定します。
疑似コードを実装する関数によって支払いが処理され、principal_paid、interest_paid、value_change、fee_paidを返すと仮定します。
-
principal_paidは支払いがカバーした元本額 -
interest_paidは支払いがカバーした利息額 -
fee_paidは支払いがカバーした手数料額 -
value_changeはローンの総価値が変化した額-
value_change<0の場合、ローン価値は減少 -
value_change>0の場合、ローン価値は増加
-
さらに、full_periodic_payments変数は支払いがカバーした支払い期間の数を表すと仮定します。
-
Loanオブジェクトの状態変更-
Loan(LoanID).Flags == lsfLoanImpairedの場合Loan(LoanID).Flags = 0
-
Loan.PaymentsRemainingをfull_periodic_paymentsだけ減少 -
Loan.PrincipalOutstandingをprincipal_paidだけ減少 -
Loan.PaymentsRemaining > 0かつLoanPrincipalOutstanding > 0の場合- 次回支払い日を設定:
Loan.NextPaymentDueDate += Loan.PaymentInterval * full_periodic_payments - 前回支払い日を設定:
Loan.PreviousPaymentDate = Loan.NextPaymentDueDate - Loan.PaymentInterval
- 次回支払い日を設定:
-
-
LoanBroker(Loan.LoanBrokerID)オブジェクトの状態変更-
管理手数料を計算
feeManagement = interest_paid x LoanBroker.ManagementFeeRate
-
First-Loss Capitalが不十分な場合
LoanBroker.CoverAvailable < LoanBroker.DebtTotal x LoanBroker.CoverRateMinimum- 管理手数料を課さず、総債務に追加
LoanBroker.DebtTotal += feeManagement
- 管理手数料を課さず、総債務に追加
-
First-Loss Capitalが十分な場合
LoanBroker.CoverAvailable >= LoanBroker.DebtTotal x LoanBroker.CoverRateMinimum- 支払総額から管理手数料を減少
totalPaid = totalPaid - feeManagement
- 支払総額から管理手数料を減少
-
支払額だけLoanBrokerの債務を減少
LoanBroker.DebtTotal -= totalPaid
-
ローン価値の変更によってLoanBrokerの債務を更新
LoanBroker.DebtTotal += valueChange
-
管理手数料の変更によってLoanBrokerの債務を更新
LoanBroker.DebtTotal -= (valueChange x LoanBroker.ManagementFeeRate)
-
LoanPaymentsRemaining == 0かつLoanPrincipalOutstanding == 0の場合- アクティブローンを減少
LoanBroker.OwnerCount = LoanBroker.OwnerCount - 1
- アクティブローンを減少
-
-
Vault(LoanBroker(Loan.LoanBrokerID).VaultID)オブジェクトの状態変更-
Vault内の利用可能な資産を支払額だけ増加
Vault.AssetsAvailable = Vault.AssetsAvailable + totalPaid
-
ローンの総価値の変更によってVaultの総価値を更新
Vault.AssetsTotal = Vault.AssetsTotal + valueChange
-
管理手数料の変更によってVaultの総価値を更新
Vault.AssetsTotal = Vault.AssetsTotal - (vaultChange x LoanBroker.managementFeeRate)
-
First-Loss Capitalが不十分な場合
LoanBroker.CoverAvailable < LoanBroker.DebtTotal x LoanBroker.CoverRateMinimum- 管理手数料が課されなかったため、Vaultの総価値を減少
Loan.AssetsTotal = Loan.AssetsTotal + feeManagement
- 管理手数料が課されなかったため、Vaultの総価値を減少
-
-
Vault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).AssetがXRPの場合-
pseudo-account
AccountRootのBalanceフィールドをprincipal_paid + (interest_paid - management_fee)だけ増加。 -
LoanBroker.CoverAvailable >= LoanBroker.DebtTotal x LoanBroker.CoverRateMinimumの場合-
LoanBroker.OwnerAccountRootのBalanceフィールドをfee_paid + management_feeだけ増加。
-
-
送信者の
AccountRootのBalanceフィールドをprincipal_paid + interest_paid + fee_paidだけ減少。
-
-
Vault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).AssetがIOUの場合-
pseudo-account
AccountRootとIssuerAccountRoot間のRippleState残高をprincipal_paid + (interest_paid - management_fee)だけ増加。 -
LoanBroker.CoverAvailable >= LoanBroker.DebtTotal x LoanBroker.CoverRateMinimumの場合-
LoanBroker.OwnerAccountRootとIssuerAccountRoot間のRippleState残高をfee_paid + management_feeだけ増加。
-
-
送信者の
AccountRootとIssuerAccountRoot間のRippleState残高をprincipal_paid + interest_paid + fee_paidだけ減少。
-
-
Vault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).AssetがMPTの場合-
pseudo-accountの
Vault.Assetに対するMPTokenオブジェクトのMPToken.MPTAmountをprincipal_paid + (interest_paid - management_fee)だけ増加。 -
LoanBroker.CoverAvailable >= LoanBroker.DebtTotal x LoanBroker.CoverRateMinimumの場合-
LoanBroker.OwnerのVault.Assetに対するMPTokenオブジェクトのMPToken.MPTAmountをfee_paid + management_feeだけ増加。
-
-
送信者の
Vault.Assetに対するMPTokenオブジェクトのMPToken.MPTAmountをprincipal_paid + interest_paid + fee_paidだけ減少。
-
3.2.5.4 不変条件
TBD
Discussion