Skip to content

Commit

Permalink
add maturity extension changed test
Browse files Browse the repository at this point in the history
  • Loading branch information
lemunozm committed Oct 26, 2023
1 parent c434bf7 commit d699e1c
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 15 deletions.
2 changes: 1 addition & 1 deletion pallets/loans/docs/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ package policy {
}
enum WriteOffTrigger {
PrincipalOverdueDays,
PrincipalOverdue,
PriceOutdated,
}
Expand Down
91 changes: 81 additions & 10 deletions runtime/integration-tests/src/generic/cases/loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ use cfg_traits::{
interest::{CompoundingSchedule, InterestRate},
Seconds, TimeAsSecs,
};
use cfg_types::{fixed_point::Quantity, oracles::OracleKey, permissions::PoolRole};
use frame_support::traits::Get;
use cfg_types::{
fixed_point::{Quantity, Rate},
oracles::OracleKey,
permissions::PoolRole,
};
use frame_support::{assert_err, traits::Get};
use pallet_loans::{
entities::{
changes::LoanMutation,
input::{PrincipalInput, RepaidInput},
loans::LoanInfo,
pricing::{
Expand All @@ -16,8 +21,8 @@ use pallet_loans::{
},
},
types::{
valuation::ValuationMethod, BorrowRestrictions, InterestPayments, LoanRestrictions,
Maturity, PayDownSchedule, RepayRestrictions, RepaymentSchedule,
valuation::ValuationMethod, BorrowLoanError, BorrowRestrictions, InterestPayments,
LoanRestrictions, Maturity, PayDownSchedule, RepayRestrictions, RepaymentSchedule,
},
};
use runtime_common::apis::{
Expand All @@ -42,6 +47,8 @@ use crate::{
const POOL_ADMIN: Keyring = Keyring::Admin;
const INVESTOR: Keyring = Keyring::Alice;
const BORROWER: Keyring = Keyring::Bob;
const LOAN_ADMIN: Keyring = Keyring::Charlie;
const ANY: Keyring = Keyring::Dave;

const POOL_A: PoolId = 23;
const NFT_A: (CollectionId, ItemId) = (1, ItemId(10));
Expand Down Expand Up @@ -72,6 +79,13 @@ mod common {
utils::give_balance::<T>(POOL_ADMIN.id(), T::PoolDeposit::get());
utils::create_empty_pool::<T>(POOL_ADMIN.id(), POOL_A, Usd6::ID);

// Setting borrower
utils::give_pool_role::<T>(BORROWER.id(), POOL_A, PoolRole::Borrower);
utils::give_nft::<T>(BORROWER.id(), NFT_A);

// Setting a loan admin
utils::give_pool_role::<T>(LOAN_ADMIN.id(), POOL_A, PoolRole::LoanAdmin);

// Funding a pool
let tranche_id = T::Api::tranche_id(POOL_A, 0).unwrap();
let tranche_investor = PoolRole::TrancheInvestor(tranche_id, Seconds::MAX);
Expand All @@ -85,10 +99,6 @@ mod common {
env.state_mut(|| {
// New epoch with the investor funds available
utils::close_pool_epoch::<T>(POOL_ADMIN.id(), POOL_A);

// Preparing borrower
utils::give_pool_role::<T>(BORROWER.id(), POOL_A, PoolRole::Borrower);
utils::give_nft::<T>(BORROWER.id(), NFT_A);
});

env
Expand All @@ -102,6 +112,14 @@ mod common {
.unwrap()
}

pub fn last_change_id<E: Env<T>, T: Runtime>(env: &E) -> T::Hash {
env.find_event(|e| match e {
pallet_pool_system::Event::<T>::ProposedChange { change_id, .. } => Some(change_id),
_ => None,
})
.unwrap()
}

pub fn default_loan_info<T: Runtime>(now: Seconds, pricing: Pricing<T>) -> LoanInfo<T> {
LoanInfo {
schedule: RepaymentSchedule {
Expand Down Expand Up @@ -212,6 +230,24 @@ mod call {
loan_id,
}
}

pub fn propose_loan_mutation<T: Runtime>(
loan_id: LoanId,
mutation: LoanMutation<Rate>,
) -> pallet_loans::Call<T> {
pallet_loans::Call::propose_loan_mutation {
pool_id: POOL_A,
loan_id,
mutation,
}
}

pub fn apply_loan_mutation<T: Runtime>(change_id: T::Hash) -> pallet_loans::Call<T> {
pallet_loans::Call::apply_loan_mutation {
pool_id: POOL_A,
change_id,
}
}
}

/// Test the basic loan flow, which consist in:
Expand All @@ -226,7 +262,6 @@ fn internal_priced<T: Runtime>() {
let now = <pallet_timestamp::Pallet<T> as TimeAsSecs>::now();
common::default_loan_info::<T>(now, common::default_internal_pricing())
});

env.submit_now(BORROWER, call::create(&info)).unwrap();

let loan_id = common::last_loan_id(&env);
Expand Down Expand Up @@ -263,7 +298,6 @@ fn oracle_priced<T: Runtime>() {
let now = <pallet_timestamp::Pallet<T> as TimeAsSecs>::now();
common::default_loan_info::<T>(now, common::default_external_pricing())
});

env.submit_now(BORROWER, call::create(&info)).unwrap();

let loan_id = common::last_loan_id(&env);
Expand Down Expand Up @@ -293,5 +327,42 @@ fn oracle_priced<T: Runtime>() {
env.submit_now(BORROWER, call::close(loan_id)).unwrap();
}

fn update_maturity_extension<T: Runtime>() {
let mut env = common::initialize_state_for_loans::<RuntimeEnv<T>, T>();

let info = env.state(|| {
let now = <pallet_timestamp::Pallet<T> as TimeAsSecs>::now();
common::default_loan_info::<T>(now, common::default_internal_pricing())
});
env.submit_now(BORROWER, call::create(&info)).unwrap();

let loan_id = common::last_loan_id(&env);

env.submit_now(BORROWER, call::borrow_internal(loan_id))
.unwrap();

env.pass(Blocks::BySeconds(SECONDS_PER_MINUTE));

// Loan at this point is overdue and trying to borrow it will fail
assert_err!(
env.submit_now(BORROWER, call::borrow_internal(loan_id)),
pallet_loans::Error::<T>::BorrowLoanError(BorrowLoanError::MaturityDatePassed),
);

env.submit_now(
LOAN_ADMIN,
call::propose_loan_mutation(loan_id, LoanMutation::MaturityExtension(12 /* seconds */)),
)
.unwrap();

let change_id = common::last_change_id(&env);
env.submit_now(LOAN_ADMIN, call::apply_loan_mutation(change_id))
.unwrap();

// Now the loan is no longer overdue and can be borrowed again
env.submit_now(ANY, call::borrow_internal(loan_id)).unwrap();
}

crate::test_for_runtimes!(all, internal_priced);
crate::test_for_runtimes!(all, oracle_priced);
crate::test_for_runtimes!(all, update_maturity_extension);
2 changes: 2 additions & 0 deletions runtime/integration-tests/src/generic/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,12 @@ pub trait Runtime:
+ TryInto<pallet_balances::Event<Self>>
+ TryInto<pallet_transaction_payment::Event<Self>>
+ TryInto<pallet_loans::Event<Self>>
+ TryInto<pallet_pool_system::Event<Self>>
+ From<frame_system::Event<Self>>
+ From<pallet_balances::Event<Self>>
+ From<pallet_transaction_payment::Event<Self>>
+ From<pallet_loans::Event<Self>>
+ From<pallet_pool_system::Event<Self>>
+ From<orml_oracle::Event<Self>>;

/// Block used by the runtime
Expand Down
6 changes: 3 additions & 3 deletions runtime/integration-tests/src/generic/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ pub trait Env<T: Runtime> {
/// Pass any number of blocks
fn pass(&mut self, blocks: Blocks<T>) {
let (next, end_block) = self.state(|| {
let next = frame_system::Pallet::<T>::block_number() + 1;
let current = frame_system::Pallet::<T>::block_number();

let end_block = next
let end_block = current
+ match blocks {
Blocks::ByNumber(n) => n,
Blocks::BySeconds(secs) => {
Expand All @@ -62,7 +62,7 @@ pub trait Env<T: Runtime> {
Blocks::UntilEvent { limit, .. } => limit,
};

(next, end_block)
(current + 1, end_block)
});

for i in next..end_block {
Expand Down
3 changes: 3 additions & 0 deletions runtime/integration-tests/src/generic/utils/currency.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! PLEASE be as much generic as possible because no domain or use cases are
//! considered at this level.
use cfg_primitives::{conversion, Balance, CFG};
use cfg_types::tokens::{AssetMetadata, CrossChainTransferability, CurrencyId, CustomMetadata};
use sp_runtime::FixedPointNumber;
Expand Down
5 changes: 5 additions & 0 deletions runtime/integration-tests/src/generic/utils/genesis.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! PLEASE be as much generic as possible because no domain or use cases are
//! considered at this level.
use std::marker::PhantomData;

use cfg_primitives::Balance;
Expand Down Expand Up @@ -36,6 +39,8 @@ impl<T: Runtime> Genesis<T> {
}
}

// Add GenesisBuild functions for initialize your pallets

pub fn balances<T: Runtime>(balance: Balance) -> impl GenesisBuild<T> {
pallet_balances::GenesisConfig::<T> {
balances: default_accounts()
Expand Down
6 changes: 5 additions & 1 deletion runtime/integration-tests/src/generic/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
// Divide this utilties into files when it grows
//! PLEASE be as much generic as possible because no domain or use cases are
//! considered at util level and below modules. If you need utilities related to
//! your use case, add them under `cases/<my_use_case.rs>`.
//!
//! Divide this utilities into files when it grows
pub mod currency;
pub mod genesis;
Expand Down

0 comments on commit d699e1c

Please sign in to comment.