> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usmewe.com/llms.txt
> Use this file to discover all available pages before exploring further.

# P2PLoan Contract

> Smart contract handling peer-to-peer loan lifecycle

# P2PLoan Contract

The P2PLoan contract manages the complete lifecycle of loans from creation to repayment or default.

## Contract Overview

```solidity theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";

contract P2PLoan is ReentrancyGuard, AccessControl {
    IERC20 public immutable usdc;
    ITrustVault public immutable trustVault;
    IInsurancePool public immutable insurancePool;

    struct Loan {
        address borrower;
        uint256 principal;
        uint256 interestRate;
        uint256 startTime;
        uint256 duration;
        uint256 repaidAmount;
        LoanStatus status;
    }

    enum LoanStatus {
        Active,
        Repaid,
        Defaulted
    }

    mapping(uint256 => Loan) public loans;
    uint256 public loanCounter;
}
```

## Key Functions

### Create Loan

```solidity theme={null}
function createLoan(
    address borrower,
    uint256 amount,
    uint256 duration,
    uint256 interestRate
) external onlyRole(LOAN_MANAGER_ROLE) returns (uint256 loanId) {
    require(amount > 0, "Amount must be positive");
    require(duration >= 7 days && duration <= 90 days, "Invalid duration");

    // Transfer funds from Trust Vault to borrower
    uint256 insuranceFee = (amount * INSURANCE_FEE_BPS) / 10000;
    uint256 netAmount = amount - insuranceFee;

    trustVault.withdrawForLoan(amount);
    insurancePool.deposit(insuranceFee);
    usdc.transfer(borrower, netAmount);

    loanId = ++loanCounter;
    loans[loanId] = Loan({
        borrower: borrower,
        principal: amount,
        interestRate: interestRate,
        startTime: block.timestamp,
        duration: duration,
        repaidAmount: 0,
        status: LoanStatus.Active
    });

    emit LoanCreated(loanId, borrower, amount, duration);
}
```

### Repay Loan

```solidity theme={null}
function repay(uint256 loanId, uint256 amount) external nonReentrant {
    Loan storage loan = loans[loanId];
    require(loan.status == LoanStatus.Active, "Loan not active");
    require(msg.sender == loan.borrower, "Not borrower");

    uint256 totalOwed = calculateTotalOwed(loanId);
    uint256 paymentAmount = amount > totalOwed ? totalOwed : amount;

    usdc.transferFrom(msg.sender, address(this), paymentAmount);
    loan.repaidAmount += paymentAmount;

    if (loan.repaidAmount >= totalOwed) {
        loan.status = LoanStatus.Repaid;

        // Return principal to vault
        usdc.transfer(address(trustVault), loan.principal);

        // Distribute interest to stakers
        uint256 interest = loan.repaidAmount - loan.principal;
        trustVault.distributeYield(interest);

        emit LoanRepaid(loanId, loan.repaidAmount);
    } else {
        emit PartialRepayment(loanId, paymentAmount, totalOwed - loan.repaidAmount);
    }
}
```

### Mark Default

```solidity theme={null}
function markDefault(uint256 loanId) external onlyRole(LOAN_MANAGER_ROLE) {
    Loan storage loan = loans[loanId];
    require(loan.status == LoanStatus.Active, "Loan not active");
    require(
        block.timestamp > loan.startTime + loan.duration + GRACE_PERIOD,
        "Grace period not ended"
    );

    loan.status = LoanStatus.Defaulted;

    // Calculate loss
    uint256 totalOwed = calculateTotalOwed(loanId);
    uint256 loss = totalOwed - loan.repaidAmount;

    // Insurance covers 80%
    uint256 insuranceCoverage = (loss * 80) / 100;
    uint256 stakerLoss = loss - insuranceCoverage;

    insurancePool.claimForDefault(loanId, insuranceCoverage);
    trustVault.recordLoss(stakerLoss);

    emit LoanDefaulted(loanId, loss, insuranceCoverage);
}
```

## View Functions

### Calculate Total Owed

```solidity theme={null}
function calculateTotalOwed(uint256 loanId) public view returns (uint256) {
    Loan storage loan = loans[loanId];
    uint256 interest = (loan.principal * loan.interestRate * loan.duration) / (365 days * 10000);
    return loan.principal + interest;
}
```

### Get Loan Details

```solidity theme={null}
function getLoan(uint256 loanId) external view returns (
    address borrower,
    uint256 principal,
    uint256 interestRate,
    uint256 startTime,
    uint256 duration,
    uint256 repaidAmount,
    uint256 totalOwed,
    LoanStatus status,
    bool isOverdue
) {
    Loan storage loan = loans[loanId];
    return (
        loan.borrower,
        loan.principal,
        loan.interestRate,
        loan.startTime,
        loan.duration,
        loan.repaidAmount,
        calculateTotalOwed(loanId),
        loan.status,
        block.timestamp > loan.startTime + loan.duration
    );
}
```

## Events

```solidity theme={null}
event LoanCreated(
    uint256 indexed loanId,
    address indexed borrower,
    uint256 amount,
    uint256 duration
);

event LoanRepaid(
    uint256 indexed loanId,
    uint256 totalAmount
);

event PartialRepayment(
    uint256 indexed loanId,
    uint256 amount,
    uint256 remainingBalance
);

event LoanDefaulted(
    uint256 indexed loanId,
    uint256 totalLoss,
    uint256 insuranceCoverage
);
```

## Constants

| Constant            | Value   | Description                 |
| ------------------- | ------- | --------------------------- |
| `INSURANCE_FEE_BPS` | 1000    | 10% insurance fee           |
| `GRACE_PERIOD`      | 7 days  | Grace period before default |
| `MIN_LOAN_DURATION` | 7 days  | Minimum loan term           |
| `MAX_LOAN_DURATION` | 90 days | Maximum loan term           |

## Access Control

| Role                 | Permissions                       |
| -------------------- | --------------------------------- |
| `LOAN_MANAGER_ROLE`  | Create loans, mark defaults       |
| `DEFAULT_ADMIN_ROLE` | Manage roles, emergency functions |

## Integration Example

```typescript theme={null}
import { ethers } from 'ethers';
import P2PLoanABI from './abis/P2PLoan.json';

const p2pLoan = new ethers.Contract(
  P2P_LOAN_ADDRESS,
  P2PLoanABI,
  signer
);

// Get loan details
const loan = await p2pLoan.getLoan(loanId);
console.log(`Principal: ${ethers.formatUnits(loan.principal, 6)} USDC`);
console.log(`Total Owed: ${ethers.formatUnits(loan.totalOwed, 6)} USDC`);

// Repay loan
const totalOwed = await p2pLoan.calculateTotalOwed(loanId);
await usdc.approve(P2P_LOAN_ADDRESS, totalOwed);
await p2pLoan.repay(loanId, totalOwed);
```

## Security Considerations

<Warning>
  This contract handles user funds. Key security measures include:
</Warning>

* **ReentrancyGuard**: Prevents reentrancy attacks
* **Access Control**: Role-based permissions
* **Input Validation**: All parameters validated
* **Overflow Protection**: Solidity 0.8+ built-in checks

## Related Contracts

<CardGroup cols={2}>
  <Card title="Trust Vault" icon="vault" href="/smart-contracts/trust-vault">
    Liquidity source for loans
  </Card>

  <Card title="Insurance Pool" icon="umbrella" href="/smart-contracts/insurance-pool">
    Default coverage
  </Card>
</CardGroup>
