Created
October 6, 2022 02:58
-
-
Save frankandrobot/296187ca4ef8c56462fb7e897e7d3b05 to your computer and use it in GitHub Desktop.
Nonworking flash loan contract
This file contains 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
// SPDX-License-Identifier: mit | |
pragma solidity >=0.6.12; | |
import "@sushiswap/bentobox/contracts/interfaces/IBentoBoxV1.sol"; | |
import "@sushiswap/bentobox/contracts/interfaces/IFlashBorrower.sol"; | |
import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol"; | |
import "hardhat/console.sol"; | |
import "../shared/Withdrawable.old.sol"; | |
/** | |
* Protocols implementing this interface: | |
* - spiritswap - https://github.com/Layer3Org/spiritswap-core/blob/f730bcb4a96088f4878dffc6b578afdfe42db945/SpiritV2/contracts/UniV2-AMM/SpiritRouterV1.sol#L963 | |
* - spookyswap - https://github.com/SpookySwap/spookyswap-core/blob/966618bfda120f65d3143494a60ed1b7efe80d52/contracts/UniswapV2Router02.sol#L224 Note: uint = uint256 | |
* - tombswap - https://ftmscan.com/address/0x6D0176C5ea1e44b08D3dd001b0784cE42F47a3A7#writeContract | |
* - beethovenx - ??? | |
*/ | |
interface UniswapRouter { | |
function swapExactTokensForTokens( | |
uint256 amountIn, | |
uint256 amountOutMin, | |
address[] calldata path, | |
address to, | |
uint256 deadline | |
) external returns (uint256[] memory amounts); | |
function factory() external pure returns (address); | |
} | |
interface UniswapFactory { | |
function getPair(address address1, address address2) | |
external | |
returns (address pairAddress); | |
} | |
contract SushiFlashLoanWithUniswap is Withdrawable, IFlashBorrower { | |
using BoringMath for uint256; | |
using BoringMath128 for uint128; | |
using BoringERC20 for IERC20; | |
IBentoBoxV1 public bentoBox; | |
constructor(address _bentoBoxV1) public { | |
bentoBox = IBentoBoxV1(_bentoBoxV1); | |
} | |
receive() external payable {} | |
/** | |
* Swap the token on the minRouter for the otherToken, | |
* then swap back (for the token) on the maxRouter. | |
* | |
* The price is higher on the maxRouter, so profit. :fingers_crossed: :-) | |
*/ | |
function go( | |
IERC20 token, | |
uint256 borrowAmount, | |
address minRouterAddress, | |
address maxRouterAddress, | |
IERC20 otherToken | |
) external onlyOwner { | |
require(borrowAmount > 0, "Gotta borrow something"); | |
console.log("Calling flashLoan"); | |
bentoBox.flashLoan( | |
this, | |
address(this), | |
token, | |
borrowAmount, | |
abi.encode(minRouterAddress, maxRouterAddress, address(otherToken)) | |
); | |
} | |
function _swap( | |
address sender, | |
uint256 amount, | |
address routerAddress, | |
address token1, | |
address token2 | |
) private returns (uint256) { | |
UniswapRouter router = UniswapRouter(routerAddress); | |
address[] memory path = new address[](2); | |
path[0] = token1; | |
path[1] = token2; | |
UniswapFactory factory = UniswapFactory(router.factory()); | |
IERC20 token = IERC20(token1); | |
token.approve(factory.getPair(token1, token2), amount); | |
token.approve(routerAddress, amount); | |
// TODO how to correctly use swapExactTokensForTokens - lets try 0 for min amount out | |
uint256[] memory result = router.swapExactTokensForTokens( | |
amount, | |
0, | |
path, | |
sender, | |
now + 60_000 | |
); | |
return result[1]; | |
} | |
function onFlashLoan( | |
address sender, | |
IERC20 token, | |
uint256 amount, | |
uint256 fee, | |
bytes calldata data | |
) external override { | |
// The flashloan callback. amount + fee needs to repayed to msg.sender before this call returns. | |
console.log("starting flash loan"); | |
(address router1Address, address router2Address, address otherToken) = abi | |
.decode(data, (address, address, address)); | |
uint256 output = _swap( | |
sender, | |
amount, | |
router1Address, | |
address(token), | |
otherToken | |
); | |
output = _swap(sender, output, router2Address, otherToken, address(token)); | |
// payback the loan | |
require(output > fee, "Need to recoup the fee"); | |
require(output > amount, "Need to recoup the loan amount"); | |
require(output > amount + fee, "Need to recoup the loan + fee"); | |
// pay back's a bitch | |
token.approve(msg.sender, amount + fee); | |
token.safeTransfer(msg.sender, amount + fee); | |
// keep the rest! | |
token.approve(sender, output - amount - fee); | |
token.safeTransfer(sender, output - amount - fee); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment