Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loans: multiple cashflows #1797

Closed
wants to merge 35 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8ca7dc2
updated from #1408
lemunozm Apr 5, 2024
9945d65
add testing
lemunozm Apr 15, 2024
d129f98
organize and polish cashflow module
lemunozm Apr 19, 2024
a4c790a
add Runtime API
lemunozm Apr 19, 2024
db17ebc
update types.md
lemunozm Apr 19, 2024
6fdf348
Merge remote-tracking branch 'origin/main' into loans/multi-cashflows
lemunozm Apr 23, 2024
85eb05f
make it works without chronoutils
lemunozm Apr 25, 2024
bd61fea
minor changes
lemunozm Apr 25, 2024
abc3ef0
add borrow check
lemunozm Apr 25, 2024
2de713b
fix legacy increase_debt test
lemunozm Apr 25, 2024
87a0d07
add loan cashflow tests
lemunozm Apr 26, 2024
4c56cb2
compute principal and interest
lemunozm Apr 27, 2024
76de6d0
correct validation
lemunozm May 7, 2024
b06d980
add CashflowPayment type
lemunozm May 7, 2024
317990a
Merge remote-tracking branch 'origin/main' into loans/multi-cashflows
lemunozm May 7, 2024
8c41d5d
add variant error
lemunozm May 7, 2024
1d60312
fix interest computation when months are partial
lemunozm May 8, 2024
df15e66
remove Rate usage and use weight
lemunozm May 8, 2024
a60d0fd
fix start date for cashflows
lemunozm May 8, 2024
a864ad4
rename api name
lemunozm May 8, 2024
39eb12d
fix benchmarks
lemunozm May 9, 2024
010469d
taplo fmt
lemunozm May 9, 2024
8216dda
using a lower discount rate to simply benchmarking
lemunozm May 9, 2024
b986de0
Merge remote-tracking branch 'origin/main' into loans/multi-cashflows
lemunozm May 13, 2024
77dada6
rewrite doc line
lemunozm May 13, 2024
3321024
Merge remote-tracking branch 'origin/main' into loans/multi-cashflows
lemunozm May 24, 2024
205fb68
Merge remote-tracking branch 'origin/main' into loans/multi-cashflows
lemunozm Jun 5, 2024
338cece
interest computed at maturity
lemunozm Jun 6, 2024
2c4a180
remove borrow support
lemunozm Jun 6, 2024
d37a4e4
Merge remote-tracking branch 'origin/main' into loans/multi-cashflows
lemunozm Jun 6, 2024
70ea49c
fix compilation
lemunozm Jun 6, 2024
f9db4fc
None to OnceAtMaturity variant
lemunozm Jun 6, 2024
12affcc
compilation fixes
lemunozm Jun 6, 2024
2e79fc2
Merge remote-tracking branch 'origin/main' into loans/multi-cashflows
lemunozm Jun 6, 2024
b7ee635
Loans: multi cashflows fix external loan (#1864)
lemunozm Jun 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ rev_slice = { version = "0.1.5", default-features = false }
impl-trait-for-tuples = "0.2.1"
num-traits = { version = "0.2", default-features = false }
num_enum = { version = "0.5.3", default-features = false }
chrono = { version = "0.4", default-features = false }
chronoutil = "0.2"

# Cumulus
cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, branch = "release-polkadot-v1.1.0" }
Expand Down
2 changes: 2 additions & 0 deletions pallets/loans/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
parity-scale-codec = { workspace = true }
scale-info = { workspace = true }
chrono = { workspace = true }
chronoutil = { workspace = true }

frame-support = { workspace = true }
frame-system = { workspace = true }
Expand Down
4 changes: 2 additions & 2 deletions pallets/loans/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ use crate::{
},
pallet::*,
types::{
cashflow::{InterestPayments, Maturity, PayDownSchedule, RepaymentSchedule},
valuation::{DiscountedCashFlow, ValuationMethod},
BorrowRestrictions, InterestPayments, LoanRestrictions, Maturity, PayDownSchedule,
RepayRestrictions, RepaymentSchedule,
BorrowRestrictions, LoanRestrictions, RepayRestrictions,
},
};

