Skip to content

Instantly share code, notes, and snippets.

@NAKsir-melody
Created September 10, 2020 06:18
Show Gist options
  • Save NAKsir-melody/c5aa38f1677d050ea91c4be2250141cc to your computer and use it in GitHub Desktop.
Save NAKsir-melody/c5aa38f1677d050ea91c4be2250141cc to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.5.17+commit.d19bba13.js&optimize=false&gist=
pragma solidity ^0.5.17;
pragma experimental ABIEncoderV2;
import "github/OpenZeppelin/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import "github/OpenZeppelin/openzeppelin-contracts/contracts/ownership/Ownable.sol";
import "github/OpenZeppelin/openzeppelin-contracts/contracts/GSN/Context.sol";
import "github/studydefi/money-legos/src/dydx/contracts/DydxFlashloanBase.sol";
import "github/studydefi/money-legos/src/dydx/contracts/ICallee.sol";
import "github/Uniswap/uniswap-v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "github/Uniswap/uniswap-v2-periphery/contracts/interfaces/IUniswapV2Router01.sol";
interface ICurveFi {
function exchange_underlying(
int128 from, int128 to, uint256 _from_amount, uint256 _min_to_amount
) external;
}
contract DydxFlashloaner is ICallee, DydxFlashloanBase, Ownable {
struct MyCustomData {
address fromToken;
address toToken;
uint256 borrowAmount;
uint256 repayAmount;
address curvepool;
int128 curveIndex1;
int128 curveIndex2;
}
/*
address _weth = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
address _usdc = address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
address _susd = address(0x57Ab1ec28D129707052df4dF418D58a2D46d5f51);
address _solo = address(0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e);
//address _swap = address(0x45F783CCE6B7FF23B2ab2D70e416cdb7D6055f51);
address _swap = address(0xA5407eAE9Ba41422680e2e00537571bcC53efBfD);
//500000000000
*/
// This is the function that will be called postLoan
// i.e. Encode the logic to handle your flashloaned funds here
function callFunction(
address sender,
Account.Info memory account,
bytes memory data
) public {
MyCustomData memory mcd = abi.decode(data, (MyCustomData));
// balOfLoanedToken = IERC20(mcd.token).balanceOf(address(this));
// Note that you can ignore the line below
// if your dydx account (this contract in this case)
// has deposited at least ~2 Wei of assets into the account
// to balance out the collaterization ratio
//require(
// balOfLoanedToken >= mcd.repayAmount,
// "Not enough funds to repay dydx loan!"
//);
IERC20(mcd.fromToken).approve(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D,uint(-1));
IUniswapV2Router02 usi = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
address[] memory path = new address[](2);
path[0] = mcd.fromToken;
path[1] = mcd.toToken;
usi.swapExactTokensForTokens(mcd.borrowAmount,1, path, address(this), now );
IERC20 susd = IERC20(mcd.toToken);
susd.approve(mcd.curvepool, uint(-1));
ICurveFi(mcd.curvepool).exchange_underlying(mcd.curveIndex1, mcd.curveIndex2, susd.balanceOf(address(this)), 0);
require(
IERC20(mcd.fromToken).balanceOf(address(this)) >= mcd.repayAmount,
"Not enough funds to repay dydx loan!"
);
}
function initiateFlashLoan(address _solo, address _fromToken, address _toToken, uint256 _amount,address _curvepool,int128 _curveIndex1,int128 _curveIndex2)
external
{
ISoloMargin solo = ISoloMargin(_solo);
// Get marketId from token address
uint256 marketId = _getMarketIdFromTokenAddress(_solo, _fromToken);
// Calculate repay amount (_amount + (2 wei))
// Approve transfer from
uint256 repayAmount = _getRepaymentAmountInternal(_amount);
IERC20(_fromToken).approve(_solo, uint(-1));
// 1. Withdraw $
// 2. Call callFunction(...)
// 3. Deposit back $
Actions.ActionArgs[] memory operations = new Actions.ActionArgs[](3);
operations[0] = _getWithdrawAction(marketId, _amount);
operations[1] = _getCallAction(
// Encode MyCustomData for callFunction
abi.encode(MyCustomData({
fromToken: _fromToken,
toToken: _toToken,
borrowAmount: _amount,
repayAmount: repayAmount,
curvepool: _curvepool,
curveIndex1: _curveIndex1,
curveIndex2: _curveIndex2
}))
);
operations[2] = _getDepositAction(marketId, repayAmount);
Account.Info[] memory accountInfos = new Account.Info[](1);
accountInfos[0] = _getAccountInfo();
solo.operate(accountInfos, operations);
}
function withdraw(
address _token
)
public onlyOwner
{
IERC20 token = IERC20(_token);
uint256 balance = token.balanceOf(address(this));
token.transfer(0xFfdcabffB9EC425FD0B469eF626c844CB68670E8, balance);
}
function destroy()
public onlyOwner
{
selfdestruct(0xFfdcabffB9EC425FD0B469eF626c844CB68670E8);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment