Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions contracts/creditline-contract/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,6 @@ pub enum CreditLineError {
InstallmentAlreadyPaid = 24,
InvalidLoanStatus = 25,
NotInitialized = 26,
LoanNotDefaultable = 27,
AlreadyDefaulted = 28,
}
57 changes: 33 additions & 24 deletions contracts/creditline-contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,39 +483,43 @@ impl CreditLineContract {
Ok(())
}

pub fn mark_defaulted(env: Env, loan_id: u64) -> Result<(), CreditLineError> {
let mut loan = storage::read_loan(&env, loan_id)?;
pub fn can_default(env: Env, loan_id: u64) -> bool {
let loan = match storage::read_loan(&env, loan_id) {
Ok(l) => l,
Err(_) => return false,
};

if loan.status != LoanStatus::Active {
return Err(CreditLineError::LoanNotActive);
return false;
}

let last_installment = loan
.repayment_schedule
.last()
.ok_or(CreditLineError::Overflow)?;
let last_installment = match loan.repayment_schedule.last() {
Some(i) => i,
None => return false,
};

let now = env.ledger().timestamp();
if now <= last_installment.due_date {
return Err(CreditLineError::LoanNotOverdue);
}

let params = Self::get_protocol_parameters(&env);
let grace_ends_at = last_installment
let grace_ends_at = match last_installment
.due_date
.checked_add(params.grace_period_seconds)
.ok_or(CreditLineError::Overflow)?;
{
Some(t) => t,
None => return false,
};

if now <= grace_ends_at {
// Still within the grace window — emit a warning and block hard default.
events::emit_loan_in_grace_period(
&env,
&loan.borrower,
loan_id,
loan.remaining_balance,
grace_ends_at,
);
return Err(CreditLineError::LoanInGracePeriod);
now > grace_ends_at
}

pub fn check_default(env: Env, loan_id: u64) -> Result<(), CreditLineError> {
let mut loan = storage::read_loan(&env, loan_id)?;

if loan.status == LoanStatus::Defaulted {
return Err(CreditLineError::AlreadyDefaulted);
}

if !Self::can_default(env.clone(), loan_id) {
return Err(CreditLineError::LoanNotDefaultable);
}

let lp_address =
Expand All @@ -532,7 +536,12 @@ impl CreditLineContract {
Self::authorize_token_transfer(&env, &token_address, &lp_address, loan.guarantee_amount);

let lp_client = LiquidityPoolContractClient::new(&env, &lp_address);
lp_client.receive_guarantee(&env.current_contract_address(), &loan.guarantee_amount);
lp_client.liquidate_funds(
&env.current_contract_address(),
&loan_id,
&loan.guarantee_amount,
&loan.borrower,
);

events::emit_loan_defaulted(
&env,
Expand Down
2 changes: 2 additions & 0 deletions contracts/creditline-contract/src/safe_math.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(dead_code)]
use crate::errors::CreditLineError;

pub fn add_i128(a: i128, b: i128) -> Result<i128, CreditLineError> {
Expand Down Expand Up @@ -28,6 +29,7 @@ pub fn mul_u64(a: u64, b: u64) -> Result<u64, CreditLineError> {
a.checked_mul(b).ok_or(CreditLineError::Overflow)
}

#[allow(dead_code)]
pub fn div_u64(a: u64, b: u64) -> Result<u64, CreditLineError> {
a.checked_div(b).ok_or(CreditLineError::Overflow)
}
Loading
Loading