Expand Down
5 changes: 3 additions & 2 deletions pallets/loans/src/entities/changes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use crate::{
entities::input::{PrincipalInput, RepaidInput},
pallet::Config,
types::{
policy::WriteOffRule, valuation::ValuationMethod, InterestPayments, Maturity,
PayDownSchedule,
cashflow::{InterestPayments, Maturity, PayDownSchedule},
policy::WriteOffRule,
valuation::ValuationMethod,
},
};

Expand Down
36 changes: 26 additions & 10 deletions pallets/loans/src/entities/loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ use crate::{
},
pallet::{AssetOf, Config, Error},
types::{
cashflow::RepaymentSchedule,
policy::{WriteOffStatus, WriteOffTrigger},
BorrowLoanError, BorrowRestrictions, CloseLoanError, CreateLoanError, LoanRestrictions,
MutationError, RepaidAmount, RepayLoanError, RepayRestrictions, RepaymentSchedule,
MutationError, RepaidAmount, RepayLoanError, RepayRestrictions,
},
};

Expand Down Expand Up @@ -237,6 +238,12 @@ impl<T: Config> ActiveLoan<T> {
}
}

pub fn principal(&self) -> Result<T::Balance, DispatchError> {
Ok(self
.total_borrowed
.ensure_sub(self.total_repaid.principal)?)
}

pub fn write_off_status(&self) -> WriteOffStatus<T::Rate> {
WriteOffStatus {
percentage: self.write_off_percentage,
Expand Down Expand Up @@ -345,6 +352,20 @@ impl<T: Config> ActiveLoan<T> {
Error::<T>::from(BorrowLoanError::MaturityDatePassed)
);

// TODO
// If the loan has an interest or pay down schedule other than None,
// then we should only allow borrowing more if no interest or principal
// payments are overdue.
//
// This is required because after borrowing more, it is not possible
// to validate anymore whether previous cashflows matched the repayment
// schedule, as we don't store historic data of the principal.
//
// Therefore, in `borrow()` we set repayments_on_schedule_until to now.
//
// TODO: check total_repaid_interest >= total_expected_interest
// and total_repaid_principal >= total_expected_principal

Ok(())
}

Expand Down Expand Up @@ -378,11 +399,8 @@ impl<T: Config> ActiveLoan<T> {
) -> Result<RepaidInput<T>, DispatchError> {
let (max_repay_principal, outstanding_interest) = match &self.pricing {
ActivePricing::Internal(inner) => {
amount.principal.internal()?;

let principal = self
.total_borrowed
.ensure_sub(self.total_repaid.principal)?;
let _ = amount.principal.internal()?;
let principal = self.principal()?;

(principal, inner.outstanding_interest(principal)?)
}
Expand Down Expand Up @@ -519,7 +537,7 @@ impl<T: Config> ActiveLoan<T> {

#[cfg(feature = "runtime-benchmarks")]
pub fn set_maturity(&mut self, duration: Seconds) {
self.schedule.maturity = crate::types::Maturity::fixed(duration);
self.schedule.maturity = crate::types::cashflow::Maturity::fixed(duration);
}
}

Expand Down Expand Up @@ -555,9 +573,7 @@ impl<T: Config> TryFrom<(T::PoolId, ActiveLoan<T>)> for ActiveLoanInfo<T> {

Ok(match &active_loan.pricing {
ActivePricing::Internal(inner) => {
let principal = active_loan
.total_borrowed
.ensure_sub(active_loan.total_repaid.principal)?;
let principal = active_loan.principal()?;

Self {
present_value,
Expand Down
6 changes: 3 additions & 3 deletions pallets/loans/src/tests/mod.rs
lemunozm marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ use super::{
},
pallet::{ActiveLoans, CreatedLoan, Error, LastLoanId, PortfolioValuation},
types::{
cashflow::{InterestPayments, Maturity, PayDownSchedule, RepaymentSchedule},
policy::{WriteOffRule, WriteOffStatus, WriteOffTrigger},
valuation::{DiscountedCashFlow, ValuationMethod},
BorrowLoanError, BorrowRestrictions, CloseLoanError, CreateLoanError, InterestPayments,
LoanRestrictions, Maturity, MutationError, PayDownSchedule, RepayLoanError,
RepayRestrictions, RepaymentSchedule, WrittenOffError,
BorrowLoanError, BorrowRestrictions, CloseLoanError, CreateLoanError, LoanRestrictions,
MutationError, RepayLoanError, RepayRestrictions, WrittenOffError,
},
};

Expand Down
Loading
Loading