diff --git a/contracts/mainnet/connectors/instapool_v3/events.sol b/contracts/mainnet/connectors/instapool_v3/events.sol new file mode 100644 index 00000000..9fc1cd40 --- /dev/null +++ b/contracts/mainnet/connectors/instapool_v3/events.sol @@ -0,0 +1,10 @@ +pragma solidity >=0.7.0; +pragma experimental ABIEncoderV2; + +contract Events { + event LogFlashBorrow(address token, uint256 tokenAmt); + event LogFlashPayback(address token, uint256 tokenAmt); + + event LogFlashMultiBorrow(address[] token, uint256[] tokenAmts); + event LogFlashMultiPayback(address[] token, uint256[] tokenAmts); +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/instapool_v3/interfaces.sol b/contracts/mainnet/connectors/instapool_v3/interfaces.sol new file mode 100644 index 00000000..89ae592a --- /dev/null +++ b/contracts/mainnet/connectors/instapool_v3/interfaces.sol @@ -0,0 +1,17 @@ +pragma solidity >=0.7.0; +pragma experimental ABIEncoderV2; + +interface InstaFlashV2Interface { + function initiateFlashLoan(address token, uint256 amt, uint route, bytes calldata data) external; + function initiateMultiFlashLoan( + address[] memory tokens_, + uint256[] memory amounts_, + uint256, + bytes calldata data + ) external; +} + +interface AccountInterface { + function enable(address) external; + function disable(address) external; +} diff --git a/contracts/mainnet/connectors/instapool_v3/main.sol b/contracts/mainnet/connectors/instapool_v3/main.sol new file mode 100644 index 00000000..a0a93e83 --- /dev/null +++ b/contracts/mainnet/connectors/instapool_v3/main.sol @@ -0,0 +1,130 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +/** + * @title Instapool. + * @dev Inbuilt Flash Loan in DSA + */ + +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; +import { Address } from "@openzeppelin/contracts/utils/Address.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { TokenInterface } from "../../common/interfaces.sol"; +import { AccountInterface } from "./interfaces.sol"; +import { DSMath } from "../../common/math.sol"; +import { Stores } from "../../common/stores.sol"; +import { Variables } from "./variables.sol"; +import { Events } from "./events.sol"; + +contract LiquidityResolver is DSMath, Stores, Variables, Events { + using SafeERC20 for IERC20; + + /** + * @dev Borrow Flashloan and Cast spells. + * @param token Token Address. + * @param amt Token Amount. + * @param route Flashloan source route. (0: dYdX(ETH,DAI,USDC only), 1: MakerDAO(DAI only), 2: Compound(All borrowable tokens in Compound), 3: AaveV2(All borrowable tokens in AaveV2)) + * @param data targets & data for cast. + */ + function flashBorrowAndCast( + address token, + uint amt, + uint route, + bytes memory data + ) external payable { + AccountInterface(address(this)).enable(address(instaPool)); + (string[] memory _targets, bytes[] memory callDatas) = abi.decode(data, (string[], bytes[])); + + bytes memory callData = abi.encodeWithSignature("cast(string[],bytes[],address)", _targets, callDatas, address(instaPool)); + + instaPool.initiateFlashLoan(token, amt, route, callData); + + emit LogFlashBorrow(token, amt); + AccountInterface(address(this)).disable(address(instaPool)); + } + + /** + * @dev Return token to InstaPool. + * @param token Token Address. + * @param amt Token Amount. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function flashPayback( + address token, + uint amt, + uint getId, + uint setId + ) external payable { + uint _amt = getUint(getId, amt); + + IERC20 tokenContract = IERC20(token); + + if (token == ethAddr) { + Address.sendValue(payable(address(instaPool)), _amt); + } else { + tokenContract.safeTransfer(address(instaPool), _amt); + } + + setUint(setId, _amt); + + emit LogFlashPayback(token, _amt); + } + + /** + * @dev Borrow Flashloan and Cast spells. + * @param token Token Address. + * @param amt Token Amount. + * @param route Flashloan source route. (0: dYdX(ETH,DAI,USDC only), 1: MakerDAO(DAI only), 2: Compound(All borrowable tokens in Compound), 3: AaveV2(All borrowable tokens in AaveV2)) + * @param data targets & data for cast. + */ + function flashMultiBorrowAndCast( + address[] memory tokens_, + uint[] memory amts_, + uint route, + bytes memory data + ) external payable { + AccountInterface(address(this)).enable(address(instaPool)); + (string[] memory _targets, bytes[] memory callDatas) = abi.decode(data, (string[], bytes[])); + + bytes memory callData = abi.encodeWithSignature("cast(string[],bytes[],address)", _targets, callDatas, address(instaPool)); + + instaPool.initiateMultiFlashLoan(tokens_, amts_, route, callData); + + emit LogMultiFlashBorrow(tokens_, amts_); + AccountInterface(address(this)).disable(address(instaPool)); + } + + /** + * @dev Return token to InstaPool. + * @param token Token Address. + * @param amt Token Amount. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function flashMultiPayback( + address[] memory tokens_, + uint[] memory amts_, + uint[] memory getIds, + uint[] memory setIds + ) external payable { + for (uint i = 0; i < tokens_.length; i++) { + amts_[i] = getUint(getIds[i], amts_[i]); + + if (tokens_[i] == ethAddr) { + Address.sendValue(payable(address(instaPool)), amts_[i]); + } else { + IERC20(tokens_[i]).safeTransfer(address(instaPool), amts_[i]); + } + + setUint(setIds[i], amts_[i]); + } + + emit LogFlashPayback(tokens_, amts_); + } + +} + +contract ConnectV2InstaPool is LiquidityResolver { + string public name = "Instapool-v1.2"; +} diff --git a/contracts/mainnet/connectors/instapool_v3/variables.sol b/contracts/mainnet/connectors/instapool_v3/variables.sol new file mode 100644 index 00000000..40eede68 --- /dev/null +++ b/contracts/mainnet/connectors/instapool_v3/variables.sol @@ -0,0 +1,17 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +import { InstaFlashV2Interface } from "./interfaces.sol"; + +contract Variables { + + /** + * @dev Instapool contract proxy + */ + InstaFlashV2Interface public immutable instaPool; + + constructor(address _instaPool) { + instaPool = InstaFlashV2Interface(_instaPool); + } + +} \ No newline at end of file