Lets hack Flash Loans | Flash loan assignment/discussion

Best assignment so far. I created a DAI/LINK exchange and had to step out, and when I got back it was already arbitraged. I found another opportunity with ZERO and ran the ArbitrageFlash loan on it.

3 Likes

That is correct. Gas is paid for every operation up until the transaction fails. In the case of an arbitrage bot that will most likely be the require statement that checks if a profit was made or not.

Where it can get costly is with the bidding war required to be the first to execute the transaction. Multiple bots are bidding up transaction fees in order for their transaction to be picked up first by the miners because only the first bot will get to execute the arbitrage and profit from it.

But it must still be profitable otherwise no bots would be doing it. So lets not get discouraged :slight_smile:

1 Like

How can I overpower a bot Damnit xD
I tried to make an attempt on the mainnet and I failedā€¦ couldnā€™t figure out the problem, iā€™ll try maybe tomorrow after work :face_with_thermometer: Do you have an approximate Idea how much can it cost for 1 attempt? failed or successfull.

1 Like

i have a question @amadeobrands , I add up to 4000 DAI in the contract that I create for the flash loan and still it gives me the error
"Gas estimation failed
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
The execution failed due to an exception. Reverted "

What could be the problem?

1 Like

I researched on etherscan the address of one of the bot discussed in the paper but I still have many questions and few answers. The decompiled contract code is hard to read and very repetitive to the point where I wonder if the decompiler worked correctly.

So unfortunately I dont have a good enough understanding to give you an intelligent answer.

2 Likes

I managed to get a three way flash loan working between dai bat and mkr using the same code format as you, however the code only started working yesterday as before that i kept getting ā€œSafeERC20: low-level call failedā€ when i tried to run it a few days ago.

Correct me if im wrong but i think it has something to do with the ERC20 code not yet supporting some of the tokens like snx for arbitrage use.

2 Likes

Amazing man good job :smiley:
Would like to see some use-cases worked out.

For some reason I am having problems borrowing more than I deposit to the contract. Can somebody help me understand why? (I donā€™t find the sense of depositing 1M DAI to my contract first, to be able to borrow another million)

The code, seems to run correctly without issues as far as the amount borrowed doesnā€™t exceed what I added to the contract.

Also, I have noticed that the flashloans with the code provided are not profitable, even tho I have in the code to cancel the transaction if itā€™s not profitable. Can somebody help me or advice why ever time I run the code my DAI gets lower and lower while itā€™s supposed to be the opposite?

Example of the transaction when the amount borrowed is > than the amount I deposit in the contract:

Example of the transaction when the amount of borrowed is <= than the amount deposited in the contract:

Here the code:

pragma solidity ^0.5.0;

import "https://github.com/mrdavey/ez-flashloan/blob/remix/contracts/aave/FlashLoanReceiverBase.sol";
import "https://github.com/mrdavey/ez-flashloan/blob/remix/contracts/aave/ILendingPool.sol";
import "https://github.com/Robsonsjre/FlashloanUsecases/blob/master/contracts/interfaces/IUniswap.sol";


//1 DAI = 1000000000000000000 (18 decimals)
/*
 * Arbitrageur is a contract to simulate the usage of flashloans
 * to make profit out of a market inbalacement
 *
 * For this example we deployed 2 Uniswap instances which we'll
 * call by ExchangeA and ExchangeB
 *
 * The steps happens as following:
 * 1. Borrow DAI from Aave
 * 2. Buy MKR with DAI on ExchangeA
 * 3. Sell MKR for DAI on ExchangeB
 * 4. Repay Aave loan
 * 5. Keep the profits
 */
contract Arbitrageur is
    FlashLoanReceiverBase(address(0x506B0B2CF20FAA8f38a4E2B524EE43e1f4458Cc5))
{
    address public constant DAI_ADDRESS = 0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD;
    address public constant KNC_ADDRESS = 0x3F80c39c0b96A0945f9F0E9f55d8A8891c5671A8;
    address public constant UNISWAP_FACTORY_A = 0x54Ac34e5cE84C501165674782582ADce2FDdc8F4;
    address public constant UNISWAP_FACTORY_B = 0xECc6C0542710a0EF07966D7d1B10fA38bbb86523;

    ILendingPool public lendingPool;
    IUniswapExchange public exchangeA;
    IUniswapExchange public exchangeB;
    IUniswapFactory public uniswapFactoryA;
    IUniswapFactory public uniswapFactoryB;

    constructor() public {
        // Instantiate Uniswap Factory A
        uniswapFactoryA = IUniswapFactory(UNISWAP_FACTORY_A);
        // get Exchange A Address
        address exchangeA_address = uniswapFactoryA.getExchange(DAI_ADDRESS);
        // Instantiate Exchange A
        exchangeA = IUniswapExchange(exchangeA_address);

        //Instantiate Uniswap Factory B
        uniswapFactoryB = IUniswapFactory(UNISWAP_FACTORY_B);
        // get Exchange B Address
        address exchangeB_address = uniswapFactoryB.getExchange(KNC_ADDRESS);
        //Instantiate Exchange B
        exchangeB = IUniswapExchange(exchangeB_address);
        // get lendingPoolAddress
        address lendingPoolAddress = addressesProvider.getLendingPool();
        //Instantiate Aaave Lending Pool B
        lendingPool = ILendingPool(lendingPoolAddress);
    }

    /*
     * Start the arbitrage
     */
    function makeArbitrage(uint256 amount) public onlyOwner {
        bytes memory data = "";

        ERC20 dai = ERC20(DAI_ADDRESS);
        lendingPool.flashLoan(address(this), DAI_ADDRESS, amount, data);

        // Any left amount of DAI is considered profit
        uint256 profit = dai.balanceOf(address(this));
        // Sending back the profits
        require(
            dai.transfer(msg.sender, profit),
            "Could not transfer back the profit"
        );
    }

    function executeOperation(
        address _reserve,
        uint256 _amount,
        uint256 _fee,
        bytes calldata _params
    ) external {
        // If transactions are not mined until deadline the transaction is reverted
        uint256 deadline = getDeadline();

        ERC20 dai = ERC20(DAI_ADDRESS);
        ERC20 mkr = ERC20(KNC_ADDRESS);

        // Buying ETH at Exchange A
        require(
            dai.approve(address(exchangeA), _amount),
            "Could not approve DAI sell"
        );

        uint256 tokenBought = exchangeA.tokenToTokenSwapInput(
            _amount,
            1,
            1,
            deadline,
            KNC_ADDRESS
        );

        require(
            mkr.approve(address(exchangeB), tokenBought),
            "Could not approve DAI sell"
        );

        // Selling ETH at Exchange B
        uint256 daiBought = exchangeB.tokenToTokenSwapInput(
            tokenBought,
            1,
            1,
            deadline,
            DAI_ADDRESS
        );

        // Repay loan
        uint256 totalDebt = _amount.add(_fee);

       require(daiBought > totalDebt, "Did not profit");

        transferFundsBackToPoolInternal(_reserve, totalDebt);
    }

    function getDeadline() internal view returns (uint256) {
        return now + 3000;
    }
}
1 Like

I experience the same problem every time the loan is higher than the amount I deposit in the contract.
If you have deposited 4000, try to borrow max 4000 DAI and see if you get the same error.

I asked what could be the reason I am not able to get loans higher than the amount deposited in the contract. I hope somebody can give us advice and enlighten where could be the problem in our code.

2 Likes

2 Likes

No worries, Iā€™m sure weā€™ll figure it out at some point ahaha
Thank you for your time dude, appreciate it! :slight_smile:

1 Like

I attach the code of the flashloan that I am using to switch between DAI, BAT and MKR the contract does not give an error when compiling it; but when I want to execute the loan it gives me a gas calculation error.

I deposit in the smartcontract created 10, 50 or 100 DAI and in the same way it gives gas error.

Error ā€œgas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? The execution failed due to an exception. Revertedā€

1 Like

It Finally worked!!
Thatā€™s quite an arbitrage created between DAI and KNC!!

Now that Iā€™ve experimented and tested and somehow without developing experience I made it work, itā€™s time to get real and start with the programming courses!

4 Likes

Hello @visualcarm Didnā€™t give you the gas error ?? What change did you make?
Thanks for the help

1 Like

Hi @Thaddeus19.
I think it has to do with the liquidity of the pool. At least in my case. After you run the smart contract what error do you get in EtherScan? How much are you requesting? In my case I tried first with 1 DAI, it was ok, then 10 DAI, ok, 100 DAI, went ok. 1000 DAI, went ok, and after that, I started having the gas error. Even with 1 DAI gave me the warning of GAS, but after running the function ignoring the GAS warning, I was getting a "Fail with error ā€˜Did not profitā€™ ".
I also have some doubts, the DeFi courses were the first courses I took in the academy, now I am taking the bitcoin blockchain and plan to start Smart contracts on Ethereum after. I hope to get my doubts resolved after taking those courses as well.

3 Likes

thanks great amando for the changes, great job dude

1 Like
tx.gasprice (uint): return the gas price of the transaction
1 Like

Hello @visualcarm
The error is:
Gas estimation failed
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
The execution failed due to an exception. Reverted

Check the pool of both exchanges and have funds, but the Tx gives me a Fail message only

2 Likes

Hi, great course so far :slight_smile: , I just have one questionā€¦ One the arbitrage part, I get my makeArbitrage function reverted every time, so I tried (like in the flash loan example) to inject some DAI to my created contract. Do we need to inject some DAI to the created contract so the arbitrage goes trough ? If so, my injected DAI never arrives to the contract after retrying a few time ā€¦
Thank you

2 Likes

@tinyHamster you need is that when making the swap you have enough profit to pay the loan fee. You should check if the swap that you are making is giving you profits or not. Because it happened to me when trying to swap with Dai and SNX. What error gives you in the transaction with the requires that it be activated.

1 Like