4

Looking into Flash Loans, is it possible to take out TWO at once (aave/dydx/uniswap)? How would you go about doing this?

Here is what I'm thinking of, but it seems too complicated:

  • Contract 1 takes a loan for COIN1.
  • Contract 1 sends COIN1 to Contract 2.
  • Contract 2 recieves COIN1 and takes a loan for COIN2.
  • Contract 2 does stuff with both coins
  • Contract 2 pays off its loan
  • Contract 2 sends remaining funds to Contract 1
  • Contract 1 pays off its loan.

The premise is that Contract 2 needs access to both coins at once and there is not way to change this. Is there a way to just ask for two loans at once in one contract or something?

1 Answer 1

6

You can actually do a double flashloan, but the success will depend on the total amount of gas consumed in the transaction.

In fact, you don't need to have two contracts and you can request the two loans from the same contract.

Below is a simple example on how this could be done:

// SPDX-License-Identifier: MIT
pragma solidity ^0.7.3;

import {IERC20} from "../aave-flashloan/interfaces/IERC20.sol";
import {FlashloanProvider2} from "./FlashloanProvider.sol";
import {IFlashloanUser2} from "./IFlashloanUser.sol";

contract FlashloanUser2 is IFlashloanUser2 {
    string public output1;
    string public output2;

    /**
     * @notice  Start the flashloan (triggered by user)
     * @param   flashloan The flashloan contract address
     * @param   amount The amount to be borrowed
     * @param   token The token to be borrowed
     */
    function startFlashloan(
        address flashloan,
        uint256 amount,
        address token
    ) external {
       // Flashloan call #1 
        FlashloanProvider2(flashloan).executeFlashloan(
            address(this),
            amount,
            token,
            'flash1',
            1
        );
        // Flashloan call #2
        FlashloanProvider2(flashloan).executeFlashloan(
            address(this),
            amount,
            token,
            'flash2',
            2
        );
    }

    /**
     * @notice  Callback function to do arbitrage (or whatever) after
     *          receiving the borrowed amount and before returning it
     * @param   amount The amount to be returned
     * @param   token The token to be returned
     * @param   data Arbitrary data
     */
    function flashloanCallback(
        uint256 amount,
        address token,
        string memory data,
        uint256 flashNumber
    ) external override {
        // do some arbitrage, liquidation, etc.
        if (flashNumber == 1) {
            output1 = data;
        } else {
            output2 = data;
        }

        // Reimburse borrowed tokens to Flashloan contract
        IERC20(token).transfer(msg.sender, amount);
    }
}

In function startFlashloan(), there are two calls to the same flashloan provider, but it could be different contracts (e.g.: Uniswap, Kyber).

In this simple example, the same amount is borrowed in the two loans, and the callback function is updating variables output1 and output2 with values 'flash1' and 'flash2' respectively.

It is just a basic demo to show that technically speaking and for a simple case, it is possible. For a real case using Production exchanges, I am not fully sure you could make it without running out of gas.

3
  • Ok thank you. One last quick thing, can I request the second flash loan from within the first callback?
    – superuser
    Commented Mar 18, 2021 at 18:30
  • 1
    Yes, you could do that but you should ensure not entering into a loop. You will need to know whether it is the first or second time the callback is called in order to determine if you do the second flashloan or you finish the execution. Commented Mar 18, 2021 at 18:41
  • Ok that makes sense!
    – superuser
    Commented Mar 18, 2021 at 23:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.