# How to use

Flash loans are instantaneous and unsecured DeFi lending solutions, enabled by smart contract code that reverses a lending transaction if the borrower is unable to fulfill borrowing obligations. Their use cases cover arbitrage, liquidation and so on. &#x20;

Flash loan borrowers on CHFRY utilize Flash Fryer reserves for flash loan operations, in the same vein as Aave’s offering, and enhance their yields with CHEESE rewards.  \
\
In order to use CHFRY flash loans follow the standard proposal [`EIP-3165`](https://eips.ethereum.org/EIPS/eip-3156).&#x20;

### Flash loan fee

The flash loan fee is currently 0.06%, changeable via the normal governance process. To get the current value, call `getConfigValue("FRYER_FLASH_FEE_PROPORTION")` on the FryerConfig.sol contract.

### Example&#x20;

For developers, a helpful mental model to consider when developing your solution:

1/ Approve the specific Fryer contract amount and the flashloan fee; fee can be calculated by Fryer's `flashFee()`.&#x20;

2/ Your contract calls the Fryer contract, requesting a Flash Loan of a certain `amount` of reserves using `flashLoan()`.&#x20;

3/ After some sanity checks, the `Fryer` transfers the requested `amount` of the reserves to your contract, then calls `onFlashLoan()` on your contract.

4/ Your contract, now holding the flash loaned `amount`, executes any arbitrary operation in its code. Keep at least `amount + fee` in your contract.

5/ Finally, Fryer will transfer `amount + fee` from your contract. All of the above happens in one transaction (hence in a single ethereum block).

#### FlashBorrower.sol

```javascript
//SPDX-License-Identifier: MIT
pragma solidity >=0.6.5 <0.8.0;

import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import './interfaces/IERC3156FlashBorrower.sol';
import './interfaces/IERC3156FlashLender.sol';
import './libraries/TransferHelper.sol';

//  FlashLoan DEMO
contract FlashBorrower2 is IERC3156FlashBorrower {
	enum Action {
		NORMAL,
		STEAL,
		REENTER
	}

  using TransferHelper for address;

	IERC3156FlashLender lender;

	uint256 public flashBalance;
	address public flashInitiator;
	address public flashToken;
	uint256 public flashAmount;
	uint256 public flashFee;

	address public admin;

	constructor(address lender_) public {
		admin = msg.sender;
		lender = IERC3156FlashLender(lender_);
	}

	function setLender(address _lender) external {
		require(msg.sender == admin, '!admin');
		lender = IERC3156FlashLender(_lender);
	}

	/// @dev ERC-3156 Flash loan callback
	function onFlashLoan(
		address initiator,
		address token,
		uint256 amount,
		uint256 fee,
		bytes calldata data
	) external override returns (bytes32) {
		require(msg.sender == address(lender), 'FlashBorrower: Untrusted lender');
		require(initiator == address(this), 'FlashBorrower: External loan initiator');
		Action action = abi.decode(data, (Action)); // Use this to unpack arbitrary data
		flashInitiator = initiator;
		flashToken = token;
		flashAmount = amount;
		flashFee = fee;
		if (action == Action.NORMAL) {
			flashBalance = IERC20(token).balanceOf(address(this));
		} else if (action == Action.STEAL) {
			// do nothing
		} else if (action == Action.REENTER) {
			flashBorrow(token, amount * 2);
		}
		return keccak256('ERC3156FlashBorrower.onFlashLoan');
	}

	function flashBorrow(address token, uint256 amount) public {
		// Use this to pack arbitrary data to `onFlashLoan`
		bytes memory data = abi.encode(Action.NORMAL);
		approveRepayment(token, amount);
		lender.flashLoan(this, token, amount, data);
	}

	function flashBorrowAndSteal(address token, uint256 amount) public {
		// Use this to pack arbitrary data to `onFlashLoan`
		bytes memory data = abi.encode(Action.STEAL);
		lender.flashLoan(this, token, amount, data);
	}

	function flashBorrowAndReenter(address token, uint256 amount) public {
		// Use this to pack arbitrary data to `onFlashLoan`
		bytes memory data = abi.encode(Action.REENTER);
		approveRepayment(token, amount);
		lender.flashLoan(this, token, amount, data);
	}

	function approveRepayment(address token, uint256 amount) public {
		uint256 _allowance = IERC20(token).allowance(address(this), address(lender));
		uint256 _fee = lender.flashFee(token, amount);
		uint256 _repayment = amount + _fee;
		token.safeApprove(address(lender), 0);
		token.safeApprove(address(lender), _allowance + _repayment);
	}

	function transferFromAdmin(
		address _token,
		address _receiver,
		uint256 _amount
	) external {
		require(msg.sender == admin, '!admin');
		_token.safeTransfer(_receiver, _amount);
	}
}

```

#### IERC3156FlashBorrower.sol

```javascript
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <=0.8.0;


interface IERC3156FlashBorrower {

    /**
     * @dev Receive a flash loan.
     * @param initiator The initiator of the loan.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @param fee The additional amount of tokens to repay.
     * @param data Arbitrary data structure, intended to contain user-defined parameters.
     * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan"
     */
    function onFlashLoan(
        address initiator,
        address token,
        uint256 amount,
        uint256 fee,
        bytes calldata data
    ) external returns (bytes32);
}

```

#### IERC3156FlashLender.sol

```javascript
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <=0.8.0;
import "./IERC3156FlashBorrower.sol";


interface IERC3156FlashLender {

    /**
     * @dev The amount of currency available to be lended.
     * @param token The loan currency.
     * @return The amount of `token` that can be borrowed.
     */
    function maxFlashLoan(
        address token
    ) external view returns (uint256);

    /**
     * @dev The fee to be charged for a given loan.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @return The amount of `token` to be charged for the loan, on top of the returned principal.
     */
    function flashFee(
        address token,
        uint256 amount
    ) external view returns (uint256);

    /**
     * @dev Initiate a flash loan.
     * @param receiver The receiver of the tokens in the loan, and the receiver of the callback.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @param data Arbitrary data structure, intended to contain user-defined parameters.
     */
    function flashLoan(
        IERC3156FlashBorrower receiver,
        address token,
        uint256 amount,
        bytes calldata data
    ) external returns (bool);
}
```

#### TransferHelper.sol

```javascript
//SPDX-License-Identifier: MIT
pragma solidity >=0.6.5 <0.8.0;

library TransferHelper {
    function safeApprove(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
    }

    function safeTransfer(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
    }

    function safeTransferFrom(address token, address from, address to, uint value) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
    }

    function safeTransferETH(address to, uint value) internal {
        (bool success,) = to.call{value:value}(new bytes(0));
        require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
    }
}

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs-chfry.gitbook.io/doc/flashloan/how-to-use.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
