🔦Flash Loan

Flash Loan is a feature for developers. There is no page for users on Palmy Finance. Developers can borrow all available assets without collateral by borrowing and repaying in one transaction. Developers can implement a contract for Flash Loan, which allows more leveraged DeFi operations than features on palmy.finance.

Flash Loans are an advanced concept aimed at developers. You must have a good understanding of Blockchain, programming, and smart contracts to be able to use this feature.

Overview

Flash-loan allows users to access liquidity of the pool (only for reserves for which borrow is enabled) for one transaction as long as the amount taken plus fee is returned or (if allowed) debt position is opened by the end of the transaction.

Execution Flow

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

  1. Your contract calls the contract which is responsible for flashloan (LendingPool for EVM, FlashloanGateway for WASM), requesting a Flash Loan of a certain amount(s) of reserve(s) using flashLoan().

  2. After some sanity checks, the contract transfers the requested amounts of the reserves to your contract, then calls executeOperation() on receiver contract.

  3. Your contract, now holding the flash loaned amount(s), executes any arbitrary operation in its code. For all the reserves either depending on FLASHLOAN_PREMIUM_TOTAL passed for the asset, either the contract must be approved for flash loaned amount + fee or must or sufficient collateral or credit delegation should be available to open debt position.

    • If the amount owing is not available (due to a lack of balance or approval or insufficient collateral for debt), then the transaction is reverted.

  4. All of the above happens in 1 transaction (hence in a single block).

Flash loan fee

The flash loan fee is initialized at deployment to 0.09% and can be updated via Governance Vote. Use FLASHLOAN_PREMIUM_TOTAL to get current value.

EVM Implementation

Base Interfaces

If you want to execute Flash Loan, your contract should implement the interface below.

IFlashLoanReceiver.sol
interface IFlashLoanReceiver {
  function executeOperation(
    address[] calldata assets,
    uint256[] calldata amounts,
    uint256[] calldata premiums,
    address initiator,
    bytes calldata params
  ) external returns (bool);

  function ADDRESSES_PROVIDER() external view returns (ILendingPoolAddressesProvider);

  function LENDING_POOL() external view returns (ILendingPool);
}

This is the base contract that implements the interface.

FlashLoanReceiverBase.sol
abstract contract FlashLoanReceiverBase is IFlashLoanReceiver {
  using SafeERC20 for IERC20;
  using SafeMath for uint256;

  ILendingPoolAddressesProvider public immutable override ADDRESSES_PROVIDER;
  ILendingPool public immutable override LENDING_POOL;

  constructor(ILendingPoolAddressesProvider provider) public {
    ADDRESSES_PROVIDER = provider;
    LENDING_POOL = ILendingPool(provider.getLendingPool());
  }
}

Example Contract

You can implement your contract by inheriting the base contract. In the executeOperation function, you can code what you want to do with the borrowed assets by Flash Loan.

MyPalmyFlashLoan.sol
contract MyPalmyFlashLoan is FlashLoanReceiverBase {

    /**
        This function is called after your contract has received the flash loaned amount
     */
    function executeOperation(
        address[] calldata assets,
        uint256[] calldata amounts,
        uint256[] calldata premiums,
        address initiator,
        bytes calldata params
    )
        external
        override
        returns (bool)
    {

        //
        // This contract now has the funds requested.
        // Your logic goes here.
        //

        // At the end of your logic above, this contract owes
        // the flashloaned amounts + premiums.
        // Therefore ensure your contract has enough to repay
        // these amounts.

        // Approve the LendingPool contract allowance to *pull* the owed amount
        for (uint i = 0; i < assets.length; i++) {
            uint amountOwing = amounts[i].add(premiums[i]);
            IERC20(assets[i]).approve(address(LENDING_POOL), amountOwing);
        }

        return true;
    }

    function myFlashLoanCall() public {
        address receiverAddress = address(this);

        address[] memory assets = new address[](2);
        assets[0] = address(INSERT_ASSET_ONE_ADDRESS);
        assets[1] = address(INSERT_ASSET_TWO_ADDRESS);

        uint256[] memory amounts = new uint256[](2);
        amounts[0] = INSERT_ASSET_ONE_AMOUNT;
        amounts[1] = INSERT_ASSET_TWO_AMOUNT;

        // 0 = no debt, 1 = stable, 2 = variable
        uint256[] memory modes = new uint256[](2);
        modes[0] = INSERT_ASSET_ONE_MODE;
        modes[1] = INSERT_ASSET_TWO_MODE;

        address onBehalfOf = address(this);
        bytes memory params = "";
        uint16 referralCode = 0;

        LENDING_POOL.flashLoan(
            receiverAddress,
            assets,
            amounts,
            modes,
            onBehalfOf,
            params,
            referralCode
        );
    }
}

Palmy Lending Pool Contract

LendingPool contract, which is provided by Palmy Finance, has the function to do Flash Loan.

LendingPool.sol

Last updated