Skip to content

TheArcadiaGroup/metaflash

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

metaflash

Deploy contracts

  1. Go to metaflash directory (the folowing commands will be executed in metaflash directory)

  2. Create environment file: .env

    and input following contents into the .env file:

    PRIVATE_KEY=

    INFURA_APIKEY=

    ETHERSCAN_APIKEY=

  3. Open command line, then install: "npm i"

  4. Deploy FlashLenders, FlashBorrower contracts:

    ETH mainnet:

     FlashLenders:
     npx hardhat deploy --tags flashlender_eth --network ethmainnet
     
     FlashBorrower:
     npx hardhat deploy --tags flashborrower --network ethmainnet
    

    BSC mainnet:

     FlashLenders:
     npx hardhat deploy --tags flashlender_bsc --network bscmainnet
    
     FlashBorrower:
     npx hardhat deploy --tags flashborrower --network bscmainnet
    

Execute flashloan

Implement FlashBorrower.sol to execute flashloan

FlashBorrower.sol

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "./interfaces/IFlashLender.sol";

contract FlashBorrower is IERC3156FlashBorrower {
    using SafeMath for uint256;

    enum Action {
        NORMAL,
        REENTER
    }

    bytes32 public constant CALLBACK_SUCCESS =
        keccak256("ERC3156FlashBorrower.onFlashLoan");

    function onFlashLoan(
        address _sender,
        address _token,
        uint256 _amount,
        uint256 _fee,
        bytes calldata _data
    ) external returns (bytes32) {
        require(
            _sender == address(this),
            "FlashBorrower: sender must be this contract"
        );

        Action action = abi.decode(_data, (Action)); 

        if (action == Action.NORMAL) {
            // ****** IMPLEMENT HERE ******
        }
        return CALLBACK_SUCCESS;
    }

    function flashBorrowWithCheapestProvider(
        IFlashLender _lender,
        address _token,
        uint256 _amount
    ) public {
        uint256 allowance = IERC20(_token).allowance(
            address(this),
            address(_lender)
        );
        uint256 _fee = _lender.flashFeeWithCheapestProvider(_token, _amount);
        uint256 repayment = _amount.add(_fee);
        IERC20(_token).approve(address(_lender), allowance.add(repayment));
        bytes memory data = abi.encode(Action.NORMAL);
        _lender.flashLoanWithCheapestProvider(this, _token, _amount, data);
    }

    function flashBorrowWithManyProviders(
        IFlashLender _lender,
        address _token,
        uint256 _amount,
        uint256 _minAmount
    ) public {
        uint256 allowance = IERC20(_token).allowance(
            address(this),
            address(_lender)
        );
        uint256 fee = _lender.flashFeeWithManyProviders(_token, _amount, _minAmount);
        uint256 repayment = _amount.add(fee);
        IERC20(_token).approve(address(_lender), allowance.add(repayment));
        bytes memory data = abi.encode(Action.NORMAL);
        _lender.flashLoanWithManyProviders(this, _token, _amount, data, _minAmount);
    }
}

IFlashLender.sol

pragma solidity ^0.8.0;

import "./IERC3156FlashBorrower.sol";

interface IFlashLender {
    function maxFlashLoanWithCheapestProvider(
        address token,
        uint256 minAmount
    ) external view returns (uint256);

    function flashFeeWithCheapestProvider(
        address token,
        uint256 minAmount
    ) external view returns (uint256);

    function flashLoanWithCheapestProvider(
        IERC3156FlashBorrower receiver,
        address token,
        uint256 amount,
        bytes calldata data
    ) external returns (bool);

    function maxFlashLoanWithManyProviders(
        address token,
        uint256 minAmount
    ) external view returns (uint256);

    function flashFeeWithManyProviders(
        address token,
        uint256 amount,
        uint256 minAmount
    ) external view returns (uint256);

    function flashLoanWithManyProviders(
        IERC3156FlashBorrower receiver,
        address token,
        uint256 amount,
        bytes calldata data,
        uint256 minAmount
    ) external returns (bool);
}

IERC3156FlashBorrower.sol

pragma solidity ^0.8.0;

interface IERC3156FlashBorrower {
    function onFlashLoan(
        address initiator,
        address token,
        uint256 amount,
        uint256 fee,
        bytes calldata data
    ) external returns (bytes32);
}

