diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000..70fc7f9a --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,27 @@ +# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. +# +# You can adjust the behavior by modifying this file. +# For more information, see: +# https://github.com/actions/stale +name: Mark stale issues and pull requests + +on: + schedule: + - cron: '31 4 * * *' + +jobs: + stale: + + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + + steps: + - uses: actions/stale@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'Stale issue message' + stale-pr-message: 'Stale pull request message' + stale-issue-label: 'no-issue-activity' + stale-pr-label: 'no-pr-activity' diff --git a/contracts/arbitrum/connectors/instapool_v4/events.sol b/contracts/arbitrum/connectors/instapool_v4/events.sol new file mode 100644 index 00000000..9fc1cd40 --- /dev/null +++ b/contracts/arbitrum/connectors/instapool_v4/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/arbitrum/connectors/instapool_v4/interfaces.sol b/contracts/arbitrum/connectors/instapool_v4/interfaces.sol new file mode 100644 index 00000000..c5a40fd4 --- /dev/null +++ b/contracts/arbitrum/connectors/instapool_v4/interfaces.sol @@ -0,0 +1,11 @@ +pragma solidity >=0.7.0; +pragma experimental ABIEncoderV2; + +interface InstaFlashV4Interface { + function flashLoan(address[] memory tokens, uint256[] memory amts, uint route, bytes memory data, bytes memory extraData) external; +} + +interface AccountInterface { + function enable(address) external; + function disable(address) external; +} diff --git a/contracts/arbitrum/connectors/instapool_v4/main.sol b/contracts/arbitrum/connectors/instapool_v4/main.sol new file mode 100644 index 00000000..d11e9639 --- /dev/null +++ b/contracts/arbitrum/connectors/instapool_v4/main.sol @@ -0,0 +1,138 @@ +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 { Stores } from "../../common/stores.sol"; +import { Variables } from "./variables.sol"; +import { Events } from "./events.sol"; + +contract LiquidityResolver is Stores, Variables, Events { + using SafeERC20 for IERC20; + + /** + * @dev Borrow Flashloan and Cast spells. + * @notice Borrow Flashloan and Cast spells. + * @param token Token Address. + * @param amt Token Amount. + * @param route Flashloan source route. + * @param data targets & data for cast. + * @param extraData to be kept bytes(0) in most cases. Can be useful to decide data for some particular routes + */ + function flashBorrowAndCast( + address token, + uint amt, + uint route, + bytes memory data, + bytes memory extraData + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + 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)); + + address[] memory tokens_ = new address[](1); + tokens_[0] = token; + uint[] memory amts_ = new uint[](1); + amts_[0] = amt; + instaPool.flashLoan(tokens_, amts_, route, callData_, extraData); + + AccountInterface(address(this)).disable(address(instaPool)); + + _eventName = "LogFlashBorrow(address,uint256)"; + _eventParam = abi.encode(token, amt); + } + + /** + * @dev Return token to InstaPool. + * @notice 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 returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + IERC20 tokenContract = IERC20(token); + + tokenContract.safeTransfer(address(instaPool), _amt); + + setUint(setId, _amt); + + _eventName = "LogFlashPayback(address,uint256)"; + _eventParam = abi.encode(token, amt); + } + + /** + * @dev Borrow multi-tokens Flashloan and Cast spells. + * @notice Borrow multi-tokens Flashloan and Cast spells. + * @param tokens_ Array of Token Addresses. + * @param amts_ Array of Token Amounts. + * @param route Flashloan source route. + * @param data targets & data for cast. + * @param extraData to be kept bytes(0) in most cases. Can be useful to decide data for some particular routes + */ + function flashMultiBorrowAndCast( + address[] memory tokens_, + uint[] memory amts_, + uint route, + bytes memory data, + bytes memory extraData + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + 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.flashLoan(tokens_, amts_, route, callData_, extraData); + + AccountInterface(address(this)).disable(address(instaPool)); + _eventName = "LogFlashMultiBorrow(address[],uint256[])"; + _eventParam = abi.encode(tokens_, amts_); + } + + /** + * @dev Return multi-tokens to InstaPool. + * @notice Return multi-tokens to InstaPool. + * @param tokens_ Array of Token Addresses. + * @param amts_ Array of Token Amounts. + * @param getIds Array of getId token amounts. + * @param setIds Array of setId token amounts. + */ + function flashMultiPayback( + address[] memory tokens_, + uint[] memory amts_, + uint[] memory getIds, + uint[] memory setIds + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + for (uint i = 0; i < tokens_.length; i++) { + amts_[i] = getUint(getIds[i], amts_[i]); + + IERC20(tokens_[i]).safeTransfer(address(instaPool), amts_[i]); + + setUint(setIds[i], amts_[i]); + } + + _eventName = "LogFlashMultiPayback(address[],uint256[])"; + _eventParam = abi.encode(tokens_, amts_); + } + +} + +contract ConnectV2InstaPoolV4 is LiquidityResolver { + string public name = "Instapool-v4"; +} diff --git a/contracts/arbitrum/connectors/instapool_v4/variables.sol b/contracts/arbitrum/connectors/instapool_v4/variables.sol new file mode 100644 index 00000000..fc2cae72 --- /dev/null +++ b/contracts/arbitrum/connectors/instapool_v4/variables.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +import { InstaFlashV4Interface } from "./interfaces.sol"; + +contract Variables { + + /** + * @dev Instapool contract proxy + */ + InstaFlashV4Interface public constant instaPool = InstaFlashV4Interface(address(0)); // TODO: update address + +} \ No newline at end of file diff --git a/contracts/avalanche/connectors/instapool_v4/events.sol b/contracts/avalanche/connectors/instapool_v4/events.sol new file mode 100644 index 00000000..9fc1cd40 --- /dev/null +++ b/contracts/avalanche/connectors/instapool_v4/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/avalanche/connectors/instapool_v4/interfaces.sol b/contracts/avalanche/connectors/instapool_v4/interfaces.sol new file mode 100644 index 00000000..c5a40fd4 --- /dev/null +++ b/contracts/avalanche/connectors/instapool_v4/interfaces.sol @@ -0,0 +1,11 @@ +pragma solidity >=0.7.0; +pragma experimental ABIEncoderV2; + +interface InstaFlashV4Interface { + function flashLoan(address[] memory tokens, uint256[] memory amts, uint route, bytes memory data, bytes memory extraData) external; +} + +interface AccountInterface { + function enable(address) external; + function disable(address) external; +} diff --git a/contracts/avalanche/connectors/instapool_v4/main.sol b/contracts/avalanche/connectors/instapool_v4/main.sol new file mode 100644 index 00000000..d11e9639 --- /dev/null +++ b/contracts/avalanche/connectors/instapool_v4/main.sol @@ -0,0 +1,138 @@ +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 { Stores } from "../../common/stores.sol"; +import { Variables } from "./variables.sol"; +import { Events } from "./events.sol"; + +contract LiquidityResolver is Stores, Variables, Events { + using SafeERC20 for IERC20; + + /** + * @dev Borrow Flashloan and Cast spells. + * @notice Borrow Flashloan and Cast spells. + * @param token Token Address. + * @param amt Token Amount. + * @param route Flashloan source route. + * @param data targets & data for cast. + * @param extraData to be kept bytes(0) in most cases. Can be useful to decide data for some particular routes + */ + function flashBorrowAndCast( + address token, + uint amt, + uint route, + bytes memory data, + bytes memory extraData + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + 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)); + + address[] memory tokens_ = new address[](1); + tokens_[0] = token; + uint[] memory amts_ = new uint[](1); + amts_[0] = amt; + instaPool.flashLoan(tokens_, amts_, route, callData_, extraData); + + AccountInterface(address(this)).disable(address(instaPool)); + + _eventName = "LogFlashBorrow(address,uint256)"; + _eventParam = abi.encode(token, amt); + } + + /** + * @dev Return token to InstaPool. + * @notice 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 returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + IERC20 tokenContract = IERC20(token); + + tokenContract.safeTransfer(address(instaPool), _amt); + + setUint(setId, _amt); + + _eventName = "LogFlashPayback(address,uint256)"; + _eventParam = abi.encode(token, amt); + } + + /** + * @dev Borrow multi-tokens Flashloan and Cast spells. + * @notice Borrow multi-tokens Flashloan and Cast spells. + * @param tokens_ Array of Token Addresses. + * @param amts_ Array of Token Amounts. + * @param route Flashloan source route. + * @param data targets & data for cast. + * @param extraData to be kept bytes(0) in most cases. Can be useful to decide data for some particular routes + */ + function flashMultiBorrowAndCast( + address[] memory tokens_, + uint[] memory amts_, + uint route, + bytes memory data, + bytes memory extraData + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + 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.flashLoan(tokens_, amts_, route, callData_, extraData); + + AccountInterface(address(this)).disable(address(instaPool)); + _eventName = "LogFlashMultiBorrow(address[],uint256[])"; + _eventParam = abi.encode(tokens_, amts_); + } + + /** + * @dev Return multi-tokens to InstaPool. + * @notice Return multi-tokens to InstaPool. + * @param tokens_ Array of Token Addresses. + * @param amts_ Array of Token Amounts. + * @param getIds Array of getId token amounts. + * @param setIds Array of setId token amounts. + */ + function flashMultiPayback( + address[] memory tokens_, + uint[] memory amts_, + uint[] memory getIds, + uint[] memory setIds + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + for (uint i = 0; i < tokens_.length; i++) { + amts_[i] = getUint(getIds[i], amts_[i]); + + IERC20(tokens_[i]).safeTransfer(address(instaPool), amts_[i]); + + setUint(setIds[i], amts_[i]); + } + + _eventName = "LogFlashMultiPayback(address[],uint256[])"; + _eventParam = abi.encode(tokens_, amts_); + } + +} + +contract ConnectV2InstaPoolV4 is LiquidityResolver { + string public name = "Instapool-v4"; +} diff --git a/contracts/avalanche/connectors/instapool_v4/variables.sol b/contracts/avalanche/connectors/instapool_v4/variables.sol new file mode 100644 index 00000000..fc2cae72 --- /dev/null +++ b/contracts/avalanche/connectors/instapool_v4/variables.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +import { InstaFlashV4Interface } from "./interfaces.sol"; + +contract Variables { + + /** + * @dev Instapool contract proxy + */ + InstaFlashV4Interface public constant instaPool = InstaFlashV4Interface(address(0)); // TODO: update address + +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/instapool_v4/events.sol b/contracts/mainnet/connectors/instapool_v4/events.sol new file mode 100644 index 00000000..9fc1cd40 --- /dev/null +++ b/contracts/mainnet/connectors/instapool_v4/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_v4/interfaces.sol b/contracts/mainnet/connectors/instapool_v4/interfaces.sol new file mode 100644 index 00000000..c5a40fd4 --- /dev/null +++ b/contracts/mainnet/connectors/instapool_v4/interfaces.sol @@ -0,0 +1,11 @@ +pragma solidity >=0.7.0; +pragma experimental ABIEncoderV2; + +interface InstaFlashV4Interface { + function flashLoan(address[] memory tokens, uint256[] memory amts, uint route, bytes memory data, bytes memory extraData) external; +} + +interface AccountInterface { + function enable(address) external; + function disable(address) external; +} diff --git a/contracts/mainnet/connectors/instapool_v4/main.sol b/contracts/mainnet/connectors/instapool_v4/main.sol new file mode 100644 index 00000000..da3a159f --- /dev/null +++ b/contracts/mainnet/connectors/instapool_v4/main.sol @@ -0,0 +1,136 @@ +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 { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { AccountInterface } from "./interfaces.sol"; +import { Stores } from "../../common/stores.sol"; +import { Variables } from "./variables.sol"; +import { Events } from "./events.sol"; + +contract LiquidityResolver is Stores, Variables, Events { + using SafeERC20 for IERC20; + + /** + * @dev Borrow Flashloan and Cast spells. + * @notice Borrow Flashloan and Cast spells. + * @param token Token Address. + * @param amt Token Amount. + * @param route Flashloan source route. + * @param data targets & data for cast. + * @param extraData to be kept bytes(0) in most cases. Can be useful to decide data for some particular routes + */ + function flashBorrowAndCast( + address token, + uint amt, + uint route, + bytes memory data, + bytes memory extraData + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + 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)); + + address[] memory tokens_ = new address[](1); + tokens_[0] = token; + uint[] memory amts_ = new uint[](1); + amts_[0] = amt; + instaPool.flashLoan(tokens_, amts_, route, callData_, extraData); + + AccountInterface(address(this)).disable(address(instaPool)); + + _eventName = "LogFlashBorrow(address,uint256)"; + _eventParam = abi.encode(token, amt); + } + + /** + * @dev Return token to InstaPool. + * @notice 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 returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + IERC20 tokenContract = IERC20(token); + + tokenContract.safeTransfer(address(instaPool), _amt); + + setUint(setId, _amt); + + _eventName = "LogFlashPayback(address,uint256)"; + _eventParam = abi.encode(token, amt); + } + + /** + * @dev Borrow multi-tokens Flashloan and Cast spells. + * @notice Borrow multi-tokens Flashloan and Cast spells. + * @param tokens_ Array of Token Addresses. + * @param amts_ Array of Token Amounts. + * @param route Flashloan source route. + * @param data targets & data for cast. + * @param extraData to be kept bytes(0) in most cases. Can be useful to decide data for some particular routes + */ + function flashMultiBorrowAndCast( + address[] memory tokens_, + uint[] memory amts_, + uint route, + bytes memory data, + bytes memory extraData + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + 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.flashLoan(tokens_, amts_, route, callData_, extraData); + + AccountInterface(address(this)).disable(address(instaPool)); + _eventName = "LogFlashMultiBorrow(address[],uint256[])"; + _eventParam = abi.encode(tokens_, amts_); + } + + /** + * @dev Return multi-tokens to InstaPool. + * @notice Return multi-tokens to InstaPool. + * @param tokens_ Array of Token Addresses. + * @param amts_ Array of Token Amounts. + * @param getIds Array of getId token amounts. + * @param setIds Array of setId token amounts. + */ + function flashMultiPayback( + address[] memory tokens_, + uint[] memory amts_, + uint[] memory getIds, + uint[] memory setIds + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + for (uint i = 0; i < tokens_.length; i++) { + amts_[i] = getUint(getIds[i], amts_[i]); + + IERC20(tokens_[i]).safeTransfer(address(instaPool), amts_[i]); + + setUint(setIds[i], amts_[i]); + } + + _eventName = "LogFlashMultiPayback(address[],uint256[])"; + _eventParam = abi.encode(tokens_, amts_); + } + +} + +contract ConnectV2InstaPoolV4 is LiquidityResolver { + string public name = "Instapool-v4"; +} diff --git a/contracts/mainnet/connectors/instapool_v4/variables.sol b/contracts/mainnet/connectors/instapool_v4/variables.sol new file mode 100644 index 00000000..9f8e350c --- /dev/null +++ b/contracts/mainnet/connectors/instapool_v4/variables.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +import { InstaFlashV4Interface } from "./interfaces.sol"; + +contract Variables { + + /** + * @dev Instapool contract proxy + */ + InstaFlashV4Interface public constant instaPool = InstaFlashV4Interface(0x619Ad2D02dBeE6ebA3CDbDA3F98430410e892882); + +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/universeFinance/events.sol b/contracts/mainnet/connectors/universeFinance/events.sol new file mode 100644 index 00000000..325ef399 --- /dev/null +++ b/contracts/mainnet/connectors/universeFinance/events.sol @@ -0,0 +1,20 @@ +pragma solidity ^0.7.0; + +contract Events { + + event LogDeposit( + address indexed universeVault, + uint256 amountA, + uint256 amountB, + uint256 share0, + uint256 share1 + ); + + event LogWithdraw( + address indexed universeVault, + uint256 amountA, + uint256 amountB, + uint256 share0, + uint256 share1 + ); +} diff --git a/contracts/mainnet/connectors/universeFinance/helpers.sol b/contracts/mainnet/connectors/universeFinance/helpers.sol new file mode 100644 index 00000000..e9a9c6cc --- /dev/null +++ b/contracts/mainnet/connectors/universeFinance/helpers.sol @@ -0,0 +1,43 @@ +pragma solidity ^0.7.6; + +import {TokenInterface} from "../../common/interfaces.sol"; +import {DSMath} from "../../common/math.sol"; +import {Basic} from "../../common/basic.sol"; + +import "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + + IUniverseAdapter constant universeAdapter = IUniverseAdapter(0x876861Ad49f911442720cF97c9b3fCe4070F07d5); + + function _deposit( + address universeVault, + uint256 amount0, + uint256 amount1 + ) internal returns(uint256, uint256){ + return universeAdapter.depositProxy(universeVault, amount0, amount1); + } + + function _withdraw( + address universeVault, + uint256 share0, + uint256 share1 + ) internal returns(uint256, uint256){ + require(share0 > 0 || share1 > 0, "ZERO"); + return IVaultV3(universeVault).withdraw(share0, share1); + } + + function _approve(address universeVault, uint256 amount0, uint256 amount1) internal { + IVaultV3 universe = IVaultV3(universeVault); + TokenInterface token; + if (amount0 > 0) { + token = universe.token0(); + token.approve(address(universeAdapter), amount0); + } + if (amount1 > 0) { + token = universe.token1(); + token.approve(address(universeAdapter), amount1); + } + } + +} diff --git a/contracts/mainnet/connectors/universeFinance/interface.sol b/contracts/mainnet/connectors/universeFinance/interface.sol new file mode 100644 index 00000000..cfc8ab8c --- /dev/null +++ b/contracts/mainnet/connectors/universeFinance/interface.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.7.6; + +import "../../common/interfaces.sol"; + +pragma abicoder v2; + +interface IUniverseAdapter { + + function depositProxy( + address universeVault, + uint256 amount0, + uint256 amount1 + ) external returns(uint256, uint256); + +} + +interface IVaultV3 { + + function token0() external returns(TokenInterface); + + function token1() external returns(TokenInterface); + + function withdraw(uint256 share0, uint256 share1) external returns(uint256, uint256); +} diff --git a/contracts/mainnet/connectors/universeFinance/main.sol b/contracts/mainnet/connectors/universeFinance/main.sol new file mode 100644 index 00000000..97e22010 --- /dev/null +++ b/contracts/mainnet/connectors/universeFinance/main.sol @@ -0,0 +1,92 @@ +pragma solidity ^0.7.6; +pragma abicoder v2; + +/** + * @title Universe finance + * @dev Maximising uniswap v3 returns + */ + +import {TokenInterface} from "../../common/interfaces.sol"; +import {Helpers} from "./helpers.sol"; +import {Events} from "./events.sol"; + +abstract contract UniverseFinanceConnect is Helpers, Events { + /** + * @notice Deposit in Universe Vault by Adapter + * @dev Deposit in universe vault + * @param universeVault Universe Official Vault Address + * @param amountA Amount of tokenA + * @param amountB Amount of tokenB + * @param getIds ID to retrieve amountA and amountB + * @param setIds ID to store amountA and amountB + */ + function deposit( + address universeVault, + uint256 amountA, + uint256 amountB, + uint256[] calldata getIds, + uint256[] calldata setIds + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + amountA = getUint(getIds[0], amountA); + amountB = getUint(getIds[1], amountB); + _approve(universeVault, amountA, amountB); + (uint256 share0, uint256 share1) = _deposit( + universeVault, + amountA, + amountB + ); + setUint(setIds[0], share0); + setUint(setIds[1], share1); + // EVENT + _eventName = "LogDeposit(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode( + universeVault, + amountA, + amountB, + share0, + share1 + ); + } + + /** + * @notice Withdraw Token0 & Token1 From Universe Vault + * @dev Withdraw supplied token0 and token1 from universe vault + * @param universeVault Universe Official Vault Address + * @param share0 Amount of uToken0. + * @param share1 Amount of uToken1. + * @param getIds ID to retrieve amount of output token + * @param setIds stores the amount of output tokens + */ + function withdraw( + address universeVault, + uint256 share0, + uint256 share1, + uint256[] calldata getIds, + uint256[] calldata setIds + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + share0 = getUint(getIds[0], share0); + share1 = getUint(getIds[1], share1); + (uint256 _amtA, uint256 _amtB) = _withdraw( + universeVault, + share0, + share1 + ); + setUint(setIds[0], _amtA); + setUint(setIds[1], _amtB); + // EVENT + _eventName = "LogWithdraw(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(universeVault, _amtA, _amtB, share0, share1); + } +} + +contract ConnectV2UniverseFinance is UniverseFinanceConnect { + string public constant name = "UniverseFinance-v1"; +} diff --git a/contracts/polygon/connectors/instapool_v4/events.sol b/contracts/polygon/connectors/instapool_v4/events.sol new file mode 100644 index 00000000..9fc1cd40 --- /dev/null +++ b/contracts/polygon/connectors/instapool_v4/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/polygon/connectors/instapool_v4/interfaces.sol b/contracts/polygon/connectors/instapool_v4/interfaces.sol new file mode 100644 index 00000000..c5a40fd4 --- /dev/null +++ b/contracts/polygon/connectors/instapool_v4/interfaces.sol @@ -0,0 +1,11 @@ +pragma solidity >=0.7.0; +pragma experimental ABIEncoderV2; + +interface InstaFlashV4Interface { + function flashLoan(address[] memory tokens, uint256[] memory amts, uint route, bytes memory data, bytes memory extraData) external; +} + +interface AccountInterface { + function enable(address) external; + function disable(address) external; +} diff --git a/contracts/polygon/connectors/instapool_v4/main.sol b/contracts/polygon/connectors/instapool_v4/main.sol new file mode 100644 index 00000000..d11e9639 --- /dev/null +++ b/contracts/polygon/connectors/instapool_v4/main.sol @@ -0,0 +1,138 @@ +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 { Stores } from "../../common/stores.sol"; +import { Variables } from "./variables.sol"; +import { Events } from "./events.sol"; + +contract LiquidityResolver is Stores, Variables, Events { + using SafeERC20 for IERC20; + + /** + * @dev Borrow Flashloan and Cast spells. + * @notice Borrow Flashloan and Cast spells. + * @param token Token Address. + * @param amt Token Amount. + * @param route Flashloan source route. + * @param data targets & data for cast. + * @param extraData to be kept bytes(0) in most cases. Can be useful to decide data for some particular routes + */ + function flashBorrowAndCast( + address token, + uint amt, + uint route, + bytes memory data, + bytes memory extraData + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + 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)); + + address[] memory tokens_ = new address[](1); + tokens_[0] = token; + uint[] memory amts_ = new uint[](1); + amts_[0] = amt; + instaPool.flashLoan(tokens_, amts_, route, callData_, extraData); + + AccountInterface(address(this)).disable(address(instaPool)); + + _eventName = "LogFlashBorrow(address,uint256)"; + _eventParam = abi.encode(token, amt); + } + + /** + * @dev Return token to InstaPool. + * @notice 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 returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + IERC20 tokenContract = IERC20(token); + + tokenContract.safeTransfer(address(instaPool), _amt); + + setUint(setId, _amt); + + _eventName = "LogFlashPayback(address,uint256)"; + _eventParam = abi.encode(token, amt); + } + + /** + * @dev Borrow multi-tokens Flashloan and Cast spells. + * @notice Borrow multi-tokens Flashloan and Cast spells. + * @param tokens_ Array of Token Addresses. + * @param amts_ Array of Token Amounts. + * @param route Flashloan source route. + * @param data targets & data for cast. + * @param extraData to be kept bytes(0) in most cases. Can be useful to decide data for some particular routes + */ + function flashMultiBorrowAndCast( + address[] memory tokens_, + uint[] memory amts_, + uint route, + bytes memory data, + bytes memory extraData + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + 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.flashLoan(tokens_, amts_, route, callData_, extraData); + + AccountInterface(address(this)).disable(address(instaPool)); + _eventName = "LogFlashMultiBorrow(address[],uint256[])"; + _eventParam = abi.encode(tokens_, amts_); + } + + /** + * @dev Return multi-tokens to InstaPool. + * @notice Return multi-tokens to InstaPool. + * @param tokens_ Array of Token Addresses. + * @param amts_ Array of Token Amounts. + * @param getIds Array of getId token amounts. + * @param setIds Array of setId token amounts. + */ + function flashMultiPayback( + address[] memory tokens_, + uint[] memory amts_, + uint[] memory getIds, + uint[] memory setIds + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + for (uint i = 0; i < tokens_.length; i++) { + amts_[i] = getUint(getIds[i], amts_[i]); + + IERC20(tokens_[i]).safeTransfer(address(instaPool), amts_[i]); + + setUint(setIds[i], amts_[i]); + } + + _eventName = "LogFlashMultiPayback(address[],uint256[])"; + _eventParam = abi.encode(tokens_, amts_); + } + +} + +contract ConnectV2InstaPoolV4 is LiquidityResolver { + string public name = "Instapool-v4"; +} diff --git a/contracts/polygon/connectors/instapool_v4/variables.sol b/contracts/polygon/connectors/instapool_v4/variables.sol new file mode 100644 index 00000000..fc2cae72 --- /dev/null +++ b/contracts/polygon/connectors/instapool_v4/variables.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +import { InstaFlashV4Interface } from "./interfaces.sol"; + +contract Variables { + + /** + * @dev Instapool contract proxy + */ + InstaFlashV4Interface public constant instaPool = InstaFlashV4Interface(address(0)); // TODO: update address + +} \ No newline at end of file diff --git a/contracts/polygon/connectors/wmatic/events.sol b/contracts/polygon/connectors/wmatic/events.sol new file mode 100644 index 00000000..f8ec366a --- /dev/null +++ b/contracts/polygon/connectors/wmatic/events.sol @@ -0,0 +1,6 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogDeposit(uint256 tokenAmt, uint256 getId, uint256 setId); + event LogWithdraw(uint256 tokenAmt, uint256 getId, uint256 setId); +} diff --git a/contracts/polygon/connectors/wmatic/helpers.sol b/contracts/polygon/connectors/wmatic/helpers.sol new file mode 100644 index 00000000..bfc084ae --- /dev/null +++ b/contracts/polygon/connectors/wmatic/helpers.sol @@ -0,0 +1,8 @@ +pragma solidity ^0.7.0; + +import { TokenInterface } from "../../common/interfaces.sol"; + + +abstract contract Helpers { + TokenInterface constant internal wmaticContract = TokenInterface(0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270); +} diff --git a/contracts/polygon/connectors/wmatic/main.sol b/contracts/polygon/connectors/wmatic/main.sol new file mode 100644 index 00000000..1f15c12b --- /dev/null +++ b/contracts/polygon/connectors/wmatic/main.sol @@ -0,0 +1,65 @@ +pragma solidity ^0.7.0; + +/** + * @title WMATIC. + * @dev Wrap and Unwrap WMATIC. + */ + +import { DSMath } from "../../common/math.sol"; +import { Basic } from "../../common/basic.sol"; +import { Events } from "./events.sol"; +import { Helpers } from "./helpers.sol"; + +abstract contract Resolver is Events, DSMath, Basic, Helpers { + + /** + * @dev Deposit MATIC into WMATIC. + * @notice Wrap MATIC into WMATIC + * @param amt The amount of MATIC to deposit. (For max: `uint256(-1)`) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of MATIC deposited. + */ + function deposit( + uint256 amt, + uint256 getId, + uint256 setId + ) public payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + _amt = _amt == uint(-1) ? address(this).balance : _amt; + wmaticContract.deposit{value: _amt}(); + + setUint(setId, _amt); + + _eventName = "LogDeposit(uint256,uint256,uint256)"; + _eventParam = abi.encode(_amt, getId, setId); + } + + /** + * @dev Withdraw MATIC from WMATIC from Smart Account + * @notice Unwrap MATIC from WMATIC + * @param amt The amount of wmatic to withdraw. (For max: `uint256(-1)`) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of MATIC withdrawn. + */ + function withdraw( + uint amt, + uint getId, + uint setId + ) public payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + _amt = _amt == uint(-1) ? wmaticContract.balanceOf(address(this)) : _amt; + approve(wmaticContract, wmaticAddr, _amt); + wmaticContract.withdraw(_amt); + + setUint(setId, _amt); + + _eventName = "LogWithdraw(uint256,uint256,uint256)"; + _eventParam = abi.encode(_amt, getId, setId); + } +} + +contract ConnectV2WMATICPolygon is Resolver { + string constant public name = "WMATIC-v1.0"; +}