# Flash Loans

### Overview

Curvance provides flash loan functionality through the `BorrowableCToken` contract, allowing developers to borrow assets without collateral for the duration of a single transaction. This guide walks you through implementing flash loans in your smart contracts.

### Key Concepts

#### What is a Flash Loan?

A flash loan is an uncollateralized loan that must be borrowed and repaid within a single transaction. If the loan is not repaid (plus fees) by the end of the transaction, the entire transaction reverts.

#### Flash Loan Fee

* **Fee Rate**: 4 basis points (0.04%)
* **Calculation**: `fee = (assets * 4) / 10000`
* The fee is added to the total assets in the market after the flash loan completes

### Implementation Steps

#### Step 1: Implement the IFlashLoan Interface

Your contract must implement the `onFlashloan()` function to receive flash loan callbacks.

```solidity
function onFlashLoan(
    uint256 assets,
    uint256 assetsReturned,
    bytes calldata data
) external returns (bytes32) {
    // Verify the callback is from the expected BorrowableCToken
    require(msg.sender == borrowableCToken, "Unauthorized callback");

    // Your custom logic here.
    // At this point, you have received 'assets' amount of tokens.

    // IMPORTANT: You must approve the BorrowableCToken to pull back
    // the loan amount + fee before this function returns.
    SafeTransferLib.safeApprove(asset, borrowableCToken, assetsReturned);

    // Return value (not currently checked by the BorrowableCToken contract).
    return keccak256("ERC3156FlashBorrower.onFlashLoan");
}
```

#### Step 2: Initiate the Flash Loan

Call the `flashLoan()` function on the `BorrowableCToken` contract.

```solidity
function myFlashloanFunction() external {
    // Prepare any data you want to pass to the callback
    bytes memory data = abi.encode(msg.sender, someData);

    // Execute the flash loan
    // This will:
    // 1. Transfer 'amount' tokens to this contract
    // 2. Call onFlashLoan() on this contract
    // 3. Pull back 'amount + fee' tokens from this contract
    IBorrowableCToken(borrowableCToken).flashLoan(amount, data);
}
```

### Flash Loan Execution Flow

1. Your contract calls `flashLoan(assets, data)` .
2. Fee is calculated `fee = (assets * FLASHLOAN_FEE) / BPS`.
3. Assets are transferred to your contract.
4. Your callback is executed.
5. Assets + fee are pulled back into BorrowableCToken.
6. Event `Flashloan(assets, fee, msg.sender)` is emitted.

### Important Considerations

#### 1. Available liquidity

Before initiating a flash loan, ensure sufficient assets are available:

```solidity
uint256 availableLiquidity = IBorrowableCToken(borrowableCToken).assetsHeld();
require(loanAmount <= availableLiquidity, "Insufficient liquidity");
```

#### 2. Fee Calculation

Always calculate the exact fee you'll need to repay:

```solidity
uint256 fee = IBorrowableCToken(borrowableCToken).flashFee(loanAmount);
uint256 totalRepayment = loanAmount + fee;
```

#### 3. Token Approval

Your contract **must** approve the BorrowableCToken to pull back the loan + fee:

```
IERC20.usdc.approve(borrowableCToken, assetsReturned);
```

If you fail to approve or don't have sufficient balance, the transaction will revert.

### Error Handling

<table><thead><tr><th width="357">Error</th><th>Cause</th><th>Solution</th></tr></thead><tbody><tr><td><code>BorrowableCToken__ZeroAmount</code></td><td>Requested amount is 0.</td><td>Request amount > 0.</td></tr><tr><td><code>BorrowableCToken_InsufficientAssetsHeld</code></td><td>Not enough liquidity.</td><td>Reduce loan amount or wait for more liquidity.</td></tr><tr><td>Transfer failure</td><td>Insufficient approval or balance.</td><td>Ensure proper approval and balance for repayment.</td></tr></tbody></table>
