Student Loan Smart Agreement
What it does:
Automates issuance, repayment, and tracking of student loans on-chain with transparent terms and schedules.
Why it matters:
Reduces administrative friction, ensures clear repayment obligations, provides transparent audit trails, and allows instant verification of loan status.
How it works:
-
Lender or institution funds the loan pool on-chain
-
Student applies for a loan, specifying amount and repayment terms
-
Loan agreement is stored on-chain with interest rate, repayment schedule, and collateral (if any)
-
Smart contract tracks repayment due dates and amounts
-
Students make repayments directly to the contract
-
Contract automatically updates loan balance and can trigger penalties for late payments
-
Full loan history, balance, and status are auditable on-chain
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title StudentLoanAgreement
* @author Nam
* @notice Automates issuance, repayment, and tracking of student loans
*/
contract StudentLoanAgreement {
address public lender;
uint256 public loanCount;
struct Loan {
address student;
uint256 principal;
uint256 interest; // simple interest in wei
uint256 totalOwed;
uint256 repaid;
uint256 dueDate;
bool active;
}
mapping(uint256 => Loan) public loans;
// -------------------- EVENTS --------------------
event LoanIssued(uint256 indexed loanId, address indexed student, uint256 principal, uint256 totalOwed, uint256 dueDate);
event PaymentMade(uint256 indexed loanId, address indexed student, uint256 amount);
event LoanClosed(uint256 indexed loanId, address indexed student);
// -------------------- MODIFIERS --------------------
modifier onlyLender() {
require(msg.sender == lender, "Not lender");
_;
}
modifier onlyStudent(uint256 _loanId) {
require(msg.sender == loans[_loanId].student, "Not borrower");
_;
}
modifier loanActive(uint256 _loanId) {
require(loans[_loanId].active, "Loan inactive");
_;
}
// -------------------- CONSTRUCTOR --------------------
constructor() {
lender = msg.sender;
}
// -------------------- LOAN MANAGEMENT --------------------
function issueLoan(address _student, uint256 _principal, uint256 _interest, uint256 _repaymentDuration) external onlyLender {
require(_student != address(0), "Invalid student");
require(_principal > 0, "Principal must be >0");
loanCount += 1;
uint256 totalOwed = _principal + _interest;
uint256 dueDate = block.timestamp + _repaymentDuration;
loans[loanCount] = Loan({
student: _student,
principal: _principal,
interest: _interest,
totalOwed: totalOwed,
repaid: 0,
dueDate: dueDate,
active: true
});
emit LoanIssued(loanCount, _student, _principal, totalOwed, dueDate);
}
function makePayment(uint256 _loanId) external payable onlyStudent(_loanId) loanActive(_loanId) {
Loan storage l = loans[_loanId];
require(msg.value > 0, "Payment must be >0");
require(l.repaid + msg.value = l.totalOwed) {
l.active = false;
emit LoanClosed(_loanId, msg.sender);
}
}
// -------------------- HELPER FUNCTIONS --------------------
function getOutstanding(uint256 _loanId) external view returns (uint256) {
Loan memory l = loans[_loanId];
return l.totalOwed - l.repaid;
}
function isLoanOverdue(uint256 _loanId) external view returns (bool) {
Loan memory l = loans[_loanId];
return l.active && block.timestamp > l.dueDate;
}
receive() external payable {}
}