Examples for executing FlashLender's functions

  1. if you don't know how much maxloan/fee to use flashLoanWithCheapestProvider or flashLoanWithManyProviders, you should use getFlashLoanInfoListWithCheaperFeePriority to get flashloan information list of providers.

    If you want to get a flashloan information list(maxloan, fee1e18, feemaxloan)(explain in "Explanation of Flashlender's functions") of providers having maxloan of DAI token >= 1000 DAI as below:

     getFlashLoanInfoListWithCheaperFeePriority("0x6b175474e89094c44da98b954eedeac495271d0f", "1000000000000000000000")
    
     - maxloan[0]: 250000000000000000000000000
     - fee1e18[0]: 5000000000000000
     - feemaxloan[0]: 1250000000000000000000000
    
     - maxloan[1]: 34666573213559721749534644
     - fee1e18[1]: 5000000000000000
     - feemaxloan[1]: 173332866067798608747673
    
     ...
    
     - maxloan[21]: 205787945408162232501371
     - fee1e18[21]: 8009027081243732
     - feemaxloan[21]: 1648161227767477860103
    
  2. If you want to borrow on the cheapest provider:

    2.a Get maxloan of the cheapest provider which has maxloan >= 1000 DAI

     maxFlashLoanWithCheapestProvider("0x6b175474e89094c44da98b954eedeac495271d0f", "1000000000000000000000");
     --> return: 250000000.000000000000000000 DAI
    

    2.b Get the cheapest fee of 250000000 DAI

     flashFeeWithCheapestProvider("0x6b175474e89094c44da98b954eedeac495271d0f", "250000000000000000000000000");
     --> return: 1250000.000000000000000000 DAI
    

    2.c Borrow 250000000 DAI on the cheapest provider

     bytes memory data = abi.encode("test");
     flashLoanWithCheapestProvider(address(FlashLender), "0x6b175474e89094c44da98b954eedeac495271d0f", "250000000000000000000000000", data);
    
  3. If you want to borrow on many providers:

    3.a Get maxloan of many providers which have maxloan >= 1000 DAI

     maxFlashLoanWithManyProviders("0x6b175474e89094c44da98b954eedeac495271d0f", "1000000000000000000000");
     --> return: 1561640514.396367875356244897 DAI
    

    3.b Get the cheapest fee of 1561640514.396367875356244897 DAI

     flashFeeWithManyProviders("0x6b175474e89094c44da98b954eedeac495271d0f", "1561640514396367875356244897", "1000000000000000000000");
     --> return: 8694933.980543179519311289 DAI
    

    3.c Borrow 1561640514.396367875356244897 DAI on many providers

     bytes memory data = abi.encode("test");
     flashLoanWithManyProviders(address(FlashLender), "0x6b175474e89094c44da98b954eedeac495271d0f", "1561640514396367875356244897", data, "1000000000000000000000");
    

Explanation of Flashlender's functions

  1. getFlashLoanInfoListWithCheaperFeePriority:

    To get a list of liquididity providers which have maxloan >= _minAmount with the following priority: cheaper fee; bigger maxloan in case of the same fee.

    each provider includes:

     - maxloan
     - fee1e18(flashfee per 1e18 tokens(including decimals))
     - feemaxloan(flashfee per maxloan tokens(including decimals))
    
    • Inputs:

      address _token : Borrowing token

      uint256 _minAmount : Minimum amount

    • Outputs:

      uint256[] maxloans : Maxloan array

      uint256[] feePer1e18s : FlashFee per 1e18 token(including decimals) array

      uint256[] feePerMaxLoans: FlashFee per maxloan token(including decimals) array

  2. maxFlashLoanWithCheapestProvider:

    To get maxFlashLoan of provider which has maxloan >= _minAmount and the cheapest fee

    • Inputs:

      address _token : Borrowing token

      uint256 _minAmount : Minimum amount

    • Outputs:

      uint256[] maxloan : Maxloan

  3. flashFeeWithCheapestProvider:

    To get flashfee of provider which has maxloan >= _amount and the cheapest fee

    • Inputs:

      address _token : Borrowing token

      uint256 _amount : Number of tokens to calculate flashfee

    • Outputs:

      uint256 : Fee

  4. flashLoanWithCheapestProvider:

    To execute flashLoan of provider which has maxloan >= _minAmount and the cheapest fee

    • Inputs:

      address _token : Borrowing token

      uint256 _amount : Number of tokens to borrow

      bytes calldata _data : Refer to FlashBorrower

    • Outputs:

      bool : True

  5. maxFlashLoanWithManyProviders:

    To get maxFlashLoan of many providers which have maxloan >= _minAmount and cheaper fee

    • Inputs:

      address _token : Borrowing token

      uint256 _minAmount : Minimum amount

    • Outputs:

      uint256[] maxloan : Maxloan

  6. flashFeeWithManyProviders:

    To get flashfee of provider which has: maxloan >= _amount and cheaper fee

    • Inputs:

      address _token : Borrowing token

      uint256 _amount : Number of tokens to calculate flashfee

      uint256 _minAmount : Minimum amount to get provider having maxloan >= _minAmount

    • Outputs:

      uint256 : Fee

  7. flashLoanWithManyProviders:

    To execute flashLoan of many providers which have maxloan >= _minAmount and cheaper fee

    • Inputs:

      IERC3156FlashBorrower _receiver : FlashBorrower

      address _token : Borrowing token

      uint256 _amount : Number of tokens to borrow

      bytes calldata _data : Refer to FlashBorrower

      uint256 _minAmount : Minimum amount

    • Outputs: bool : True

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published