> ## 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.

# InsurancePool Contract

> Smart contract managing default protection for lenders

# InsurancePool Contract

The InsurancePool contract collects fees from loans and covers lender losses when borrowers 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 InsurancePool is ReentrancyGuard, AccessControl {
    IERC20 public immutable usdc;

    uint256 public totalPoolBalance;
    uint256 public totalClaimsPaid;
    uint256 public totalFeesCollected;

    // Coverage ratio: 80% of defaults covered
    uint256 public constant COVERAGE_RATIO = 80;

    // Minimum pool balance before restricting new loans
    uint256 public minimumPoolBalance;

    struct Claim {
        uint256 loanId;
        uint256 amount;
        uint256 timestamp;
        bool paid;
    }

    mapping(uint256 => Claim) public claims;
    uint256 public claimCounter;

    // Surplus distribution tracking
    mapping(address => uint256) public contributorShares;
    uint256 public totalShares;
}
```

## Key Functions

### Deposit Insurance Fee

Called when a new loan is created:

```solidity theme={null}
function deposit(uint256 amount) external onlyRole(LOAN_CONTRACT_ROLE) {
    usdc.transferFrom(msg.sender, address(this), amount);
    totalPoolBalance += amount;
    totalFeesCollected += amount;

    emit FeeDeposited(amount, totalPoolBalance);
}
```

### Claim for Default

Called when a loan defaults:

```solidity theme={null}
function claimForDefault(
    uint256 loanId,
    uint256 requestedAmount
) external onlyRole(LOAN_CONTRACT_ROLE) returns (uint256 paidAmount) {
    require(claims[loanId].loanId == 0, "Already claimed");

    // Calculate coverage (80% of loss)
    uint256 maxCoverage = (requestedAmount * COVERAGE_RATIO) / 100;

    // Pay what we can, up to max coverage
    paidAmount = maxCoverage > totalPoolBalance ? totalPoolBalance : maxCoverage;

    claims[++claimCounter] = Claim({
        loanId: loanId,
        amount: paidAmount,
        timestamp: block.timestamp,
        paid: true
    });

    totalPoolBalance -= paidAmount;
    totalClaimsPaid += paidAmount;

    // Transfer to Trust Vault to cover staker losses
    usdc.transfer(msg.sender, paidAmount);

    emit ClaimPaid(loanId, paidAmount, totalPoolBalance);

    return paidAmount;
}
```

### Voluntary Contribution

Users can contribute to increase coverage and earn surplus distributions:

```solidity theme={null}
function contribute(uint256 amount) external nonReentrant {
    require(amount >= MIN_CONTRIBUTION, "Below minimum");

    usdc.transferFrom(msg.sender, address(this), amount);

    // Calculate shares based on contribution
    uint256 shares = (totalShares == 0)
        ? amount
        : (amount * totalShares) / totalPoolBalance;

    contributorShares[msg.sender] += shares;
    totalShares += shares;
    totalPoolBalance += amount;

    emit ContributionMade(msg.sender, amount, shares);
}
```

### Withdraw Contribution

Contributors can withdraw their share plus earned surplus:

```solidity theme={null}
function withdrawContribution(uint256 shares) external nonReentrant {
    require(contributorShares[msg.sender] >= shares, "Insufficient shares");

    uint256 withdrawAmount = (shares * totalPoolBalance) / totalShares;

    // Ensure minimum pool balance maintained
    require(
        totalPoolBalance - withdrawAmount >= minimumPoolBalance,
        "Would breach minimum"
    );

    contributorShares[msg.sender] -= shares;
    totalShares -= shares;
    totalPoolBalance -= withdrawAmount;

    usdc.transfer(msg.sender, withdrawAmount);

    emit ContributionWithdrawn(msg.sender, withdrawAmount, shares);
}
```

### Distribute Surplus

When pool grows beyond target, distribute surplus to contributors:

```solidity theme={null}
function distributeSurplus() external onlyRole(POOL_MANAGER_ROLE) {
    uint256 targetBalance = calculateTargetBalance();
    require(totalPoolBalance > targetBalance, "No surplus");

    uint256 surplus = totalPoolBalance - targetBalance;

    // Keep 20% as buffer
    uint256 distributableSurplus = (surplus * 80) / 100;

    // Distribute pro-rata to contributors
    // (Actual distribution happens via claim mechanism)

    emit SurplusDistributed(distributableSurplus, totalShares);
}
```

## View Functions

### Get Pool Status

```solidity theme={null}
function getPoolStatus() external view returns (
    uint256 balance,
    uint256 claimsPaid,
    uint256 feesCollected,
    uint256 coverageCapacity,
    uint256 utilizationRatio
) {
    uint256 capacity = (totalPoolBalance * 100) / COVERAGE_RATIO;
    uint256 utilization = totalClaimsPaid > 0
        ? (totalClaimsPaid * 100) / totalFeesCollected
        : 0;

    return (
        totalPoolBalance,
        totalClaimsPaid,
        totalFeesCollected,
        capacity,
        utilization
    );
}
```

### Get Contributor Info

```solidity theme={null}
function getContributorInfo(address contributor) external view returns (
    uint256 shares,
    uint256 shareValue,
    uint256 percentageOfPool
) {
    uint256 userShares = contributorShares[contributor];
    uint256 value = totalShares > 0
        ? (userShares * totalPoolBalance) / totalShares
        : 0;
    uint256 percentage = totalShares > 0
        ? (userShares * 10000) / totalShares
        : 0;

    return (userShares, value, percentage);
}
```

## Events

```solidity theme={null}
event FeeDeposited(uint256 amount, uint256 newBalance);
event ClaimPaid(uint256 indexed loanId, uint256 amount, uint256 remainingBalance);
event ContributionMade(address indexed contributor, uint256 amount, uint256 shares);
event ContributionWithdrawn(address indexed contributor, uint256 amount, uint256 shares);
event SurplusDistributed(uint256 amount, uint256 totalShares);
event MinimumBalanceUpdated(uint256 oldMinimum, uint256 newMinimum);
```

## Pool Economics

### Fee Collection

```
┌─────────────────────────────────────────────────────────────────┐
│  Every Loan: 10% Insurance Fee                                  │
├─────────────────────────────────────────────────────────────────┤
│  $100 loan requested                                            │
│  └── $10 → Insurance Pool                                       │
│  └── $90 → Borrower receives                                    │
└─────────────────────────────────────────────────────────────────┘
```

### Default Coverage

```
┌─────────────────────────────────────────────────────────────────┐
│  When Loan Defaults: 80% Coverage                               │
├─────────────────────────────────────────────────────────────────┤
│  $100 loan defaults                                             │
│  └── $80 → Covered by Insurance Pool                            │
│  └── $20 → Absorbed by Trust Vault stakers                      │
└─────────────────────────────────────────────────────────────────┘
```

### Surplus Distribution

| Pool Status   | Action                              |
| ------------- | ----------------------------------- |
| Below minimum | New loans restricted                |
| At target     | Normal operation                    |
| Above target  | Surplus distributed to contributors |

## Constants

| Constant            | Value    | Description                    |
| ------------------- | -------- | ------------------------------ |
| `COVERAGE_RATIO`    | 80       | Percentage of defaults covered |
| `INSURANCE_FEE_BPS` | 1000     | 10% fee on loans               |
| `MIN_CONTRIBUTION`  | 100 USDC | Minimum voluntary contribution |
| `SURPLUS_THRESHOLD` | 120%     | When to distribute surplus     |

## Access Control

| Role                 | Permissions                           |
| -------------------- | ------------------------------------- |
| `LOAN_CONTRACT_ROLE` | Deposit fees, claim for defaults      |
| `POOL_MANAGER_ROLE`  | Distribute surplus, update parameters |
| `DEFAULT_ADMIN_ROLE` | Manage roles                          |

## Integration Example

```typescript theme={null}
import { ethers } from 'ethers';

// Check pool status
const status = await insurancePool.getPoolStatus();
console.log(`Pool Balance: $${ethers.formatUnits(status.balance, 6)}`);
console.log(`Coverage Capacity: $${ethers.formatUnits(status.coverageCapacity, 6)}`);

// Contribute to pool
await usdc.approve(insurancePool.address, contribution);
await insurancePool.contribute(ethers.parseUnits("1000", 6));

// Check your contribution
const info = await insurancePool.getContributorInfo(myAddress);
console.log(`Your share value: $${ethers.formatUnits(info.shareValue, 6)}`);
```

## Related Documentation

<CardGroup cols={2}>
  <Card title="Trust Vault" icon="vault" href="/smart-contracts/trust-vault">
    Main liquidity pool
  </Card>

  <Card title="P2P Loan" icon="handshake" href="/smart-contracts/p2p-loan">
    Loan contract integration
  </Card>
</CardGroup>
