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%に相当します。 |
LoanBroker
pseudo-account
2.1.3 レンディングプロトコルは、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 トークン
Loan
レジャーエントリ
2.2. 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. トランザクション
LoanBroker
トランザクション
3.1. このセクションではLoanBroker
レジャーエントリに関連するトランザクションを指定します。
LoanBrokerSet
3.1.1 このトランザクションは新しい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
LoanBrokerID
is specified:- Update appropriate fields.
3.1.1.3 不変条件
TBD
LoanBrokerDelete
3.1.2 フィールド名 | 必須? | 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
LoanBrokerCoverDeposit
3.1.3 このトランザクションは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
LoanBrokerCoverWithdraw
3.1.4 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
減少。
Loan
トランザクション
3.2. このセクションではLoan
レジャーエントリーに関連するトランザクションを指定します。
LoanSet
トランザクション
3.2.1 このトランザクションは新しい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
LoanDelete
トランザクション
3.2.2 このトランザクションは既存の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に返還。
LoanManage
トランザクション
3.2.3 フィールド名 | 必須? | 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 = lsfLoanDefault
Loan(LoanID).PaymentsRemaining = 0
Loan(LoanID).AssetsAvailable = 0
Loan(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
LoanDraw
トランザクション
3.2.4 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
とIssuer
AccountRoot
間のRippleState
残高をAmount
分減少。 - 送信者の
AccountRoot
とIssuer
AccountRoot
間の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
LoanPay
トランザクション
3.2.5 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.Owner
AccountRoot
のBalance
フィールドをfee_paid + management_fee
だけ増加。
-
-
送信者の
AccountRoot
のBalance
フィールドをprincipal_paid + interest_paid + fee_paid
だけ減少。
-
-
Vault(LoanBroker(Loan(LoanID).LoanBrokerID).VaultID).Asset
がIOU
の場合-
pseudo-account
AccountRoot
とIssuer
AccountRoot
間のRippleState
残高をprincipal_paid + (interest_paid - management_fee)
だけ増加。 -
LoanBroker.CoverAvailable >= LoanBroker.DebtTotal x LoanBroker.CoverRateMinimum
の場合-
LoanBroker.Owner
AccountRoot
とIssuer
AccountRoot
間のRippleState
残高をfee_paid + management_fee
だけ増加。
-
-
送信者の
AccountRoot
とIssuer
AccountRoot
間の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