Skip to content

Instantly share code, notes, and snippets.

@frankandrobot
Created October 6, 2022 02:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frankandrobot/296187ca4ef8c56462fb7e897e7d3b05 to your computer and use it in GitHub Desktop.
Save frankandrobot/296187ca4ef8c56462fb7e897e7d3b05 to your computer and use it in GitHub Desktop.
Nonworking flash loan contract
// 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