Created
May 29, 2021 16:16
-
-
Save earthchie/5f106bbd3c2ac460c09ad53be68d09db to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.5.16; | |
interface IERC20 { | |
function balanceOf(address _owner) external view returns (uint256 balance); | |
function transfer(address _to, uint256 _value) external returns (bool success); | |
} | |
interface IFlashloanReceiver { | |
function executeOperation( | |
address sender, | |
address underlying, | |
uint amount, | |
uint fee, | |
bytes calldata params | |
) external payable; | |
} | |
interface ICTokenFlashloan { | |
function flashLoan( | |
address receiver, | |
uint amount, | |
bytes calldata params | |
) external; | |
} | |
interface IRouter{ | |
function swapExactTokensForTokens( | |
uint amountIn, | |
uint amountOutMin, | |
address[] calldata path, | |
address to, | |
uint deadline | |
) external returns (uint[] memory amounts); | |
function getAmountsOut( | |
uint amountIn, | |
address[] calldata path | |
) external view returns (uint[] memory amounts); | |
} | |
contract FlashArbitrage is IFlashloanReceiver { | |
address public owner; | |
address public feePoolAddr; | |
constructor() public { | |
owner = msg.sender; | |
feePoolAddr = msg.sender; | |
} | |
function setFeePoolAddress(address _feePoolAddr) public { | |
require(msg.sender == owner, "unauthorized"); | |
feePoolAddr = _feePoolAddr; | |
} | |
function arbitrage(IERC20 Capital, bytes memory params) internal { | |
// parse params | |
( | |
address buyFromThisRouterAddr, | |
address sellToThisRouterAddr, | |
address token1Addr, | |
address token2Addr, | |
uint deadline | |
) = abi.decode(params, ( | |
address, | |
address, | |
address, | |
address, | |
uint | |
)); | |
// prepare routers | |
IRouter buyFromThisRouter = IRouter(buyFromThisRouterAddr); | |
IRouter sellToThisRouter = IRouter(sellToThisRouterAddr); | |
// make buy order | |
address[] memory pair1 = new address[](2); | |
pair1[0] = token1Addr; | |
pair1[1] = token2Addr; | |
uint256 amount2 = buyFromThisRouter.getAmountsOut(Capital.balanceOf(address(this)), pair1)[1]; | |
buyFromThisRouter.swapExactTokensForTokens(Capital.balanceOf(address(this)), amount2, pair1, address(this), deadline); // buy | |
// make sell order | |
address[] memory pair2 = new address[](2); | |
pair2[0] = token2Addr; | |
pair2[1] = token1Addr; | |
sellToThisRouter.swapExactTokensForTokens(amount2, sellToThisRouter.getAmountsOut(amount2, pair2)[1], pair2, address(this), deadline); // sell | |
} | |
function doFlashArbitrage(address lenderAddr, uint256 borrowAmount, bytes calldata params) external payable { | |
ICTokenFlashloan(lenderAddr).flashLoan(address(msg.sender), borrowAmount, params); | |
} | |
function executeOperation(address signerAddr, address tokenAddr, uint amount, uint fee, bytes calldata params) external payable { | |
IERC20 Capital = IERC20(tokenAddr); | |
require(Capital.balanceOf(address(this)) >= amount, "Invalid balance, was the flashLoan successful?"); | |
arbitrage(Capital, params); | |
require(Capital.transfer(msg.sender, amount + fee), "Transfer fund back failed"); | |
Capital.transfer(feePoolAddr, Capital.balanceOf(address(this))/10); // deduct 10% to fee pool | |
Capital.transfer(signerAddr, Capital.balanceOf(address(this))); // transfer remaining to signer | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment