OK, I am trying to use a simplified version of a flash loan contract I am working on. The main version has two contracts and allows for variations on whether you start with a token loan or an eth loan and then which exchange you trade on first or second (UNI or KYBER).
But I was having a hard time getting it to run, so I made this leaner, streamlined, one-use-case contract. that is designed to pull an amount of eth from aave as a loan, and then trade it for a token on UNI and then trade that token back to ETH on KYBER. But still having issues trying to run this through remix on Ropsten.
pragma solidity ^0.5.16;
import "https://github.com/CryptoEatsTheWorld/flashloan-arbitrage/blob/master/contracts/FlashLoanReceiverBase.sol";
import "https://github.com/CryptoEatsTheWorld/flashloan-arbitrage/blob/master/contracts/ILendingPool.sol";
import "https://github.com/CryptoEatsTheWorld/flashloan-arbitrage/blob/master/contracts/ILendingPoolAddressesProvider.sol";
import "https://github.com/CryptoEatsTheWorld/flashloan-arbitrage/blob/master/contracts/ERC20.sol";
import "https://github.com/CryptoEatsTheWorld/flashloan-arbitrage/blob/master/contracts/IUniswap.sol";
interface IKyberNetworkProxy {
function getExpectedRate(ERC20 src, ERC20 dest, uint srcQty) external view returns (uint expectedRate, uint slippageRate);
}
interface ISimpleKyberProxy {
function swapTokenToEther(IERC20 token, uint256 srcAmount, uint256 minConversionRate) external returns (uint256 destAmount);
function swapEtherToToken(IERC20 token, uint256 minConversionRate) external payable returns (uint256 destAmount);
function swapTokenToToken(IERC20 src, uint256 srcAmount, IERC20 dest, uint256 minConversionRate) external returns (uint256 destAmount);
}
interface IWETH {
function deposit() external payable;
function withdraw(uint wad) external;
function totalSupply() external view returns (uint);
function approve(address guy, uint wad) external returns (bool);
function transfer(address dst, uint wad) external returns (bool);
function transferFrom(address src, address dst, uint wad) external returns (bool);
}
// MAINNET ADDRESS: 0x24a42fD28C976A61Df5D00D0599C34c4f90748c8
// KOVAN ADDRESS: 0x506B0B2CF20FAA8f38a4E2B524EE43e1f4458Cc5 // V2: 0x652B2937Efd0B5beA1c8d54293FC1289672AFC6b
// ROPSTEN ADDRESS: 0x1c8756FD2B28e9426CDBDcC7E3c4d64fa9A54728
contract OneFlashLoan is FlashLoanReceiverBase(address(0x1c8756FD2B28e9426CDBDcC7E3c4d64fa9A54728)){
using SafeMath for uint;
address erc20AddressOfAsset;
uint8 firstSwapDEX;
address firstSwapCoin;
uint8 secondSwapDEX;
address secondSwapCoin;
address owner;
address constant UNISWAP_FACTORY = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f; // MAINNET, KOVAN & ROPSTEN ADDRESS ARE THE SAME
IUniswapFactory public uniswapFactory = IUniswapFactory(UNISWAP_FACTORY);
// MAINNET ADDRESS: 0x9AAb3f75489902f3a48495025729a0AF77d4b11e
// KOVAN ADDRES: 0xc153eeAD19e0DBbDb3462Dcc2B703cC6D738A37c
// ROPSTEN ADDRESS: 0x818E6FECD516Ecc3849DAf6845e3EC868087B755
address constant KYBER_PROXY = 0x818E6FECD516Ecc3849DAf6845e3EC868087B755;
IKyberNetworkProxy public kyberProxy = IKyberNetworkProxy(KYBER_PROXY);
ISimpleKyberProxy public simpleKyberProxy = ISimpleKyberProxy(KYBER_PROXY);
constructor() public { owner = msg.sender; }
function() external payable {}
function startArbUsingEthReserve(uint _amount, address _firstSwapCoin) external onlyOwner {
firstSwapDEX = 1;
firstSwapCoin = _firstSwapCoin;
secondSwapDEX = 2;
secondSwapCoin = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
bytes memory data = "";
// THEN WE INITIATE THE LOAN, WHICH ON CALLBALL WILL TRIGGER executeoperation()
ILendingPool lendingPool = ILendingPool(addressesProvider.getLendingPool());
lendingPool.flashLoan(address(this), address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE), _amount, data);
}
function executeOperation(address _reserve, uint256 _amount, uint256 _fee, bytes calldata) external {
require(_amount <= getBalanceInternal(address(this), _reserve), "Invalid balance, was the flashLoan successful?");
address tempHeldToken;
uint256 tempHeldTokenAmount;
uint256 finalAmount;
uint256 deadline;
deadline = now + 3000;
(tempHeldToken, tempHeldTokenAmount) = swapEthToTokenFirstStep(firstSwapCoin, deadline);
finalAmount = swapTokenToEth(tempHeldToken, tempHeldTokenAmount);
erc20AddressOfAsset = address(0);
firstSwapDEX = 0;
firstSwapCoin = address(0);
secondSwapDEX = 0;
secondSwapCoin = address(0);
uint256 totalDebt = _amount.add(_fee);
require(finalAmount > totalDebt, "Did not profit");
transferFundsBackToPoolInternal(_reserve, totalDebt);
}
function swapEthToTokenFirstStep(address _destinationCoin, uint256 _deadline) internal returns (address, uint256) {
uint256 boughtCoinAmount;
address uniswap_token_Address = uniswapFactory.getExchange(_destinationCoin);
IUniswapExchange specificUniswapExchange = IUniswapExchange(uniswap_token_Address);
// SWAPPING AT EXCHANGE
boughtCoinAmount = specificUniswapExchange.ethToTokenSwapInput.value(address(this).balance)(1, _deadline);
return (_destinationCoin, boughtCoinAmount);
}
function swapTokenToEth(address _tempHeldToken, uint256 _tempHeldTokenAmount) internal returns (uint256) {
uint256 boughtCoinAmount;
ERC20 startingCoin = ERC20(_tempHeldToken);
ERC20 eth = ERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
(uint256 expectedRate, ) = kyberProxy.getExpectedRate(startingCoin, eth, _tempHeldTokenAmount);
// SWAPPING AT EXCHANGE
require(startingCoin.approve(address(kyberProxy), _tempHeldTokenAmount), "Could not approve token-to-token purchase (KYBER).");
boughtCoinAmount = simpleKyberProxy.swapTokenToEther(startingCoin, _tempHeldTokenAmount, expectedRate);
return boughtCoinAmount;
}
}
All you need to input is an amount of the loan (in WEI) and the Ropsten contract address of the token you want to swap to on the first swap and input those into the startArbUsinEthReserve function.
When I try on Remix it gives me that “Transaction likely to fail…” error and in the log it shows
transact to OneFlashLoan.startArbUsingEthReserve pending ...
transact to OneFlashLoan.startArbUsingEthReserve errored: [object Object]
It appears that it isn’t even getting past the first function where the loan is requested.
Any help would be awesome.