This document details the state management and lifecycle of loans within the Remitlend Soroban smart contracts.
The core logic of Remitlend resides in two primary contracts:
- Loan Manager: Manages the loan lifecycle (Request -> Approve -> Repay/Default).
- Remittance NFT: Tracks user credit scores and locks/unlocks NFTs as collateral.
The LoanManager contract defines the following states for a loan:
stateDiagram-v2
[*] --> Pending: request_loan()
Pending --> Approved: approve_loan()
Approved --> Repaid: repay() (full amount)
Approved --> Defaulted: system_trigger (after due date)
Repaid --> [*]
Defaulted --> [*]
- Trigger:
request_loan(borrower, amount) - Conditions:
- Borrower must have a
RemittanceNft. - Credit score must be >=
min_score. - Borrower cannot have an active loan (limit: 1 active loan per user).
- Borrower must have a
- Actions:
- Increments
LoanCounter. - Stores
Loanstruct in persistent storage. - Emits
LoanRequestedevent.
- Increments
- Trigger:
approve_loan(loan_id) - Conditions:
- Only
Admincan call this. - Loan must be in
Pendingstate. - Lending Pool must have sufficient liquidity.
- Only
- Actions:
- Updates status to
Approved. - Transfers tokens from
LendingPooltoBorrower. - Emits
LoanApprovedevent.
- Updates status to
- Trigger:
repay(borrower, amount) - Conditions:
- Loan must be in
Approvedstate. - Repayment amount must be positive.
- Loan must be in
- Actions:
- Updates loan status (if fully repaid).
- Cross-contract call to
RemittanceNftto update user's credit score (+points for timely repayment). - Emits
LoanRepaidevent.
DataKey::Loan(u32): Persistent storage forLoanstructs.DataKey::LoanCounter: Instance storage for total loans issued.DataKey::MinScore: Instance storage for prefixing credit worthiness.
DataKey::Score(Address): User credit score (0-1000).DataKey::AuthorizedMinter(Address): Membership flag for each authorized minter address.DataKey::AuthorizedMinters: EnumeratedVec<Address>of authorized minters (max 32).
is_authorized_minter(addr) -> bool: Checks whether a specific address can mint.get_authorized_minters() -> Vec<Address>: Returns the current authorized minter set for audit and admin UIs.
- Atomic State Transitions: All state changes are completed within a single Soroban transaction.
- Auth Checks:
borrower.require_auth()andadmin.require_auth()are used to ensure only authorized parties can trigger transitions. - Paused State: A global
Pausedflag can stop allrequest_loan,approve_loan, andrepayoperations in case of emergency.