From 1338e6f5c92674c926e63ea3b71e15db52e8f250 Mon Sep 17 00:00:00 2001 From: Samyak Jain <34437877+KaymasJain@users.noreply.github.com> Date: Sat, 7 May 2022 01:54:51 +0400 Subject: [PATCH 01/36] update transfer fee --- contracts/aggregator/mainnet/flashloan/main.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/aggregator/mainnet/flashloan/main.sol b/contracts/aggregator/mainnet/flashloan/main.sol index 4c66f5d3..d0a713e3 100644 --- a/contracts/aggregator/mainnet/flashloan/main.sol +++ b/contracts/aggregator/mainnet/flashloan/main.sol @@ -673,7 +673,7 @@ contract FlashAggregator is Setups { * @notice Function to transfer fee to the treasury. Will be called manually. * @param _tokens token addresses for transferring fee to treasury. */ - function transferFeeToTreasury(address[] memory _tokens) public { + function transferFee(address[] memory _tokens, address _to) public onlyOwner { for (uint256 i = 0; i < _tokens.length; i++) { IERC20 token_ = IERC20(_tokens[i]); uint256 decimals_ = TokenInterface(_tokens[i]).decimals(); @@ -686,7 +686,7 @@ contract FlashAggregator is Setups { ? (token_.balanceOf(address(this)) - amtToSub_) : 0; if (amtToTransfer_ > 0) - token_.safeTransfer(treasuryAddr, amtToTransfer_); + token_.safeTransfer(_to, amtToTransfer_); } } } From 0f4be4088c2f8d597ab3b1ab2de940c4e569c838 Mon Sep 17 00:00:00 2001 From: Samyak Jain <34437877+KaymasJain@users.noreply.github.com> Date: Sat, 7 May 2022 03:02:23 +0400 Subject: [PATCH 02/36] added event --- contracts/aggregator/mainnet/flashloan/main.sol | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/contracts/aggregator/mainnet/flashloan/main.sol b/contracts/aggregator/mainnet/flashloan/main.sol index d0a713e3..7b751da1 100644 --- a/contracts/aggregator/mainnet/flashloan/main.sol +++ b/contracts/aggregator/mainnet/flashloan/main.sol @@ -82,6 +82,12 @@ contract FlashAggregator is Setups { uint256[] amounts ); + event LogCollectRevenue( + address to, + address[] tokens, + uint256[] amounts + ); + /** * @dev Callback function for aave flashloan. * @notice Callback function for aave flashloan. @@ -674,6 +680,7 @@ contract FlashAggregator is Setups { * @param _tokens token addresses for transferring fee to treasury. */ function transferFee(address[] memory _tokens, address _to) public onlyOwner { + uint256[] memory _amts = new uint256[](_tokens.length); for (uint256 i = 0; i < _tokens.length; i++) { IERC20 token_ = IERC20(_tokens[i]); uint256 decimals_ = TokenInterface(_tokens[i]).decimals(); @@ -682,12 +689,13 @@ contract FlashAggregator is Setups { : decimals_ > 7 ? 100 : 10; - uint256 amtToTransfer_ = token_.balanceOf(address(this)) > amtToSub_ + _amts[i] = token_.balanceOf(address(this)) > amtToSub_ ? (token_.balanceOf(address(this)) - amtToSub_) : 0; - if (amtToTransfer_ > 0) - token_.safeTransfer(_to, amtToTransfer_); + if (_amts[i] > 0) + token_.safeTransfer(_to, _amts[i]); } + emit LogCollectRevenue(_to, _tokens, _amts); } } From e0996b5c2e0b91ae45564e62473b4b9a33d6fbcd Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 9 May 2022 20:44:00 +0400 Subject: [PATCH 03/36] Implementations created --- contracts/ProxyAave/main.sol | 101 +++++ contracts/ProxyBalancer/main.sol | 243 +++++++++++ contracts/ProxyMaker/main.sol | 205 +++++++++ .../aggregator/mainnet/flashloan/helpers.sol | 25 ++ .../aggregator/mainnet/flashloan/main.sol | 408 +----------------- .../mainnet/flashloan/variables.sol | 6 + test/mainnet/newFlashAggr.ts | 126 ++++++ 7 files changed, 729 insertions(+), 385 deletions(-) create mode 100644 contracts/ProxyAave/main.sol create mode 100644 contracts/ProxyBalancer/main.sol create mode 100644 contracts/ProxyMaker/main.sol create mode 100644 test/mainnet/newFlashAggr.ts diff --git a/contracts/ProxyAave/main.sol b/contracts/ProxyAave/main.sol new file mode 100644 index 00000000..7e9abab5 --- /dev/null +++ b/contracts/ProxyAave/main.sol @@ -0,0 +1,101 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +import "../aggregator/mainnet/flashloan/helpers.sol"; + +contract AaveImplementation is Helper { + + /** + * @dev Callback function for aave flashloan. + * @notice Callback function for aave flashloan. + * @param _assets list of asset addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets for flashloan. + * @param _premiums list of premiums/fees for the corresponding addresses for flashloan. + * @param _initiator initiator address for flashloan. + * @param _data extra data passed. + */ + function executeOperation( + address[] memory _assets, + uint256[] memory _amounts, + uint256[] memory _premiums, + address _initiator, + bytes memory _data + ) external verifyDataHash(_data) returns (bool) { + require(_initiator == address(this), "not-same-sender"); + require(msg.sender == address(aaveLending), "not-aave-sender"); + + FlashloanVariables memory instaLoanVariables_; + + (address sender_, bytes memory data_) = abi.decode( + _data, + (address, bytes) + ); + + instaLoanVariables_._tokens = _assets; + instaLoanVariables_._amounts = _amounts; + instaLoanVariables_._instaFees = calculateFees( + _amounts, + calculateFeeBPS(1, sender_) + ); + instaLoanVariables_._iniBals = calculateBalances( + _assets, + address(this) + ); + + safeApprove(instaLoanVariables_, _premiums, address(aaveLending)); + safeTransfer(instaLoanVariables_, sender_); + + if (checkIfDsa(sender_)) { + Address.functionCall( + sender_, + data_, + "DSA-flashloan-fallback-failed" + ); + } else { + InstaFlashReceiverInterface(sender_).executeOperation( + _assets, + _amounts, + instaLoanVariables_._instaFees, + sender_, + data_ + ); + } + + instaLoanVariables_._finBals = calculateBalances( + _assets, + address(this) + ); + validateFlashloan(instaLoanVariables_); + + return true; + } + + /** + * @dev Middle function for route 1. + * @notice Middle function for route 1. + * @param _tokens list of token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets or amount of ether to borrow as collateral for flashloan. + * @param _data extra data passed. + */ + function routeAave( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal { + bytes memory data_ = abi.encode(msg.sender, _data); + uint256 length_ = _tokens.length; + uint256[] memory _modes = new uint256[](length_); + for (uint256 i = 0; i < length_; i++) { + _modes[i] = 0; + } + dataHash = bytes32(keccak256(data_)); + aaveLending.flashLoan( + address(this), + _tokens, + _amounts, + _modes, + address(0), + data_, + 3228 + ); + } +} \ No newline at end of file diff --git a/contracts/ProxyBalancer/main.sol b/contracts/ProxyBalancer/main.sol new file mode 100644 index 00000000..0bec320f --- /dev/null +++ b/contracts/ProxyBalancer/main.sol @@ -0,0 +1,243 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +import "../aggregator/mainnet/flashloan/helpers.sol"; + +contract BalancerImplementation is Helper { + + /** + * @dev Fallback function for balancer flashloan. + * @notice Fallback function for balancer flashloan. + * @param _amounts list of amounts for the corresponding assets or amount of ether to borrow as collateral for flashloan. + * @param _fees list of fees for the corresponding addresses for flashloan. + * @param _data extra data passed(includes route info aswell). + */ + function receiveFlashLoan( + IERC20[] memory, + uint256[] memory _amounts, + uint256[] memory _fees, + bytes memory _data + ) external verifyDataHash(_data) { + require(msg.sender == address(balancerLending), "not-balancer-sender"); + + FlashloanVariables memory instaLoanVariables_; + + ( + uint256 route_, + address[] memory tokens_, + uint256[] memory amounts_, + address sender_, + bytes memory data_ + ) = abi.decode(_data, (uint256, address[], uint256[], address, bytes)); + + instaLoanVariables_._tokens = tokens_; + instaLoanVariables_._amounts = amounts_; + instaLoanVariables_._iniBals = calculateBalances( + tokens_, + address(this) + ); + instaLoanVariables_._instaFees = calculateFees( + amounts_, + calculateFeeBPS(route_, sender_) + ); + + if (route_ == 5) { + if (tokens_[0] == stEthTokenAddr) { + wstEthToken.unwrap(_amounts[0]); + } + safeTransfer(instaLoanVariables_, sender_); + if (checkIfDsa(sender_)) { + Address.functionCall( + sender_, + data_, + "DSA-flashloan-fallback-failed" + ); + } else { + InstaFlashReceiverInterface(sender_).executeOperation( + tokens_, + amounts_, + instaLoanVariables_._instaFees, + sender_, + data_ + ); + } + if (tokens_[0] == stEthTokenAddr) { + wstEthToken.wrap(amounts_[0]); + } + + instaLoanVariables_._finBals = calculateBalances( + tokens_, + address(this) + ); + if (tokens_[0] == stEthTokenAddr) { + // adding 10 wei to avoid any possible decimal errors in final calculations + instaLoanVariables_._finBals[0] = + instaLoanVariables_._finBals[0] + + 10; + instaLoanVariables_._tokens[0] = address(wstEthToken); + instaLoanVariables_._amounts[0] = _amounts[0]; + } + validateFlashloan(instaLoanVariables_); + safeTransferWithFee( + instaLoanVariables_, + _fees, + address(balancerLending) + ); + } else if (route_ == 6 || route_ == 7) { + require(_fees[0] == 0, "flash-ETH-fee-not-0"); + + address[] memory wEthTokenList = new address[](1); + wEthTokenList[0] = address(wethToken); + + if (route_ == 6) { + compoundSupply(wEthTokenList, _amounts); + compoundBorrow(tokens_, amounts_); + } else { + aaveSupply(wEthTokenList, _amounts); + aaveBorrow(tokens_, amounts_); + } + + safeTransfer(instaLoanVariables_, sender_); + + if (checkIfDsa(sender_)) { + Address.functionCall( + sender_, + data_, + "DSA-flashloan-fallback-failed" + ); + } else { + InstaFlashReceiverInterface(sender_).executeOperation( + tokens_, + amounts_, + instaLoanVariables_._instaFees, + sender_, + data_ + ); + } + + if (route_ == 6) { + compoundPayback(tokens_, amounts_); + compoundWithdraw(wEthTokenList, _amounts); + } else { + aavePayback(tokens_, amounts_); + aaveWithdraw(wEthTokenList, _amounts); + } + instaLoanVariables_._finBals = calculateBalances( + tokens_, + address(this) + ); + validateFlashloan(instaLoanVariables_); + instaLoanVariables_._tokens = wEthTokenList; + instaLoanVariables_._amounts = _amounts; + safeTransferWithFee( + instaLoanVariables_, + _fees, + address(balancerLending) + ); + } else { + revert("wrong-route"); + } + } + + /** + * @dev Middle function for route 5. + * @notice Middle function for route 5. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _data extra data passed. + */ + function routeBalancer( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal { + uint256 length_ = _tokens.length; + IERC20[] memory tokens_ = new IERC20[](length_); + for (uint256 i = 0; i < length_; i++) { + tokens_[i] = IERC20(_tokens[i]); + } + bytes memory data_ = abi.encode( + 5, + _tokens, + _amounts, + msg.sender, + _data + ); + dataHash = bytes32(keccak256(data_)); + if (_tokens[0] == stEthTokenAddr) { + require(length_ == 1, "steth-length-should-be-1"); + tokens_[0] = IERC20(address(wstEthToken)); + _amounts[0] = wstEthToken.getWstETHByStETH(_amounts[0]); + } + balancerLending.flashLoan( + InstaFlashReceiverInterface(address(this)), + tokens_, + _amounts, + data_ + ); + } + + /** + * @dev Middle function for route 6. + * @notice Middle function for route 6. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _data extra data passed. + */ + function routeBalancerCompound( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal { + bytes memory data_ = abi.encode( + 6, + _tokens, + _amounts, + msg.sender, + _data + ); + IERC20[] memory wethTokenList_ = new IERC20[](1); + uint256[] memory wethAmountList_ = new uint256[](1); + wethTokenList_[0] = IERC20(wethToken); + wethAmountList_[0] = getWEthBorrowAmount(); + dataHash = bytes32(keccak256(data_)); + balancerLending.flashLoan( + InstaFlashReceiverInterface(address(this)), + wethTokenList_, + wethAmountList_, + data_ + ); + } + + /** + * @dev Middle function for route 7. + * @notice Middle function for route 7. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _data extra data passed. + */ + function routeBalancerAave( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal { + bytes memory data_ = abi.encode( + 7, + _tokens, + _amounts, + msg.sender, + _data + ); + IERC20[] memory wethTokenList_ = new IERC20[](1); + uint256[] memory wethAmountList_ = new uint256[](1); + wethTokenList_[0] = wethToken; + wethAmountList_[0] = getWEthBorrowAmount(); + dataHash = bytes32(keccak256(data_)); + balancerLending.flashLoan( + InstaFlashReceiverInterface(address(this)), + wethTokenList_, + wethAmountList_, + data_ + ); + } + +} \ No newline at end of file diff --git a/contracts/ProxyMaker/main.sol b/contracts/ProxyMaker/main.sol new file mode 100644 index 00000000..252e97ad --- /dev/null +++ b/contracts/ProxyMaker/main.sol @@ -0,0 +1,205 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +import "../aggregator/mainnet/flashloan/helpers.sol"; + +contract MakerImplementation is Helper { + + /** + * @dev Fallback function for makerdao flashloan. + * @notice Fallback function for makerdao flashloan. + * @param _initiator initiator address for flashloan. + * @param _amount DAI amount for flashloan. + * @param _fee fee for the flashloan. + * @param _data extra data passed(includes route info aswell). + */ + function onFlashLoan( + address _initiator, + address, + uint256 _amount, + uint256 _fee, + bytes calldata _data + ) external verifyDataHash(_data) returns (bytes32) { + require(_initiator == address(this), "not-same-sender"); + require(msg.sender == address(makerLending), "not-maker-sender"); + + FlashloanVariables memory instaLoanVariables_; + + ( + uint256 route_, + address[] memory tokens_, + uint256[] memory amounts_, + address sender_, + bytes memory data_ + ) = abi.decode(_data, (uint256, address[], uint256[], address, bytes)); + + instaLoanVariables_._tokens = tokens_; + instaLoanVariables_._amounts = amounts_; + instaLoanVariables_._iniBals = calculateBalances( + tokens_, + address(this) + ); + instaLoanVariables_._instaFees = calculateFees( + amounts_, + calculateFeeBPS(route_, sender_) + ); + + if (route_ == 2) { + safeTransfer(instaLoanVariables_, sender_); + + if (checkIfDsa(sender_)) { + Address.functionCall( + sender_, + data_, + "DSA-flashloan-fallback-failed" + ); + } else { + InstaFlashReceiverInterface(sender_).executeOperation( + tokens_, + amounts_, + instaLoanVariables_._instaFees, + sender_, + data_ + ); + } + } else if (route_ == 3 || route_ == 4) { + require(_fee == 0, "flash-DAI-fee-not-0"); + + address[] memory _daiTokenList = new address[](1); + uint256[] memory _daiTokenAmountsList = new uint256[](1); + _daiTokenList[0] = daiTokenAddr; + _daiTokenAmountsList[0] = _amount; + + if (route_ == 3) { + compoundSupply(_daiTokenList, _daiTokenAmountsList); + compoundBorrow(tokens_, amounts_); + } else { + aaveSupply(_daiTokenList, _daiTokenAmountsList); + aaveBorrow(tokens_, amounts_); + } + + safeTransfer(instaLoanVariables_, sender_); + + if (checkIfDsa(sender_)) { + Address.functionCall( + sender_, + data_, + "DSA-flashloan-fallback-failed" + ); + } else { + InstaFlashReceiverInterface(sender_).executeOperation( + tokens_, + amounts_, + instaLoanVariables_._instaFees, + sender_, + data_ + ); + } + + if (route_ == 3) { + compoundPayback(tokens_, amounts_); + compoundWithdraw(_daiTokenList, _daiTokenAmountsList); + } else { + aavePayback(tokens_, amounts_); + aaveWithdraw(_daiTokenList, _daiTokenAmountsList); + } + } else { + revert("wrong-route"); + } + + instaLoanVariables_._finBals = calculateBalances( + tokens_, + address(this) + ); + validateFlashloan(instaLoanVariables_); + + return keccak256("ERC3156FlashBorrower.onFlashLoan"); + } + + /** + * @dev Middle function for route 2. + * @notice Middle function for route 2. + * @param _token token address for flashloan(DAI). + * @param _amount DAI amount for flashloan. + * @param _data extra data passed. + */ + function routeMaker( + address _token, + uint256 _amount, + bytes memory _data + ) internal { + address[] memory tokens_ = new address[](1); + uint256[] memory amounts_ = new uint256[](1); + tokens_[0] = _token; + amounts_[0] = _amount; + bytes memory data_ = abi.encode( + 2, + tokens_, + amounts_, + msg.sender, + _data + ); + dataHash = bytes32(keccak256(data_)); + makerLending.flashLoan( + InstaFlashReceiverInterface(address(this)), + _token, + _amount, + data_ + ); + } + + /** + * @dev Middle function for route 3. + * @notice Middle function for route 3. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _data extra data passed. + */ + function routeMakerCompound( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal { + bytes memory data_ = abi.encode( + 3, + _tokens, + _amounts, + msg.sender, + _data + ); + dataHash = bytes32(keccak256(data_)); + makerLending.flashLoan( + InstaFlashReceiverInterface(address(this)), + daiTokenAddr, + daiBorrowAmount, + data_ + ); + } + + /** + * @dev Middle function for route 4. + * @notice Middle function for route 4. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _data extra data passed. + */ + function routeMakerAave( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal { + bytes memory data_ = abi.encode( + 4, + _tokens, + _amounts, + msg.sender, + _data + ); + dataHash = bytes32(keccak256(data_)); + makerLending.flashLoan( + InstaFlashReceiverInterface(address(this)), + daiTokenAddr, + daiBorrowAmount, + data_ + ); + } +} \ No newline at end of file diff --git a/contracts/aggregator/mainnet/flashloan/helpers.sol b/contracts/aggregator/mainnet/flashloan/helpers.sol index ddf5369e..3b53b13a 100644 --- a/contracts/aggregator/mainnet/flashloan/helpers.sol +++ b/contracts/aggregator/mainnet/flashloan/helpers.sol @@ -7,6 +7,31 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; contract Helper is Variables { using SafeERC20 for IERC20; + /** + * @dev Delegate the calls to Connector. + * @param _target Connector address + * @param _data CallData of function. + */ + function spell(address _target, bytes memory _data) internal returns (bytes memory response) { + require(_target != address(0), "target-invalid"); + assembly { + let succeeded := delegatecall(gas(), _target, add(_data, 0x20), mload(_data), 0, 0) + let size := returndatasize() + + response := mload(0x40) + mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f)))) + mstore(response, size) + returndatacopy(add(response, 0x20), 0, size) + + switch iszero(succeeded) + case 1 { + // throw if delegatecall failed + returndatacopy(0x00, 0x00, size) + revert(0x00, size) + } + } + } + /** * @dev Approves the token to the spender address with allowance amount. * @notice Approves the token to the spender address with allowance amount. diff --git a/contracts/aggregator/mainnet/flashloan/main.sol b/contracts/aggregator/mainnet/flashloan/main.sol index 7b751da1..2b7d3119 100644 --- a/contracts/aggregator/mainnet/flashloan/main.sol +++ b/contracts/aggregator/mainnet/flashloan/main.sol @@ -7,6 +7,7 @@ pragma solidity ^0.8.0; */ import "./helpers.sol"; +import "hardhat/console.sol"; import "@openzeppelin/contracts/utils/Address.sol"; contract AdminModule is Helper { @@ -103,54 +104,9 @@ contract FlashAggregator is Setups { uint256[] memory _premiums, address _initiator, bytes memory _data - ) external verifyDataHash(_data) returns (bool) { - require(_initiator == address(this), "not-same-sender"); - require(msg.sender == address(aaveLending), "not-aave-sender"); - - FlashloanVariables memory instaLoanVariables_; - - (address sender_, bytes memory data_) = abi.decode( - _data, - (address, bytes) - ); - - instaLoanVariables_._tokens = _assets; - instaLoanVariables_._amounts = _amounts; - instaLoanVariables_._instaFees = calculateFees( - _amounts, - calculateFeeBPS(1, sender_) - ); - instaLoanVariables_._iniBals = calculateBalances( - _assets, - address(this) - ); - - safeApprove(instaLoanVariables_, _premiums, address(aaveLending)); - safeTransfer(instaLoanVariables_, sender_); - - if (checkIfDsa(sender_)) { - Address.functionCall( - sender_, - data_, - "DSA-flashloan-fallback-failed" - ); - } else { - InstaFlashReceiverInterface(sender_).executeOperation( - _assets, - _amounts, - instaLoanVariables_._instaFees, - sender_, - data_ - ); - } - - instaLoanVariables_._finBals = calculateBalances( - _assets, - address(this) - ); - validateFlashloan(instaLoanVariables_); - - return true; + ) external returns (bool) { + bytes memory response = spell(AAVE_PROXY, msg.data); + return (abi.decode(response, (bool))); } /** @@ -167,101 +123,9 @@ contract FlashAggregator is Setups { uint256 _amount, uint256 _fee, bytes calldata _data - ) external verifyDataHash(_data) returns (bytes32) { - require(_initiator == address(this), "not-same-sender"); - require(msg.sender == address(makerLending), "not-maker-sender"); - - FlashloanVariables memory instaLoanVariables_; - - ( - uint256 route_, - address[] memory tokens_, - uint256[] memory amounts_, - address sender_, - bytes memory data_ - ) = abi.decode(_data, (uint256, address[], uint256[], address, bytes)); - - instaLoanVariables_._tokens = tokens_; - instaLoanVariables_._amounts = amounts_; - instaLoanVariables_._iniBals = calculateBalances( - tokens_, - address(this) - ); - instaLoanVariables_._instaFees = calculateFees( - amounts_, - calculateFeeBPS(route_, sender_) - ); - - if (route_ == 2) { - safeTransfer(instaLoanVariables_, sender_); - - if (checkIfDsa(sender_)) { - Address.functionCall( - sender_, - data_, - "DSA-flashloan-fallback-failed" - ); - } else { - InstaFlashReceiverInterface(sender_).executeOperation( - tokens_, - amounts_, - instaLoanVariables_._instaFees, - sender_, - data_ - ); - } - } else if (route_ == 3 || route_ == 4) { - require(_fee == 0, "flash-DAI-fee-not-0"); - - address[] memory _daiTokenList = new address[](1); - uint256[] memory _daiTokenAmountsList = new uint256[](1); - _daiTokenList[0] = daiTokenAddr; - _daiTokenAmountsList[0] = _amount; - - if (route_ == 3) { - compoundSupply(_daiTokenList, _daiTokenAmountsList); - compoundBorrow(tokens_, amounts_); - } else { - aaveSupply(_daiTokenList, _daiTokenAmountsList); - aaveBorrow(tokens_, amounts_); - } - - safeTransfer(instaLoanVariables_, sender_); - - if (checkIfDsa(sender_)) { - Address.functionCall( - sender_, - data_, - "DSA-flashloan-fallback-failed" - ); - } else { - InstaFlashReceiverInterface(sender_).executeOperation( - tokens_, - amounts_, - instaLoanVariables_._instaFees, - sender_, - data_ - ); - } - - if (route_ == 3) { - compoundPayback(tokens_, amounts_); - compoundWithdraw(_daiTokenList, _daiTokenAmountsList); - } else { - aavePayback(tokens_, amounts_); - aaveWithdraw(_daiTokenList, _daiTokenAmountsList); - } - } else { - revert("wrong-route"); - } - - instaLoanVariables_._finBals = calculateBalances( - tokens_, - address(this) - ); - validateFlashloan(instaLoanVariables_); - - return keccak256("ERC3156FlashBorrower.onFlashLoan"); + ) external returns (bytes32) { + bytes memory response = spell(MAKER_PROXY, msg.data); + return (abi.decode(response, (bytes32))); } /** @@ -276,126 +140,8 @@ contract FlashAggregator is Setups { uint256[] memory _amounts, uint256[] memory _fees, bytes memory _data - ) external verifyDataHash(_data) { - require(msg.sender == address(balancerLending), "not-balancer-sender"); - - FlashloanVariables memory instaLoanVariables_; - - ( - uint256 route_, - address[] memory tokens_, - uint256[] memory amounts_, - address sender_, - bytes memory data_ - ) = abi.decode(_data, (uint256, address[], uint256[], address, bytes)); - - instaLoanVariables_._tokens = tokens_; - instaLoanVariables_._amounts = amounts_; - instaLoanVariables_._iniBals = calculateBalances( - tokens_, - address(this) - ); - instaLoanVariables_._instaFees = calculateFees( - amounts_, - calculateFeeBPS(route_, sender_) - ); - - if (route_ == 5) { - if (tokens_[0] == stEthTokenAddr) { - wstEthToken.unwrap(_amounts[0]); - } - safeTransfer(instaLoanVariables_, sender_); - if (checkIfDsa(sender_)) { - Address.functionCall( - sender_, - data_, - "DSA-flashloan-fallback-failed" - ); - } else { - InstaFlashReceiverInterface(sender_).executeOperation( - tokens_, - amounts_, - instaLoanVariables_._instaFees, - sender_, - data_ - ); - } - if (tokens_[0] == stEthTokenAddr) { - wstEthToken.wrap(amounts_[0]); - } - - instaLoanVariables_._finBals = calculateBalances( - tokens_, - address(this) - ); - if (tokens_[0] == stEthTokenAddr) { - // adding 10 wei to avoid any possible decimal errors in final calculations - instaLoanVariables_._finBals[0] = - instaLoanVariables_._finBals[0] + - 10; - instaLoanVariables_._tokens[0] = address(wstEthToken); - instaLoanVariables_._amounts[0] = _amounts[0]; - } - validateFlashloan(instaLoanVariables_); - safeTransferWithFee( - instaLoanVariables_, - _fees, - address(balancerLending) - ); - } else if (route_ == 6 || route_ == 7) { - require(_fees[0] == 0, "flash-ETH-fee-not-0"); - - address[] memory wEthTokenList = new address[](1); - wEthTokenList[0] = address(wethToken); - - if (route_ == 6) { - compoundSupply(wEthTokenList, _amounts); - compoundBorrow(tokens_, amounts_); - } else { - aaveSupply(wEthTokenList, _amounts); - aaveBorrow(tokens_, amounts_); - } - - safeTransfer(instaLoanVariables_, sender_); - - if (checkIfDsa(sender_)) { - Address.functionCall( - sender_, - data_, - "DSA-flashloan-fallback-failed" - ); - } else { - InstaFlashReceiverInterface(sender_).executeOperation( - tokens_, - amounts_, - instaLoanVariables_._instaFees, - sender_, - data_ - ); - } - - if (route_ == 6) { - compoundPayback(tokens_, amounts_); - compoundWithdraw(wEthTokenList, _amounts); - } else { - aavePayback(tokens_, amounts_); - aaveWithdraw(wEthTokenList, _amounts); - } - instaLoanVariables_._finBals = calculateBalances( - tokens_, - address(this) - ); - validateFlashloan(instaLoanVariables_); - instaLoanVariables_._tokens = wEthTokenList; - instaLoanVariables_._amounts = _amounts; - safeTransferWithFee( - instaLoanVariables_, - _fees, - address(balancerLending) - ); - } else { - revert("wrong-route"); - } + ) external { + spell(BALANCER_PROXY, msg.data); } /** @@ -410,22 +156,7 @@ contract FlashAggregator is Setups { uint256[] memory _amounts, bytes memory _data ) internal { - bytes memory data_ = abi.encode(msg.sender, _data); - uint256 length_ = _tokens.length; - uint256[] memory _modes = new uint256[](length_); - for (uint256 i = 0; i < length_; i++) { - _modes[i] = 0; - } - dataHash = bytes32(keccak256(data_)); - aaveLending.flashLoan( - address(this), - _tokens, - _amounts, - _modes, - address(0), - data_, - 3228 - ); + spell(AAVE_PROXY, msg.data); } /** @@ -440,24 +171,7 @@ contract FlashAggregator is Setups { uint256 _amount, bytes memory _data ) internal { - address[] memory tokens_ = new address[](1); - uint256[] memory amounts_ = new uint256[](1); - tokens_[0] = _token; - amounts_[0] = _amount; - bytes memory data_ = abi.encode( - 2, - tokens_, - amounts_, - msg.sender, - _data - ); - dataHash = bytes32(keccak256(data_)); - makerLending.flashLoan( - InstaFlashReceiverInterface(address(this)), - _token, - _amount, - data_ - ); + spell(MAKER_PROXY, msg.data); } /** @@ -472,20 +186,7 @@ contract FlashAggregator is Setups { uint256[] memory _amounts, bytes memory _data ) internal { - bytes memory data_ = abi.encode( - 3, - _tokens, - _amounts, - msg.sender, - _data - ); - dataHash = bytes32(keccak256(data_)); - makerLending.flashLoan( - InstaFlashReceiverInterface(address(this)), - daiTokenAddr, - daiBorrowAmount, - data_ - ); + spell(MAKER_PROXY, msg.data); } /** @@ -500,20 +201,7 @@ contract FlashAggregator is Setups { uint256[] memory _amounts, bytes memory _data ) internal { - bytes memory data_ = abi.encode( - 4, - _tokens, - _amounts, - msg.sender, - _data - ); - dataHash = bytes32(keccak256(data_)); - makerLending.flashLoan( - InstaFlashReceiverInterface(address(this)), - daiTokenAddr, - daiBorrowAmount, - data_ - ); + spell(MAKER_PROXY, msg.data); } /** @@ -528,30 +216,7 @@ contract FlashAggregator is Setups { uint256[] memory _amounts, bytes memory _data ) internal { - uint256 length_ = _tokens.length; - IERC20[] memory tokens_ = new IERC20[](length_); - for (uint256 i = 0; i < length_; i++) { - tokens_[i] = IERC20(_tokens[i]); - } - bytes memory data_ = abi.encode( - 5, - _tokens, - _amounts, - msg.sender, - _data - ); - dataHash = bytes32(keccak256(data_)); - if (_tokens[0] == stEthTokenAddr) { - require(length_ == 1, "steth-length-should-be-1"); - tokens_[0] = IERC20(address(wstEthToken)); - _amounts[0] = wstEthToken.getWstETHByStETH(_amounts[0]); - } - balancerLending.flashLoan( - InstaFlashReceiverInterface(address(this)), - tokens_, - _amounts, - data_ - ); + spell(BALANCER_PROXY, msg.data); } /** @@ -566,24 +231,7 @@ contract FlashAggregator is Setups { uint256[] memory _amounts, bytes memory _data ) internal { - bytes memory data_ = abi.encode( - 6, - _tokens, - _amounts, - msg.sender, - _data - ); - IERC20[] memory wethTokenList_ = new IERC20[](1); - uint256[] memory wethAmountList_ = new uint256[](1); - wethTokenList_[0] = IERC20(wethToken); - wethAmountList_[0] = getWEthBorrowAmount(); - dataHash = bytes32(keccak256(data_)); - balancerLending.flashLoan( - InstaFlashReceiverInterface(address(this)), - wethTokenList_, - wethAmountList_, - data_ - ); + spell(BALANCER_PROXY, msg.data); } /** @@ -598,24 +246,7 @@ contract FlashAggregator is Setups { uint256[] memory _amounts, bytes memory _data ) internal { - bytes memory data_ = abi.encode( - 7, - _tokens, - _amounts, - msg.sender, - _data - ); - IERC20[] memory wethTokenList_ = new IERC20[](1); - uint256[] memory wethAmountList_ = new uint256[](1); - wethTokenList_[0] = wethToken; - wethAmountList_[0] = getWEthBorrowAmount(); - dataHash = bytes32(keccak256(data_)); - balancerLending.flashLoan( - InstaFlashReceiverInterface(address(this)), - wethTokenList_, - wethAmountList_, - data_ - ); + spell(BALANCER_PROXY, msg.data); } /** @@ -702,6 +333,13 @@ contract FlashAggregator is Setups { contract InstaFlashAggregator is FlashAggregator { using SafeERC20 for IERC20; + function initialize(address aave, address maker, address balancer) public { + AAVE_PROXY = aave; + MAKER_PROXY = maker; + BALANCER_PROXY = balancer; + console.log("initialize call successful! AAVE_PROXY = ", AAVE_PROXY); + } + /* Deprecated */ diff --git a/contracts/aggregator/mainnet/flashloan/variables.sol b/contracts/aggregator/mainnet/flashloan/variables.sol index 61497a81..75e7f136 100644 --- a/contracts/aggregator/mainnet/flashloan/variables.sol +++ b/contracts/aggregator/mainnet/flashloan/variables.sol @@ -31,6 +31,12 @@ contract ConstantVariables { ListInterface internal constant instaList = ListInterface(0x4c8a1BEb8a87765788946D6B19C6C6355194AbEb); uint256 public constant InstaFeeBPS = 5; // in BPS; 1 BPS = 0.01% + // address internal constant AAVE_PROXY; + // address internal constant MAKER_PROXY; + // address internal constant BALANCER_PROXY; + address internal AAVE_PROXY; + address internal MAKER_PROXY; + address internal BALANCER_PROXY; } contract Variables is ConstantVariables { diff --git a/test/mainnet/newFlashAggr.ts b/test/mainnet/newFlashAggr.ts new file mode 100644 index 00000000..326bafd2 --- /dev/null +++ b/test/mainnet/newFlashAggr.ts @@ -0,0 +1,126 @@ +const hre = require('hardhat') +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +const { ethers } = hre + + +import { + AaveImplementation, + BalancerImplementation, + MakerImplementation, + AaveImplementation__factory, + BalancerImplementation__factory, + MakerImplementation__factory, + InstaFlashAggregator, + InstaFlashAggregator__factory, + IERC20__factory, + IERC20, + InstaFlashReceiver__factory, + InstaFlashReceiver, + InstaFlashAggregatorProxy, + InstaFlashAggregatorProxy__factory, + } from '../../typechain' + + describe('FlashLoan', function () { + + let proxyA : AaveImplementation, + proxyB : BalancerImplementation, + proxyM : MakerImplementation, + aggregator : InstaFlashAggregator, + ProxyA, + ProxyB, + ProxyM, + Aggregator, + admin = "0xb208CDF8e1c319d0019397dceC8E0bA3Fb9A149F", + proxyAddr = "0x619Ad2D02dBeE6ebA3CDbDA3F98430410e892882", + proxyCon: { connect: (arg0: any) => { (): any; new(): any; upgradeTo: { (arg0: string): any; new(): any }; callStatic: { (): any; new(): any; implementation: { (): any; new(): any } } }; initialize: (arg0: string, arg1: string, arg2: string) => any }, + Receiver, + receiver: InstaFlashReceiver + + let signer: SignerWithAddress + + const _data = '0x' + let _instaData = '0x' + +//############## + const Dai = ethers.utils.parseUnits('5000', 18) + +//############## + const DAI = '0x6b175474e89094c44da98b954eedeac495271d0f' + const ACC_DAI = '0x9a7a9d980ed6239b89232c012e21f4c210f4bef1' + + + it('Should deploy', async function () { + ;[signer] = await ethers.getSigners() + + ProxyA = new AaveImplementation__factory + proxyA = await ProxyA.deploy() + await proxyA.deployed() + console.log("Aave proxy deployed at: ", proxyA.address); + + ProxyB = new BalancerImplementation__factory + proxyB = await ProxyB.deploy() + await proxyB.deployed() + console.log("Balancer proxy deployed at: ", proxyB.address); + + ProxyM = new MakerImplementation__factory + proxyM = await ProxyM.deploy() + await proxyM.deployed() + console.log("Maker proxy deployed at: ", proxyM.address); + + Aggregator = new InstaFlashAggregator__factory(signer) + aggregator = await Aggregator.deploy() + await aggregator.deployed() + console.log("Aggregator deployed at: ", aggregator.address); + + proxyCon = new hre.ethers.Contract( + proxyAddr, + [{"inputs":[{"internalType":"address","name":"_logic","type":"address"},{"internalType":"address","name":"admin_","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"admin_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}] + ) + + Receiver = new InstaFlashReceiver__factory(signer) + receiver = await Receiver.deploy(proxyAddr) + await receiver.deployed() + console.log("Receiver deployed at: ", receiver.address); + + const token_dai = new ethers.Contract( + DAI, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) + }) + + describe('Upgrade proxy implementation', async function () { + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [admin], + }) + + await hre.network.provider.send("hardhat_setBalance", [ + admin, + ethers.utils.parseEther("10.0").toHexString(), + ]); + + let impersonateAcc = await ethers.getSigner(admin); + + let tx = await proxyCon.connect(impersonateAcc).upgradeTo(aggregator.address); + let receipt = tx.wait(); + console.log("Implementation updated!") + + let addr = await proxyCon.connect(impersonateAcc).callStatic.implementation(); + console.log("Implementation at: ", addr); + + await proxyCon.initialize(proxyA.address, proxyB.address, proxyM.address);//todo: doubt + }) + + describe('Single token', async function () { + it('Should be able to take flashLoan of a single token from AAVE', async function () { + await receiver.flashBorrow([DAI], [Dai], 1, _data, _instaData) + }) + }) + }) + \ No newline at end of file From e88ad6a22068295bec01a06a2be72b669b8f2ba0 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Wed, 11 May 2022 00:47:01 +0400 Subject: [PATCH 04/36] flashloan func added in implementations --- contracts/ProxyAave/main.sol | 19 ++ contracts/ProxyBalancer/main.sol | 26 ++ contracts/ProxyMaker/main.sol | 26 ++ .../aggregator/mainnet/flashloan/main.sol | 135 +------- .../mainnet/flashloan/variables.sol | 10 +- test/mainnet/newFlashAggr.ts | 304 ++++++++++++++++-- 6 files changed, 355 insertions(+), 165 deletions(-) diff --git a/contracts/ProxyAave/main.sol b/contracts/ProxyAave/main.sol index 7e9abab5..053dca25 100644 --- a/contracts/ProxyAave/main.sol +++ b/contracts/ProxyAave/main.sol @@ -4,6 +4,25 @@ import "../aggregator/mainnet/flashloan/helpers.sol"; contract AaveImplementation is Helper { + /** + * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. + * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _route route for flashloan. + * @param _data extra data passed. + */ + function flashLoan( + address[] memory _tokens, + uint256[] memory _amounts, + uint256 _route, + bytes calldata _data, + bytes calldata // kept for future use by instadapp. Currently not used anywhere. + ) external reentrancy { + require(_route == 1, "invalid AAVE flashloan route"); + routeAave(_tokens, _amounts, _data); + } + /** * @dev Callback function for aave flashloan. * @notice Callback function for aave flashloan. diff --git a/contracts/ProxyBalancer/main.sol b/contracts/ProxyBalancer/main.sol index 0bec320f..cb7bf0c9 100644 --- a/contracts/ProxyBalancer/main.sol +++ b/contracts/ProxyBalancer/main.sol @@ -4,6 +4,32 @@ import "../aggregator/mainnet/flashloan/helpers.sol"; contract BalancerImplementation is Helper { + /** + * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. + * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _route route for flashloan. + * @param _data extra data passed. + */ + function flashLoan( + address[] memory _tokens, + uint256[] memory _amounts, + uint256 _route, + bytes calldata _data, + bytes calldata // kept for future use by instadapp. Currently not used anywhere. + ) external reentrancy { + require(_route == 5 || _route == 6 || _route == 7, "invalid BALANCER flashloan route"); + + if (_route == 5) { + routeBalancer(_tokens, _amounts, _data); + } else if (_route == 6) { + routeBalancerCompound(_tokens, _amounts, _data); + } else if (_route == 7) { + routeBalancerAave(_tokens, _amounts, _data); + } + } + /** * @dev Fallback function for balancer flashloan. * @notice Fallback function for balancer flashloan. diff --git a/contracts/ProxyMaker/main.sol b/contracts/ProxyMaker/main.sol index 252e97ad..c0565e2e 100644 --- a/contracts/ProxyMaker/main.sol +++ b/contracts/ProxyMaker/main.sol @@ -4,6 +4,32 @@ import "../aggregator/mainnet/flashloan/helpers.sol"; contract MakerImplementation is Helper { + /** + * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. + * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _route route for flashloan. + * @param _data extra data passed. + */ + function flashLoan( + address[] memory _tokens, + uint256[] memory _amounts, + uint256 _route, + bytes calldata _data, + bytes calldata // kept for future use by instadapp. Currently not used anywhere. + ) external reentrancy { + require((_route == 2 || _route == 3 || _route == 4), "invalid MAKER flashloan route"); + + if (_route == 2) { + routeMaker(_tokens[0], _amounts[0], _data); + } else if (_route == 3) { + routeMakerCompound(_tokens, _amounts, _data); + } else if (_route == 4) { + routeMakerAave(_tokens, _amounts, _data); + } + } + /** * @dev Fallback function for makerdao flashloan. * @notice Fallback function for makerdao flashloan. diff --git a/contracts/aggregator/mainnet/flashloan/main.sol b/contracts/aggregator/mainnet/flashloan/main.sol index 2b7d3119..9ca48d66 100644 --- a/contracts/aggregator/mainnet/flashloan/main.sol +++ b/contracts/aggregator/mainnet/flashloan/main.sol @@ -7,7 +7,6 @@ pragma solidity ^0.8.0; */ import "./helpers.sol"; -import "hardhat/console.sol"; import "@openzeppelin/contracts/utils/Address.sol"; contract AdminModule is Helper { @@ -105,7 +104,7 @@ contract FlashAggregator is Setups { address _initiator, bytes memory _data ) external returns (bool) { - bytes memory response = spell(AAVE_PROXY, msg.data); + bytes memory response = spell(AAVE_IMP, msg.data); return (abi.decode(response, (bool))); } @@ -124,7 +123,7 @@ contract FlashAggregator is Setups { uint256 _fee, bytes calldata _data ) external returns (bytes32) { - bytes memory response = spell(MAKER_PROXY, msg.data); + bytes memory response = spell(MAKER_IMP, msg.data); return (abi.decode(response, (bytes32))); } @@ -141,112 +140,7 @@ contract FlashAggregator is Setups { uint256[] memory _fees, bytes memory _data ) external { - spell(BALANCER_PROXY, msg.data); - } - - /** - * @dev Middle function for route 1. - * @notice Middle function for route 1. - * @param _tokens list of token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets or amount of ether to borrow as collateral for flashloan. - * @param _data extra data passed. - */ - function routeAave( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data - ) internal { - spell(AAVE_PROXY, msg.data); - } - - /** - * @dev Middle function for route 2. - * @notice Middle function for route 2. - * @param _token token address for flashloan(DAI). - * @param _amount DAI amount for flashloan. - * @param _data extra data passed. - */ - function routeMaker( - address _token, - uint256 _amount, - bytes memory _data - ) internal { - spell(MAKER_PROXY, msg.data); - } - - /** - * @dev Middle function for route 3. - * @notice Middle function for route 3. - * @param _tokens token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets. - * @param _data extra data passed. - */ - function routeMakerCompound( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data - ) internal { - spell(MAKER_PROXY, msg.data); - } - - /** - * @dev Middle function for route 4. - * @notice Middle function for route 4. - * @param _tokens token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets. - * @param _data extra data passed. - */ - function routeMakerAave( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data - ) internal { - spell(MAKER_PROXY, msg.data); - } - - /** - * @dev Middle function for route 5. - * @notice Middle function for route 5. - * @param _tokens token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets. - * @param _data extra data passed. - */ - function routeBalancer( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data - ) internal { - spell(BALANCER_PROXY, msg.data); - } - - /** - * @dev Middle function for route 6. - * @notice Middle function for route 6. - * @param _tokens token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets. - * @param _data extra data passed. - */ - function routeBalancerCompound( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data - ) internal { - spell(BALANCER_PROXY, msg.data); - } - - /** - * @dev Middle function for route 7. - * @notice Middle function for route 7. - * @param _tokens token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets. - * @param _data extra data passed. - */ - function routeBalancerAave( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data - ) internal { - spell(BALANCER_PROXY, msg.data); + spell(BALANCER_IMP, msg.data); } /** @@ -263,26 +157,26 @@ contract FlashAggregator is Setups { uint256 _route, bytes calldata _data, bytes calldata // kept for future use by instadapp. Currently not used anywhere. - ) external reentrancy { + ) external { require(_tokens.length == _amounts.length, "array-lengths-not-same"); (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); if (_route == 1) { - routeAave(_tokens, _amounts, _data); + spell(AAVE_IMP, msg.data); } else if (_route == 2) { - routeMaker(_tokens[0], _amounts[0], _data); + spell(MAKER_IMP, msg.data); } else if (_route == 3) { - routeMakerCompound(_tokens, _amounts, _data); + spell(MAKER_IMP, msg.data); } else if (_route == 4) { - routeMakerAave(_tokens, _amounts, _data); + spell(MAKER_IMP, msg.data); } else if (_route == 5) { - routeBalancer(_tokens, _amounts, _data); + spell(BALANCER_IMP, msg.data); } else if (_route == 6) { - routeBalancerCompound(_tokens, _amounts, _data); + spell(BALANCER_IMP, msg.data); } else if (_route == 7) { - routeBalancerAave(_tokens, _amounts, _data); + spell(BALANCER_IMP, msg.data); } else { revert("route-does-not-exist"); } @@ -333,13 +227,6 @@ contract FlashAggregator is Setups { contract InstaFlashAggregator is FlashAggregator { using SafeERC20 for IERC20; - function initialize(address aave, address maker, address balancer) public { - AAVE_PROXY = aave; - MAKER_PROXY = maker; - BALANCER_PROXY = balancer; - console.log("initialize call successful! AAVE_PROXY = ", AAVE_PROXY); - } - /* Deprecated */ diff --git a/contracts/aggregator/mainnet/flashloan/variables.sol b/contracts/aggregator/mainnet/flashloan/variables.sol index 75e7f136..1dfbf80e 100644 --- a/contracts/aggregator/mainnet/flashloan/variables.sol +++ b/contracts/aggregator/mainnet/flashloan/variables.sol @@ -31,12 +31,6 @@ contract ConstantVariables { ListInterface internal constant instaList = ListInterface(0x4c8a1BEb8a87765788946D6B19C6C6355194AbEb); uint256 public constant InstaFeeBPS = 5; // in BPS; 1 BPS = 0.01% - // address internal constant AAVE_PROXY; - // address internal constant MAKER_PROXY; - // address internal constant BALANCER_PROXY; - address internal AAVE_PROXY; - address internal MAKER_PROXY; - address internal BALANCER_PROXY; } contract Variables is ConstantVariables { @@ -62,4 +56,8 @@ contract Variables is ConstantVariables { uint256 internal ownerStatus; mapping(address => bool) public isWhitelisted; + + address internal AAVE_IMP; + address internal MAKER_IMP; + address internal BALANCER_IMP; } diff --git a/test/mainnet/newFlashAggr.ts b/test/mainnet/newFlashAggr.ts index 326bafd2..70cc657b 100644 --- a/test/mainnet/newFlashAggr.ts +++ b/test/mainnet/newFlashAggr.ts @@ -26,13 +26,15 @@ import { proxyB : BalancerImplementation, proxyM : MakerImplementation, aggregator : InstaFlashAggregator, + Proxy, + proxy: InstaFlashAggregatorProxy, ProxyA, ProxyB, ProxyM, + aaveImp,BalancerImp,MakerImp, Aggregator, admin = "0xb208CDF8e1c319d0019397dceC8E0bA3Fb9A149F", proxyAddr = "0x619Ad2D02dBeE6ebA3CDbDA3F98430410e892882", - proxyCon: { connect: (arg0: any) => { (): any; new(): any; upgradeTo: { (arg0: string): any; new(): any }; callStatic: { (): any; new(): any; implementation: { (): any; new(): any } } }; initialize: (arg0: string, arg1: string, arg2: string) => any }, Receiver, receiver: InstaFlashReceiver @@ -40,87 +42,319 @@ import { const _data = '0x' let _instaData = '0x' + const master = '0xa8c31E39e40E6765BEdBd83D92D6AA0B33f1CCC5' + const aaveLendingAddr = '0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9' + let ABI = ['function initialize(address[],address,address,address,address)'] + let iface = new ethers.utils.Interface(ABI) -//############## - const Dai = ethers.utils.parseUnits('5000', 18) - -//############## const DAI = '0x6b175474e89094c44da98b954eedeac495271d0f' + const USDT = '0xdac17f958d2ee523a2206206994597c13d831ec7' + const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' + const STETH = '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84' + const ACC_DAI = '0x9a7a9d980ed6239b89232c012e21f4c210f4bef1' + const ACC_USDT = '0x6D5Be15f9Aa170e207C043CDf8E0BaDbF2A48ed0' + const ACC_WETH = '0xe78388b4ce79068e89bf8aa7f218ef6b9ab0e9d0' + const ACC_STETH = '0xdc24316b9ae028f1497c275eb9192a3ea0f67022' + + const dai = ethers.utils.parseUnits('10', 18) + const usdt = ethers.utils.parseUnits('10', 6) + const weth = ethers.utils.parseUnits('10', 18) + const Dai = ethers.utils.parseUnits('5000', 18) + const Usdt = ethers.utils.parseUnits('5000', 6) + const Weth = ethers.utils.parseUnits('1000', 18) + const steth = ethers.utils.parseUnits('1', 18) + const Steth = ethers.utils.parseUnits('100', 18) - it('Should deploy', async function () { + beforeEach(async function () { ;[signer] = await ethers.getSigners() - ProxyA = new AaveImplementation__factory + ProxyA = new AaveImplementation__factory(signer) proxyA = await ProxyA.deploy() await proxyA.deployed() console.log("Aave proxy deployed at: ", proxyA.address); - ProxyB = new BalancerImplementation__factory + + ProxyB = new BalancerImplementation__factory(signer) proxyB = await ProxyB.deploy() await proxyB.deployed() console.log("Balancer proxy deployed at: ", proxyB.address); - ProxyM = new MakerImplementation__factory + + ProxyM = new MakerImplementation__factory(signer) proxyM = await ProxyM.deploy() await proxyM.deployed() console.log("Maker proxy deployed at: ", proxyM.address); + Aggregator = new InstaFlashAggregator__factory(signer) aggregator = await Aggregator.deploy() await aggregator.deployed() console.log("Aggregator deployed at: ", aggregator.address); - proxyCon = new hre.ethers.Contract( - proxyAddr, - [{"inputs":[{"internalType":"address","name":"_logic","type":"address"},{"internalType":"address","name":"admin_","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"admin_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}] - ) + const data = iface.encodeFunctionData('initialize', [ + [ + '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643', // DAI + '0xf650C3d88D12dB855b8bf7D11Be6C55A4e07dCC9', // USDT + '0x39AA39c021dfbaE8faC545936693aC917d5E7563', // USDC + '0xe65cdb6479bac1e22340e4e755fae7e509ecd06c', // AAVE + '0x6c8c6b02e7b2be14d4fa6022dfd6d75921d90e4e', // BAT + '0x70e36f6bf80a52b3b46b3af8e106cc0ed743e8e4', // COMP + '0xface851a4921ce59e912d19329929ce6da6eb0c7', // LINK + '0x95b4ef2869ebd94beb4eee400a99824bf5dc325b', // MKR + '0x158079ee67fce2f58472a96584a73c7ab9ac95c1', // REP + '0x4b0181102a0112a2ef11abee5563bb4a3176c9d7', // SUSHI + '0x12392f67bdf24fae0af363c24ac620a2f67dad86', // TUSD + '0x35a18000230da775cac24873d00ff85bccded550', // UNI + '0xccf4429db6322d5c611ee964527d42e5d685dd6a', // WBTC2 + '0x80a2ae356fc9ef4305676f7a3e2ed04e12c33946', // YFI + '0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407', // ZRX + ],master,proxyA.address,proxyB.address,proxyM.address + ]) + + Proxy = new InstaFlashAggregatorProxy__factory(signer) + proxy = await Proxy.deploy(aggregator.address, master, data) + await proxy.deployed() + console.log("Proxy deployed at: ", proxy.address); Receiver = new InstaFlashReceiver__factory(signer) - receiver = await Receiver.deploy(proxyAddr) + receiver = await Receiver.deploy(proxy.address) await receiver.deployed() console.log("Receiver deployed at: ", receiver.address); - + + await hre.network.provider.send('hardhat_setBalance', [ + proxy.address, + ethers.utils.parseEther('10.0').toHexString(), + ]) + const token_dai = new ethers.Contract( - DAI, - IERC20__factory.abi, - ethers.provider, + DAI, + IERC20__factory.abi, + ethers.provider, + ) + + const token_steth = new ethers.Contract( + STETH, + IERC20__factory.abi, + ethers.provider, ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) await hre.network.provider.send('hardhat_setBalance', [ - ACC_DAI, + ACC_STETH, ethers.utils.parseEther('10.0').toHexString(), ]) - }) - describe('Upgrade proxy implementation', async function () { + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_DAI], + }) + + const signer_dai = await ethers.getSigner(ACC_DAI) + await token_dai.connect(signer_dai).transfer(receiver.address, dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) + await hre.network.provider.request({ method: 'hardhat_impersonateAccount', - params: [admin], - }) + params: [ACC_STETH], + }) - await hre.network.provider.send("hardhat_setBalance", [ - admin, - ethers.utils.parseEther("10.0").toHexString(), - ]); + const signer_steth = await ethers.getSigner(ACC_STETH) + await token_steth.connect(signer_steth).transfer(receiver.address, steth) + await token_steth.connect(signer_steth).transfer(proxy.address, steth) - let impersonateAcc = await ethers.getSigner(admin); + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_STETH], + }) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [proxy.address], + }) - let tx = await proxyCon.connect(impersonateAcc).upgradeTo(aggregator.address); - let receipt = tx.wait(); - console.log("Implementation updated!") + const signer_fla = await ethers.getSigner(proxy.address) + await token_dai.connect(signer_fla).approve(aaveLendingAddr, 100) - let addr = await proxyCon.connect(impersonateAcc).callStatic.implementation(); - console.log("Implementation at: ", addr); - - await proxyCon.initialize(proxyA.address, proxyB.address, proxyM.address);//todo: doubt + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [proxy.address], + }) }) describe('Single token', async function () { it('Should be able to take flashLoan of a single token from AAVE', async function () { await receiver.flashBorrow([DAI], [Dai], 1, _data, _instaData) }) + it('Should be able to take flashLoan of a single token from MakerDAO', async function () { + await receiver.flashBorrow([DAI], [Dai], 2, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from Compound(MakerDAO)', async function () { + await receiver.flashBorrow([DAI], [Dai], 3, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from AAVE(MakerDAO)', async function () { + await receiver.flashBorrow([DAI], [Dai], 4, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from Balancer', async function () { + await receiver.flashBorrow([DAI], [Dai], 5, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from Compound(Balancer)', async function () { + await receiver.flashBorrow([DAI], [Dai], 6, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from AAVE(Balancer)', async function () { + await receiver.flashBorrow([DAI], [Dai], 7, _data, _instaData) + }) + it('Should be able to take flashLoan of a steth token from AAVE(Balancer)', async function () { + await receiver.flashBorrow([STETH], [Steth], 5, _data, _instaData) + }) }) + + describe('Multi token', async function () { + beforeEach(async function () { + const token_usdt = new ethers.Contract( + USDT, + IERC20__factory.abi, + ethers.provider, + ) + + const token_weth = new ethers.Contract( + WETH, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_USDT, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_WETH, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_USDT], + }) + + const signer_usdt = await ethers.getSigner(ACC_USDT) + await token_usdt.connect(signer_usdt).transfer(receiver.address, usdt) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDT], + }) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_WETH], + }) + + const signer_weth = await ethers.getSigner(ACC_WETH) + await token_weth.connect(signer_weth).transfer(receiver.address, weth) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_WETH], + }) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [proxy.address], + }) + + const signer_fla = await ethers.getSigner(proxy.address) + await token_usdt.connect(signer_fla).approve(aaveLendingAddr, 100) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [proxy.address], + }) + _instaData = '0x' + }) + + it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 1, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from MakerDAO', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 2, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from Compound(MakerDAO)', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 3, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from AAVE(MakerDAO)', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 4, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple sorted tokens together from Balancer', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 5, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple unsorted tokens together from Balancer', async function () { + await receiver.flashBorrow( + [USDT, DAI, WETH], + [Usdt, Dai, Weth], + 5, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from Compound(Balancer)', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 6, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from AAVE(Balancer)', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 7, + _data, + _instaData, + ) + }) + }) }) \ No newline at end of file From 0c5c1586a4a74fa69a84a86a1f2c4088f4d28810 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Wed, 11 May 2022 00:50:00 +0400 Subject: [PATCH 05/36] changed file names --- contracts/{ProxyBalancer => implBalancer}/main.sol | 0 contracts/{ProxyMaker => implMaker}/main.sol | 0 contracts/{ProxyAave => impleAave}/main.sol | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename contracts/{ProxyBalancer => implBalancer}/main.sol (100%) rename contracts/{ProxyMaker => implMaker}/main.sol (100%) rename contracts/{ProxyAave => impleAave}/main.sol (100%) diff --git a/contracts/ProxyBalancer/main.sol b/contracts/implBalancer/main.sol similarity index 100% rename from contracts/ProxyBalancer/main.sol rename to contracts/implBalancer/main.sol diff --git a/contracts/ProxyMaker/main.sol b/contracts/implMaker/main.sol similarity index 100% rename from contracts/ProxyMaker/main.sol rename to contracts/implMaker/main.sol diff --git a/contracts/ProxyAave/main.sol b/contracts/impleAave/main.sol similarity index 100% rename from contracts/ProxyAave/main.sol rename to contracts/impleAave/main.sol From c7d3a69859322ce4d979b021b19c0bac7df0445f Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Wed, 11 May 2022 00:53:30 +0400 Subject: [PATCH 06/36] minor update --- contracts/{impleAave => implAave}/main.sol | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename contracts/{impleAave => implAave}/main.sol (100%) diff --git a/contracts/impleAave/main.sol b/contracts/implAave/main.sol similarity index 100% rename from contracts/impleAave/main.sol rename to contracts/implAave/main.sol From 2ba7c66ea11b3b1c2061240e6ee17081b69d5eac Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sat, 14 May 2022 02:44:26 +0400 Subject: [PATCH 07/36] added common helper and interface --- contracts/aggregator/common/helpers.sol | 114 ++++++++++++++++++++++ contracts/aggregator/common/interface.sol | 35 +++++++ 2 files changed, 149 insertions(+) create mode 100644 contracts/aggregator/common/helpers.sol create mode 100644 contracts/aggregator/common/interface.sol diff --git a/contracts/aggregator/common/helpers.sol b/contracts/aggregator/common/helpers.sol new file mode 100644 index 00000000..853a461a --- /dev/null +++ b/contracts/aggregator/common/helpers.sol @@ -0,0 +1,114 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +contract HelpersCommon { + using SafeERC20 for IERC20; + + /** + * @dev Delegate the calls to Connector. + * @param _target Connector address + * @param _data CallData of function. + */ + function spell(address _target, bytes memory _data) internal returns (bytes memory response) { + require(_target != address(0), "target-invalid"); + assembly { + let succeeded := delegatecall(gas(), _target, add(_data, 0x20), mload(_data), 0, 0) + let size := returndatasize() + + response := mload(0x40) + mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f)))) + mstore(response, size) + returndatacopy(add(response, 0x20), 0, size) + + switch iszero(succeeded) + case 1 { + // throw if delegatecall failed + returndatacopy(0x00, 0x00, size) + revert(0x00, size) + } + } + } + + /** + * @dev Calculates the balances.. + * @notice Calculates the balances of the account passed for the tokens. + * @param _tokens list of token addresses to calculate balance for. + * @param _account account to calculate balance for. + */ + function calculateBalances(address[] memory _tokens, address _account) + internal + view + returns (uint256[] memory) + { + uint256 _length = _tokens.length; + uint256[] memory balances_ = new uint256[](_length); + for (uint256 i = 0; i < _length; i++) { + IERC20 token = IERC20(_tokens[i]); + balances_[i] = token.balanceOf(_account); + } + return balances_; + } + + /** + * @dev Validates if token addresses are unique. Just need to check adjacent tokens as the array was sorted first + * @notice Validates if token addresses are unique. + * @param _tokens list of token addresses. + */ + function validateTokens(address[] memory _tokens) internal pure { + for (uint256 i = 0; i < _tokens.length - 1; i++) { + require(_tokens[i] != _tokens[i + 1], "non-unique-tokens"); + } + } + + /** + * @dev Calculate fees for the respective amounts and fee in BPS passed. + * @notice Calculate fees for the respective amounts and fee in BPS passed. 1 BPS == 0.01%. + * @param _amounts list of amounts. + * @param _BPS fee in BPS. + */ + function calculateFees(uint256[] memory _amounts, uint256 _BPS) + internal + pure + returns (uint256[] memory) + { + uint256 length_ = _amounts.length; + uint256[] memory InstaFees = new uint256[](length_); + for (uint256 i = 0; i < length_; i++) { + InstaFees[i] = (_amounts[i] * _BPS) / (10**4); + } + return InstaFees; + } + + /** + * @dev Sort the tokens and amounts arrays according to token addresses. + * @notice Sort the tokens and amounts arrays according to token addresses. + * @param _tokens list of token addresses. + * @param _amounts list of respective amounts. + */ + function bubbleSort(address[] memory _tokens, uint256[] memory _amounts) + internal + pure + returns (address[] memory, uint256[] memory) + { + for (uint256 i = 0; i < _tokens.length - 1; i++) { + for (uint256 j = 0; j < _tokens.length - i - 1; j++) { + if (_tokens[j] > _tokens[j + 1]) { + ( + _tokens[j], + _tokens[j + 1], + _amounts[j], + _amounts[j + 1] + ) = ( + _tokens[j + 1], + _tokens[j], + _amounts[j + 1], + _amounts[j] + ); + } + } + } + return (_tokens, _amounts); + } +} diff --git a/contracts/aggregator/common/interface.sol b/contracts/aggregator/common/interface.sol new file mode 100644 index 00000000..b800be8a --- /dev/null +++ b/contracts/aggregator/common/interface.sol @@ -0,0 +1,35 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +pragma experimental ABIEncoderV2; + +interface IndexInterface { + function master() external view returns (address); + + function list() external view returns (address); +} + +interface ListInterface { + function accountID(address) external view returns (uint64); +} + +interface TokenInterface { + function approve(address, uint256) external; + + function transfer(address, uint256) external; + + function transferFrom( + address, + address, + uint256 + ) external; + + function deposit() external payable; + + function withdraw(uint256) external; + + function balanceOf(address) external view returns (uint256); + + function decimals() external view returns (uint256); + + function totalSupply() external view returns (uint256); +} From c549c3a7753d7f26014981782ad543c991633f43 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 15 May 2022 02:12:28 +0400 Subject: [PATCH 08/36] Added Implementation proxy - Arbitrum --- .../arbitrum/flashloan/implBalancer/main.sol | 118 +++++++++ .../arbitrum/flashloan/implUniswap/main.sol | 173 ++++++++++++++ .../aggregator/arbitrum/flashloan/main.sol | 223 +----------------- 3 files changed, 298 insertions(+), 216 deletions(-) create mode 100644 contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol create mode 100644 contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol diff --git a/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol b/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol new file mode 100644 index 00000000..849a2e15 --- /dev/null +++ b/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol @@ -0,0 +1,118 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; +import "../helpers.sol"; + +contract BalancerImplementation is Helper { + + /** + * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. + * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _route route for flashloan. + * @param _data extra data passed. + */ + function flashLoan( + address[] memory _tokens, + uint256[] memory _amounts, + uint256 _route, + bytes calldata _data, + bytes memory _instadata + ) external reentrancy { + require(_route == 5 , "invalid BALANCER flashloan route"); + routeBalancer(_tokens, _amounts, _data); + } + + /** + * @dev Callback function for balancer flashloan. + * @notice Fallback function for balancer flashloan. + * @param _amounts list of amounts for the corresponding assets or amount of ether to borrow as collateral for flashloan. + * @param _fees list of fees for the corresponding addresses for flashloan. + * @param _data extra data passed. + */ + function receiveFlashLoan( + IERC20[] memory _tokens, + uint256[] memory _amounts, + uint256[] memory _fees, + bytes memory _data + ) external verifyDataHash(_data) { + require(msg.sender == balancerLendingAddr, "not-balancer-sender"); + + FlashloanVariables memory instaLoanVariables_; + + uint256 length_ = _tokens.length; + instaLoanVariables_._tokens = new address[](length_); + for (uint256 i = 0; i < length_; i++) { + instaLoanVariables_._tokens[i] = address(_tokens[i]); + } + + (address sender_, bytes memory data_) = abi.decode( + _data, + (address, bytes) + ); + + instaLoanVariables_._amounts = _amounts; + instaLoanVariables_._iniBals = calculateBalances( + instaLoanVariables_._tokens, + address(this) + ); + instaLoanVariables_._instaFees = calculateFees( + _amounts, + calculateFeeBPS(5) + ); + + safeTransfer(instaLoanVariables_, sender_); + + if (checkIfDsa(sender_)) { + Address.functionCall( + sender_, + data_, + "DSA-flashloan-fallback-failed" + ); + } else { + InstaFlashReceiverInterface(sender_).executeOperation( + instaLoanVariables_._tokens, + _amounts, + instaLoanVariables_._instaFees, + sender_, + data_ + ); + } + + instaLoanVariables_._finBals = calculateBalances( + instaLoanVariables_._tokens, + address(this) + ); + validateFlashloan(instaLoanVariables_); + + safeTransferWithFee(instaLoanVariables_, _fees, balancerLendingAddr); + } + + + /** + * @dev Middle function for route 5. + * @notice Middle function for route 5. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _data extra data passed. + */ + function routeBalancer( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal { + bytes memory data_ = abi.encode(msg.sender, _data); + uint256 length_ = _tokens.length; + IERC20[] memory tokens_ = new IERC20[](length_); + for (uint256 i = 0; i < length_; i++) { + tokens_[i] = IERC20(_tokens[i]); + } + dataHash = bytes32(keccak256(data_)); + balancerLending.flashLoan( + InstaFlashReceiverInterface(address(this)), + tokens_, + _amounts, + data_ + ); + } +} diff --git a/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol b/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol new file mode 100644 index 00000000..a6d1c759 --- /dev/null +++ b/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol @@ -0,0 +1,173 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; +import "../helpers.sol"; + +contract UniswapImplementation is Helper { + + /** + * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. + * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _route route for flashloan. + * @param _data extra data passed. + */ + function flashLoan( + address[] memory _tokens, + uint256[] memory _amounts, + uint256 _route, + bytes calldata _data, + bytes memory _instadata + ) external reentrancy { + require(_route == 8, "invalid UNISWAP flashloan route"); + routeUniswap(_tokens, _amounts, _data, _instadata); + } + + struct UniswapFlashInfo { + address sender; + PoolKey key; + bytes data; + } + + /** + * @dev Callback function for uniswap flashloan. + * @notice Callback function for uniswap flashloan. + * @param fee0 The fee from calling flash for token0 + * @param fee1 The fee from calling flash for token1 + * @param data extra data passed(includes route info aswell). + */ + function uniswapV3FlashCallback( + uint256 fee0, + uint256 fee1, + bytes memory data + ) external verifyDataHash(data) { + FlashloanVariables memory instaLoanVariables_; + UniswapFlashInfo memory uniswapFlashData_; + + ( + instaLoanVariables_._tokens, + instaLoanVariables_._amounts, + uniswapFlashData_.sender, + uniswapFlashData_.key, + uniswapFlashData_.data + ) = abi.decode(data, (address[], uint256[], address, PoolKey, bytes)); + + address pool = computeAddress( + uniswapFactoryAddr, + uniswapFlashData_.key + ); + require(msg.sender == pool, "invalid-sender"); + + instaLoanVariables_._iniBals = calculateBalances( + instaLoanVariables_._tokens, + address(this) + ); + + uint256 feeBPS = uint256(uniswapFlashData_.key.fee / 100); + if (feeBPS < InstaFeeBPS) { + feeBPS = InstaFeeBPS; + } + + instaLoanVariables_._instaFees = calculateFees( + instaLoanVariables_._amounts, + feeBPS + ); + + safeTransfer(instaLoanVariables_, uniswapFlashData_.sender); + + if (checkIfDsa(uniswapFlashData_.sender)) { + Address.functionCall( + uniswapFlashData_.sender, + uniswapFlashData_.data, + "DSA-flashloan-fallback-failed" + ); + } else { + InstaFlashReceiverInterface(uniswapFlashData_.sender) + .executeOperation( + instaLoanVariables_._tokens, + instaLoanVariables_._amounts, + instaLoanVariables_._instaFees, + uniswapFlashData_.sender, + uniswapFlashData_.data + ); + } + + instaLoanVariables_._finBals = calculateBalances( + instaLoanVariables_._tokens, + address(this) + ); + + validateFlashloan(instaLoanVariables_); + + uint256[] memory fees_; + if (instaLoanVariables_._tokens.length == 2) { + fees_ = new uint256[](2); + fees_[0] = fee0; + fees_[1] = fee1; + } else if ( + instaLoanVariables_._tokens[0] == uniswapFlashData_.key.token0 + ) { + fees_ = new uint256[](1); + fees_[0] = fee0; + } else { + fees_ = new uint256[](1); + fees_[0] = fee1; + } + safeTransferWithFee(instaLoanVariables_, fees_, msg.sender); + } + + /** + * @dev Middle function for route 8. + * @notice Middle function for route 8. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _data extra data passed. + * @param _instadata pool key encoded + */ + function routeUniswap( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data, + bytes memory _instadata + ) internal { + PoolKey memory key = abi.decode(_instadata, (PoolKey)); + + uint256 amount0_; + uint256 amount1_; + + if (_tokens.length == 1) { + require( + (_tokens[0] == key.token0 || _tokens[0] == key.token1), + "tokens-do-not-match-pool" + ); + if (_tokens[0] == key.token0) { + amount0_ = _amounts[0]; + } else { + amount1_ = _amounts[0]; + } + } else if (_tokens.length == 2) { + require( + (_tokens[0] == key.token0 && _tokens[1] == key.token1), + "tokens-do-not-match-pool" + ); + amount0_ = _amounts[0]; + amount1_ = _amounts[1]; + } else { + revert("Number of tokens do not match"); + } + + IUniswapV3Pool pool = IUniswapV3Pool( + computeAddress(uniswapFactoryAddr, key) + ); + + bytes memory data_ = abi.encode( + _tokens, + _amounts, + msg.sender, + key, + _data + ); + dataHash = bytes32(keccak256(data_)); + pool.flash(address(this), amount0_, amount1_, data_); + } +} diff --git a/contracts/aggregator/arbitrum/flashloan/main.sol b/contracts/aggregator/arbitrum/flashloan/main.sol index 7f0470cc..c96d8c6c 100644 --- a/contracts/aggregator/arbitrum/flashloan/main.sol +++ b/contracts/aggregator/arbitrum/flashloan/main.sol @@ -26,63 +26,8 @@ contract FlashAggregatorArbitrum is Helper { uint256[] memory _amounts, uint256[] memory _fees, bytes memory _data - ) external verifyDataHash(_data) { - require(msg.sender == balancerLendingAddr, "not-balancer-sender"); - - FlashloanVariables memory instaLoanVariables_; - - uint256 length_ = _tokens.length; - instaLoanVariables_._tokens = new address[](length_); - for (uint256 i = 0; i < length_; i++) { - instaLoanVariables_._tokens[i] = address(_tokens[i]); - } - - (address sender_, bytes memory data_) = abi.decode( - _data, - (address, bytes) - ); - - instaLoanVariables_._amounts = _amounts; - instaLoanVariables_._iniBals = calculateBalances( - instaLoanVariables_._tokens, - address(this) - ); - instaLoanVariables_._instaFees = calculateFees( - _amounts, - calculateFeeBPS(5) - ); - - safeTransfer(instaLoanVariables_, sender_); - - if (checkIfDsa(sender_)) { - Address.functionCall( - sender_, - data_, - "DSA-flashloan-fallback-failed" - ); - } else { - InstaFlashReceiverInterface(sender_).executeOperation( - instaLoanVariables_._tokens, - _amounts, - instaLoanVariables_._instaFees, - sender_, - data_ - ); - } - - instaLoanVariables_._finBals = calculateBalances( - instaLoanVariables_._tokens, - address(this) - ); - validateFlashloan(instaLoanVariables_); - - safeTransferWithFee(instaLoanVariables_, _fees, balancerLendingAddr); - } - - struct UniswapFlashInfo { - address sender; - PoolKey key; - bytes data; + ) external { + spell(BALANCER_IMP, msg.data); } /** @@ -96,162 +41,8 @@ contract FlashAggregatorArbitrum is Helper { uint256 fee0, uint256 fee1, bytes memory data - ) external verifyDataHash(data) { - FlashloanVariables memory instaLoanVariables_; - UniswapFlashInfo memory uniswapFlashData_; - - ( - instaLoanVariables_._tokens, - instaLoanVariables_._amounts, - uniswapFlashData_.sender, - uniswapFlashData_.key, - uniswapFlashData_.data - ) = abi.decode(data, (address[], uint256[], address, PoolKey, bytes)); - - address pool = computeAddress( - uniswapFactoryAddr, - uniswapFlashData_.key - ); - require(msg.sender == pool, "invalid-sender"); - - instaLoanVariables_._iniBals = calculateBalances( - instaLoanVariables_._tokens, - address(this) - ); - - uint256 feeBPS = uint256(uniswapFlashData_.key.fee / 100); - if (feeBPS < InstaFeeBPS) { - feeBPS = InstaFeeBPS; - } - - instaLoanVariables_._instaFees = calculateFees( - instaLoanVariables_._amounts, - feeBPS - ); - - safeTransfer(instaLoanVariables_, uniswapFlashData_.sender); - - if (checkIfDsa(uniswapFlashData_.sender)) { - Address.functionCall( - uniswapFlashData_.sender, - uniswapFlashData_.data, - "DSA-flashloan-fallback-failed" - ); - } else { - InstaFlashReceiverInterface(uniswapFlashData_.sender) - .executeOperation( - instaLoanVariables_._tokens, - instaLoanVariables_._amounts, - instaLoanVariables_._instaFees, - uniswapFlashData_.sender, - uniswapFlashData_.data - ); - } - - instaLoanVariables_._finBals = calculateBalances( - instaLoanVariables_._tokens, - address(this) - ); - - validateFlashloan(instaLoanVariables_); - - uint256[] memory fees_; - if (instaLoanVariables_._tokens.length == 2) { - fees_ = new uint256[](2); - fees_[0] = fee0; - fees_[1] = fee1; - } else if ( - instaLoanVariables_._tokens[0] == uniswapFlashData_.key.token0 - ) { - fees_ = new uint256[](1); - fees_[0] = fee0; - } else { - fees_ = new uint256[](1); - fees_[0] = fee1; - } - safeTransferWithFee(instaLoanVariables_, fees_, msg.sender); - } - - /** - * @dev Middle function for route 5. - * @notice Middle function for route 5. - * @param _tokens token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets. - * @param _data extra data passed. - */ - function routeBalancer( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data - ) internal { - bytes memory data_ = abi.encode(msg.sender, _data); - uint256 length_ = _tokens.length; - IERC20[] memory tokens_ = new IERC20[](length_); - for (uint256 i = 0; i < length_; i++) { - tokens_[i] = IERC20(_tokens[i]); - } - dataHash = bytes32(keccak256(data_)); - balancerLending.flashLoan( - InstaFlashReceiverInterface(address(this)), - tokens_, - _amounts, - data_ - ); - } - - /** - * @dev Middle function for route 8. - * @notice Middle function for route 8. - * @param _tokens token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets. - * @param _data extra data passed. - * @param _instadata pool key encoded - */ - function routeUniswap( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data, - bytes memory _instadata - ) internal { - PoolKey memory key = abi.decode(_instadata, (PoolKey)); - - uint256 amount0_; - uint256 amount1_; - - if (_tokens.length == 1) { - require( - (_tokens[0] == key.token0 || _tokens[0] == key.token1), - "tokens-do-not-match-pool" - ); - if (_tokens[0] == key.token0) { - amount0_ = _amounts[0]; - } else { - amount1_ = _amounts[0]; - } - } else if (_tokens.length == 2) { - require( - (_tokens[0] == key.token0 && _tokens[1] == key.token1), - "tokens-do-not-match-pool" - ); - amount0_ = _amounts[0]; - amount1_ = _amounts[1]; - } else { - revert("Number of tokens do not match"); - } - - IUniswapV3Pool pool = IUniswapV3Pool( - computeAddress(uniswapFactoryAddr, key) - ); - - bytes memory data_ = abi.encode( - _tokens, - _amounts, - msg.sender, - key, - _data - ); - dataHash = bytes32(keccak256(data_)); - pool.flash(address(this), amount0_, amount1_, data_); + ) external { + spell(UNISWAP_IMP, msg.data); } /** @@ -268,16 +59,16 @@ contract FlashAggregatorArbitrum is Helper { uint256 _route, bytes calldata _data, bytes memory _instadata - ) external reentrancy { + ) external { require(_tokens.length == _amounts.length, "array-lengths-not-same"); (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); if (_route == 5) { - routeBalancer(_tokens, _amounts, _data); + spell(BALANCER_IMP, msg.data); } else if (_route == 8) { - routeUniswap(_tokens, _amounts, _data, _instadata); + spell(UNISWAP_IMP, msg.data); } else { revert("route-does-not-exist"); } From 4c64449057ff6d7bf5400b04e3a94b3afe276805 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 15 May 2022 02:26:36 +0400 Subject: [PATCH 09/36] Added implementation proxy - Avalanche --- .../avalanche/flashloan/implAave/main.sol | 90 +++++++++++++++++++ .../aggregator/avalanche/flashloan/main.sol | 59 ++---------- .../avalanche/flashloan/variables.sol | 9 +- 3 files changed, 100 insertions(+), 58 deletions(-) create mode 100644 contracts/aggregator/avalanche/flashloan/implAave/main.sol diff --git a/contracts/aggregator/avalanche/flashloan/implAave/main.sol b/contracts/aggregator/avalanche/flashloan/implAave/main.sol new file mode 100644 index 00000000..7ce12001 --- /dev/null +++ b/contracts/aggregator/avalanche/flashloan/implAave/main.sol @@ -0,0 +1,90 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +import "../helpers.sol"; + + +contract BalancerImplementation is Helper { + + /** + * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. + * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _route route for flashloan. + * @param _data extra data passed. + */ + function flashLoan( + address[] memory _tokens, + uint256[] memory _amounts, + uint256 _route, + bytes calldata _data, + bytes calldata // kept for future use by instadapp. Currently not used anywhere. + ) external reentrancy { + require(_route == 1, "invalid AAVE route"); + routeAave(_tokens, _amounts, _data); + } + + /** + * @dev Callback function for aave flashloan. + * @notice Callback function for aave flashloan. + * @param _assets list of asset addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets for flashloan. + * @param _premiums list of premiums/fees for the corresponding addresses for flashloan. + * @param _initiator initiator address for flashloan. + * @param _data extra data passed. + */ + function executeOperation( + address[] memory _assets, + uint256[] memory _amounts, + uint256[] memory _premiums, + address _initiator, + bytes memory _data + ) external verifyDataHash(_data) returns (bool) { + require(_initiator == address(this), "not-same-sender"); + require(msg.sender == aaveLendingAddr, "not-aave-sender"); + + FlashloanVariables memory instaLoanVariables_; + + (address sender_, bytes memory data_) = abi.decode( + _data, + (address, bytes) + ); + + instaLoanVariables_._tokens = _assets; + instaLoanVariables_._amounts = _amounts; + instaLoanVariables_._instaFees = calculateFees(_amounts, calculateFeeBPS(1)); + instaLoanVariables_._iniBals = calculateBalances(_assets, address(this)); + + safeApprove(instaLoanVariables_, _premiums, aaveLendingAddr); + safeTransfer(instaLoanVariables_, sender_); + + if (checkIfDsa(sender_)) { + Address.functionCall(sender_, data_, "DSA-flashloan-fallback-failed"); + } else { + InstaFlashReceiverInterface(sender_).executeOperation(_assets, _amounts, instaLoanVariables_._instaFees, sender_, data_); + } + + instaLoanVariables_._finBals = calculateBalances(_assets, address(this)); + validateFlashloan(instaLoanVariables_); + + return true; + } + + /** + * @dev Middle function for route 1. + * @notice Middle function for route 1. + * @param _tokens list of token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets or amount of ether to borrow as collateral for flashloan. + * @param _data extra data passed. + */ + function routeAave(address[] memory _tokens, uint256[] memory _amounts, bytes memory _data) internal { + bytes memory data_ = abi.encode(msg.sender, _data); + uint length_ = _tokens.length; + uint[] memory _modes = new uint[](length_); + for (uint i = 0; i < length_; i++) { + _modes[i]=0; + } + dataHash = bytes32(keccak256(data_)); + aaveLending.flashLoan(address(this), _tokens, _amounts, _modes, address(0), data_, 3228); + } +} diff --git a/contracts/aggregator/avalanche/flashloan/main.sol b/contracts/aggregator/avalanche/flashloan/main.sol index 18d56664..383d1452 100644 --- a/contracts/aggregator/avalanche/flashloan/main.sol +++ b/contracts/aggregator/avalanche/flashloan/main.sol @@ -10,11 +10,8 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import { Helper } from "./helpers.sol"; - -import { - TokenInterface, - InstaFlashReceiverInterface -} from "./interfaces.sol"; +import { InstaFlashReceiverInterface } from "./interfaces.sol"; +import { TokenInterface } from "../../common/interface.sol"; contract FlashAggregatorAvalanche is Helper { using SafeERC20 for IERC20; @@ -41,53 +38,9 @@ contract FlashAggregatorAvalanche is Helper { uint256[] memory _premiums, address _initiator, bytes memory _data - ) external verifyDataHash(_data) returns (bool) { - require(_initiator == address(this), "not-same-sender"); - require(msg.sender == aaveLendingAddr, "not-aave-sender"); - - FlashloanVariables memory instaLoanVariables_; - - (address sender_, bytes memory data_) = abi.decode( - _data, - (address, bytes) - ); - - instaLoanVariables_._tokens = _assets; - instaLoanVariables_._amounts = _amounts; - instaLoanVariables_._instaFees = calculateFees(_amounts, calculateFeeBPS(1)); - instaLoanVariables_._iniBals = calculateBalances(_assets, address(this)); - - safeApprove(instaLoanVariables_, _premiums, aaveLendingAddr); - safeTransfer(instaLoanVariables_, sender_); - - if (checkIfDsa(sender_)) { - Address.functionCall(sender_, data_, "DSA-flashloan-fallback-failed"); - } else { - InstaFlashReceiverInterface(sender_).executeOperation(_assets, _amounts, instaLoanVariables_._instaFees, sender_, data_); - } - - instaLoanVariables_._finBals = calculateBalances(_assets, address(this)); - validateFlashloan(instaLoanVariables_); - - return true; - } - - /** - * @dev Middle function for route 1. - * @notice Middle function for route 1. - * @param _tokens list of token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets or amount of ether to borrow as collateral for flashloan. - * @param _data extra data passed. - */ - function routeAave(address[] memory _tokens, uint256[] memory _amounts, bytes memory _data) internal { - bytes memory data_ = abi.encode(msg.sender, _data); - uint length_ = _tokens.length; - uint[] memory _modes = new uint[](length_); - for (uint i = 0; i < length_; i++) { - _modes[i]=0; - } - dataHash = bytes32(keccak256(data_)); - aaveLending.flashLoan(address(this), _tokens, _amounts, _modes, address(0), data_, 3228); + ) external returns (bool) { + bytes memory response = spell(AAVE_IMP, msg.data); + return (abi.decode(response, (bool))); } /** @@ -112,7 +65,7 @@ contract FlashAggregatorAvalanche is Helper { validateTokens(_tokens); if (_route == 1) { - routeAave(_tokens, _amounts, _data); + spell(AAVE_IMP, msg.data); } else if (_route == 2) { revert("this route is only for mainnet"); } else if (_route == 3) { diff --git a/contracts/aggregator/avalanche/flashloan/variables.sol b/contracts/aggregator/avalanche/flashloan/variables.sol index 4fa2dbc5..a0f10cbd 100644 --- a/contracts/aggregator/avalanche/flashloan/variables.sol +++ b/contracts/aggregator/avalanche/flashloan/variables.sol @@ -1,11 +1,8 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import { - IndexInterface, - ListInterface, - IAaveLending -} from "./interfaces.sol"; +import "./interfaces.sol"; +import "../../common/interface.sol"; contract ConstantVariables { @@ -34,4 +31,6 @@ contract Variables is ConstantVariables { uint256[] _instaFees; } + address internal AAVE_IMP; + } \ No newline at end of file From 2ab801947049a357a2fa32629b4a1458ad97da03 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 15 May 2022 16:05:38 +0400 Subject: [PATCH 10/36] Added implementation proxy - Optimism --- .../optimism/flashloan/implUniswap/main.sol | 174 ++++++++++++++++++ .../aggregator/optimism/flashloan/main.sol | 136 +------------- .../optimism/flashloan/variables.sol | 3 + 3 files changed, 181 insertions(+), 132 deletions(-) create mode 100644 contracts/aggregator/optimism/flashloan/implUniswap/main.sol diff --git a/contracts/aggregator/optimism/flashloan/implUniswap/main.sol b/contracts/aggregator/optimism/flashloan/implUniswap/main.sol new file mode 100644 index 00000000..ab09c402 --- /dev/null +++ b/contracts/aggregator/optimism/flashloan/implUniswap/main.sol @@ -0,0 +1,174 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../helpers.sol"; + +contract BalancerImplementation is Helper { + + /** + * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. + * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _route route for flashloan. + * @param _data extra data passed. + */ + function flashLoan( + address[] memory _tokens, + uint256[] memory _amounts, + uint256 _route, + bytes calldata _data, + bytes calldata _instadata + ) external reentrancy { + require(_route == 8, "invalid route for Uniswap"); + routeUniswap(_tokens, _amounts, _data, _instadata); + } + + /** + * @dev Middle function for route 8. + * @notice Middle function for route 8. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _data extra data passed. + * @param _instadata pool key encoded + */ + function routeUniswap( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data, + bytes memory _instadata + ) internal { + PoolKey memory key = abi.decode(_instadata, (PoolKey)); + + uint256 amount0_; + uint256 amount1_; + + if (_tokens.length == 1) { + require( + (_tokens[0] == key.token0 || _tokens[0] == key.token1), + "tokens-do-not-match-pool" + ); + if (_tokens[0] == key.token0) { + amount0_ = _amounts[0]; + } else { + amount1_ = _amounts[0]; + } + } else if (_tokens.length == 2) { + require( + (_tokens[0] == key.token0 && _tokens[1] == key.token1), + "tokens-do-not-match-pool" + ); + amount0_ = _amounts[0]; + amount1_ = _amounts[1]; + } else { + revert("Number of tokens do not match"); + } + + IUniswapV3Pool pool = IUniswapV3Pool( + computeAddress(uniswapFactoryAddr, key) + ); + + bytes memory data_ = abi.encode( + _tokens, + _amounts, + msg.sender, + key, + _data + ); + dataHash = bytes32(keccak256(data_)); + pool.flash(address(this), amount0_, amount1_, data_); + } + + struct UniswapFlashInfo { + address sender; + PoolKey key; + bytes data; + } + + /** + * @dev Callback function for uniswap flashloan. + * @notice Callback function for uniswap flashloan. + * @param fee0 The fee from calling flash for token0 + * @param fee1 The fee from calling flash for token1 + * @param data extra data passed(includes route info aswell). + */ + function uniswapV3FlashCallback( + uint256 fee0, + uint256 fee1, + bytes memory data + ) external verifyDataHash(data) { + FlashloanVariables memory instaLoanVariables_; + UniswapFlashInfo memory uniswapFlashData_; + ( + instaLoanVariables_._tokens, + instaLoanVariables_._amounts, + uniswapFlashData_.sender, + uniswapFlashData_.key, + uniswapFlashData_.data + ) = abi.decode(data, (address[], uint256[], address, PoolKey, bytes)); + + address pool = computeAddress( + uniswapFactoryAddr, + uniswapFlashData_.key + ); + require(msg.sender == pool, "invalid-sender"); + instaLoanVariables_._iniBals = calculateBalances( + instaLoanVariables_._tokens, + address(this) + ); + + uint256 feeBPS = uint256(uniswapFlashData_.key.fee / 100); + if (feeBPS < InstaFeeBPS) { + feeBPS = InstaFeeBPS; + } + + instaLoanVariables_._instaFees = calculateFees( + instaLoanVariables_._amounts, + feeBPS + ); + + safeTransfer(instaLoanVariables_, uniswapFlashData_.sender); + + if (checkIfDsa(uniswapFlashData_.sender)) { + Address.functionCall( + uniswapFlashData_.sender, + uniswapFlashData_.data, + "DSA-flashloan-fallback-failed" + ); + } else { + InstaFlashReceiverInterface(uniswapFlashData_.sender) + .executeOperation( + instaLoanVariables_._tokens, + instaLoanVariables_._amounts, + instaLoanVariables_._instaFees, + uniswapFlashData_.sender, + uniswapFlashData_.data + ); + } + + instaLoanVariables_._finBals = calculateBalances( + instaLoanVariables_._tokens, + address(this) + ); + + validateFlashloan(instaLoanVariables_); + uint256[] memory fees_; + if (instaLoanVariables_._tokens.length == 2) { + fees_ = new uint256[](2); + fees_[0] = fee0; + fees_[1] = fee1; + } else if ( + instaLoanVariables_._tokens[0] == uniswapFlashData_.key.token0 + ) { + fees_ = new uint256[](1); + fees_[0] = fee0; + } else { + fees_ = new uint256[](1); + fees_[0] = fee1; + } + safeTransferWithFee(instaLoanVariables_, fees_, msg.sender); + } + + + +} \ No newline at end of file diff --git a/contracts/aggregator/optimism/flashloan/main.sol b/contracts/aggregator/optimism/flashloan/main.sol index 3198ed3b..1dc2b653 100644 --- a/contracts/aggregator/optimism/flashloan/main.sol +++ b/contracts/aggregator/optimism/flashloan/main.sol @@ -31,132 +31,8 @@ contract FlashAggregatorOptimism is Helper { uint256 fee0, uint256 fee1, bytes memory data - ) external verifyDataHash(data) { - FlashloanVariables memory instaLoanVariables_; - UniswapFlashInfo memory uniswapFlashData_; - ( - instaLoanVariables_._tokens, - instaLoanVariables_._amounts, - uniswapFlashData_.sender, - uniswapFlashData_.key, - uniswapFlashData_.data - ) = abi.decode(data, (address[], uint256[], address, PoolKey, bytes)); - - address pool = computeAddress( - uniswapFactoryAddr, - uniswapFlashData_.key - ); - require(msg.sender == pool, "invalid-sender"); - instaLoanVariables_._iniBals = calculateBalances( - instaLoanVariables_._tokens, - address(this) - ); - - uint256 feeBPS = uint256(uniswapFlashData_.key.fee / 100); - if (feeBPS < InstaFeeBPS) { - feeBPS = InstaFeeBPS; - } - - instaLoanVariables_._instaFees = calculateFees( - instaLoanVariables_._amounts, - feeBPS - ); - - safeTransfer(instaLoanVariables_, uniswapFlashData_.sender); - - if (checkIfDsa(uniswapFlashData_.sender)) { - Address.functionCall( - uniswapFlashData_.sender, - uniswapFlashData_.data, - "DSA-flashloan-fallback-failed" - ); - } else { - InstaFlashReceiverInterface(uniswapFlashData_.sender) - .executeOperation( - instaLoanVariables_._tokens, - instaLoanVariables_._amounts, - instaLoanVariables_._instaFees, - uniswapFlashData_.sender, - uniswapFlashData_.data - ); - } - - instaLoanVariables_._finBals = calculateBalances( - instaLoanVariables_._tokens, - address(this) - ); - - validateFlashloan(instaLoanVariables_); - uint256[] memory fees_; - if (instaLoanVariables_._tokens.length == 2) { - fees_ = new uint256[](2); - fees_[0] = fee0; - fees_[1] = fee1; - } else if ( - instaLoanVariables_._tokens[0] == uniswapFlashData_.key.token0 - ) { - fees_ = new uint256[](1); - fees_[0] = fee0; - } else { - fees_ = new uint256[](1); - fees_[0] = fee1; - } - safeTransferWithFee(instaLoanVariables_, fees_, msg.sender); - } - - /** - * @dev Middle function for route 8. - * @notice Middle function for route 8. - * @param _tokens token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets. - * @param _data extra data passed. - * @param _instadata pool key encoded - */ - function routeUniswap( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data, - bytes memory _instadata - ) internal { - PoolKey memory key = abi.decode(_instadata, (PoolKey)); - - uint256 amount0_; - uint256 amount1_; - - if (_tokens.length == 1) { - require( - (_tokens[0] == key.token0 || _tokens[0] == key.token1), - "tokens-do-not-match-pool" - ); - if (_tokens[0] == key.token0) { - amount0_ = _amounts[0]; - } else { - amount1_ = _amounts[0]; - } - } else if (_tokens.length == 2) { - require( - (_tokens[0] == key.token0 && _tokens[1] == key.token1), - "tokens-do-not-match-pool" - ); - amount0_ = _amounts[0]; - amount1_ = _amounts[1]; - } else { - revert("Number of tokens do not match"); - } - - IUniswapV3Pool pool = IUniswapV3Pool( - computeAddress(uniswapFactoryAddr, key) - ); - - bytes memory data_ = abi.encode( - _tokens, - _amounts, - msg.sender, - key, - _data - ); - dataHash = bytes32(keccak256(data_)); - pool.flash(address(this), amount0_, amount1_, data_); + ) external { + spell(UNISWAP_IMP, msg.data); } /** @@ -173,17 +49,13 @@ contract FlashAggregatorOptimism is Helper { uint256 _route, bytes calldata _data, bytes calldata _instadata - ) external reentrancy { + ) external { require(_tokens.length == _amounts.length, "array-lengths-not-same"); (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); - if (_route == 8) { - routeUniswap(_tokens, _amounts, _data, _instadata); - } else { - revert("route-does-not-exist"); - } + spell(UNISWAP_IMP, msg.data); emit LogFlashloan(msg.sender, _route, _tokens, _amounts); } diff --git a/contracts/aggregator/optimism/flashloan/variables.sol b/contracts/aggregator/optimism/flashloan/variables.sol index 0cd3b06e..b8fffd4e 100644 --- a/contracts/aggregator/optimism/flashloan/variables.sol +++ b/contracts/aggregator/optimism/flashloan/variables.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import "./interfaces.sol"; +import "../../common/interface.sol"; contract ConstantVariables { address public constant treasuryAddr = @@ -37,4 +38,6 @@ contract Variables is ConstantVariables { address token1; uint24 fee; } + + address internal UNISWAP_IMP; } From 907b1ec5676a95c2b71ec01ed000dd7d17785bd5 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 15 May 2022 16:22:44 +0400 Subject: [PATCH 11/36] Added implementation proxy - Polygon --- .../polygon/flashloan/implAave/main.sol | 122 ++++++ .../polygon/flashloan/implBalancer/main.sol | 207 +++++++++ .../polygon/flashloan/implUniswap/main.sol | 175 ++++++++ .../aggregator/polygon/flashloan/main.sol | 393 +----------------- .../polygon/flashloan/variables.sol | 5 + 5 files changed, 521 insertions(+), 381 deletions(-) create mode 100644 contracts/aggregator/polygon/flashloan/implAave/main.sol create mode 100644 contracts/aggregator/polygon/flashloan/implBalancer/main.sol create mode 100644 contracts/aggregator/polygon/flashloan/implUniswap/main.sol diff --git a/contracts/aggregator/polygon/flashloan/implAave/main.sol b/contracts/aggregator/polygon/flashloan/implAave/main.sol new file mode 100644 index 00000000..be4c8f60 --- /dev/null +++ b/contracts/aggregator/polygon/flashloan/implAave/main.sol @@ -0,0 +1,122 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../helpers.sol"; + +contract AaveImplementation is Helper { + + /** + * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. + * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _route route for flashloan. + * @param _data extra data passed. + */ + function flashLoan( + address[] memory _tokens, + uint256[] memory _amounts, + uint256 _route, + bytes calldata _data, + bytes calldata _instadata + ) external reentrancy { + require(_route == 1, "invalid route for Aave"); + routeAave(_tokens, _amounts, _data); + } + + /** + * @dev Callback function for aave flashloan. + * @notice Callback function for aave flashloan. + * @param _assets list of asset addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets for flashloan. + * @param _premiums list of premiums/fees for the corresponding addresses for flashloan. + * @param _initiator initiator address for flashloan. + * @param _data extra data passed. + */ + function executeOperation( + address[] memory _assets, + uint256[] memory _amounts, + uint256[] memory _premiums, + address _initiator, + bytes memory _data + ) external verifyDataHash(_data) returns (bool) { + require(_initiator == address(this), "not-same-sender"); + require(msg.sender == aaveLendingAddr, "not-aave-sender"); + + FlashloanVariables memory instaLoanVariables_; + + (address sender_, bytes memory data_) = abi.decode( + _data, + (address, bytes) + ); + + instaLoanVariables_._tokens = _assets; + instaLoanVariables_._amounts = _amounts; + instaLoanVariables_._instaFees = calculateFees( + _amounts, + calculateFeeBPS(1) + ); + instaLoanVariables_._iniBals = calculateBalances( + _assets, + address(this) + ); + + safeApprove(instaLoanVariables_, _premiums, aaveLendingAddr); + safeTransfer(instaLoanVariables_, sender_); + + if (checkIfDsa(sender_)) { + Address.functionCall( + sender_, + data_, + "DSA-flashloan-fallback-failed" + ); + } else { + InstaFlashReceiverInterface(sender_).executeOperation( + _assets, + _amounts, + instaLoanVariables_._instaFees, + sender_, + data_ + ); + } + + instaLoanVariables_._finBals = calculateBalances( + _assets, + address(this) + ); + validateFlashloan(instaLoanVariables_); + + return true; + } + + /** + * @dev Middle function for route 1. + * @notice Middle function for route 1. + * @param _tokens list of token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets or amount of ether to borrow as collateral for flashloan. + * @param _data extra data passed. + */ + function routeAave( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal { + bytes memory data_ = abi.encode(msg.sender, _data); + uint256 length_ = _tokens.length; + uint256[] memory _modes = new uint256[](length_); + for (uint256 i = 0; i < length_; i++) { + _modes[i] = 0; + } + dataHash = bytes32(keccak256(data_)); + aaveLending.flashLoan( + address(this), + _tokens, + _amounts, + _modes, + address(0), + data_, + 3228 + ); + } + +} \ No newline at end of file diff --git a/contracts/aggregator/polygon/flashloan/implBalancer/main.sol b/contracts/aggregator/polygon/flashloan/implBalancer/main.sol new file mode 100644 index 00000000..473b3e1e --- /dev/null +++ b/contracts/aggregator/polygon/flashloan/implBalancer/main.sol @@ -0,0 +1,207 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../helpers.sol"; + +contract BalancerImplementation is Helper { + + /** + * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. + * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _route route for flashloan. + * @param _data extra data passed. + */ + function flashLoan( + address[] memory _tokens, + uint256[] memory _amounts, + uint256 _route, + bytes calldata _data, + bytes calldata _instadata + ) external reentrancy { + require(_route == 5 || _route == 7, "inavlid route for BALANCER"); + + if (_route == 5) { + routeBalancer(_tokens, _amounts, _data); + } else if (_route == 7) { + routeBalancerAave(_tokens, _amounts, _data); + } + } + + /** + * @dev Callback function for balancer flashloan. + * @notice Callback function for balancer flashloan. + * @param _amounts list of amounts for the corresponding assets or amount of ether to borrow as collateral for flashloan. + * @param _fees list of fees for the corresponding addresses for flashloan. + * @param _data extra data passed(includes route info aswell). + */ + function receiveFlashLoan( + IERC20[] memory, + uint256[] memory _amounts, + uint256[] memory _fees, + bytes memory _data + ) external verifyDataHash(_data) { + require(msg.sender == balancerLendingAddr, "not-balancer-sender"); + + FlashloanVariables memory instaLoanVariables_; + + ( + uint256 route_, + address[] memory tokens_, + uint256[] memory amounts_, + address sender_, + bytes memory data_ + ) = abi.decode(_data, (uint256, address[], uint256[], address, bytes)); + + instaLoanVariables_._tokens = tokens_; + instaLoanVariables_._amounts = amounts_; + instaLoanVariables_._iniBals = calculateBalances( + tokens_, + address(this) + ); + instaLoanVariables_._instaFees = calculateFees( + amounts_, + calculateFeeBPS(route_) + ); + + if (route_ == 5) { + safeTransfer(instaLoanVariables_, sender_); + + if (checkIfDsa(sender_)) { + Address.functionCall( + sender_, + data_, + "DSA-flashloan-fallback-failed" + ); + } else { + InstaFlashReceiverInterface(sender_).executeOperation( + tokens_, + amounts_, + instaLoanVariables_._instaFees, + sender_, + data_ + ); + } + + instaLoanVariables_._finBals = calculateBalances( + tokens_, + address(this) + ); + validateFlashloan(instaLoanVariables_); + safeTransferWithFee( + instaLoanVariables_, + _fees, + balancerLendingAddr + ); + } else if (route_ == 7) { + require(_fees[0] == 0, "flash-ETH-fee-not-0"); + + address[] memory wEthTokenList = new address[](1); + wEthTokenList[0] = wEthToken; + + aaveSupply(wEthTokenList, _amounts); + aaveBorrow(tokens_, amounts_); + safeTransfer(instaLoanVariables_, sender_); + + if (checkIfDsa(sender_)) { + Address.functionCall( + sender_, + data_, + "DSA-flashloan-fallback-failed" + ); + } else { + InstaFlashReceiverInterface(sender_).executeOperation( + tokens_, + amounts_, + instaLoanVariables_._instaFees, + sender_, + data_ + ); + } + + aavePayback(tokens_, amounts_); + aaveWithdraw(wEthTokenList, _amounts); + instaLoanVariables_._finBals = calculateBalances( + tokens_, + address(this) + ); + validateFlashloan(instaLoanVariables_); + instaLoanVariables_._amounts = _amounts; + instaLoanVariables_._tokens = wEthTokenList; + safeTransferWithFee( + instaLoanVariables_, + _fees, + balancerLendingAddr + ); + } else { + revert("wrong-route"); + } + } + + /** + * @dev Middle function for route 5. + * @notice Middle function for route 5. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _data extra data passed. + */ + function routeBalancer( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal { + uint256 length_ = _tokens.length; + IERC20[] memory tokens_ = new IERC20[](length_); + for (uint256 i = 0; i < length_; i++) { + tokens_[i] = IERC20(_tokens[i]); + } + bytes memory data_ = abi.encode( + 5, + _tokens, + _amounts, + msg.sender, + _data + ); + dataHash = bytes32(keccak256(data_)); + balancerLending.flashLoan( + InstaFlashReceiverInterface(address(this)), + tokens_, + _amounts, + data_ + ); + } + + /** + * @dev Middle function for route 7. + * @notice Middle function for route 7. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _data extra data passed. + */ + function routeBalancerAave( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal { + bytes memory data_ = abi.encode( + 7, + _tokens, + _amounts, + msg.sender, + _data + ); + IERC20[] memory wethTokenList_ = new IERC20[](1); + uint256[] memory wethAmountList_ = new uint256[](1); + wethTokenList_[0] = IERC20(wEthToken); + wethAmountList_[0] = getWEthBorrowAmount(); + dataHash = bytes32(keccak256(data_)); + balancerLending.flashLoan( + InstaFlashReceiverInterface(address(this)), + wethTokenList_, + wethAmountList_, + data_ + ); + } + +} \ No newline at end of file diff --git a/contracts/aggregator/polygon/flashloan/implUniswap/main.sol b/contracts/aggregator/polygon/flashloan/implUniswap/main.sol new file mode 100644 index 00000000..1f17d788 --- /dev/null +++ b/contracts/aggregator/polygon/flashloan/implUniswap/main.sol @@ -0,0 +1,175 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../helpers.sol"; + +contract UniswapImplementation is Helper { + + /** + * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. + * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _route route for flashloan. + * @param _data extra data passed. + */ + function flashLoan( + address[] memory _tokens, + uint256[] memory _amounts, + uint256 _route, + bytes calldata _data, + bytes calldata _instadata + ) external reentrancy { + require(_route == 8, "invalid route for UNISWAP"); + routeUniswap(_tokens, _amounts, _data, _instadata); + } + + struct UniswapFlashInfo { + address sender; + PoolKey key; + bytes data; + } + + /** + * @dev Callback function for uniswap flashloan. + * @notice Callback function for uniswap flashloan. + * @param fee0 The fee from calling flash for token0 + * @param fee1 The fee from calling flash for token1 + * @param data extra data passed(includes route info aswell). + */ + function uniswapV3FlashCallback( + uint256 fee0, + uint256 fee1, + bytes memory data + ) external verifyDataHash(data) { + FlashloanVariables memory instaLoanVariables_; + UniswapFlashInfo memory uniswapFlashData_; + + ( + instaLoanVariables_._tokens, + instaLoanVariables_._amounts, + uniswapFlashData_.sender, + uniswapFlashData_.key, + uniswapFlashData_.data + ) = abi.decode(data, (address[], uint256[], address, PoolKey, bytes)); + + address pool = computeAddress( + uniswapFactoryAddr, + uniswapFlashData_.key + ); + require(msg.sender == pool, "invalid-sender"); + + instaLoanVariables_._iniBals = calculateBalances( + instaLoanVariables_._tokens, + address(this) + ); + + uint256 feeBPS = uint256(uniswapFlashData_.key.fee / 100); + if (feeBPS < InstaFeeBPS) { + feeBPS = InstaFeeBPS; + } + + instaLoanVariables_._instaFees = calculateFees( + instaLoanVariables_._amounts, + feeBPS + ); + + safeTransfer(instaLoanVariables_, uniswapFlashData_.sender); + + if (checkIfDsa(uniswapFlashData_.sender)) { + Address.functionCall( + uniswapFlashData_.sender, + uniswapFlashData_.data, + "DSA-flashloan-fallback-failed" + ); + } else { + InstaFlashReceiverInterface(uniswapFlashData_.sender) + .executeOperation( + instaLoanVariables_._tokens, + instaLoanVariables_._amounts, + instaLoanVariables_._instaFees, + uniswapFlashData_.sender, + uniswapFlashData_.data + ); + } + + instaLoanVariables_._finBals = calculateBalances( + instaLoanVariables_._tokens, + address(this) + ); + + validateFlashloan(instaLoanVariables_); + + uint256[] memory fees_; + if (instaLoanVariables_._tokens.length == 2) { + fees_ = new uint256[](2); + fees_[0] = fee0; + fees_[1] = fee1; + } else if ( + instaLoanVariables_._tokens[0] == uniswapFlashData_.key.token0 + ) { + fees_ = new uint256[](1); + fees_[0] = fee0; + } else { + fees_ = new uint256[](1); + fees_[0] = fee1; + } + safeTransferWithFee(instaLoanVariables_, fees_, msg.sender); + } + + /** + * @dev Middle function for route 8. + * @notice Middle function for route 8. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _data extra data passed. + *@param _instadata pool key encoded + */ + function routeUniswap( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data, + bytes memory _instadata + ) internal { + PoolKey memory key = abi.decode(_instadata, (PoolKey)); + + uint256 amount0_; + uint256 amount1_; + + if (_tokens.length == 1) { + require( + (_tokens[0] == key.token0 || _tokens[0] == key.token1), + "tokens-do-not-match-pool" + ); + if (_tokens[0] == key.token0) { + amount0_ = _amounts[0]; + } else { + amount1_ = _amounts[0]; + } + } else if (_tokens.length == 2) { + require( + (_tokens[0] == key.token0 && _tokens[1] == key.token1), + "tokens-do-not-match-pool" + ); + amount0_ = _amounts[0]; + amount1_ = _amounts[1]; + } else { + revert("Number of tokens do not match"); + } + + IUniswapV3Pool pool = IUniswapV3Pool( + computeAddress(uniswapFactoryAddr, key) + ); + + bytes memory data_ = abi.encode( + _tokens, + _amounts, + msg.sender, + key, + _data + ); + dataHash = bytes32(keccak256(data_)); + pool.flash(address(this), amount0_, amount1_, data_); + } + +} \ No newline at end of file diff --git a/contracts/aggregator/polygon/flashloan/main.sol b/contracts/aggregator/polygon/flashloan/main.sol index b4323e61..fe10a7b8 100644 --- a/contracts/aggregator/polygon/flashloan/main.sol +++ b/contracts/aggregator/polygon/flashloan/main.sol @@ -29,54 +29,9 @@ contract FlashAggregatorPolygon is Helper { uint256[] memory _premiums, address _initiator, bytes memory _data - ) external verifyDataHash(_data) returns (bool) { - require(_initiator == address(this), "not-same-sender"); - require(msg.sender == aaveLendingAddr, "not-aave-sender"); - - FlashloanVariables memory instaLoanVariables_; - - (address sender_, bytes memory data_) = abi.decode( - _data, - (address, bytes) - ); - - instaLoanVariables_._tokens = _assets; - instaLoanVariables_._amounts = _amounts; - instaLoanVariables_._instaFees = calculateFees( - _amounts, - calculateFeeBPS(1) - ); - instaLoanVariables_._iniBals = calculateBalances( - _assets, - address(this) - ); - - safeApprove(instaLoanVariables_, _premiums, aaveLendingAddr); - safeTransfer(instaLoanVariables_, sender_); - - if (checkIfDsa(sender_)) { - Address.functionCall( - sender_, - data_, - "DSA-flashloan-fallback-failed" - ); - } else { - InstaFlashReceiverInterface(sender_).executeOperation( - _assets, - _amounts, - instaLoanVariables_._instaFees, - sender_, - data_ - ); - } - - instaLoanVariables_._finBals = calculateBalances( - _assets, - address(this) - ); - validateFlashloan(instaLoanVariables_); - - return true; + ) external returns (bool) { + bytes memory response_ = spell(AAVE_IMP, msg.data); + return (abi.decode(response_, (bool))); } /** @@ -91,108 +46,8 @@ contract FlashAggregatorPolygon is Helper { uint256[] memory _amounts, uint256[] memory _fees, bytes memory _data - ) external verifyDataHash(_data) { - require(msg.sender == balancerLendingAddr, "not-balancer-sender"); - - FlashloanVariables memory instaLoanVariables_; - - ( - uint256 route_, - address[] memory tokens_, - uint256[] memory amounts_, - address sender_, - bytes memory data_ - ) = abi.decode(_data, (uint256, address[], uint256[], address, bytes)); - - instaLoanVariables_._tokens = tokens_; - instaLoanVariables_._amounts = amounts_; - instaLoanVariables_._iniBals = calculateBalances( - tokens_, - address(this) - ); - instaLoanVariables_._instaFees = calculateFees( - amounts_, - calculateFeeBPS(route_) - ); - - if (route_ == 5) { - safeTransfer(instaLoanVariables_, sender_); - - if (checkIfDsa(sender_)) { - Address.functionCall( - sender_, - data_, - "DSA-flashloan-fallback-failed" - ); - } else { - InstaFlashReceiverInterface(sender_).executeOperation( - tokens_, - amounts_, - instaLoanVariables_._instaFees, - sender_, - data_ - ); - } - - instaLoanVariables_._finBals = calculateBalances( - tokens_, - address(this) - ); - validateFlashloan(instaLoanVariables_); - safeTransferWithFee( - instaLoanVariables_, - _fees, - balancerLendingAddr - ); - } else if (route_ == 7) { - require(_fees[0] == 0, "flash-ETH-fee-not-0"); - - address[] memory wEthTokenList = new address[](1); - wEthTokenList[0] = wEthToken; - - aaveSupply(wEthTokenList, _amounts); - aaveBorrow(tokens_, amounts_); - safeTransfer(instaLoanVariables_, sender_); - - if (checkIfDsa(sender_)) { - Address.functionCall( - sender_, - data_, - "DSA-flashloan-fallback-failed" - ); - } else { - InstaFlashReceiverInterface(sender_).executeOperation( - tokens_, - amounts_, - instaLoanVariables_._instaFees, - sender_, - data_ - ); - } - - aavePayback(tokens_, amounts_); - aaveWithdraw(wEthTokenList, _amounts); - instaLoanVariables_._finBals = calculateBalances( - tokens_, - address(this) - ); - validateFlashloan(instaLoanVariables_); - instaLoanVariables_._amounts = _amounts; - instaLoanVariables_._tokens = wEthTokenList; - safeTransferWithFee( - instaLoanVariables_, - _fees, - balancerLendingAddr - ); - } else { - revert("wrong-route"); - } - } - - struct UniswapFlashInfo { - address sender; - PoolKey key; - bytes data; + ) external { + spell(BALANCER_IMP, msg.data); } /** @@ -206,230 +61,8 @@ contract FlashAggregatorPolygon is Helper { uint256 fee0, uint256 fee1, bytes memory data - ) external verifyDataHash(data) { - FlashloanVariables memory instaLoanVariables_; - UniswapFlashInfo memory uniswapFlashData_; - - ( - instaLoanVariables_._tokens, - instaLoanVariables_._amounts, - uniswapFlashData_.sender, - uniswapFlashData_.key, - uniswapFlashData_.data - ) = abi.decode(data, (address[], uint256[], address, PoolKey, bytes)); - - address pool = computeAddress( - uniswapFactoryAddr, - uniswapFlashData_.key - ); - require(msg.sender == pool, "invalid-sender"); - - instaLoanVariables_._iniBals = calculateBalances( - instaLoanVariables_._tokens, - address(this) - ); - - uint256 feeBPS = uint256(uniswapFlashData_.key.fee / 100); - if (feeBPS < InstaFeeBPS) { - feeBPS = InstaFeeBPS; - } - - instaLoanVariables_._instaFees = calculateFees( - instaLoanVariables_._amounts, - feeBPS - ); - - safeTransfer(instaLoanVariables_, uniswapFlashData_.sender); - - if (checkIfDsa(uniswapFlashData_.sender)) { - Address.functionCall( - uniswapFlashData_.sender, - uniswapFlashData_.data, - "DSA-flashloan-fallback-failed" - ); - } else { - InstaFlashReceiverInterface(uniswapFlashData_.sender) - .executeOperation( - instaLoanVariables_._tokens, - instaLoanVariables_._amounts, - instaLoanVariables_._instaFees, - uniswapFlashData_.sender, - uniswapFlashData_.data - ); - } - - instaLoanVariables_._finBals = calculateBalances( - instaLoanVariables_._tokens, - address(this) - ); - - validateFlashloan(instaLoanVariables_); - - uint256[] memory fees_; - if (instaLoanVariables_._tokens.length == 2) { - fees_ = new uint256[](2); - fees_[0] = fee0; - fees_[1] = fee1; - } else if ( - instaLoanVariables_._tokens[0] == uniswapFlashData_.key.token0 - ) { - fees_ = new uint256[](1); - fees_[0] = fee0; - } else { - fees_ = new uint256[](1); - fees_[0] = fee1; - } - safeTransferWithFee(instaLoanVariables_, fees_, msg.sender); - } - - /** - * @dev Middle function for route 1. - * @notice Middle function for route 1. - * @param _tokens list of token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets or amount of ether to borrow as collateral for flashloan. - * @param _data extra data passed. - */ - function routeAave( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data - ) internal { - bytes memory data_ = abi.encode(msg.sender, _data); - uint256 length_ = _tokens.length; - uint256[] memory _modes = new uint256[](length_); - for (uint256 i = 0; i < length_; i++) { - _modes[i] = 0; - } - dataHash = bytes32(keccak256(data_)); - aaveLending.flashLoan( - address(this), - _tokens, - _amounts, - _modes, - address(0), - data_, - 3228 - ); - } - - /** - * @dev Middle function for route 5. - * @notice Middle function for route 5. - * @param _tokens token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets. - * @param _data extra data passed. - */ - function routeBalancer( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data - ) internal { - uint256 length_ = _tokens.length; - IERC20[] memory tokens_ = new IERC20[](length_); - for (uint256 i = 0; i < length_; i++) { - tokens_[i] = IERC20(_tokens[i]); - } - bytes memory data_ = abi.encode( - 5, - _tokens, - _amounts, - msg.sender, - _data - ); - dataHash = bytes32(keccak256(data_)); - balancerLending.flashLoan( - InstaFlashReceiverInterface(address(this)), - tokens_, - _amounts, - data_ - ); - } - - /** - * @dev Middle function for route 7. - * @notice Middle function for route 7. - * @param _tokens token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets. - * @param _data extra data passed. - */ - function routeBalancerAave( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data - ) internal { - bytes memory data_ = abi.encode( - 7, - _tokens, - _amounts, - msg.sender, - _data - ); - IERC20[] memory wethTokenList_ = new IERC20[](1); - uint256[] memory wethAmountList_ = new uint256[](1); - wethTokenList_[0] = IERC20(wEthToken); - wethAmountList_[0] = getWEthBorrowAmount(); - dataHash = bytes32(keccak256(data_)); - balancerLending.flashLoan( - InstaFlashReceiverInterface(address(this)), - wethTokenList_, - wethAmountList_, - data_ - ); - } - - /** - * @dev Middle function for route 8. - * @notice Middle function for route 8. - * @param _tokens token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets. - * @param _data extra data passed. - *@param _instadata pool key encoded - */ - function routeUniswap( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data, - bytes memory _instadata - ) internal { - PoolKey memory key = abi.decode(_instadata, (PoolKey)); - - uint256 amount0_; - uint256 amount1_; - - if (_tokens.length == 1) { - require( - (_tokens[0] == key.token0 || _tokens[0] == key.token1), - "tokens-do-not-match-pool" - ); - if (_tokens[0] == key.token0) { - amount0_ = _amounts[0]; - } else { - amount1_ = _amounts[0]; - } - } else if (_tokens.length == 2) { - require( - (_tokens[0] == key.token0 && _tokens[1] == key.token1), - "tokens-do-not-match-pool" - ); - amount0_ = _amounts[0]; - amount1_ = _amounts[1]; - } else { - revert("Number of tokens do not match"); - } - - IUniswapV3Pool pool = IUniswapV3Pool( - computeAddress(uniswapFactoryAddr, key) - ); - - bytes memory data_ = abi.encode( - _tokens, - _amounts, - msg.sender, - key, - _data - ); - dataHash = bytes32(keccak256(data_)); - pool.flash(address(this), amount0_, amount1_, data_); + ) external { + spell(UNISWAP_IMP, msg.data); } /** @@ -446,20 +79,18 @@ contract FlashAggregatorPolygon is Helper { uint256 _route, bytes calldata _data, bytes calldata _instadata - ) external reentrancy { + ) external { require(_tokens.length == _amounts.length, "array-lengths-not-same"); (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); if (_route == 1) { - routeAave(_tokens, _amounts, _data); - } else if (_route == 5) { - routeBalancer(_tokens, _amounts, _data); - } else if (_route == 7) { - routeBalancerAave(_tokens, _amounts, _data); + spell(AAVE_IMP, msg.data); + } else if (_route == 5 || _route == 7) { + spell(BALANCER_IMP, msg.data); } else if (_route == 8) { - routeUniswap(_tokens, _amounts, _data, _instadata); + spell(UNISWAP_IMP, msg.data); } else { revert("route-does-not-exist"); } diff --git a/contracts/aggregator/polygon/flashloan/variables.sol b/contracts/aggregator/polygon/flashloan/variables.sol index 9d533e3c..f71ffced 100644 --- a/contracts/aggregator/polygon/flashloan/variables.sol +++ b/contracts/aggregator/polygon/flashloan/variables.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import "./interfaces.sol"; +import "../../common/interface.sol"; contract ConstantVariables { address public constant aaveLendingAddr = @@ -50,4 +51,8 @@ contract Variables is ConstantVariables { address token1; uint24 fee; } + + address internal AAVE_IMP; + address internal BALANCER_IMP; + address internal UNISWAP_IMP; } From cd8a4845a462dce218758a43697769dab8b1dfdb Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 15 May 2022 17:06:48 +0400 Subject: [PATCH 12/36] code refactored --- .../aggregator/arbitrum/flashloan/helpers.sol | 83 +----------- .../arbitrum/flashloan/implBalancer/main.sol | 2 +- .../arbitrum/flashloan/implUniswap/main.sol | 2 +- .../arbitrum/flashloan/interfaces.sol | 32 ----- .../arbitrum/flashloan/variables.sol | 4 + .../avalanche/flashloan/helpers.sol | 73 +---------- .../avalanche/flashloan/implAave/main.sol | 4 +- .../avalanche/flashloan/interfaces.sol | 28 ---- .../aggregator/avalanche/flashloan/main.sol | 6 +- .../aggregator/mainnet/flashloan/helpers.sol | 121 +----------------- .../mainnet/flashloan}/implAave/main.sol | 6 +- .../mainnet/flashloan}/implBalancer/main.sol | 7 +- .../mainnet/flashloan}/implMaker/main.sol | 4 +- .../mainnet/flashloan/interfaces.sol | 32 ----- .../mainnet/flashloan/variables.sol | 1 + .../aggregator/optimism/flashloan/helpers.sol | 84 +----------- .../optimism/flashloan/implUniswap/main.sol | 4 +- .../optimism/flashloan/interfaces.sol | 32 ----- .../aggregator/polygon/flashloan/helpers.sol | 84 +----------- .../polygon/flashloan/implAave/main.sol | 2 +- .../polygon/flashloan/implBalancer/main.sol | 2 +- .../polygon/flashloan/implUniswap/main.sol | 2 +- .../polygon/flashloan/interfaces.sol | 32 ----- 23 files changed, 41 insertions(+), 606 deletions(-) rename contracts/{ => aggregator/mainnet/flashloan}/implAave/main.sol (97%) rename contracts/{ => aggregator/mainnet/flashloan}/implBalancer/main.sol (99%) rename contracts/{ => aggregator/mainnet/flashloan}/implMaker/main.sol (98%) diff --git a/contracts/aggregator/arbitrum/flashloan/helpers.sol b/contracts/aggregator/arbitrum/flashloan/helpers.sol index 1929b714..2ac4bd41 100644 --- a/contracts/aggregator/arbitrum/flashloan/helpers.sol +++ b/contracts/aggregator/arbitrum/flashloan/helpers.sol @@ -2,9 +2,10 @@ pragma solidity ^0.8.0; import "./variables.sol"; +import "../../common/helpers.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -contract Helper is Variables { +contract Helper is HelpersCommon, Variables { using SafeERC20 for IERC20; /** @@ -102,25 +103,6 @@ contract Helper is Variables { } } - /** - * @dev Calculates the balances.. - * @notice Calculates the balances of the account passed for the tokens. - * @param _tokens list of token addresses to calculate balance for. - * @param _account account to calculate balance for. - */ - function calculateBalances(address[] memory _tokens, address _account) - internal - view - returns (uint256[] memory) - { - uint256 _length = _tokens.length; - uint256[] memory balances_ = new uint256[](_length); - for (uint256 i = 0; i < _length; i++) { - IERC20 token = IERC20(_tokens[i]); - balances_[i] = token.balanceOf(_account); - } - return balances_; - } /** * @dev Validates if the receiver sent the correct amounts of funds. @@ -141,17 +123,6 @@ contract Helper is Variables { } } - /** - * @dev Validates if token addresses are unique. Just need to check adjacent tokens as the array was sorted first - * @notice Validates if token addresses are unique. - * @param _tokens list of token addresses. - */ - function validateTokens(address[] memory _tokens) internal pure { - for (uint256 i = 0; i < _tokens.length - 1; i++) { - require(_tokens[i] != _tokens[i + 1], "non-unique-tokens"); - } - } - /** * @dev Returns fee for the passed route in BPS. * @notice Returns fee for the passed route in BPS. 1 BPS == 0.01%. @@ -179,56 +150,6 @@ contract Helper is Variables { } } - /** - * @dev Calculate fees for the respective amounts and fee in BPS passed. - * @notice Calculate fees for the respective amounts and fee in BPS passed. 1 BPS == 0.01%. - * @param _amounts list of amounts. - * @param _BPS fee in BPS. - */ - function calculateFees(uint256[] memory _amounts, uint256 _BPS) - internal - pure - returns (uint256[] memory) - { - uint256 length_ = _amounts.length; - uint256[] memory InstaFees = new uint256[](length_); - for (uint256 i = 0; i < length_; i++) { - InstaFees[i] = (_amounts[i] * _BPS) / (10**4); - } - return InstaFees; - } - - /** - * @dev Sort the tokens and amounts arrays according to token addresses. - * @notice Sort the tokens and amounts arrays according to token addresses. - * @param _tokens list of token addresses. - * @param _amounts list of respective amounts. - */ - function bubbleSort(address[] memory _tokens, uint256[] memory _amounts) - internal - pure - returns (address[] memory, uint256[] memory) - { - for (uint256 i = 0; i < _tokens.length - 1; i++) { - for (uint256 j = 0; j < _tokens.length - i - 1; j++) { - if (_tokens[j] > _tokens[j + 1]) { - ( - _tokens[j], - _tokens[j + 1], - _amounts[j], - _amounts[j + 1] - ) = ( - _tokens[j + 1], - _tokens[j], - _amounts[j + 1], - _amounts[j] - ); - } - } - } - return (_tokens, _amounts); - } - /** * @dev Returns to true if the passed address is a DSA else returns false. * @notice Returns to true if the passed address is a DSA else returns false. diff --git a/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol b/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol index 849a2e15..df36e67b 100644 --- a/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol +++ b/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol @@ -19,7 +19,7 @@ contract BalancerImplementation is Helper { bytes calldata _data, bytes memory _instadata ) external reentrancy { - require(_route == 5 , "invalid BALANCER flashloan route"); + require(_route == 5 , "invalid-BALANCER-route"); routeBalancer(_tokens, _amounts, _data); } diff --git a/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol b/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol index a6d1c759..00327815 100644 --- a/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol +++ b/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol @@ -19,7 +19,7 @@ contract UniswapImplementation is Helper { bytes calldata _data, bytes memory _instadata ) external reentrancy { - require(_route == 8, "invalid UNISWAP flashloan route"); + require(_route == 8, "invalid-UNISWAP-route"); routeUniswap(_tokens, _amounts, _data, _instadata); } diff --git a/contracts/aggregator/arbitrum/flashloan/interfaces.sol b/contracts/aggregator/arbitrum/flashloan/interfaces.sol index 7c6dbacb..333d9a63 100644 --- a/contracts/aggregator/arbitrum/flashloan/interfaces.sol +++ b/contracts/aggregator/arbitrum/flashloan/interfaces.sol @@ -12,38 +12,6 @@ interface InstaFlashReceiverInterface { ) external returns (bool); } -interface IndexInterface { - function master() external view returns (address); - - function list() external view returns (address); -} - -interface ListInterface { - function accountID(address) external view returns (uint64); -} - -interface TokenInterface { - function approve(address, uint256) external; - - function transfer(address, uint256) external; - - function transferFrom( - address, - address, - uint256 - ) external; - - function deposit() external payable; - - function withdraw(uint256) external; - - function balanceOf(address) external view returns (uint256); - - function decimals() external view returns (uint256); - - function totalSupply() external view returns (uint256); -} - interface ProtocolFeesCollector { function getFlashLoanFeePercentage() external view returns (uint256); } diff --git a/contracts/aggregator/arbitrum/flashloan/variables.sol b/contracts/aggregator/arbitrum/flashloan/variables.sol index f790c033..2cd3d413 100644 --- a/contracts/aggregator/arbitrum/flashloan/variables.sol +++ b/contracts/aggregator/arbitrum/flashloan/variables.sol @@ -1,6 +1,7 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import "../../common/interface.sol"; import "./interfaces.sol"; contract ConstantVariables { @@ -43,4 +44,7 @@ contract Variables is ConstantVariables { address token1; uint24 fee; } + + address internal BALANCER_IMP; + address internal UNISWAP_IMP; } diff --git a/contracts/aggregator/avalanche/flashloan/helpers.sol b/contracts/aggregator/avalanche/flashloan/helpers.sol index 779c45f1..d3e80cd2 100644 --- a/contracts/aggregator/avalanche/flashloan/helpers.sol +++ b/contracts/aggregator/avalanche/flashloan/helpers.sol @@ -2,16 +2,13 @@ pragma solidity ^0.8.0; import {Variables} from "./variables.sol"; - +import "../../common/helpers.sol"; +import "./interfaces.sol"; +import "../../common/interface.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { - TokenInterface, - InstaFlashReceiverInterface -} from "./interfaces.sol"; - -contract Helper is Variables { +contract Helper is HelpersCommon, Variables { using SafeERC20 for IERC20; /** @@ -70,25 +67,6 @@ contract Helper is Variables { } } - /** - * @dev Calculates the balances.. - * @notice Calculates the balances of the account passed for the tokens. - * @param _tokens list of token addresses to calculate balance for. - * @param _account account to calculate balance for. - */ - function calculateBalances( - address[] memory _tokens, - address _account - ) internal view returns (uint256[] memory) { - uint256 _length = _tokens.length; - uint256[] memory balances_ = new uint256[](_length); - for (uint i = 0; i < _length; i++) { - IERC20 token = IERC20(_tokens[i]); - balances_[i] = token.balanceOf(_account); - } - return balances_; - } - /** * @dev Validates if the receiver sent the correct amounts of funds. * @notice Validates if the receiver sent the correct amounts of funds. @@ -102,17 +80,6 @@ contract Helper is Variables { } } - /** - * @dev Validates if token addresses are unique. Just need to check adjacent tokens as the array was sorted first - * @notice Validates if token addresses are unique. - * @param _tokens list of token addresses. - */ - function validateTokens(address[] memory _tokens) internal pure { - for (uint i = 0; i < _tokens.length - 1; i++) { - require(_tokens[i] != _tokens[i+1], "non-unique-tokens"); - } - } - /** * @dev Returns fee for the passed route in BPS. * @notice Returns fee for the passed route in BPS. 1 BPS == 0.01%. @@ -130,38 +97,6 @@ contract Helper is Variables { } } - /** - * @dev Calculate fees for the respective amounts and fee in BPS passed. - * @notice Calculate fees for the respective amounts and fee in BPS passed. 1 BPS == 0.01%. - * @param _amounts list of amounts. - * @param _BPS fee in BPS. - */ - function calculateFees(uint256[] memory _amounts, uint256 _BPS) internal pure returns (uint256[] memory) { - uint256 length_ = _amounts.length; - uint256[] memory InstaFees = new uint256[](length_); - for (uint i = 0; i < length_; i++) { - InstaFees[i] = (_amounts[i] * _BPS) / (10 ** 4); - } - return InstaFees; - } - - /** - * @dev Sort the tokens and amounts arrays according to token addresses. - * @notice Sort the tokens and amounts arrays according to token addresses. - * @param _tokens list of token addresses. - * @param _amounts list of respective amounts. - */ - function bubbleSort(address[] memory _tokens, uint256[] memory _amounts) internal pure returns (address[] memory, uint256[] memory) { - for (uint256 i = 0; i < _tokens.length - 1; i++) { - for( uint256 j = 0; j < _tokens.length - i - 1 ; j++) { - if(_tokens[j] > _tokens[j+1]) { - (_tokens[j], _tokens[j+1], _amounts[j], _amounts[j+1]) = (_tokens[j+1], _tokens[j], _amounts[j+1], _amounts[j]); - } - } - } - return (_tokens, _amounts); - } - /** * @dev Returns to true if the passed address is a DSA else returns false. * @notice Returns to true if the passed address is a DSA else returns false. diff --git a/contracts/aggregator/avalanche/flashloan/implAave/main.sol b/contracts/aggregator/avalanche/flashloan/implAave/main.sol index 7ce12001..9916abfa 100644 --- a/contracts/aggregator/avalanche/flashloan/implAave/main.sol +++ b/contracts/aggregator/avalanche/flashloan/implAave/main.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "../helpers.sol"; -contract BalancerImplementation is Helper { +contract AaveImplementation is Helper { /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -20,7 +20,7 @@ contract BalancerImplementation is Helper { bytes calldata _data, bytes calldata // kept for future use by instadapp. Currently not used anywhere. ) external reentrancy { - require(_route == 1, "invalid AAVE route"); + require(_route == 1, "invalid-AAVE-route"); routeAave(_tokens, _amounts, _data); } diff --git a/contracts/aggregator/avalanche/flashloan/interfaces.sol b/contracts/aggregator/avalanche/flashloan/interfaces.sol index 5c226c95..61279c6e 100644 --- a/contracts/aggregator/avalanche/flashloan/interfaces.sol +++ b/contracts/aggregator/avalanche/flashloan/interfaces.sol @@ -12,34 +12,6 @@ interface InstaFlashReceiverInterface { ) external returns (bool); } -interface IndexInterface { - function master() external view returns (address); - - function list() external view returns (address); -} - -interface ListInterface { - function accountID(address) external view returns (uint64); -} - -interface TokenInterface { - function approve(address, uint256) external; - - function transfer(address, uint) external; - - function transferFrom(address, address, uint) external; - - function deposit() external payable; - - function withdraw(uint) external; - - function balanceOf(address) external view returns (uint256); - - function decimals() external view returns (uint256); - - function totalSupply() external view returns (uint256); -} - interface IAaveLending { function flashLoan( address receiverAddress, diff --git a/contracts/aggregator/avalanche/flashloan/main.sol b/contracts/aggregator/avalanche/flashloan/main.sol index 383d1452..f8b98242 100644 --- a/contracts/aggregator/avalanche/flashloan/main.sol +++ b/contracts/aggregator/avalanche/flashloan/main.sol @@ -6,9 +6,7 @@ pragma solidity ^0.8.0; * @dev Flashloan aggregator. */ -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; import { Helper } from "./helpers.sol"; import { InstaFlashReceiverInterface } from "./interfaces.sol"; import { TokenInterface } from "../../common/interface.sol"; @@ -39,8 +37,8 @@ contract FlashAggregatorAvalanche is Helper { address _initiator, bytes memory _data ) external returns (bool) { - bytes memory response = spell(AAVE_IMP, msg.data); - return (abi.decode(response, (bool))); + bytes memory response_ = spell(AAVE_IMP, msg.data); + return (abi.decode(response_, (bool))); } /** diff --git a/contracts/aggregator/mainnet/flashloan/helpers.sol b/contracts/aggregator/mainnet/flashloan/helpers.sol index 3b53b13a..6fb8ae4d 100644 --- a/contracts/aggregator/mainnet/flashloan/helpers.sol +++ b/contracts/aggregator/mainnet/flashloan/helpers.sol @@ -2,50 +2,24 @@ pragma solidity ^0.8.0; import "./variables.sol"; +import "../../common/helpers.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -contract Helper is Variables { +contract Helper is HelpersCommon, Variables { using SafeERC20 for IERC20; - /** - * @dev Delegate the calls to Connector. - * @param _target Connector address - * @param _data CallData of function. - */ - function spell(address _target, bytes memory _data) internal returns (bytes memory response) { - require(_target != address(0), "target-invalid"); - assembly { - let succeeded := delegatecall(gas(), _target, add(_data, 0x20), mload(_data), 0, 0) - let size := returndatasize() - - response := mload(0x40) - mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f)))) - mstore(response, size) - returndatacopy(add(response, 0x20), 0, size) - - switch iszero(succeeded) - case 1 { - // throw if delegatecall failed - returndatacopy(0x00, 0x00, size) - revert(0x00, size) - } - } - } - /** * @dev Approves the token to the spender address with allowance amount. * @notice Approves the token to the spender address with allowance amount. * @param token_ token for which allowance is to be given. * @param spender_ the address to which the allowance is to be given. * @param amount_ amount of token. - */ - function approve( - address token_, - address spender_, - uint256 amount_ - ) internal { + */ + function approve(address token_, address spender_, uint256 amount_) internal { TokenInterface tokenContract_ = TokenInterface(token_); - try tokenContract_.approve(spender_, amount_) {} catch { + try tokenContract_.approve(spender_, amount_) { + + } catch { IERC20 token = IERC20(token_); token.safeApprove(spender_, 0); token.safeApprove(spender_, amount_); @@ -127,26 +101,6 @@ contract Helper is Variables { } } - /** - * @dev Calculates the balances.. - * @notice Calculates the balances of the account passed for the tokens. - * @param _tokens list of token addresses to calculate balance for. - * @param _account account to calculate balance for. - */ - function calculateBalances(address[] memory _tokens, address _account) - internal - view - returns (uint256[] memory) - { - uint256 _length = _tokens.length; - uint256[] memory balances_ = new uint256[](_length); - for (uint256 i = 0; i < _length; i++) { - IERC20 token = IERC20(_tokens[i]); - balances_[i] = token.balanceOf(_account); - } - return balances_; - } - /** * @dev Validates if the receiver sent the correct amounts of funds. * @notice Validates if the receiver sent the correct amounts of funds. @@ -166,17 +120,6 @@ contract Helper is Variables { } } - /** - * @dev Validates if token addresses are unique. Just need to check adjacent tokens as the array was sorted first - * @notice Validates if token addresses are unique. - * @param _tokens list of token addresses. - */ - function validateTokens(address[] memory _tokens) internal pure { - for (uint256 i = 0; i < _tokens.length - 1; i++) { - require(_tokens[i] != _tokens[i + 1], "non-unique-tokens"); - } - } - /** * @dev Supply tokens for the amounts to compound. * @notice Supply tokens for the amounts to compound. @@ -388,56 +331,6 @@ contract Helper is Variables { } } - /** - * @dev Calculate fees for the respective amounts and fee in BPS passed. - * @notice Calculate fees for the respective amounts and fee in BPS passed. 1 BPS == 0.01%. - * @param _amounts list of amounts. - * @param _BPS fee in BPS. - */ - function calculateFees(uint256[] memory _amounts, uint256 _BPS) - internal - pure - returns (uint256[] memory) - { - uint256 length_ = _amounts.length; - uint256[] memory InstaFees = new uint256[](length_); - for (uint256 i = 0; i < length_; i++) { - InstaFees[i] = (_amounts[i] * _BPS) / (10**4); - } - return InstaFees; - } - - /** - * @dev Sort the tokens and amounts arrays according to token addresses. - * @notice Sort the tokens and amounts arrays according to token addresses. - * @param _tokens list of token addresses. - * @param _amounts list of respective amounts. - */ - function bubbleSort(address[] memory _tokens, uint256[] memory _amounts) - internal - pure - returns (address[] memory, uint256[] memory) - { - for (uint256 i = 0; i < _tokens.length - 1; i++) { - for (uint256 j = 0; j < _tokens.length - i - 1; j++) { - if (_tokens[j] > _tokens[j + 1]) { - ( - _tokens[j], - _tokens[j + 1], - _amounts[j], - _amounts[j + 1] - ) = ( - _tokens[j + 1], - _tokens[j], - _amounts[j + 1], - _amounts[j] - ); - } - } - } - return (_tokens, _amounts); - } - /** * @dev Returns to wEth amount to be borrowed. * @notice Returns to wEth amount to be borrowed. diff --git a/contracts/implAave/main.sol b/contracts/aggregator/mainnet/flashloan/implAave/main.sol similarity index 97% rename from contracts/implAave/main.sol rename to contracts/aggregator/mainnet/flashloan/implAave/main.sol index 053dca25..09359d83 100644 --- a/contracts/implAave/main.sol +++ b/contracts/aggregator/mainnet/flashloan/implAave/main.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "../aggregator/mainnet/flashloan/helpers.sol"; +import "../helpers.sol"; contract AaveImplementation is Helper { @@ -19,7 +19,7 @@ contract AaveImplementation is Helper { bytes calldata _data, bytes calldata // kept for future use by instadapp. Currently not used anywhere. ) external reentrancy { - require(_route == 1, "invalid AAVE flashloan route"); + require(_route == 1, "invalid-AAVE-route"); routeAave(_tokens, _amounts, _data); } @@ -117,4 +117,4 @@ contract AaveImplementation is Helper { 3228 ); } -} \ No newline at end of file +} diff --git a/contracts/implBalancer/main.sol b/contracts/aggregator/mainnet/flashloan/implBalancer/main.sol similarity index 99% rename from contracts/implBalancer/main.sol rename to contracts/aggregator/mainnet/flashloan/implBalancer/main.sol index cb7bf0c9..e13185d0 100644 --- a/contracts/implBalancer/main.sol +++ b/contracts/aggregator/mainnet/flashloan/implBalancer/main.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "../aggregator/mainnet/flashloan/helpers.sol"; +import "../helpers.sol"; contract BalancerImplementation is Helper { @@ -19,7 +19,7 @@ contract BalancerImplementation is Helper { bytes calldata _data, bytes calldata // kept for future use by instadapp. Currently not used anywhere. ) external reentrancy { - require(_route == 5 || _route == 6 || _route == 7, "invalid BALANCER flashloan route"); + require(_route == 5 || _route == 6 || _route == 7, "invalid-BALANCER-route"); if (_route == 5) { routeBalancer(_tokens, _amounts, _data); @@ -265,5 +265,4 @@ contract BalancerImplementation is Helper { data_ ); } - -} \ No newline at end of file +} diff --git a/contracts/implMaker/main.sol b/contracts/aggregator/mainnet/flashloan/implMaker/main.sol similarity index 98% rename from contracts/implMaker/main.sol rename to contracts/aggregator/mainnet/flashloan/implMaker/main.sol index c0565e2e..1586e21c 100644 --- a/contracts/implMaker/main.sol +++ b/contracts/aggregator/mainnet/flashloan/implMaker/main.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "../aggregator/mainnet/flashloan/helpers.sol"; +import "../helpers.sol"; contract MakerImplementation is Helper { @@ -19,7 +19,7 @@ contract MakerImplementation is Helper { bytes calldata _data, bytes calldata // kept for future use by instadapp. Currently not used anywhere. ) external reentrancy { - require((_route == 2 || _route == 3 || _route == 4), "invalid MAKER flashloan route"); + require((_route == 2 || _route == 3 || _route == 4), "invalid-MAKER-route"); if (_route == 2) { routeMaker(_tokens[0], _amounts[0], _data); diff --git a/contracts/aggregator/mainnet/flashloan/interfaces.sol b/contracts/aggregator/mainnet/flashloan/interfaces.sol index 9516f055..4d3f4d70 100644 --- a/contracts/aggregator/mainnet/flashloan/interfaces.sol +++ b/contracts/aggregator/mainnet/flashloan/interfaces.sol @@ -13,38 +13,6 @@ interface InstaFlashReceiverInterface { ) external returns (bool); } -interface IndexInterface { - function master() external view returns (address); - - function list() external view returns (address); -} - -interface ListInterface { - function accountID(address) external view returns (uint64); -} - -interface TokenInterface { - function approve(address, uint256) external; - - function transfer(address, uint256) external; - - function transferFrom( - address, - address, - uint256 - ) external; - - function deposit() external payable; - - function withdraw(uint256) external; - - function balanceOf(address) external view returns (uint256); - - function decimals() external view returns (uint256); - - function totalSupply() external view returns (uint256); -} - interface CTokenInterface { function mint(uint256) external returns (uint256); diff --git a/contracts/aggregator/mainnet/flashloan/variables.sol b/contracts/aggregator/mainnet/flashloan/variables.sol index 1dfbf80e..b97fa14c 100644 --- a/contracts/aggregator/mainnet/flashloan/variables.sol +++ b/contracts/aggregator/mainnet/flashloan/variables.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import "./interfaces.sol"; +import "../../common/interface.sol"; contract ConstantVariables { IWeth internal constant wethToken = diff --git a/contracts/aggregator/optimism/flashloan/helpers.sol b/contracts/aggregator/optimism/flashloan/helpers.sol index ebb04218..a4d92c3e 100644 --- a/contracts/aggregator/optimism/flashloan/helpers.sol +++ b/contracts/aggregator/optimism/flashloan/helpers.sol @@ -2,9 +2,10 @@ pragma solidity ^0.8.0; import "./variables.sol"; +import "../../common/helpers.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -contract Helper is Variables { +contract Helper is HelpersCommon, Variables { using SafeERC20 for IERC20; /** @@ -102,26 +103,6 @@ contract Helper is Variables { } } - /** - * @dev Calculates the balances.. - * @notice Calculates the balances of the account passed for the tokens. - * @param _tokens list of token addresses to calculate balance for. - * @param _account account to calculate balances for. - */ - function calculateBalances(address[] memory _tokens, address _account) - internal - view - returns (uint256[] memory) - { - uint256 _length = _tokens.length; - uint256[] memory balances_ = new uint256[](_length); - for (uint256 i = 0; i < _length; i++) { - IERC20 token = IERC20(_tokens[i]); - balances_[i] = token.balanceOf(_account); - } - return balances_; - } - /** * @dev Validates if the receiver sent the correct amounts of funds. * @notice Validates if the receiver sent the correct amounts of funds. @@ -141,67 +122,6 @@ contract Helper is Variables { } } - /** - * @dev Validates if token addresses are unique. Just need to check adjacent tokens as the array was sorted first - * @notice Validates if token addresses are unique. - * @param _tokens list of token addresses. - */ - function validateTokens(address[] memory _tokens) internal pure { - for (uint256 i = 0; i < _tokens.length - 1; i++) { - require(_tokens[i] != _tokens[i + 1], "non-unique-tokens"); - } - } - - /** - * @dev Calculate fees for the respective amounts and fee in BPS passed. - * @notice Calculate fees for the respective amounts and fee in BPS passed. 1 BPS == 0.01%. - * @param _amounts list of amounts. - * @param _BPS fee in BPS. - */ - function calculateFees(uint256[] memory _amounts, uint256 _BPS) - internal - pure - returns (uint256[] memory) - { - uint256 length_ = _amounts.length; - uint256[] memory InstaFees = new uint256[](length_); - for (uint256 i = 0; i < length_; i++) { - InstaFees[i] = (_amounts[i] * _BPS) / (10**4); - } - return InstaFees; - } - - /** - * @dev Sort the tokens and amounts arrays according to token addresses. - * @notice Sort the tokens and amounts arrays according to token addresses. - * @param _tokens list of token addresses. - * @param _amounts list of respective amounts. - */ - function bubbleSort(address[] memory _tokens, uint256[] memory _amounts) - internal - pure - returns (address[] memory, uint256[] memory) - { - for (uint256 i = 0; i < _tokens.length - 1; i++) { - for (uint256 j = 0; j < _tokens.length - i - 1; j++) { - if (_tokens[j] > _tokens[j + 1]) { - ( - _tokens[j], - _tokens[j + 1], - _amounts[j], - _amounts[j + 1] - ) = ( - _tokens[j + 1], - _tokens[j], - _amounts[j + 1], - _amounts[j] - ); - } - } - } - return (_tokens, _amounts); - } - /** * @dev Returns to true if the passed address is a DSA else returns false. * @notice Returns to true if the passed address is a DSA else returns false. diff --git a/contracts/aggregator/optimism/flashloan/implUniswap/main.sol b/contracts/aggregator/optimism/flashloan/implUniswap/main.sol index ab09c402..d69fd98b 100644 --- a/contracts/aggregator/optimism/flashloan/implUniswap/main.sol +++ b/contracts/aggregator/optimism/flashloan/implUniswap/main.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "../helpers.sol"; -contract BalancerImplementation is Helper { +contract UniswapImplementation is Helper { /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -20,7 +20,7 @@ contract BalancerImplementation is Helper { bytes calldata _data, bytes calldata _instadata ) external reentrancy { - require(_route == 8, "invalid route for Uniswap"); + require(_route == 8, "invalid-UNISWAP-route"); routeUniswap(_tokens, _amounts, _data, _instadata); } diff --git a/contracts/aggregator/optimism/flashloan/interfaces.sol b/contracts/aggregator/optimism/flashloan/interfaces.sol index 0a8c4c3d..5e63eebb 100644 --- a/contracts/aggregator/optimism/flashloan/interfaces.sol +++ b/contracts/aggregator/optimism/flashloan/interfaces.sol @@ -12,38 +12,6 @@ interface InstaFlashReceiverInterface { ) external returns (bool); } -interface IndexInterface { - function master() external view returns (address); - - function list() external view returns (address); -} - -interface ListInterface { - function accountID(address) external view returns (uint64); -} - -interface TokenInterface { - function approve(address, uint256) external; - - function transfer(address, uint256) external; - - function transferFrom( - address, - address, - uint256 - ) external; - - function deposit() external payable; - - function withdraw(uint256) external; - - function balanceOf(address) external view returns (uint256); - - function decimals() external view returns (uint256); - - function totalSupply() external view returns (uint256); -} - interface IUniswapV3Pool { function flash( address recipient, diff --git a/contracts/aggregator/polygon/flashloan/helpers.sol b/contracts/aggregator/polygon/flashloan/helpers.sol index 2f18ce0d..d1eeb83f 100644 --- a/contracts/aggregator/polygon/flashloan/helpers.sol +++ b/contracts/aggregator/polygon/flashloan/helpers.sol @@ -2,10 +2,11 @@ pragma solidity ^0.8.0; import "./variables.sol"; +import "../../common/helpers.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -contract Helper is Variables { +contract Helper is HelpersCommon, Variables { using SafeERC20 for IERC20; /** @@ -103,26 +104,6 @@ contract Helper is Variables { } } - /** - * @dev Calculates the balances.. - * @notice Calculates the balances of the account passed for the tokens. - * @param _tokens list of token addresses to calculate balance for. - * @param _account account to calculate balance for. - */ - function calculateBalances(address[] memory _tokens, address _account) - internal - view - returns (uint256[] memory) - { - uint256 _length = _tokens.length; - uint256[] memory balances_ = new uint256[](_length); - for (uint256 i = 0; i < _length; i++) { - IERC20 token = IERC20(_tokens[i]); - balances_[i] = token.balanceOf(_account); - } - return balances_; - } - /** * @dev Validates if the receiver sent the correct amounts of funds. * @notice Validates if the receiver sent the correct amounts of funds. @@ -142,17 +123,6 @@ contract Helper is Variables { } } - /** - * @dev Validates if token addresses are unique. Just need to check adjacent tokens as the array was sorted first - * @notice Validates if token addresses are unique. - * @param _tokens list of token addresses. - */ - function validateTokens(address[] memory _tokens) internal pure { - for (uint256 i = 0; i < _tokens.length - 1; i++) { - require(_tokens[i] != _tokens[i + 1], "non-unique-tokens"); - } - } - /** * @dev Supply tokens to aave. * @notice Supply tokens to aave. @@ -249,56 +219,6 @@ contract Helper is Variables { } } - /** - * @dev Calculate fees for the respective amounts and fee in BPS passed. - * @notice Calculate fees for the respective amounts and fee in BPS passed. 1 BPS == 0.01%. - * @param _amounts list of amounts. - * @param _BPS fee in BPS. - */ - function calculateFees(uint256[] memory _amounts, uint256 _BPS) - internal - pure - returns (uint256[] memory) - { - uint256 length_ = _amounts.length; - uint256[] memory InstaFees = new uint256[](length_); - for (uint256 i = 0; i < length_; i++) { - InstaFees[i] = (_amounts[i] * _BPS) / (10**4); - } - return InstaFees; - } - - /** - * @dev Sort the tokens and amounts arrays according to token addresses. - * @notice Sort the tokens and amounts arrays according to token addresses. - * @param _tokens list of token addresses. - * @param _amounts list of respective amounts. - */ - function bubbleSort(address[] memory _tokens, uint256[] memory _amounts) - internal - pure - returns (address[] memory, uint256[] memory) - { - for (uint256 i = 0; i < _tokens.length - 1; i++) { - for (uint256 j = 0; j < _tokens.length - i - 1; j++) { - if (_tokens[j] > _tokens[j + 1]) { - ( - _tokens[j], - _tokens[j + 1], - _amounts[j], - _amounts[j + 1] - ) = ( - _tokens[j + 1], - _tokens[j], - _amounts[j + 1], - _amounts[j] - ); - } - } - } - return (_tokens, _amounts); - } - /** * @dev Returns to wEth amount to be borrowed. * @notice Returns to wEth amount to be borrowed. diff --git a/contracts/aggregator/polygon/flashloan/implAave/main.sol b/contracts/aggregator/polygon/flashloan/implAave/main.sol index be4c8f60..282e23c1 100644 --- a/contracts/aggregator/polygon/flashloan/implAave/main.sol +++ b/contracts/aggregator/polygon/flashloan/implAave/main.sol @@ -20,7 +20,7 @@ contract AaveImplementation is Helper { bytes calldata _data, bytes calldata _instadata ) external reentrancy { - require(_route == 1, "invalid route for Aave"); + require(_route == 1, "invalid-AAVE-route"); routeAave(_tokens, _amounts, _data); } diff --git a/contracts/aggregator/polygon/flashloan/implBalancer/main.sol b/contracts/aggregator/polygon/flashloan/implBalancer/main.sol index 473b3e1e..825ebbf4 100644 --- a/contracts/aggregator/polygon/flashloan/implBalancer/main.sol +++ b/contracts/aggregator/polygon/flashloan/implBalancer/main.sol @@ -20,7 +20,7 @@ contract BalancerImplementation is Helper { bytes calldata _data, bytes calldata _instadata ) external reentrancy { - require(_route == 5 || _route == 7, "inavlid route for BALANCER"); + require(_route == 5 || _route == 7, "invalid-BALANCER-route"); if (_route == 5) { routeBalancer(_tokens, _amounts, _data); diff --git a/contracts/aggregator/polygon/flashloan/implUniswap/main.sol b/contracts/aggregator/polygon/flashloan/implUniswap/main.sol index 1f17d788..65750f06 100644 --- a/contracts/aggregator/polygon/flashloan/implUniswap/main.sol +++ b/contracts/aggregator/polygon/flashloan/implUniswap/main.sol @@ -20,7 +20,7 @@ contract UniswapImplementation is Helper { bytes calldata _data, bytes calldata _instadata ) external reentrancy { - require(_route == 8, "invalid route for UNISWAP"); + require(_route == 8, "invalid-UNISWAP-route"); routeUniswap(_tokens, _amounts, _data, _instadata); } diff --git a/contracts/aggregator/polygon/flashloan/interfaces.sol b/contracts/aggregator/polygon/flashloan/interfaces.sol index 866c7d12..94cae8b6 100644 --- a/contracts/aggregator/polygon/flashloan/interfaces.sol +++ b/contracts/aggregator/polygon/flashloan/interfaces.sol @@ -12,38 +12,6 @@ interface InstaFlashReceiverInterface { ) external returns (bool); } -interface IndexInterface { - function master() external view returns (address); - - function list() external view returns (address); -} - -interface ListInterface { - function accountID(address) external view returns (uint64); -} - -interface TokenInterface { - function approve(address, uint256) external; - - function transfer(address, uint256) external; - - function transferFrom( - address, - address, - uint256 - ) external; - - function deposit() external payable; - - function withdraw(uint256) external; - - function balanceOf(address) external view returns (uint256); - - function decimals() external view returns (uint256); - - function totalSupply() external view returns (uint256); -} - interface IAaveLending { function flashLoan( address receiverAddress, From 7c7e650f7d9a6487192688cb962b62dff7d8e4b5 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 19 May 2022 16:57:44 +0530 Subject: [PATCH 13/36] arbitrum updates + testcases --- .../arbitrum/flashloan/implBalancer/main.sol | 2 +- .../arbitrum/flashloan/implUniswap/main.sol | 2 +- .../aggregator/arbitrum/flashloan/main.sol | 16 +- .../arbitrum/flashloan/variables.sol | 4 +- test/arbitrum/newFlashloan.ts | 202 ++++++++++++++++++ 5 files changed, 216 insertions(+), 10 deletions(-) create mode 100644 test/arbitrum/newFlashloan.ts diff --git a/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol b/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol index df36e67b..21ed405d 100644 --- a/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol +++ b/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import "../helpers.sol"; -contract BalancerImplementation is Helper { +contract BalancerImplementationArbitrum is Helper { /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. diff --git a/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol b/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol index 00327815..a4934469 100644 --- a/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol +++ b/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import "../helpers.sol"; -contract UniswapImplementation is Helper { +contract UniswapImplementationArbitrum is Helper { /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. diff --git a/contracts/aggregator/arbitrum/flashloan/main.sol b/contracts/aggregator/arbitrum/flashloan/main.sol index c96d8c6c..3ce047dd 100644 --- a/contracts/aggregator/arbitrum/flashloan/main.sol +++ b/contracts/aggregator/arbitrum/flashloan/main.sol @@ -1,8 +1,6 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; - import "./helpers.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; contract FlashAggregatorArbitrum is Helper { using SafeERC20 for IERC20; @@ -27,7 +25,7 @@ contract FlashAggregatorArbitrum is Helper { uint256[] memory _fees, bytes memory _data ) external { - spell(BALANCER_IMP, msg.data); + spell(BALANCER_IMPL, msg.data); } /** @@ -42,7 +40,7 @@ contract FlashAggregatorArbitrum is Helper { uint256 fee1, bytes memory data ) external { - spell(UNISWAP_IMP, msg.data); + spell(UNISWAP_IMPL, msg.data); } /** @@ -66,9 +64,9 @@ contract FlashAggregatorArbitrum is Helper { validateTokens(_tokens); if (_route == 5) { - spell(BALANCER_IMP, msg.data); + spell(BALANCER_IMPL, msg.data); } else if (_route == 8) { - spell(UNISWAP_IMP, msg.data); + spell(UNISWAP_IMPL, msg.data); } else { revert("route-does-not-exist"); } @@ -118,5 +116,11 @@ contract InstaFlashAggregatorArbitrum is FlashAggregatorArbitrum { // status = 1; // } + + function initialize(address bImp, address uImp) public { + BALANCER_IMPL = bImp; + UNISWAP_IMPL = uImp; + } + receive() external payable {} } diff --git a/contracts/aggregator/arbitrum/flashloan/variables.sol b/contracts/aggregator/arbitrum/flashloan/variables.sol index 2cd3d413..5649b65c 100644 --- a/contracts/aggregator/arbitrum/flashloan/variables.sol +++ b/contracts/aggregator/arbitrum/flashloan/variables.sol @@ -45,6 +45,6 @@ contract Variables is ConstantVariables { uint24 fee; } - address internal BALANCER_IMP; - address internal UNISWAP_IMP; + address internal BALANCER_IMPL; + address internal UNISWAP_IMPL; } diff --git a/test/arbitrum/newFlashloan.ts b/test/arbitrum/newFlashloan.ts new file mode 100644 index 00000000..88a4b763 --- /dev/null +++ b/test/arbitrum/newFlashloan.ts @@ -0,0 +1,202 @@ +const hre = require('hardhat') +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +const { ethers } = hre + +import { + BalancerImplementationArbitrum__factory, + UniswapImplementationArbitrum__factory, + InstaFlashAggregatorProxy__factory, + IERC20__factory, + InstaFlashReceiver__factory, + InstaFlashReceiver, + InstaFlashAggregatorArbitrum__factory, + } from '../../typechain' + + describe('FlashLoan', function () { + let Aggregator, + aggregator, + Receiver, + receiver: InstaFlashReceiver, + BalancerImp, + UniswapImp, + balancerImpl, + uniswapImpl, + proxyAddr = "0x1f882522DF99820dF8e586b6df8bAae2b91a782d", + admin = "0x82D57efa1cE59A0cA3492e189c72B360c7a1Dcdd", + adminSigner; + + let signer: SignerWithAddress + + const master = '0xa8c31E39e40E6765BEdBd83D92D6AA0B33f1CCC5' + const aaveLendingAddr = '0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9' + + let iface = new ethers.utils.Interface(["function initialize(address bImp,address uImp)"]); + + const USDC = "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8"; + const USDT = "0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9"; + const ACC_USDC = "0xce2cc46682e9c6d5f174af598fb4931a9c0be68e"; + const ACC_USDT = "0x0db3fe3b770c95a0b99d1ed6f2627933466c0dd8"; + + const usdc = ethers.utils.parseUnits("10", 6); + const usdt = ethers.utils.parseUnits("10", 6); + const Usdc = ethers.utils.parseUnits("5000", 6); + const Usdt = ethers.utils.parseUnits("5000", 6); + + const _data = '0x' + + let _instaData = '0x' + + beforeEach('Should set up', async function () { + ;[signer] = await ethers.getSigners() + + Aggregator = new InstaFlashAggregatorArbitrum__factory(signer) + aggregator = await Aggregator.deploy() + await aggregator.deployed() + console.log("aggregator: ", aggregator.address) + + BalancerImp = new BalancerImplementationArbitrum__factory(signer) + balancerImpl = await BalancerImp.deploy() + await balancerImpl.deployed() + console.log("balancerImpl: ", balancerImpl.address) + + UniswapImp = new UniswapImplementationArbitrum__factory(signer) + uniswapImpl = await UniswapImp.deploy() + await uniswapImpl.deployed() + console.log("uniswapImpl: ", uniswapImpl.address) + + const proxy = new ethers.Contract( + proxyAddr, + InstaFlashAggregatorProxy__factory.abi, + ethers.provider, + ) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [admin], + }) + + adminSigner = await ethers.getSigner(admin); + + await hre.network.provider.send('hardhat_setBalance', [ + admin, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + const dataNew = await iface.encodeFunctionData('initialize', [balancerImpl.address,uniswapImpl.address]) + console.log("dataNew: ", dataNew) + await proxy.connect(adminSigner).upgradeToAndCall(aggregator.address, dataNew); + + Receiver = new InstaFlashReceiver__factory(signer); + receiver = await Receiver.deploy(proxyAddr); + await receiver.deployed(); + console.log("receiver: ", receiver.address) + + const token_usdc = new ethers.Contract( + USDC, + IERC20__factory.abi, + ethers.provider + ); + + await hre.network.provider.send("hardhat_setBalance", [ + ACC_USDC, + ethers.utils.parseEther("10.0").toHexString(), + ]); + + await hre.network.provider.request({ + method: "hardhat_impersonateAccount", + params: [ACC_USDC], + }); + + const signer_usdc = await ethers.getSigner(ACC_USDC); + await token_usdc.connect(signer_usdc).transfer(receiver.address, usdc); + + await hre.network.provider.request({ + method: "hardhat_stopImpersonatingAccount", + params: [ACC_USDC], + }); + _instaData = "0x"; + }) + + describe("Single token", async function () { + it("Should be able to take flashLoan of a single token from Balancer", async function () { + await receiver.flashBorrow([USDC], [Usdc], 5, _data, _instaData); + }); + }); + + describe("Uniswap Route", async function () { + beforeEach(async function () { + _instaData = await ethers.utils.defaultAbiCoder.encode( + ["tuple(address, address, uint24)"], + [[USDT, USDC, "500"]] + ); + }); + it("Should be able to take flashLoan of a single token from Uniswap", async function () { + await receiver.flashBorrow([USDC], [Usdc], 8, _data, _instaData); + }); + }); + + describe("Multi token", async function () { + beforeEach(async function () { + const token = new ethers.Contract( + USDT, + IERC20__factory.abi, + ethers.provider + ); + + await hre.network.provider.send("hardhat_setBalance", [ + ACC_USDT, + ethers.utils.parseEther("10.0").toHexString(), + ]); + + await hre.network.provider.request({ + method: "hardhat_impersonateAccount", + params: [ACC_USDT], + }); + + const signer_usdt = await ethers.getSigner(ACC_USDT); + await token.connect(signer_usdt).transfer(receiver.address, usdt); + + await hre.network.provider.request({ + method: "hardhat_stopImpersonatingAccount", + params: [ACC_USDT], + }); + _instaData = "0x"; + }); + it("Should be able to take flashLoan of multiple sorted tokens together from Balancer", async function () { + await receiver.flashBorrow( + [USDT, USDC], + [Usdt, Usdc], + 5, + _data, + _instaData + ); + }); + it("Should be able to take flashLoan of multiple unsorted tokens together from Balancer", async function () { + await receiver.flashBorrow( + [USDT, USDC], + [Usdc, Usdt], + 5, + _data, + _instaData + ); + }); + + describe("Uniswap Route", async function () { + beforeEach(async function () { + _instaData = await ethers.utils.defaultAbiCoder.encode( + ["tuple(address, address, uint24)"], + [[USDT, USDC, "500"]] + ); + }); + it("Should be able to take flashLoan of multiple tokens together from Uniswap", async function () { + await receiver.flashBorrow( + [USDT, USDC], + [Usdc, Usdt], + 8, + _data, + _instaData + ); + }); + }); + }); + }) From 4c232b19a28db60e50cd92c21bcf17a8c22f282a Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 20 May 2022 19:37:27 +0530 Subject: [PATCH 14/36] added sortTokens for uniswap key sorting --- contracts/aggregator/common/helpers.sol | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/contracts/aggregator/common/helpers.sol b/contracts/aggregator/common/helpers.sol index 853a461a..e1ba1740 100644 --- a/contracts/aggregator/common/helpers.sol +++ b/contracts/aggregator/common/helpers.sol @@ -111,4 +111,21 @@ contract HelpersCommon { } return (_tokens, _amounts); } + + /** + * @dev Sort the tokens and amounts arrays according to token addresses. + * @notice Sort the tokens and amounts arrays according to token addresses. + * @param _token0 address of token0. + * @param _token1 address of token1. + */ + function sortTokens(address _token0, address _token1) + internal + pure + returns (address, address) + { + if(_token1 < _token0) { + (_token0, _token1) = (_token1, _token0); + } + return (_token0 , _token1); + } } From 57b3aca7239782d49c0034a27b480a0c5da673a1 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 20 May 2022 19:42:56 +0530 Subject: [PATCH 15/36] minor updates + optimism testcases --- .../aggregator/optimism/flashloan/main.sol | 19 ++- .../optimism/flashloan/variables.sol | 2 +- test/optimism/newFlash.ts | 153 ++++++++++++++++++ 3 files changed, 163 insertions(+), 11 deletions(-) create mode 100644 test/optimism/newFlash.ts diff --git a/contracts/aggregator/optimism/flashloan/main.sol b/contracts/aggregator/optimism/flashloan/main.sol index 1dc2b653..c1ad2fb7 100644 --- a/contracts/aggregator/optimism/flashloan/main.sol +++ b/contracts/aggregator/optimism/flashloan/main.sol @@ -32,7 +32,7 @@ contract FlashAggregatorOptimism is Helper { uint256 fee1, bytes memory data ) external { - spell(UNISWAP_IMP, msg.data); + spell(UNISWAP_IMPL, msg.data); } /** @@ -51,11 +51,7 @@ contract FlashAggregatorOptimism is Helper { bytes calldata _instadata ) external { require(_tokens.length == _amounts.length, "array-lengths-not-same"); - - (_tokens, _amounts) = bubbleSort(_tokens, _amounts); - validateTokens(_tokens); - - spell(UNISWAP_IMP, msg.data); + spell(UNISWAP_IMPL, msg.data); emit LogFlashloan(msg.sender, _route, _tokens, _amounts); } @@ -93,10 +89,13 @@ contract FlashAggregatorOptimism is Helper { } contract InstaFlashAggregatorOptimism is FlashAggregatorOptimism { - function initialize() public { - require(status == 0, "cannot-call-again"); - status = 1; - } + // function initialize() public { + // require(status == 0, "cannot-call-again"); + // status = 1; + // } + // function initialize(address uniswap) public { + // UNISWAP_IMPL = uniswap; + // } receive() external payable {} } diff --git a/contracts/aggregator/optimism/flashloan/variables.sol b/contracts/aggregator/optimism/flashloan/variables.sol index b8fffd4e..6541ae2a 100644 --- a/contracts/aggregator/optimism/flashloan/variables.sol +++ b/contracts/aggregator/optimism/flashloan/variables.sol @@ -39,5 +39,5 @@ contract Variables is ConstantVariables { uint24 fee; } - address internal UNISWAP_IMP; + address internal UNISWAP_IMPL; } diff --git a/test/optimism/newFlash.ts b/test/optimism/newFlash.ts new file mode 100644 index 00000000..6ced1dc8 --- /dev/null +++ b/test/optimism/newFlash.ts @@ -0,0 +1,153 @@ +const hre = require('hardhat') +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +const { ethers } = hre + +import { + InstaFlashAggregatorOptimism__factory, + IERC20__factory, + InstaFlashReceiver__factory, + InstaFlashReceiver, + InstaFlashAggregatorProxy__factory, + UniswapImplementationOptimism, + UniswapImplementationOptimism__factory +} from '../../typechain' + +describe('FlashLoan', function () { + let Aggregator, + aggregator, + Receiver, + receiver: InstaFlashReceiver, + implUniswap : UniswapImplementationOptimism, + ImplUniswap, + proxyAddr = "0x84E6b05A089d5677A702cF61dc14335b4bE5b282", + admin = "0xd4e5e20ef32b4750d4cd185a8e970b89851e7775", + adminSigner + + let signer: SignerWithAddress + + const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' + + let ABI = ['function initialize(address)'] + let iface = new ethers.utils.Interface(ABI) + + const DAI = '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1' + const USDT = '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58' + const ACC_DAI = '0xadb35413ec50e0afe41039eac8b930d313e94fa4' + const ACC_USDT = '0x9d39fc627a6d9d9f8c831c16995b209548cc3401' + + const dai = ethers.utils.parseUnits('1000', 18) + const usdt = ethers.utils.parseUnits('1000', 6) + const Dai = ethers.utils.parseUnits('5000', 18) + const Usdt = ethers.utils.parseUnits('5000', 6) + + const _data = '0x' + + let _instaData = '0x' + + beforeEach(async function () { + ;[signer] = await ethers.getSigners() + Aggregator = new InstaFlashAggregatorOptimism__factory(signer) + aggregator = await Aggregator.deploy() + await aggregator.deployed() + + ImplUniswap = new UniswapImplementationOptimism__factory(signer) + implUniswap = await ImplUniswap.deploy() + await implUniswap.deployed() + + const proxy = new ethers.Contract( + proxyAddr, + InstaFlashAggregatorProxy__factory.abi, + ethers.provider, + ) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [admin], + }) + + adminSigner = await ethers.getSigner(admin); + + await hre.network.provider.send('hardhat_setBalance', [ + admin, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + const data = iface.encodeFunctionData('initialize',[implUniswap.address]) + console.log("data: ", data) + await proxy.connect(adminSigner).upgradeToAndCall(aggregator.address, data); + + Receiver = new InstaFlashReceiver__factory(signer) + receiver = await Receiver.deploy(proxy.address) + await receiver.deployed() + + const token_dai = new ethers.Contract( + DAI, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_DAI], + }) + + const signer_dai = await ethers.getSigner(ACC_DAI) + await token_dai.connect(signer_dai).transfer(receiver.address, dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) + + _instaData = await ethers.utils.defaultAbiCoder.encode( + ['tuple(address, address, uint24)'], + [[USDT, DAI, '500']], + ) + }) + + describe('Single token', async function () { + it('Should be able to take flashLoan of a single token from Uniswap', async function () { + await receiver.flashBorrow([DAI], [Dai], 8, _data, _instaData) + }) + }) + + describe('Multi token', async function () { + beforeEach(async function () { + const token = new ethers.Contract( + USDT, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_USDT, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_USDT], + }) + + const signer_usdt = await ethers.getSigner(ACC_USDT) + await token.connect(signer_usdt).transfer(receiver.address, usdt) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDT], + }) + _instaData = await ethers.utils.defaultAbiCoder.encode( + ['tuple(address, address, uint24)'], + [[USDT, DAI, '500']], + ) + }) + it('Should be able to take flashLoan of multiple tokens together from Uniswap', async function () { + await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 8, _data, _instaData) + }) + }) +}) From 8ddef00a8a3fbc02e997ce0a8ccf1a3df0100c27 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 20 May 2022 19:45:33 +0530 Subject: [PATCH 16/36] bubbleSort added in new implementations --- .../arbitrum/flashloan/implBalancer/main.sol | 2 ++ .../arbitrum/flashloan/implUniswap/main.sol | 2 ++ contracts/aggregator/arbitrum/flashloan/main.sol | 16 +++++++++------- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol b/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol index 21ed405d..934b3451 100644 --- a/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol +++ b/contracts/aggregator/arbitrum/flashloan/implBalancer/main.sol @@ -20,6 +20,8 @@ contract BalancerImplementationArbitrum is Helper { bytes memory _instadata ) external reentrancy { require(_route == 5 , "invalid-BALANCER-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); routeBalancer(_tokens, _amounts, _data); } diff --git a/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol b/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol index a4934469..dde48a5e 100644 --- a/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol +++ b/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol @@ -20,6 +20,8 @@ contract UniswapImplementationArbitrum is Helper { bytes memory _instadata ) external reentrancy { require(_route == 8, "invalid-UNISWAP-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); routeUniswap(_tokens, _amounts, _data, _instadata); } diff --git a/contracts/aggregator/arbitrum/flashloan/main.sol b/contracts/aggregator/arbitrum/flashloan/main.sol index 3ce047dd..09c9c498 100644 --- a/contracts/aggregator/arbitrum/flashloan/main.sol +++ b/contracts/aggregator/arbitrum/flashloan/main.sol @@ -1,5 +1,10 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; + +/** + * @title Flashloan. + * @dev Flashloan aggregator for Arbitrum. + */ import "./helpers.sol"; contract FlashAggregatorArbitrum is Helper { @@ -60,9 +65,6 @@ contract FlashAggregatorArbitrum is Helper { ) external { require(_tokens.length == _amounts.length, "array-lengths-not-same"); - (_tokens, _amounts) = bubbleSort(_tokens, _amounts); - validateTokens(_tokens); - if (_route == 5) { spell(BALANCER_IMPL, msg.data); } else if (_route == 8) { @@ -117,10 +119,10 @@ contract InstaFlashAggregatorArbitrum is FlashAggregatorArbitrum { // } - function initialize(address bImp, address uImp) public { - BALANCER_IMPL = bImp; - UNISWAP_IMPL = uImp; - } + // function initialize(address bImp, address uImp) public { + // BALANCER_IMPL = bImp; + // UNISWAP_IMPL = uImp; + // } receive() external payable {} } From 6cd9969752ecfa5328d7a38e3a0e478916be293b Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 20 May 2022 19:54:36 +0530 Subject: [PATCH 17/36] minor updates on all chains --- .../avalanche/flashloan/implAave/main.sol | 5 +- .../aggregator/avalanche/flashloan/main.sol | 20 ++++---- .../mainnet/flashloan/implAave/main.sol | 2 + .../mainnet/flashloan/implBalancer/main.sol | 2 + .../mainnet/flashloan/implMaker/main.sol | 2 + .../aggregator/mainnet/flashloan/main.sol | 49 ++++++++----------- .../polygon/flashloan/implAave/main.sol | 2 + .../polygon/flashloan/implBalancer/main.sol | 2 + .../polygon/flashloan/implUniswap/main.sol | 2 + .../aggregator/polygon/flashloan/main.sol | 3 -- 10 files changed, 45 insertions(+), 44 deletions(-) diff --git a/contracts/aggregator/avalanche/flashloan/implAave/main.sol b/contracts/aggregator/avalanche/flashloan/implAave/main.sol index 9916abfa..7504067f 100644 --- a/contracts/aggregator/avalanche/flashloan/implAave/main.sol +++ b/contracts/aggregator/avalanche/flashloan/implAave/main.sol @@ -2,8 +2,7 @@ pragma solidity ^0.8.0; import "../helpers.sol"; - -contract AaveImplementation is Helper { +contract AaveImplementationAvalanche is Helper { /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -21,6 +20,8 @@ contract AaveImplementation is Helper { bytes calldata // kept for future use by instadapp. Currently not used anywhere. ) external reentrancy { require(_route == 1, "invalid-AAVE-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); routeAave(_tokens, _amounts, _data); } diff --git a/contracts/aggregator/avalanche/flashloan/main.sol b/contracts/aggregator/avalanche/flashloan/main.sol index f8b98242..053a1519 100644 --- a/contracts/aggregator/avalanche/flashloan/main.sol +++ b/contracts/aggregator/avalanche/flashloan/main.sol @@ -3,13 +3,9 @@ pragma solidity ^0.8.0; /** * @title Flashloan. - * @dev Flashloan aggregator. + * @dev Flashloan aggregator for Avalanche. */ - -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { Helper } from "./helpers.sol"; -import { InstaFlashReceiverInterface } from "./interfaces.sol"; -import { TokenInterface } from "../../common/interface.sol"; +import "./helpers.sol"; contract FlashAggregatorAvalanche is Helper { using SafeERC20 for IERC20; @@ -37,7 +33,7 @@ contract FlashAggregatorAvalanche is Helper { address _initiator, bytes memory _data ) external returns (bool) { - bytes memory response_ = spell(AAVE_IMP, msg.data); + bytes memory response_ = spell(AAVE_IMPL, msg.data); return (abi.decode(response_, (bool))); } @@ -55,15 +51,14 @@ contract FlashAggregatorAvalanche is Helper { uint256 _route, bytes calldata _data, bytes calldata // kept for future use by instadapp. Currently not used anywhere. - ) external reentrancy { - + ) external { require(_tokens.length == _amounts.length, "array-lengths-not-same"); (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); if (_route == 1) { - spell(AAVE_IMP, msg.data); + spell(AAVE_IMPL, msg.data); } else if (_route == 2) { revert("this route is only for mainnet"); } else if (_route == 3) { @@ -76,6 +71,8 @@ contract FlashAggregatorAvalanche is Helper { revert("this route is only for mainnet"); } else if (_route == 7) { revert("this route is only for mainnet and polygon"); + } else if (_route == 8) { + revert("this route is only for arbitrum, polygon and optimism"); } else { revert("route-does-not-exist"); } @@ -117,9 +114,10 @@ contract InstaFlashAggregatorAvalanche is FlashAggregatorAvalanche { /* Deprecated */ - // function initialize() public { + // function initialize(address aave) public { // require(status == 0, "cannot-call-again"); // status = 1; + // AAVE_IMPL = aave; // } receive() external payable {} diff --git a/contracts/aggregator/mainnet/flashloan/implAave/main.sol b/contracts/aggregator/mainnet/flashloan/implAave/main.sol index 09359d83..cc14dcd3 100644 --- a/contracts/aggregator/mainnet/flashloan/implAave/main.sol +++ b/contracts/aggregator/mainnet/flashloan/implAave/main.sol @@ -20,6 +20,8 @@ contract AaveImplementation is Helper { bytes calldata // kept for future use by instadapp. Currently not used anywhere. ) external reentrancy { require(_route == 1, "invalid-AAVE-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); routeAave(_tokens, _amounts, _data); } diff --git a/contracts/aggregator/mainnet/flashloan/implBalancer/main.sol b/contracts/aggregator/mainnet/flashloan/implBalancer/main.sol index e13185d0..6ee1f141 100644 --- a/contracts/aggregator/mainnet/flashloan/implBalancer/main.sol +++ b/contracts/aggregator/mainnet/flashloan/implBalancer/main.sol @@ -20,6 +20,8 @@ contract BalancerImplementation is Helper { bytes calldata // kept for future use by instadapp. Currently not used anywhere. ) external reentrancy { require(_route == 5 || _route == 6 || _route == 7, "invalid-BALANCER-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); if (_route == 5) { routeBalancer(_tokens, _amounts, _data); diff --git a/contracts/aggregator/mainnet/flashloan/implMaker/main.sol b/contracts/aggregator/mainnet/flashloan/implMaker/main.sol index 1586e21c..90c23e4d 100644 --- a/contracts/aggregator/mainnet/flashloan/implMaker/main.sol +++ b/contracts/aggregator/mainnet/flashloan/implMaker/main.sol @@ -20,6 +20,8 @@ contract MakerImplementation is Helper { bytes calldata // kept for future use by instadapp. Currently not used anywhere. ) external reentrancy { require((_route == 2 || _route == 3 || _route == 4), "invalid-MAKER-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); if (_route == 2) { routeMaker(_tokens[0], _amounts[0], _data); diff --git a/contracts/aggregator/mainnet/flashloan/main.sol b/contracts/aggregator/mainnet/flashloan/main.sol index 9ca48d66..5cd65cbb 100644 --- a/contracts/aggregator/mainnet/flashloan/main.sol +++ b/contracts/aggregator/mainnet/flashloan/main.sol @@ -9,6 +9,7 @@ pragma solidity ^0.8.0; import "./helpers.sol"; import "@openzeppelin/contracts/utils/Address.sol"; + contract AdminModule is Helper { event updateOwnerLog(address indexed oldOwner, address indexed newOwner); @@ -82,12 +83,6 @@ contract FlashAggregator is Setups { uint256[] amounts ); - event LogCollectRevenue( - address to, - address[] tokens, - uint256[] amounts - ); - /** * @dev Callback function for aave flashloan. * @notice Callback function for aave flashloan. @@ -104,8 +99,8 @@ contract FlashAggregator is Setups { address _initiator, bytes memory _data ) external returns (bool) { - bytes memory response = spell(AAVE_IMP, msg.data); - return (abi.decode(response, (bool))); + bytes memory response_ = spell(AAVE_IMPL, msg.data); + return (abi.decode(response_, (bool))); } /** @@ -123,8 +118,8 @@ contract FlashAggregator is Setups { uint256 _fee, bytes calldata _data ) external returns (bytes32) { - bytes memory response = spell(MAKER_IMP, msg.data); - return (abi.decode(response, (bytes32))); + bytes memory response_ = spell(MAKER_IMPL, msg.data); + return (abi.decode(response_, (bytes32))); } /** @@ -140,7 +135,7 @@ contract FlashAggregator is Setups { uint256[] memory _fees, bytes memory _data ) external { - spell(BALANCER_IMP, msg.data); + spell(BALANCER_IMPL, msg.data); } /** @@ -160,23 +155,20 @@ contract FlashAggregator is Setups { ) external { require(_tokens.length == _amounts.length, "array-lengths-not-same"); - (_tokens, _amounts) = bubbleSort(_tokens, _amounts); - validateTokens(_tokens); - if (_route == 1) { - spell(AAVE_IMP, msg.data); + spell(AAVE_IMPL, msg.data); } else if (_route == 2) { - spell(MAKER_IMP, msg.data); + spell(MAKER_IMPL, msg.data); } else if (_route == 3) { - spell(MAKER_IMP, msg.data); + spell(MAKER_IMPL, msg.data); } else if (_route == 4) { - spell(MAKER_IMP, msg.data); + spell(MAKER_IMPL, msg.data); } else if (_route == 5) { - spell(BALANCER_IMP, msg.data); + spell(BALANCER_IMPL, msg.data); } else if (_route == 6) { - spell(BALANCER_IMP, msg.data); + spell(BALANCER_IMPL, msg.data); } else if (_route == 7) { - spell(BALANCER_IMP, msg.data); + spell(BALANCER_IMPL, msg.data); } else { revert("route-does-not-exist"); } @@ -204,8 +196,7 @@ contract FlashAggregator is Setups { * @notice Function to transfer fee to the treasury. Will be called manually. * @param _tokens token addresses for transferring fee to treasury. */ - function transferFee(address[] memory _tokens, address _to) public onlyOwner { - uint256[] memory _amts = new uint256[](_tokens.length); + function transferFeeToTreasury(address[] memory _tokens) public { for (uint256 i = 0; i < _tokens.length; i++) { IERC20 token_ = IERC20(_tokens[i]); uint256 decimals_ = TokenInterface(_tokens[i]).decimals(); @@ -214,13 +205,12 @@ contract FlashAggregator is Setups { : decimals_ > 7 ? 100 : 10; - _amts[i] = token_.balanceOf(address(this)) > amtToSub_ + uint256 amtToTransfer_ = token_.balanceOf(address(this)) > amtToSub_ ? (token_.balanceOf(address(this)) - amtToSub_) : 0; - if (_amts[i] > 0) - token_.safeTransfer(_to, _amts[i]); + if (amtToTransfer_ > 0) + token_.safeTransfer(treasuryAddr, amtToTransfer_); } - emit LogCollectRevenue(_to, _tokens, _amts); } } @@ -230,7 +220,7 @@ contract InstaFlashAggregator is FlashAggregator { /* Deprecated */ - // function initialize(address[] memory _ctokens, address owner_) public { + // function initialize(address[] memory _ctokens, address owner_, address aave, address balancer, address maker) public { // require(status == 0, "cannot-call-again"); // require(stETHStatus == 0, "only-once"); // require(ownerStatus == 0, "only-once"); @@ -248,6 +238,9 @@ contract InstaFlashAggregator is FlashAggregator { // ownerStatus = 1; // stETHStatus = 1; // status = 1; + // AAVE_IMPL = aave; + // BALANCER_IMPL = balancer; + // MAKER_IMPL = maker; // } receive() external payable {} diff --git a/contracts/aggregator/polygon/flashloan/implAave/main.sol b/contracts/aggregator/polygon/flashloan/implAave/main.sol index 282e23c1..e3a3078e 100644 --- a/contracts/aggregator/polygon/flashloan/implAave/main.sol +++ b/contracts/aggregator/polygon/flashloan/implAave/main.sol @@ -21,6 +21,8 @@ contract AaveImplementation is Helper { bytes calldata _instadata ) external reentrancy { require(_route == 1, "invalid-AAVE-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); routeAave(_tokens, _amounts, _data); } diff --git a/contracts/aggregator/polygon/flashloan/implBalancer/main.sol b/contracts/aggregator/polygon/flashloan/implBalancer/main.sol index 825ebbf4..be05ce96 100644 --- a/contracts/aggregator/polygon/flashloan/implBalancer/main.sol +++ b/contracts/aggregator/polygon/flashloan/implBalancer/main.sol @@ -21,6 +21,8 @@ contract BalancerImplementation is Helper { bytes calldata _instadata ) external reentrancy { require(_route == 5 || _route == 7, "invalid-BALANCER-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); if (_route == 5) { routeBalancer(_tokens, _amounts, _data); diff --git a/contracts/aggregator/polygon/flashloan/implUniswap/main.sol b/contracts/aggregator/polygon/flashloan/implUniswap/main.sol index 65750f06..17a48848 100644 --- a/contracts/aggregator/polygon/flashloan/implUniswap/main.sol +++ b/contracts/aggregator/polygon/flashloan/implUniswap/main.sol @@ -21,6 +21,8 @@ contract UniswapImplementation is Helper { bytes calldata _instadata ) external reentrancy { require(_route == 8, "invalid-UNISWAP-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); routeUniswap(_tokens, _amounts, _data, _instadata); } diff --git a/contracts/aggregator/polygon/flashloan/main.sol b/contracts/aggregator/polygon/flashloan/main.sol index fe10a7b8..4f266980 100644 --- a/contracts/aggregator/polygon/flashloan/main.sol +++ b/contracts/aggregator/polygon/flashloan/main.sol @@ -82,9 +82,6 @@ contract FlashAggregatorPolygon is Helper { ) external { require(_tokens.length == _amounts.length, "array-lengths-not-same"); - (_tokens, _amounts) = bubbleSort(_tokens, _amounts); - validateTokens(_tokens); - if (_route == 1) { spell(AAVE_IMP, msg.data); } else if (_route == 5 || _route == 7) { From 76ab257eb69a1e5366ae99c9bf138a9d5a32e43f Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sat, 21 May 2022 02:08:56 +0530 Subject: [PATCH 18/36] polygon testcase + polygon updates --- .../polygon/flashloan/implAave/main.sol | 2 +- .../polygon/flashloan/implBalancer/main.sol | 2 +- .../polygon/flashloan/implUniswap/main.sol | 5 +- .../aggregator/polygon/flashloan/main.sol | 26 ++- .../polygon/flashloan/variables.sol | 6 +- test/polygon/newFlashloan.ts | 218 ++++++++++++++++++ 6 files changed, 246 insertions(+), 13 deletions(-) create mode 100644 test/polygon/newFlashloan.ts diff --git a/contracts/aggregator/polygon/flashloan/implAave/main.sol b/contracts/aggregator/polygon/flashloan/implAave/main.sol index e3a3078e..8ceb737b 100644 --- a/contracts/aggregator/polygon/flashloan/implAave/main.sol +++ b/contracts/aggregator/polygon/flashloan/implAave/main.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "../helpers.sol"; -contract AaveImplementation is Helper { +contract AaveImplementationPolygon is Helper { /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. diff --git a/contracts/aggregator/polygon/flashloan/implBalancer/main.sol b/contracts/aggregator/polygon/flashloan/implBalancer/main.sol index be05ce96..e2cd6573 100644 --- a/contracts/aggregator/polygon/flashloan/implBalancer/main.sol +++ b/contracts/aggregator/polygon/flashloan/implBalancer/main.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "../helpers.sol"; -contract BalancerImplementation is Helper { +contract BalancerImplementationPolygon is Helper { /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. diff --git a/contracts/aggregator/polygon/flashloan/implUniswap/main.sol b/contracts/aggregator/polygon/flashloan/implUniswap/main.sol index 17a48848..d807ecad 100644 --- a/contracts/aggregator/polygon/flashloan/implUniswap/main.sol +++ b/contracts/aggregator/polygon/flashloan/implUniswap/main.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "../helpers.sol"; -contract UniswapImplementation is Helper { +contract UniswapImplementationPolygon is Helper { /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -134,13 +134,14 @@ contract UniswapImplementation is Helper { bytes memory _instadata ) internal { PoolKey memory key = abi.decode(_instadata, (PoolKey)); + (key.token0, key.token1) = sortTokens(key.token0, key.token1); uint256 amount0_; uint256 amount1_; if (_tokens.length == 1) { require( - (_tokens[0] == key.token0 || _tokens[0] == key.token1), + (_tokens[0] == key.token0 ), "tokens-do-not-match-pool" ); if (_tokens[0] == key.token0) { diff --git a/contracts/aggregator/polygon/flashloan/main.sol b/contracts/aggregator/polygon/flashloan/main.sol index 4f266980..c4833300 100644 --- a/contracts/aggregator/polygon/flashloan/main.sol +++ b/contracts/aggregator/polygon/flashloan/main.sol @@ -1,6 +1,11 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +/** + * @title Flashloan. + * @dev Flashloan aggregator for Polygon. + */ + import "./helpers.sol"; import "@openzeppelin/contracts/utils/Address.sol"; @@ -30,7 +35,7 @@ contract FlashAggregatorPolygon is Helper { address _initiator, bytes memory _data ) external returns (bool) { - bytes memory response_ = spell(AAVE_IMP, msg.data); + bytes memory response_ = spell(AAVE_IMPL, msg.data); return (abi.decode(response_, (bool))); } @@ -47,7 +52,7 @@ contract FlashAggregatorPolygon is Helper { uint256[] memory _fees, bytes memory _data ) external { - spell(BALANCER_IMP, msg.data); + spell(BALANCER_IMPL, msg.data); } /** @@ -62,7 +67,7 @@ contract FlashAggregatorPolygon is Helper { uint256 fee1, bytes memory data ) external { - spell(UNISWAP_IMP, msg.data); + spell(UNISWAP_IMPL, msg.data); } /** @@ -83,11 +88,13 @@ contract FlashAggregatorPolygon is Helper { require(_tokens.length == _amounts.length, "array-lengths-not-same"); if (_route == 1) { - spell(AAVE_IMP, msg.data); + spell(AAVE_IMPL, msg.data); } else if (_route == 5 || _route == 7) { - spell(BALANCER_IMP, msg.data); + spell(BALANCER_IMPL, msg.data); } else if (_route == 8) { - spell(UNISWAP_IMP, msg.data); + spell(UNISWAP_IMPL, msg.data); + } else if (_route == 2 || _route == 3 || _route == 4 || _route == 6) { + revert("this route is only for mainnet"); } else { revert("route-does-not-exist"); } @@ -139,5 +146,12 @@ contract InstaFlashAggregatorPolygon is FlashAggregatorPolygon { // status = 1; // } + //Function created for testing upgradable implementations + // function initialize(address aave, address balancer, address uniswap) public { + // AAVE_IMPL = aave; + // BALANCER_IMPL = balancer; + // UNISWAP_IMPL = uniswap; + // } + receive() external payable {} } diff --git a/contracts/aggregator/polygon/flashloan/variables.sol b/contracts/aggregator/polygon/flashloan/variables.sol index f71ffced..999bda49 100644 --- a/contracts/aggregator/polygon/flashloan/variables.sol +++ b/contracts/aggregator/polygon/flashloan/variables.sol @@ -52,7 +52,7 @@ contract Variables is ConstantVariables { uint24 fee; } - address internal AAVE_IMP; - address internal BALANCER_IMP; - address internal UNISWAP_IMP; + address internal AAVE_IMPL; + address internal BALANCER_IMPL; + address internal UNISWAP_IMPL; } diff --git a/test/polygon/newFlashloan.ts b/test/polygon/newFlashloan.ts new file mode 100644 index 00000000..f25a4e0e --- /dev/null +++ b/test/polygon/newFlashloan.ts @@ -0,0 +1,218 @@ +const hre = require('hardhat') +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +const { ethers } = hre + +import { + InstaFlashAggregatorPolygon__factory, + IERC20__factory, + InstaFlashReceiver__factory, + InstaFlashReceiver, + InstaFlashAggregatorProxy__factory, + UniswapImplementationPolygon__factory, + BalancerImplementationPolygon__factory, + AaveImplementationPolygon__factory +} from '../../typechain' + +describe('FlashLoan', function () { + let Aggregator, + aggregator, + Receiver, + receiver: InstaFlashReceiver, + implUniswap, + ImplUniswap, + implBalancer, + ImplBalancer, + implAave, + ImplAave, + proxyAddr = "0xB2A7F20D10A006B0bEA86Ce42F2524Fde5D6a0F4", + admin = "0x90cf378a297c7ef6dabed36ea5e112c6646bb3a4", + adminSigner + + let signer: SignerWithAddress + + const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' + + let ABI = ['function initialize(address aave, address balancer, address uniswap)'] + let iface = new ethers.utils.Interface(ABI) + + const DAI = '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063' + const USDT = '0xc2132d05d31c914a87c6611c10748aeb04b58e8f' + const ACC_DAI = '0x4a35582a710e1f4b2030a3f826da20bfb6703c09' + const ACC_USDT = '0x0d0707963952f2fba59dd06f2b425ace40b492fe' + //dai < usdt + + const dai = ethers.utils.parseUnits('1000', 18) + const usdt = ethers.utils.parseUnits('1000', 6) + const Dai = ethers.utils.parseUnits('5000', 18) + const Usdt = ethers.utils.parseUnits('5000', 6) + + const _data = '0x' + + let _instaData = '0x' + + beforeEach(async function () { + ;[signer] = await ethers.getSigners() + Aggregator = new InstaFlashAggregatorPolygon__factory(signer) + aggregator = await Aggregator.deploy() + await aggregator.deployed() + console.log("aggregator deployed at: ", aggregator.address); + + ImplAave = new AaveImplementationPolygon__factory(signer) + implAave = await ImplAave.deploy() + await implAave.deployed() + console.log("implAave deployed at: ", implAave.address); + + ImplBalancer = new BalancerImplementationPolygon__factory(signer) + implBalancer = await ImplBalancer.deploy() + await implBalancer.deployed() + console.log("implBalancer deployed at: ", implBalancer.address); + + ImplUniswap = new UniswapImplementationPolygon__factory(signer) + implUniswap = await ImplUniswap.deploy() + await implUniswap.deployed() + console.log("implUniswap deployed at: ", implUniswap.address); + + const proxy = new ethers.Contract( + proxyAddr, + InstaFlashAggregatorProxy__factory.abi, + ethers.provider, + ) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [admin], + }) + + adminSigner = await ethers.getSigner(admin); + + await hre.network.provider.send('hardhat_setBalance', [ + admin, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + const data = iface.encodeFunctionData('initialize', [implAave.address, implBalancer.address,implUniswap.address]) + await proxy.connect(adminSigner).upgradeToAndCall(aggregator.address, data); + + Receiver = new InstaFlashReceiver__factory(signer) + receiver = await Receiver.deploy(proxy.address) + await receiver.deployed() + console.log("receiver deployed at: ", receiver.address); + + const token_dai = new ethers.Contract( + DAI, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_DAI], + }) + + const signer_dai = await ethers.getSigner(ACC_DAI) + await token_dai.connect(signer_dai).transfer(receiver.address, dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) + _instaData = '0x' + }) + + describe('Single token', async function () { + it('Should be able to take flashLoan of a single token from AAVE', async function () { + await receiver.flashBorrow([DAI], [Dai], 1, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from Balancer', async function () { + await receiver.flashBorrow([DAI], [Dai], 5, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from AAVE(Balancer)', async function () { + await receiver.flashBorrow([DAI], [Dai], 7, _data, _instaData) + }) + + describe('Uniswap Route', async function () { + beforeEach(async function () { + _instaData = await ethers.utils.defaultAbiCoder.encode( + ['tuple(address, address, uint24)'], + [[DAI, USDT, '500']], + ) + }) + it('Should be able to take flashLoan of a single token from Uniswap', async function () { + await receiver.flashBorrow([DAI], [Dai], 8, _data, _instaData) + }) + }) + }) + + describe('Multi token', async function () { + beforeEach(async function () { + const token = new ethers.Contract( + USDT, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_USDT, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_USDT], + }) + + const signer_usdt = await ethers.getSigner(ACC_USDT) + await token.connect(signer_usdt).transfer(receiver.address, usdt) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDT], + }) + _instaData = '0x' + }) + it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { + await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 1, _data, _instaData) + }) + it('Should be able to take flashLoan of multiple sorted tokens together from Balancer', async function () { + await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 5, _data, _instaData) + }) + it('Should be able to take flashLoan of multiple unsorted tokens together from Balancer', async function () { + await receiver.flashBorrow([USDT, DAI], [Usdt, Dai], 5, _data, _instaData) + }) + it('Should be able to take flashLoan of multiple tokens together from AAVE(Balancer)', async function () { + await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 7, _data, _instaData) + }) + + describe('Uniswap Route', async function () { + beforeEach(async function () { + _instaData = await ethers.utils.defaultAbiCoder.encode( + ['tuple(address, address, uint24)'], + [[USDT, DAI, '500']], + ) + }) + it('Should be able to take flashLoan of multiple unsorted tokens together from Uniswap', async function () { + await receiver.flashBorrow( + [USDT, DAI], + [Usdt, Dai], + 8, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens sorted together from Uniswap', async function () { + await receiver.flashBorrow( + [DAI, USDT], + [Dai, Usdt], + 8, + _data, + _instaData, + ) + }) + }) + }) +}) From cc7ca71e67cc15e9adbb4e289ce82bf0f358a4d7 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sat, 21 May 2022 02:26:48 +0530 Subject: [PATCH 19/36] Avalanche testcases + new updates --- README.md | 15 -- .../arbitrum/flashloan/implUniswap/main.sol | 1 + .../aggregator/arbitrum/flashloan/main.sol | 4 +- .../avalanche/flashloan/helpers.sol | 7 +- .../aggregator/avalanche/flashloan/main.sol | 3 +- .../avalanche/flashloan/variables.sol | 2 +- .../aggregator/polygon/flashloan/main.sol | 4 +- test/avalanche/newFlashloan.ts | 137 ++++++++++++++++++ 8 files changed, 147 insertions(+), 26 deletions(-) create mode 100644 test/avalanche/newFlashloan.ts diff --git a/README.md b/README.md index 88bd68b0..381da85e 100644 --- a/README.md +++ b/README.md @@ -47,18 +47,3 @@ Deploy the contracts to Hardhat Network: ```sh $ npm run deploy ``` - -## Syntax Highlighting - -If you use VSCode, you can enjoy syntax highlighting for your Solidity code via the -[vscode-solidity](https://github.com/juanfranblanco/vscode-solidity) extension. The recommended approach to set the -compiler version is to add the following fields to your VSCode user settings: - -```json -{ - "solidity.compileUsingRemoteVersion": "v0.8.4+commit.c7e474f2", - "solidity.defaultCompiler": "remote" -} -``` - -Where of course `v0.8.4+commit.c7e474f2` can be replaced with any other version. diff --git a/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol b/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol index dde48a5e..02b8f2c3 100644 --- a/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol +++ b/contracts/aggregator/arbitrum/flashloan/implUniswap/main.sol @@ -133,6 +133,7 @@ contract UniswapImplementationArbitrum is Helper { bytes memory _instadata ) internal { PoolKey memory key = abi.decode(_instadata, (PoolKey)); + (key.token0, key.token1) = sortTokens(key.token0, key.token1); uint256 amount0_; uint256 amount1_; diff --git a/contracts/aggregator/arbitrum/flashloan/main.sol b/contracts/aggregator/arbitrum/flashloan/main.sol index 09c9c498..93e89cdc 100644 --- a/contracts/aggregator/arbitrum/flashloan/main.sol +++ b/contracts/aggregator/arbitrum/flashloan/main.sol @@ -118,7 +118,9 @@ contract InstaFlashAggregatorArbitrum is FlashAggregatorArbitrum { // status = 1; // } - + /** + * @dev Function created for testing upgradable implementations + */ // function initialize(address bImp, address uImp) public { // BALANCER_IMPL = bImp; // UNISWAP_IMPL = uImp; diff --git a/contracts/aggregator/avalanche/flashloan/helpers.sol b/contracts/aggregator/avalanche/flashloan/helpers.sol index d3e80cd2..7392e3dd 100644 --- a/contracts/aggregator/avalanche/flashloan/helpers.sol +++ b/contracts/aggregator/avalanche/flashloan/helpers.sol @@ -1,12 +1,7 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; - -import {Variables} from "./variables.sol"; +import "./variables.sol"; import "../../common/helpers.sol"; -import "./interfaces.sol"; -import "../../common/interface.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; contract Helper is HelpersCommon, Variables { using SafeERC20 for IERC20; diff --git a/contracts/aggregator/avalanche/flashloan/main.sol b/contracts/aggregator/avalanche/flashloan/main.sol index 053a1519..642a0cc0 100644 --- a/contracts/aggregator/avalanche/flashloan/main.sol +++ b/contracts/aggregator/avalanche/flashloan/main.sol @@ -114,10 +114,9 @@ contract InstaFlashAggregatorAvalanche is FlashAggregatorAvalanche { /* Deprecated */ - // function initialize(address aave) public { + // function initialize() public { // require(status == 0, "cannot-call-again"); // status = 1; - // AAVE_IMPL = aave; // } receive() external payable {} diff --git a/contracts/aggregator/avalanche/flashloan/variables.sol b/contracts/aggregator/avalanche/flashloan/variables.sol index a0f10cbd..9e75fd6a 100644 --- a/contracts/aggregator/avalanche/flashloan/variables.sol +++ b/contracts/aggregator/avalanche/flashloan/variables.sol @@ -31,6 +31,6 @@ contract Variables is ConstantVariables { uint256[] _instaFees; } - address internal AAVE_IMP; + address internal AAVE_IMPL; } \ No newline at end of file diff --git a/contracts/aggregator/polygon/flashloan/main.sol b/contracts/aggregator/polygon/flashloan/main.sol index c4833300..61a642a8 100644 --- a/contracts/aggregator/polygon/flashloan/main.sol +++ b/contracts/aggregator/polygon/flashloan/main.sol @@ -146,7 +146,9 @@ contract InstaFlashAggregatorPolygon is FlashAggregatorPolygon { // status = 1; // } - //Function created for testing upgradable implementations + /** + * @dev Function created for testing upgradable implementations + */ // function initialize(address aave, address balancer, address uniswap) public { // AAVE_IMPL = aave; // BALANCER_IMPL = balancer; diff --git a/test/avalanche/newFlashloan.ts b/test/avalanche/newFlashloan.ts new file mode 100644 index 00000000..54e58fcf --- /dev/null +++ b/test/avalanche/newFlashloan.ts @@ -0,0 +1,137 @@ +const hre = require('hardhat') +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +const { ethers } = hre + +import { + InstaFlashAggregatorAvalanche__factory, + IERC20__factory, + InstaFlashReceiver__factory, + InstaFlashReceiver, + InstaFlashAggregatorProxy__factory, + AaveImplementationAvalanche, + AaveImplementationAvalanche__factory +} from '../../typechain' + +describe('FlashLoan', function () { + let Aggregator, + aggregator, + Receiver, + receiver: InstaFlashReceiver, + Proxy, + proxy, + ImplAave, + implAave, + proxyAddr = "0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19", + admin = "0x7b0990a249a215c9a88ebec3849920e29725f2d0", + adminSigner + + let signer: SignerWithAddress + + const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' + + let ABI = ['function initialize(address aave)'] + let iface = new ethers.utils.Interface(ABI) + + const DAI = '0xd586e7f844cea2f87f50152665bcbc2c279d8d70' + const USDT = '0xc7198437980c041c805a1edcba50c1ce5db95118' + const ACC_DAI = '0xed2a7edd7413021d440b09d654f3b87712abab66' + const ACC_USDT = '0xed2a7edd7413021d440b09d654f3b87712abab66' + + const dai = ethers.utils.parseUnits('10', 18) + const usdt = ethers.utils.parseUnits('10', 6) + const Dai = ethers.utils.parseUnits('5000', 18) + const Usdt = ethers.utils.parseUnits('5000', 6) + + const zeroAddr = + '0x0000000000000000000000000000000000000000000000000000000000000000' + let _instaData = '' + + + beforeEach(async function () { + ;[signer] = await ethers.getSigners() + Aggregator = new InstaFlashAggregatorAvalanche__factory(signer) + aggregator = await Aggregator.deploy() + await aggregator.deployed() + console.log("aggregator: ", aggregator.address) + + ImplAave = new AaveImplementationAvalanche__factory(signer) + implAave = await ImplAave.deploy() + await implAave.deployed() + console.log("implAave: ", implAave.address) + + const data = iface.encodeFunctionData('initialize',[implAave.address]) + + Proxy = new InstaFlashAggregatorProxy__factory(signer) + proxy = await Proxy.deploy(aggregator.address, master, data) + await proxy.deployed() + console.log("proxy: ", proxy.address) + + Receiver = new InstaFlashReceiver__factory(signer) + receiver = await Receiver.deploy(proxy.address) + await receiver.deployed() + console.log("receiver: ", receiver.address) + + const token_dai = new ethers.Contract( + DAI, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_DAI], + }) + + const signer_dai = await ethers.getSigner(ACC_DAI) + await token_dai.connect(signer_dai).transfer(receiver.address, dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) + _instaData = '0x' + }) + + describe('Single token', async function () { + it('Should be able to take flashLoan of a single token from AAVE', async function () { + await receiver.flashBorrow([DAI], [Dai], 1, zeroAddr,_instaData) + }) + }) + + describe('Multi token', async function () { + beforeEach(async function () { + const token = new ethers.Contract( + USDT, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_USDT, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_USDT], + }) + + const signer_usdt = await ethers.getSigner(ACC_USDT) + await token.connect(signer_usdt).transfer(receiver.address, usdt) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDT], + }) + _instaData = '0x' + }) + it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { + await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 1, zeroAddr,_instaData ) + }) + }) +}) From 3d93a5745d156200900b10657a81595bffd6c7f7 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sat, 21 May 2022 02:43:39 +0530 Subject: [PATCH 20/36] minor updates --- .../aggregator/mainnet/flashloan/main.sol | 5 +- .../mainnet/flashloan/variables.sol | 6 +- .../optimism/flashloan/implUniswap/main.sol | 5 +- .../aggregator/optimism/flashloan/main.sol | 4 + test/arbitrum/newFlashloan.ts | 5 +- test/mainnet/newFlash.ts | 360 ++++++++++++++++++ test/mainnet/newFlashAggr.ts | 360 ------------------ test/polygon/flashloan.ts | 5 + 8 files changed, 380 insertions(+), 370 deletions(-) create mode 100644 test/mainnet/newFlash.ts delete mode 100644 test/mainnet/newFlashAggr.ts diff --git a/contracts/aggregator/mainnet/flashloan/main.sol b/contracts/aggregator/mainnet/flashloan/main.sol index 5cd65cbb..c57a33df 100644 --- a/contracts/aggregator/mainnet/flashloan/main.sol +++ b/contracts/aggregator/mainnet/flashloan/main.sol @@ -220,7 +220,7 @@ contract InstaFlashAggregator is FlashAggregator { /* Deprecated */ - // function initialize(address[] memory _ctokens, address owner_, address aave, address balancer, address maker) public { + // function initialize(address[] memory _ctokens, address owner_) public { // require(status == 0, "cannot-call-again"); // require(stETHStatus == 0, "only-once"); // require(ownerStatus == 0, "only-once"); @@ -238,9 +238,6 @@ contract InstaFlashAggregator is FlashAggregator { // ownerStatus = 1; // stETHStatus = 1; // status = 1; - // AAVE_IMPL = aave; - // BALANCER_IMPL = balancer; - // MAKER_IMPL = maker; // } receive() external payable {} diff --git a/contracts/aggregator/mainnet/flashloan/variables.sol b/contracts/aggregator/mainnet/flashloan/variables.sol index b97fa14c..483b3dbc 100644 --- a/contracts/aggregator/mainnet/flashloan/variables.sol +++ b/contracts/aggregator/mainnet/flashloan/variables.sol @@ -58,7 +58,7 @@ contract Variables is ConstantVariables { mapping(address => bool) public isWhitelisted; - address internal AAVE_IMP; - address internal MAKER_IMP; - address internal BALANCER_IMP; + address internal AAVE_IMPL; + address internal MAKER_IMPL; + address internal BALANCER_IMPL; } diff --git a/contracts/aggregator/optimism/flashloan/implUniswap/main.sol b/contracts/aggregator/optimism/flashloan/implUniswap/main.sol index d69fd98b..33c08aa4 100644 --- a/contracts/aggregator/optimism/flashloan/implUniswap/main.sol +++ b/contracts/aggregator/optimism/flashloan/implUniswap/main.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "../helpers.sol"; -contract UniswapImplementation is Helper { +contract UniswapImplementationOptimism is Helper { /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -21,6 +21,8 @@ contract UniswapImplementation is Helper { bytes calldata _instadata ) external reentrancy { require(_route == 8, "invalid-UNISWAP-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); routeUniswap(_tokens, _amounts, _data, _instadata); } @@ -39,6 +41,7 @@ contract UniswapImplementation is Helper { bytes memory _instadata ) internal { PoolKey memory key = abi.decode(_instadata, (PoolKey)); + (key.token0, key.token1) = sortTokens(key.token0, key.token1); uint256 amount0_; uint256 amount1_; diff --git a/contracts/aggregator/optimism/flashloan/main.sol b/contracts/aggregator/optimism/flashloan/main.sol index c1ad2fb7..6a91dc5f 100644 --- a/contracts/aggregator/optimism/flashloan/main.sol +++ b/contracts/aggregator/optimism/flashloan/main.sol @@ -93,6 +93,10 @@ contract InstaFlashAggregatorOptimism is FlashAggregatorOptimism { // require(status == 0, "cannot-call-again"); // status = 1; // } + + /** + * @dev Function created for testing upgradable implementations + */ // function initialize(address uniswap) public { // UNISWAP_IMPL = uniswap; // } diff --git a/test/arbitrum/newFlashloan.ts b/test/arbitrum/newFlashloan.ts index 88a4b763..11b0b53b 100644 --- a/test/arbitrum/newFlashloan.ts +++ b/test/arbitrum/newFlashloan.ts @@ -36,6 +36,7 @@ import { const USDT = "0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9"; const ACC_USDC = "0xce2cc46682e9c6d5f174af598fb4931a9c0be68e"; const ACC_USDT = "0x0db3fe3b770c95a0b99d1ed6f2627933466c0dd8"; + //usdt < usdc const usdc = ethers.utils.parseUnits("10", 6); const usdt = ethers.utils.parseUnits("10", 6); @@ -173,7 +174,7 @@ import { }); it("Should be able to take flashLoan of multiple unsorted tokens together from Balancer", async function () { await receiver.flashBorrow( - [USDT, USDC], + [USDC, USDT], [Usdc, Usdt], 5, _data, @@ -191,7 +192,7 @@ import { it("Should be able to take flashLoan of multiple tokens together from Uniswap", async function () { await receiver.flashBorrow( [USDT, USDC], - [Usdc, Usdt], + [Usdt, Usdc], 8, _data, _instaData diff --git a/test/mainnet/newFlash.ts b/test/mainnet/newFlash.ts new file mode 100644 index 00000000..dbba0eca --- /dev/null +++ b/test/mainnet/newFlash.ts @@ -0,0 +1,360 @@ +const hre = require('hardhat') +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +const { ethers } = hre + +import { + InstaFlashAggregator, + InstaFlashAggregator__factory, + IERC20__factory, + IERC20, + InstaFlashReceiver__factory, + InstaFlashReceiver, + InstaFlashAggregatorProxy, + InstaFlashAggregatorProxy__factory, + AaveImplementation__factory, + AaveImplementation, + BalancerImplementation, + MakerImplementation, + BalancerImplementation__factory, + MakerImplementation__factory +} from '../../typechain' + +describe('FlashLoan', function () { + let Aggregator, + aggregator, + Receiver, + receiver: InstaFlashReceiver, + Proxy, + proxy: InstaFlashAggregatorProxy, + proxyA : AaveImplementation, + proxyB : BalancerImplementation, + proxyM : MakerImplementation, + ProxyA, + ProxyB, + ProxyM, + admin = "0xb208CDF8e1c319d0019397dceC8E0bA3Fb9A149F", + proxyAddr = "0x619Ad2D02dBeE6ebA3CDbDA3F98430410e892882", + adminSigner + + let signer: SignerWithAddress + + const master = '0xa8c31E39e40E6765BEdBd83D92D6AA0B33f1CCC5' + const aaveLendingAddr = '0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9' + + let ABI = ['function initialize(address[],address,address,address,address)'] + let iface = new ethers.utils.Interface(ABI) + + const DAI = '0x6b175474e89094c44da98b954eedeac495271d0f' + const USDT = '0xdac17f958d2ee523a2206206994597c13d831ec7' + const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' + const ACC_DAI = '0x9a7a9d980ed6239b89232c012e21f4c210f4bef1' + const ACC_USDT = '0x6D5Be15f9Aa170e207C043CDf8E0BaDbF2A48ed0' + const ACC_WETH = '0xe78388b4ce79068e89bf8aa7f218ef6b9ab0e9d0' + + const STETH = '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84' + const ACC_STETH = '0xdc24316b9ae028f1497c275eb9192a3ea0f67022' + + const dai = ethers.utils.parseUnits('10', 18) + const usdt = ethers.utils.parseUnits('10', 6) + const weth = ethers.utils.parseUnits('10', 18) + const Dai = ethers.utils.parseUnits('5000', 18) + const Usdt = ethers.utils.parseUnits('5000', 6) + const Weth = ethers.utils.parseUnits('1000', 18) + const steth = ethers.utils.parseUnits('1', 18) + const Steth = ethers.utils.parseUnits('100', 18) + + const _data = '0x' + + let _instaData = '0x' + + beforeEach(async function () { + ;[signer] = await ethers.getSigners() + + ProxyA = new AaveImplementation__factory(signer) + proxyA = await ProxyA.deploy() + await proxyA.deployed() + console.log("Aave proxy deployed at: ", proxyA.address); + + ProxyB = new BalancerImplementation__factory(signer) + proxyB = await ProxyB.deploy() + await proxyB.deployed() + console.log("Balancer proxy deployed at: ", proxyB.address); + + + ProxyM = new MakerImplementation__factory(signer) + proxyM = await ProxyM.deploy() + await proxyM.deployed() + console.log("Maker proxy deployed at: ", proxyM.address); + + + Aggregator = new InstaFlashAggregator__factory(signer) + aggregator = await Aggregator.deploy() + await aggregator.deployed() + console.log("aggregator deployed at: ", aggregator.address); + + const data = iface.encodeFunctionData('initialize', [ + [ + '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643', // DAI + '0xf650C3d88D12dB855b8bf7D11Be6C55A4e07dCC9', // USDT + '0x39AA39c021dfbaE8faC545936693aC917d5E7563', // USDC + '0xe65cdb6479bac1e22340e4e755fae7e509ecd06c', // AAVE + '0x6c8c6b02e7b2be14d4fa6022dfd6d75921d90e4e', // BAT + '0x70e36f6bf80a52b3b46b3af8e106cc0ed743e8e4', // COMP + '0xface851a4921ce59e912d19329929ce6da6eb0c7', // LINK + '0x95b4ef2869ebd94beb4eee400a99824bf5dc325b', // MKR + '0x158079ee67fce2f58472a96584a73c7ab9ac95c1', // REP + '0x4b0181102a0112a2ef11abee5563bb4a3176c9d7', // SUSHI + '0x12392f67bdf24fae0af363c24ac620a2f67dad86', // TUSD + '0x35a18000230da775cac24873d00ff85bccded550', // UNI + '0xccf4429db6322d5c611ee964527d42e5d685dd6a', // WBTC2 + '0x80a2ae356fc9ef4305676f7a3e2ed04e12c33946', // YFI + '0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407', // ZRX + ],master,proxyA.address,proxyB.address,proxyM.address + ]) + + Proxy = new InstaFlashAggregatorProxy__factory(signer) + proxy = await Proxy.deploy(aggregator.address, master, data) + await proxy.deployed() + console.log("Proxy deployed at: ", proxy.address); + + + Receiver = new InstaFlashReceiver__factory(signer) + receiver = await Receiver.deploy(proxy.address) + await receiver.deployed() + console.log("receiver deployed at: ", receiver.address); + + const token_steth = new ethers.Contract( + STETH, + IERC20__factory.abi, + ethers.provider, + ) + + const token_dai = new ethers.Contract( + DAI, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_STETH, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.send('hardhat_setBalance', [ + proxy.address, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_DAI], + }) + + const signer_dai = await ethers.getSigner(ACC_DAI) + await token_dai.connect(signer_dai).transfer(receiver.address, dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_STETH], + }) + + const signer_steth = await ethers.getSigner(ACC_STETH) + await token_steth.connect(signer_steth).transfer(receiver.address, steth) + await token_steth.connect(signer_steth).transfer(proxy.address, steth) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_STETH], + }) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [proxy.address], + }) + + const signer_fla = await ethers.getSigner(proxy.address) + await token_dai.connect(signer_fla).approve(aaveLendingAddr, 100) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [proxy.address], + }) + _instaData = '0x' + }) + + describe('Single token', async function () { + it('Should be able to take flashLoan of a single token from AAVE', async function () { + await receiver.flashBorrow([DAI], [Dai], 1, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from MakerDAO', async function () { + await receiver.flashBorrow([DAI], [Dai], 2, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from Compound(MakerDAO)', async function () { + await receiver.flashBorrow([DAI], [Dai], 3, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from AAVE(MakerDAO)', async function () { + await receiver.flashBorrow([DAI], [Dai], 4, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from Balancer', async function () { + await receiver.flashBorrow([DAI], [Dai], 5, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from Compound(Balancer)', async function () { + await receiver.flashBorrow([DAI], [Dai], 6, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from AAVE(Balancer)', async function () { + await receiver.flashBorrow([DAI], [Dai], 7, _data, _instaData) + }) + it('Should be able to take flashLoan of a steth token from AAVE(Balancer)', async function () { + await receiver.flashBorrow([STETH], [Steth], 5, _data, _instaData) + }) + }) + + describe('Multi token', async function () { + beforeEach(async function () { + const token_usdt = new ethers.Contract( + USDT, + IERC20__factory.abi, + ethers.provider, + ) + + const token_weth = new ethers.Contract( + WETH, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_USDT, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_WETH, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_USDT], + }) + + const signer_usdt = await ethers.getSigner(ACC_USDT) + await token_usdt.connect(signer_usdt).transfer(receiver.address, usdt) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDT], + }) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_WETH], + }) + + const signer_weth = await ethers.getSigner(ACC_WETH) + await token_weth.connect(signer_weth).transfer(receiver.address, weth) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_WETH], + }) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [proxy.address], + }) + + const signer_fla = await ethers.getSigner(proxy.address) + await token_usdt.connect(signer_fla).approve(aaveLendingAddr, 100) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [proxy.address], + }) + _instaData = '0x' + }) + + it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 1, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from MakerDAO', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 2, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from Compound(MakerDAO)', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 3, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from AAVE(MakerDAO)', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 4, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple sorted tokens together from Balancer', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 5, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple unsorted tokens together from Balancer', async function () { + await receiver.flashBorrow( + [USDT, DAI, WETH], + [Usdt, Dai, Weth], + 5, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from Compound(Balancer)', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 6, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from AAVE(Balancer)', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 7, + _data, + _instaData, + ) + }) + }) +}) diff --git a/test/mainnet/newFlashAggr.ts b/test/mainnet/newFlashAggr.ts deleted file mode 100644 index 70cc657b..00000000 --- a/test/mainnet/newFlashAggr.ts +++ /dev/null @@ -1,360 +0,0 @@ -const hre = require('hardhat') -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -const { ethers } = hre - - -import { - AaveImplementation, - BalancerImplementation, - MakerImplementation, - AaveImplementation__factory, - BalancerImplementation__factory, - MakerImplementation__factory, - InstaFlashAggregator, - InstaFlashAggregator__factory, - IERC20__factory, - IERC20, - InstaFlashReceiver__factory, - InstaFlashReceiver, - InstaFlashAggregatorProxy, - InstaFlashAggregatorProxy__factory, - } from '../../typechain' - - describe('FlashLoan', function () { - - let proxyA : AaveImplementation, - proxyB : BalancerImplementation, - proxyM : MakerImplementation, - aggregator : InstaFlashAggregator, - Proxy, - proxy: InstaFlashAggregatorProxy, - ProxyA, - ProxyB, - ProxyM, - aaveImp,BalancerImp,MakerImp, - Aggregator, - admin = "0xb208CDF8e1c319d0019397dceC8E0bA3Fb9A149F", - proxyAddr = "0x619Ad2D02dBeE6ebA3CDbDA3F98430410e892882", - Receiver, - receiver: InstaFlashReceiver - - let signer: SignerWithAddress - - const _data = '0x' - let _instaData = '0x' - const master = '0xa8c31E39e40E6765BEdBd83D92D6AA0B33f1CCC5' - const aaveLendingAddr = '0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9' - let ABI = ['function initialize(address[],address,address,address,address)'] - let iface = new ethers.utils.Interface(ABI) - - const DAI = '0x6b175474e89094c44da98b954eedeac495271d0f' - const USDT = '0xdac17f958d2ee523a2206206994597c13d831ec7' - const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' - const STETH = '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84' - - const ACC_DAI = '0x9a7a9d980ed6239b89232c012e21f4c210f4bef1' - const ACC_USDT = '0x6D5Be15f9Aa170e207C043CDf8E0BaDbF2A48ed0' - const ACC_WETH = '0xe78388b4ce79068e89bf8aa7f218ef6b9ab0e9d0' - const ACC_STETH = '0xdc24316b9ae028f1497c275eb9192a3ea0f67022' - - const dai = ethers.utils.parseUnits('10', 18) - const usdt = ethers.utils.parseUnits('10', 6) - const weth = ethers.utils.parseUnits('10', 18) - const Dai = ethers.utils.parseUnits('5000', 18) - const Usdt = ethers.utils.parseUnits('5000', 6) - const Weth = ethers.utils.parseUnits('1000', 18) - const steth = ethers.utils.parseUnits('1', 18) - const Steth = ethers.utils.parseUnits('100', 18) - - - beforeEach(async function () { - ;[signer] = await ethers.getSigners() - - ProxyA = new AaveImplementation__factory(signer) - proxyA = await ProxyA.deploy() - await proxyA.deployed() - console.log("Aave proxy deployed at: ", proxyA.address); - - - ProxyB = new BalancerImplementation__factory(signer) - proxyB = await ProxyB.deploy() - await proxyB.deployed() - console.log("Balancer proxy deployed at: ", proxyB.address); - - - ProxyM = new MakerImplementation__factory(signer) - proxyM = await ProxyM.deploy() - await proxyM.deployed() - console.log("Maker proxy deployed at: ", proxyM.address); - - - Aggregator = new InstaFlashAggregator__factory(signer) - aggregator = await Aggregator.deploy() - await aggregator.deployed() - console.log("Aggregator deployed at: ", aggregator.address); - - const data = iface.encodeFunctionData('initialize', [ - [ - '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643', // DAI - '0xf650C3d88D12dB855b8bf7D11Be6C55A4e07dCC9', // USDT - '0x39AA39c021dfbaE8faC545936693aC917d5E7563', // USDC - '0xe65cdb6479bac1e22340e4e755fae7e509ecd06c', // AAVE - '0x6c8c6b02e7b2be14d4fa6022dfd6d75921d90e4e', // BAT - '0x70e36f6bf80a52b3b46b3af8e106cc0ed743e8e4', // COMP - '0xface851a4921ce59e912d19329929ce6da6eb0c7', // LINK - '0x95b4ef2869ebd94beb4eee400a99824bf5dc325b', // MKR - '0x158079ee67fce2f58472a96584a73c7ab9ac95c1', // REP - '0x4b0181102a0112a2ef11abee5563bb4a3176c9d7', // SUSHI - '0x12392f67bdf24fae0af363c24ac620a2f67dad86', // TUSD - '0x35a18000230da775cac24873d00ff85bccded550', // UNI - '0xccf4429db6322d5c611ee964527d42e5d685dd6a', // WBTC2 - '0x80a2ae356fc9ef4305676f7a3e2ed04e12c33946', // YFI - '0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407', // ZRX - ],master,proxyA.address,proxyB.address,proxyM.address - ]) - - Proxy = new InstaFlashAggregatorProxy__factory(signer) - proxy = await Proxy.deploy(aggregator.address, master, data) - await proxy.deployed() - console.log("Proxy deployed at: ", proxy.address); - - Receiver = new InstaFlashReceiver__factory(signer) - receiver = await Receiver.deploy(proxy.address) - await receiver.deployed() - console.log("Receiver deployed at: ", receiver.address); - - await hre.network.provider.send('hardhat_setBalance', [ - proxy.address, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - const token_dai = new ethers.Contract( - DAI, - IERC20__factory.abi, - ethers.provider, - ) - - const token_steth = new ethers.Contract( - STETH, - IERC20__factory.abi, - ethers.provider, - ) - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_DAI, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_STETH, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_DAI], - }) - - const signer_dai = await ethers.getSigner(ACC_DAI) - await token_dai.connect(signer_dai).transfer(receiver.address, dai) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_DAI], - }) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_STETH], - }) - - const signer_steth = await ethers.getSigner(ACC_STETH) - await token_steth.connect(signer_steth).transfer(receiver.address, steth) - await token_steth.connect(signer_steth).transfer(proxy.address, steth) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_STETH], - }) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [proxy.address], - }) - - const signer_fla = await ethers.getSigner(proxy.address) - await token_dai.connect(signer_fla).approve(aaveLendingAddr, 100) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [proxy.address], - }) - }) - - describe('Single token', async function () { - it('Should be able to take flashLoan of a single token from AAVE', async function () { - await receiver.flashBorrow([DAI], [Dai], 1, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from MakerDAO', async function () { - await receiver.flashBorrow([DAI], [Dai], 2, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from Compound(MakerDAO)', async function () { - await receiver.flashBorrow([DAI], [Dai], 3, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from AAVE(MakerDAO)', async function () { - await receiver.flashBorrow([DAI], [Dai], 4, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from Balancer', async function () { - await receiver.flashBorrow([DAI], [Dai], 5, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from Compound(Balancer)', async function () { - await receiver.flashBorrow([DAI], [Dai], 6, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from AAVE(Balancer)', async function () { - await receiver.flashBorrow([DAI], [Dai], 7, _data, _instaData) - }) - it('Should be able to take flashLoan of a steth token from AAVE(Balancer)', async function () { - await receiver.flashBorrow([STETH], [Steth], 5, _data, _instaData) - }) - }) - - describe('Multi token', async function () { - beforeEach(async function () { - const token_usdt = new ethers.Contract( - USDT, - IERC20__factory.abi, - ethers.provider, - ) - - const token_weth = new ethers.Contract( - WETH, - IERC20__factory.abi, - ethers.provider, - ) - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_USDT, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_WETH, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_USDT], - }) - - const signer_usdt = await ethers.getSigner(ACC_USDT) - await token_usdt.connect(signer_usdt).transfer(receiver.address, usdt) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_USDT], - }) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_WETH], - }) - - const signer_weth = await ethers.getSigner(ACC_WETH) - await token_weth.connect(signer_weth).transfer(receiver.address, weth) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_WETH], - }) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [proxy.address], - }) - - const signer_fla = await ethers.getSigner(proxy.address) - await token_usdt.connect(signer_fla).approve(aaveLendingAddr, 100) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [proxy.address], - }) - _instaData = '0x' - }) - - it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 1, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple tokens together from MakerDAO', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 2, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple tokens together from Compound(MakerDAO)', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 3, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple tokens together from AAVE(MakerDAO)', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 4, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple sorted tokens together from Balancer', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 5, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple unsorted tokens together from Balancer', async function () { - await receiver.flashBorrow( - [USDT, DAI, WETH], - [Usdt, Dai, Weth], - 5, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple tokens together from Compound(Balancer)', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 6, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple tokens together from AAVE(Balancer)', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 7, - _data, - _instaData, - ) - }) - }) - }) - \ No newline at end of file diff --git a/test/polygon/flashloan.ts b/test/polygon/flashloan.ts index fb675053..64be98e5 100644 --- a/test/polygon/flashloan.ts +++ b/test/polygon/flashloan.ts @@ -48,14 +48,19 @@ describe('FlashLoan', function () { Aggregator = new InstaFlashAggregatorPolygon__factory(signer) aggregator = await Aggregator.deploy() await aggregator.deployed() + console.log("aggregator deployed at: ", aggregator.address); + Proxy = new InstaFlashAggregatorProxy__factory(signer) proxy = await Proxy.deploy(aggregator.address, master, data) await proxy.deployed() + console.log("proxy deployed at: ", proxy.address); + Receiver = new InstaFlashReceiver__factory(signer) receiver = await Receiver.deploy(proxy.address) await receiver.deployed() + console.log("receiver deployed at: ", receiver.address); const token_dai = new ethers.Contract( DAI, From 1277d61a2ffb77057c4ac04b7cebaf98680780d9 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Wed, 25 May 2022 23:29:35 +0530 Subject: [PATCH 21/36] Uni v3 flashloan added --- .../aggregator/mainnet/flashloan/helpers.sol | 30 +++ .../mainnet/flashloan/implUniswap/main.sol | 174 ++++++++++++++++++ .../mainnet/flashloan/interfaces.sol | 9 + .../aggregator/mainnet/flashloan/main.sol | 70 +++++-- .../mainnet/flashloan/variables.sol | 46 ++++- 5 files changed, 300 insertions(+), 29 deletions(-) create mode 100644 contracts/aggregator/mainnet/flashloan/implUniswap/main.sol diff --git a/contracts/aggregator/mainnet/flashloan/helpers.sol b/contracts/aggregator/mainnet/flashloan/helpers.sol index 6fb8ae4d..5228d9b6 100644 --- a/contracts/aggregator/mainnet/flashloan/helpers.sol +++ b/contracts/aggregator/mainnet/flashloan/helpers.sol @@ -349,6 +349,36 @@ contract Helper is HelpersCommon, Variables { return instaList.accountID(_account) > 0; } + /** + * @notice Deterministically computes the pool address given the factory and PoolKey + * @param factory The Uniswap V3 factory contract address + * @param key The PoolKey + * @return pool The contract address of the V3 pool + */ + function computeAddress(address factory, PoolKey memory key) + internal + pure + returns (address pool) + { + require(key.token0 < key.token1, "Token not sorted"); + pool = address( + uint160( + uint256( + keccak256( + abi.encodePacked( + hex"ff", + factory, + keccak256( + abi.encode(key.token0, key.token1, key.fee) + ), + POOL_INIT_CODE_HASH + ) + ) + ) + ) + ); + } + /** * @dev better checking by double encoding the data. * @notice better checking by double encoding the data. diff --git a/contracts/aggregator/mainnet/flashloan/implUniswap/main.sol b/contracts/aggregator/mainnet/flashloan/implUniswap/main.sol new file mode 100644 index 00000000..b2ce197c --- /dev/null +++ b/contracts/aggregator/mainnet/flashloan/implUniswap/main.sol @@ -0,0 +1,174 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../helpers.sol"; + +contract UniswapImplementation is Helper { + + /** + * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. + * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _route route for flashloan. + * @param _data extra data passed. + */ + function flashLoan( + address[] memory _tokens, + uint256[] memory _amounts, + uint256 _route, + bytes calldata _data, + bytes calldata _instadata + ) external reentrancy { + require(_route == 8, "invalid-UNISWAP-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + routeUniswap(_tokens, _amounts, _data, _instadata); + } + + /** + * @dev Middle function for route 8. + * @notice Middle function for route 8. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _data extra data passed. + * @param _instadata pool key encoded + */ + function routeUniswap( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data, + bytes memory _instadata + ) internal { + PoolKey memory key = abi.decode(_instadata, (PoolKey)); + (key.token0, key.token1) = sortTokens(key.token0, key.token1); + + uint256 amount0_; + uint256 amount1_; + + if (_tokens.length == 1) { + require( + (_tokens[0] == key.token0 || _tokens[0] == key.token1), + "tokens-do-not-match-pool" + ); + if (_tokens[0] == key.token0) { + amount0_ = _amounts[0]; + } else { + amount1_ = _amounts[0]; + } + } else if (_tokens.length == 2) { + require( + (_tokens[0] == key.token0 && _tokens[1] == key.token1), + "tokens-do-not-match-pool" + ); + amount0_ = _amounts[0]; + amount1_ = _amounts[1]; + } else { + revert("Number of tokens do not match"); + } + + IUniswapV3Pool pool = IUniswapV3Pool( + computeAddress(uniswapFactoryAddr, key) + ); + + bytes memory data_ = abi.encode( + _tokens, + _amounts, + msg.sender, + key, + _data + ); + dataHash = bytes32(keccak256(data_)); + pool.flash(address(this), amount0_, amount1_, data_); + } + + struct UniswapFlashInfo { + address sender; + PoolKey key; + bytes data; + } + + /** + * @dev Callback function for uniswap flashloan. + * @notice Callback function for uniswap flashloan. + * @param fee0 The fee from calling flash for token0 + * @param fee1 The fee from calling flash for token1 + * @param data extra data passed(includes route info aswell). + */ + function uniswapV3FlashCallback( + uint256 fee0, + uint256 fee1, + bytes memory data + ) external verifyDataHash(data) { + FlashloanVariables memory instaLoanVariables_; + UniswapFlashInfo memory uniswapFlashData_; + ( + instaLoanVariables_._tokens, + instaLoanVariables_._amounts, + uniswapFlashData_.sender, + uniswapFlashData_.key, + uniswapFlashData_.data + ) = abi.decode(data, (address[], uint256[], address, PoolKey, bytes)); + + address pool = computeAddress( + uniswapFactoryAddr, + uniswapFlashData_.key + ); + require(msg.sender == pool, "invalid-sender"); + instaLoanVariables_._iniBals = calculateBalances( + instaLoanVariables_._tokens, + address(this) + ); + + uint256 feeBPS = uint256(uniswapFlashData_.key.fee / 100); + if (feeBPS < InstaFeeBPS) { + feeBPS = InstaFeeBPS; + } + + instaLoanVariables_._instaFees = calculateFees( + instaLoanVariables_._amounts, + feeBPS + ); + + safeTransfer(instaLoanVariables_, uniswapFlashData_.sender); + + if (checkIfDsa(uniswapFlashData_.sender)) { + Address.functionCall( + uniswapFlashData_.sender, + uniswapFlashData_.data, + "DSA-flashloan-fallback-failed" + ); + } else { + InstaFlashReceiverInterface(uniswapFlashData_.sender) + .executeOperation( + instaLoanVariables_._tokens, + instaLoanVariables_._amounts, + instaLoanVariables_._instaFees, + uniswapFlashData_.sender, + uniswapFlashData_.data + ); + } + + instaLoanVariables_._finBals = calculateBalances( + instaLoanVariables_._tokens, + address(this) + ); + + validateFlashloan(instaLoanVariables_); + uint256[] memory fees_; + if (instaLoanVariables_._tokens.length == 2) { + fees_ = new uint256[](2); + fees_[0] = fee0; + fees_[1] = fee1; + } else if ( + instaLoanVariables_._tokens[0] == uniswapFlashData_.key.token0 + ) { + fees_ = new uint256[](1); + fees_[0] = fee0; + } else { + fees_ = new uint256[](1); + fees_[0] = fee1; + } + safeTransferWithFee(instaLoanVariables_, fees_, msg.sender); + } +} diff --git a/contracts/aggregator/mainnet/flashloan/interfaces.sol b/contracts/aggregator/mainnet/flashloan/interfaces.sol index 4d3f4d70..70ec6f07 100644 --- a/contracts/aggregator/mainnet/flashloan/interfaces.sol +++ b/contracts/aggregator/mainnet/flashloan/interfaces.sol @@ -158,3 +158,12 @@ interface IWstETH { function unwrap(uint256 _wstETHAmount) external returns (uint256); } + +interface IUniswapV3Pool { + function flash( + address recipient, + uint256 amount0, + uint256 amount1, + bytes calldata data + ) external; +} diff --git a/contracts/aggregator/mainnet/flashloan/main.sol b/contracts/aggregator/mainnet/flashloan/main.sol index c57a33df..235a10ec 100644 --- a/contracts/aggregator/mainnet/flashloan/main.sol +++ b/contracts/aggregator/mainnet/flashloan/main.sol @@ -138,6 +138,21 @@ contract FlashAggregator is Setups { spell(BALANCER_IMPL, msg.data); } + /** + * @dev Callback function for uniswap flashloan. + * @notice Callback function for uniswap flashloan. + * @param fee0 The fee from calling flash for token0 + * @param fee1 The fee from calling flash for token1 + * @param data extra data passed(includes route info aswell). + */ + function uniswapV3FlashCallback( + uint256 fee0, + uint256 fee1, + bytes memory data + ) external { + spell(UNISWAP_IMPL, msg.data); + } + /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -169,6 +184,8 @@ contract FlashAggregator is Setups { spell(BALANCER_IMPL, msg.data); } else if (_route == 7) { spell(BALANCER_IMPL, msg.data); + } else if (_route == 8) { + spell(UNISWAP_IMPL, msg.data); } else { revert("route-does-not-exist"); } @@ -181,7 +198,7 @@ contract FlashAggregator is Setups { * @notice Function to get the list of available routes. */ function getRoutes() public pure returns (uint16[] memory routes_) { - routes_ = new uint16[](7); + routes_ = new uint16[](8); routes_[0] = 1; routes_[1] = 2; routes_[2] = 3; @@ -189,6 +206,7 @@ contract FlashAggregator is Setups { routes_[4] = 5; routes_[5] = 6; routes_[6] = 7; + routes_[7] = 8; } /** @@ -220,25 +238,37 @@ contract InstaFlashAggregator is FlashAggregator { /* Deprecated */ - // function initialize(address[] memory _ctokens, address owner_) public { - // require(status == 0, "cannot-call-again"); - // require(stETHStatus == 0, "only-once"); - // require(ownerStatus == 0, "only-once"); - // IERC20(daiTokenAddr).safeApprove(address(makerLending), type(uint256).max); - // addTokenToCToken(_ctokens); - // address[] memory cTokens_ = new address[](2); - // cTokens_[0] = cethTokenAddr; - // cTokens_[1] = cdaiTokenAddr; - // uint256[] memory errors_ = troller.enterMarkets(cTokens_); - // for(uint256 j = 0; j < errors_.length; j++){ - // require(errors_[j] == 0, "Comptroller.enterMarkets failed."); - // } - // IERC20(stEthTokenAddr).approve(address(wstEthToken), type(uint256).max); - // owner = owner_; - // ownerStatus = 1; - // stETHStatus = 1; - // status = 1; - // } + function initialize(address[] memory _ctokens, address owner_) public { + require(status == 0, "cannot-call-again"); + require(stETHStatus == 0, "only-once"); + require(ownerStatus == 0, "only-once"); + IERC20(daiTokenAddr).safeApprove(address(makerLending), type(uint256).max); + addTokenToCToken(_ctokens); + address[] memory cTokens_ = new address[](2); + cTokens_[0] = cethTokenAddr; + cTokens_[1] = cdaiTokenAddr; + uint256[] memory errors_ = troller.enterMarkets(cTokens_); + for(uint256 j = 0; j < errors_.length; j++){ + require(errors_[j] == 0, "Comptroller.enterMarkets failed."); + } + IERC20(stEthTokenAddr).approve(address(wstEthToken), type(uint256).max); + owner = owner_; + ownerStatus = 1; + stETHStatus = 1; + status = 1; + } + + /** + * @dev Function to set implementations + * @notice Function to set implementations + * @param uniswap uniswap implementation address + */ + function setImplementations(address aave, address balancer, address maker, address uniswap) public onlyOwner { + AAVE_IMPL = aave; + BALANCER_IMPL = balancer; + MAKER_IMPL = maker; + UNISWAP_IMPL = uniswap; + } receive() external payable {} } diff --git a/contracts/aggregator/mainnet/flashloan/variables.sol b/contracts/aggregator/mainnet/flashloan/variables.sol index 483b3dbc..4da3a0dd 100644 --- a/contracts/aggregator/mainnet/flashloan/variables.sol +++ b/contracts/aggregator/mainnet/flashloan/variables.sol @@ -7,30 +7,50 @@ import "../../common/interface.sol"; contract ConstantVariables { IWeth internal constant wethToken = IWeth(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); + IAaveLending internal constant aaveLending = IAaveLending(0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9); + IERC3156FlashLender internal constant makerLending = IERC3156FlashLender(0x1EB4CF3A948E7D72A198fe073cCb8C7a948cD853); + IBalancerLending internal constant balancerLending = IBalancerLending(0xBA12222222228d8Ba445958a75a0704d566BF2C8); + + IWstETH internal constant wstEthToken = + IWstETH(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0); + + Comptroller internal constant troller = + Comptroller(0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B); + + ListInterface internal constant instaList = + ListInterface(0x4c8a1BEb8a87765788946D6B19C6C6355194AbEb); + address internal constant daiTokenAddr = 0x6B175474E89094C44Da98b954EedeAC495271d0F; + address internal constant cdaiTokenAddr = 0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643; - uint256 internal constant daiBorrowAmount = 500000000000000000000000000; + address internal constant cethTokenAddr = 0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5; - uint256 internal constant wethBorrowAmountPercentage = 80; + address internal constant stEthTokenAddr = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; - IWstETH internal constant wstEthToken = - IWstETH(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0); - Comptroller internal constant troller = - Comptroller(0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B); + address internal constant treasuryAddr = 0x28849D2b63fA8D361e5fc15cB8aBB13019884d09; - ListInterface internal constant instaList = - ListInterface(0x4c8a1BEb8a87765788946D6B19C6C6355194AbEb); + + address public constant uniswapFactoryAddr = + 0x1F98431c8aD98523631AE4a59f267346ea31F984; + + bytes32 internal constant POOL_INIT_CODE_HASH = + 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54; + + uint256 internal constant daiBorrowAmount = 500000000000000000000000000; + + uint256 internal constant wethBorrowAmountPercentage = 80; + uint256 public constant InstaFeeBPS = 5; // in BPS; 1 BPS = 0.01% } @@ -58,7 +78,15 @@ contract Variables is ConstantVariables { mapping(address => bool) public isWhitelisted; + /// @notice The identifying key of the pool + struct PoolKey { + address token0; + address token1; + uint24 fee; + } + address internal AAVE_IMPL; - address internal MAKER_IMPL; address internal BALANCER_IMPL; + address internal MAKER_IMPL; + address internal UNISWAP_IMPL; } From f6b80f46c60315eaee8f9afa8e01da9952e53142 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 26 May 2022 00:24:36 +0530 Subject: [PATCH 22/36] testcases added --- test/mainnet/newFlash.ts | 59 ++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/test/mainnet/newFlash.ts b/test/mainnet/newFlash.ts index dbba0eca..7bf674e9 100644 --- a/test/mainnet/newFlash.ts +++ b/test/mainnet/newFlash.ts @@ -3,20 +3,20 @@ import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' const { ethers } = hre import { - InstaFlashAggregator, InstaFlashAggregator__factory, IERC20__factory, - IERC20, InstaFlashReceiver__factory, InstaFlashReceiver, - InstaFlashAggregatorProxy, InstaFlashAggregatorProxy__factory, + InstaFlashAggregatorProxy, AaveImplementation__factory, + BalancerImplementation__factory, + MakerImplementation__factory, + UniswapImplementation__factory, AaveImplementation, BalancerImplementation, MakerImplementation, - BalancerImplementation__factory, - MakerImplementation__factory + UniswapImplementation } from '../../typechain' describe('FlashLoan', function () { @@ -29,9 +29,11 @@ describe('FlashLoan', function () { proxyA : AaveImplementation, proxyB : BalancerImplementation, proxyM : MakerImplementation, + proxyU : UniswapImplementation, ProxyA, ProxyB, ProxyM, + ProxyU, admin = "0xb208CDF8e1c319d0019397dceC8E0bA3Fb9A149F", proxyAddr = "0x619Ad2D02dBeE6ebA3CDbDA3F98430410e892882", adminSigner @@ -41,7 +43,7 @@ describe('FlashLoan', function () { const master = '0xa8c31E39e40E6765BEdBd83D92D6AA0B33f1CCC5' const aaveLendingAddr = '0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9' - let ABI = ['function initialize(address[],address,address,address,address)'] + let ABI = ['function initialize(address[],address,address,address,address,address)'] let iface = new ethers.utils.Interface(ABI) const DAI = '0x6b175474e89094c44da98b954eedeac495271d0f' @@ -86,6 +88,11 @@ describe('FlashLoan', function () { await proxyM.deployed() console.log("Maker proxy deployed at: ", proxyM.address); + ProxyU = new UniswapImplementation__factory(signer) + proxyU = await ProxyU.deploy() + await proxyU.deployed() + console.log("Uniswap proxy deployed at: ", proxyU.address); + Aggregator = new InstaFlashAggregator__factory(signer) aggregator = await Aggregator.deploy() @@ -109,7 +116,7 @@ describe('FlashLoan', function () { '0xccf4429db6322d5c611ee964527d42e5d685dd6a', // WBTC2 '0x80a2ae356fc9ef4305676f7a3e2ed04e12c33946', // YFI '0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407', // ZRX - ],master,proxyA.address,proxyB.address,proxyM.address + ],master,proxyA.address,proxyB.address,proxyM.address,proxyU.address ]) Proxy = new InstaFlashAggregatorProxy__factory(signer) @@ -117,7 +124,6 @@ describe('FlashLoan', function () { await proxy.deployed() console.log("Proxy deployed at: ", proxy.address); - Receiver = new InstaFlashReceiver__factory(signer) receiver = await Receiver.deploy(proxy.address) await receiver.deployed() @@ -217,6 +223,17 @@ describe('FlashLoan', function () { it('Should be able to take flashLoan of a steth token from AAVE(Balancer)', async function () { await receiver.flashBorrow([STETH], [Steth], 5, _data, _instaData) }) + describe('Uniswap Route', async function () { + beforeEach(async function () { + _instaData = await ethers.utils.defaultAbiCoder.encode( + ['tuple(address, address, uint24)'], + [[DAI, USDT, '500']], + ) + }) + it('Should be able to take flashLoan of a single token from Uniswap', async function () { + await receiver.flashBorrow([DAI], [Dai], 8, _data, _instaData) + }) + }) }) describe('Multi token', async function () { @@ -356,5 +373,31 @@ describe('FlashLoan', function () { _instaData, ) }) + describe('Uniswap Route', async function () { + beforeEach(async function () { + _instaData = await ethers.utils.defaultAbiCoder.encode( + ['tuple(address, address, uint24)'], + [[USDT, DAI, '500']], + ) + }) + it('Should be able to take flashLoan of multiple unsorted tokens together from Uniswap', async function () { + await receiver.flashBorrow( + [USDT, DAI], + [Usdt, Dai], + 8, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens sorted together from Uniswap', async function () { + await receiver.flashBorrow( + [DAI, USDT], + [Dai, Usdt], + 8, + _data, + _instaData, + ) + }) + }) }) }) From baccd8c4081b7f8bf8eb307d9487b2a52037fac3 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 27 May 2022 21:13:58 +0530 Subject: [PATCH 23/36] self-route set up --- .../aggregator/mainnet/flashloan/helpers.sol | 2 + .../mainnet/flashloan/implFLA/main.sol | 223 ++++++++++++++++++ .../aggregator/mainnet/flashloan/main.sol | 61 ++++- .../mainnet/flashloan/variables.sol | 1 + 4 files changed, 277 insertions(+), 10 deletions(-) create mode 100644 contracts/aggregator/mainnet/flashloan/implFLA/main.sol diff --git a/contracts/aggregator/mainnet/flashloan/helpers.sol b/contracts/aggregator/mainnet/flashloan/helpers.sol index 5228d9b6..6ec7d7d1 100644 --- a/contracts/aggregator/mainnet/flashloan/helpers.sol +++ b/contracts/aggregator/mainnet/flashloan/helpers.sol @@ -322,6 +322,8 @@ contract Helper is HelpersCommon, Variables { .getFlashLoanFeePercentage() ) * 100; + } else if (_route == 9){ + BPS_ = InstaFeeBPS; } else { revert("Invalid source"); } diff --git a/contracts/aggregator/mainnet/flashloan/implFLA/main.sol b/contracts/aggregator/mainnet/flashloan/implFLA/main.sol new file mode 100644 index 00000000..3ef59eae --- /dev/null +++ b/contracts/aggregator/mainnet/flashloan/implFLA/main.sol @@ -0,0 +1,223 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +import "../helpers.sol"; + +contract FLAImplementation is Helper { + + /** + * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. + * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. + * @param _tokens token addresses for flashloan. + * @param _amounts list of amounts for the corresponding assets. + * @param _route route for flashloan. + * @param _data extra data passed. + */ + function flashLoan( + address[] memory _tokens, + uint256[] memory _amounts, + uint256 _route, + bytes calldata _data, + bytes calldata // kept for future use by instadapp. Currently not used anywhere. + ) external reentrancy { + require(_route == 9, "invalid-FLA-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + routeFLA(_tokens, _amounts, _data); + } + + function routeFLA( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal returns (bool) { + + FlashloanVariables memory instaLoanVariables_; + instaLoanVariables_._tokens = _tokens; + instaLoanVariables_._amounts = _amounts; + instaLoanVariables_._instaFees = calculateFees( + _amounts, + calculateFeeBPS(9, msg.sender) + ); + instaLoanVariables_._iniBals = calculateBalances( + _tokens, + address(this) + ); + safeTransfer(instaLoanVariables_, msg.sender); + + if (checkIfDsa(msg.sender)) { + Address.functionCall( + msg.sender, + _data, + "DSA-flashloan-fallback-failed" + ); + } else { + require(InstaFlashReceiverInterface(msg.sender).executeOperation( + _tokens, + _amounts, + instaLoanVariables_._instaFees, + msg.sender, + _data + ), "invalid flashloan execution"); + } + + instaLoanVariables_._finBals = calculateBalances( + _tokens, + address(this) + ); + validateFlashloan(instaLoanVariables_); + + return true; + } + +// function routeFLA( +// address[] memory _tokens, +// uint256[] memory _amounts, +// bytes memory _data +// ) internal { +// bytes memory data_ = abi.encode(msg.sender, _data); +// uint256 length_ = _tokens.length; +// uint256[] memory _modes = new uint256[](length_); +// for (uint256 i = 0; i < length_; i++) { +// _modes[i] = 0; +// } +// dataHash = bytes32(keccak256(data_)); +// aaveLending.flashLoan( +// address(this), +// _tokens, +// _amounts, +// _modes, +// address(0), +// data_, +// 3228 +// ); +// for (uint256 i = 0; i < length_; i++) { +// require(vaultFactory.tokenToVault(token) != address(0), 'FLASH_LENDER_UNSUPPORTED_CURRENCY'); +// } +// Vault vault = Vault(vaultFactory.tokenToVault(token)); +// require(vault.isPaused() == false, 'VAULT_IS_PAUSED'); +// require(amount > vault.minAmountForFlash(), 'FLASH_VALUE_IS_LESS_THAN_MIN_AMOUNT'); +// require( +// amount <= vault.stakedToken().balanceOf(address(vault)), +// 'AMOUNT_BIGGER_THAN_BALANCE' +// ); +// uint256 fee = _flashFee(token, amount); +// require(vault.transferToAccount(address(receiver), amount), 'FLASH_LENDER_TRANSFER_FAILED'); +// require( +// receiver.onFlashLoan(msg.sender, token, amount, fee, data) == CALLBACK_SUCCESS, +// 'FLASH_LENDER_CALLBACK_FAILED' +// ); +// require( +// ERC20(vault.stakedToken()).transferFrom( +// address(receiver), +// address(vault), +// amount + fee +// ), +// 'FLASH_LENDER_REPAY_FAILED' +// ); +// uint256 treasuryFee = vault.splitFees(fee); +// emit FlashLoan(address(receiver), token, amount, fee, treasuryFee); +// return true; +// } +// } + + +// /** +// * @dev Allows smartcontracts to access the liquidity of the pool within one transaction, +// * as long as the amount taken plus a fee is returned. +// * IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration. +// * For further details please visit https://developers.aave.com +// * @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface +// * @param assets The addresses of the assets being flash-borrowed +// * @param amounts The amounts amounts being flash-borrowed +// * @param modes Types of the debt to open if the flash loan is not returned: +// * 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver +// * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address +// * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address +// * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2 +// * @param params Variadic packed params to pass to the receiver as extra information +// * @param referralCode Code used to register the integrator originating the operation, for potential rewards. +// * 0 if the action is executed directly by the user, without any middle-man +// **/ +// function flashLoann( +// address receiverAddress, +// address[] calldata assets, +// uint256[] calldata amounts, +// uint256[] calldata modes, +// address onBehalfOf, +// bytes calldata params, +// uint16 referralCode +// ) override whenNotPaused { +// FlashLoanLocalVars memory vars; + +// ValidationLogic.validateFlashloan(assets, amounts); + +// address[] memory aTokenAddresses = new address[](assets.length); +// uint256[] memory premiums = new uint256[](assets.length); + +// vars.receiver = IFlashLoanReceiver(receiverAddress); + +// for (vars.i = 0; vars.i < assets.length; vars.i++) { +// aTokenAddresses[vars.i] = _reserves[assets[vars.i]].aTokenAddress; + +// premiums[vars.i] = amounts[vars.i].mul(FLASHLOAN_PREMIUM_TOTAL).div(10000); + +// IAToken(aTokenAddresses[vars.i]).transferUnderlyingTo(receiverAddress, amounts[vars.i]); +// } + +// require( +// vars.receiver.executeOperation(assets, amounts, premiums, msg.sender, params), +// Errors.LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN +// ); + +// for (vars.i = 0; vars.i < assets.length; vars.i++) { +// vars.currentAsset = assets[vars.i]; +// vars.currentAmount = amounts[vars.i]; +// vars.currentPremium = premiums[vars.i]; +// vars.currentATokenAddress = aTokenAddresses[vars.i]; +// vars.currentAmountPlusPremium = vars.currentAmount.add(vars.currentPremium); + +// if (DataTypes.InterestRateMode(modes[vars.i]) == DataTypes.InterestRateMode.NONE) { +// _reserves[vars.currentAsset].updateState(); +// _reserves[vars.currentAsset].cumulateToLiquidityIndex( +// IERC20(vars.currentATokenAddress).totalSupply(), +// vars.currentPremium +// ); +// _reserves[vars.currentAsset].updateInterestRates( +// vars.currentAsset, +// vars.currentATokenAddress, +// vars.currentAmountPlusPremium, +// 0 +// ); + +// IERC20(vars.currentAsset).safeTransferFrom( +// receiverAddress, +// vars.currentATokenAddress, +// vars.currentAmountPlusPremium +// ); +// } else { +// // If the user chose to not return the funds, the system checks if there is enough collateral and +// // eventually opens a debt position +// _executeBorrow( +// ExecuteBorrowParams( +// vars.currentAsset, +// msg.sender, +// onBehalfOf, +// vars.currentAmount, +// modes[vars.i], +// vars.currentATokenAddress, +// referralCode, +// false +// ) +// ); +// } +// emit FlashLoan( +// receiverAddress, +// msg.sender, +// vars.currentAsset, +// vars.currentAmount, +// vars.currentPremium, +// referralCode +// ); +// } +// } +} \ No newline at end of file diff --git a/contracts/aggregator/mainnet/flashloan/main.sol b/contracts/aggregator/mainnet/flashloan/main.sol index 235a10ec..33d072ef 100644 --- a/contracts/aggregator/mainnet/flashloan/main.sol +++ b/contracts/aggregator/mainnet/flashloan/main.sol @@ -153,6 +153,50 @@ contract FlashAggregator is Setups { spell(UNISWAP_IMPL, msg.data); } + function routeFLA( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal returns (bool) { + + FlashloanVariables memory instaLoanVariables_; + instaLoanVariables_._tokens = _tokens; + instaLoanVariables_._amounts = _amounts; + instaLoanVariables_._instaFees = calculateFees( + _amounts, + calculateFeeBPS(9, msg.sender) + ); + instaLoanVariables_._iniBals = calculateBalances( + _tokens, + address(this) + ); + safeTransfer(instaLoanVariables_, msg.sender); + + if (checkIfDsa(msg.sender)) { + Address.functionCall( + msg.sender, + _data, + "DSA-flashloan-fallback-failed" + ); + } else { + require(InstaFlashReceiverInterface(msg.sender).executeOperation( + _tokens, + _amounts, + instaLoanVariables_._instaFees, + msg.sender, + _data + ), "invalid flashloan execution"); + } + + instaLoanVariables_._finBals = calculateBalances( + _tokens, + address(this) + ); + validateFlashloan(instaLoanVariables_); + + return true; + } + /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -186,6 +230,10 @@ contract FlashAggregator is Setups { spell(BALANCER_IMPL, msg.data); } else if (_route == 8) { spell(UNISWAP_IMPL, msg.data); + } else if (_route == 9) { + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + routeFLA(_tokens, _amounts, _data); } else { revert("route-does-not-exist"); } @@ -198,7 +246,7 @@ contract FlashAggregator is Setups { * @notice Function to get the list of available routes. */ function getRoutes() public pure returns (uint16[] memory routes_) { - routes_ = new uint16[](8); + routes_ = new uint16[](9); routes_[0] = 1; routes_[1] = 2; routes_[2] = 3; @@ -207,6 +255,7 @@ contract FlashAggregator is Setups { routes_[5] = 6; routes_[6] = 7; routes_[7] = 8; + routes_[8] = 9; } /** @@ -238,7 +287,7 @@ contract InstaFlashAggregator is FlashAggregator { /* Deprecated */ - function initialize(address[] memory _ctokens, address owner_) public { + function initialize(address[] memory _ctokens, address owner_, address aave, address balancer, address maker,address uniswap) public { require(status == 0, "cannot-call-again"); require(stETHStatus == 0, "only-once"); require(ownerStatus == 0, "only-once"); @@ -256,14 +305,6 @@ contract InstaFlashAggregator is FlashAggregator { ownerStatus = 1; stETHStatus = 1; status = 1; - } - - /** - * @dev Function to set implementations - * @notice Function to set implementations - * @param uniswap uniswap implementation address - */ - function setImplementations(address aave, address balancer, address maker, address uniswap) public onlyOwner { AAVE_IMPL = aave; BALANCER_IMPL = balancer; MAKER_IMPL = maker; diff --git a/contracts/aggregator/mainnet/flashloan/variables.sol b/contracts/aggregator/mainnet/flashloan/variables.sol index 4da3a0dd..dfce6b0b 100644 --- a/contracts/aggregator/mainnet/flashloan/variables.sol +++ b/contracts/aggregator/mainnet/flashloan/variables.sol @@ -89,4 +89,5 @@ contract Variables is ConstantVariables { address internal BALANCER_IMPL; address internal MAKER_IMPL; address internal UNISWAP_IMPL; + address internal FLA_IMPL; } From 78327ea9e72e91eca7b7b11e5fb6eb826dd1aed3 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sat, 28 May 2022 04:26:30 +0530 Subject: [PATCH 24/36] testcases added --- test/mainnet/updatedFlash.ts | 477 +++++++++++++++++++++++++++++++++++ 1 file changed, 477 insertions(+) create mode 100644 test/mainnet/updatedFlash.ts diff --git a/test/mainnet/updatedFlash.ts b/test/mainnet/updatedFlash.ts new file mode 100644 index 00000000..adabdf21 --- /dev/null +++ b/test/mainnet/updatedFlash.ts @@ -0,0 +1,477 @@ +const hre = require('hardhat') +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +const { ethers } = hre + +import { + InstaFlashAggregator__factory, + IERC20__factory, + InstaFlashReceiver__factory, + InstaFlashReceiver, + InstaFlashAggregatorProxy__factory, + InstaFlashAggregatorProxy, + AaveImplementation__factory, + BalancerImplementation__factory, + MakerImplementation__factory, + UniswapImplementation__factory, + AaveImplementation, + BalancerImplementation, + MakerImplementation, + UniswapImplementation +} from '../../typechain' + +describe('FlashLoan', function () { + let Aggregator, + aggregator, + Receiver, + receiver: InstaFlashReceiver, + Proxy, + proxy: InstaFlashAggregatorProxy, + proxyA : AaveImplementation, + proxyB : BalancerImplementation, + proxyM : MakerImplementation, + proxyU : UniswapImplementation, + ProxyA, + ProxyB, + ProxyM, + ProxyU, + admin = "0xb208CDF8e1c319d0019397dceC8E0bA3Fb9A149F", + proxyAddr = "0x619Ad2D02dBeE6ebA3CDbDA3F98430410e892882", + adminSigner + + let signer: SignerWithAddress + + const master = '0xa8c31E39e40E6765BEdBd83D92D6AA0B33f1CCC5' + const aaveLendingAddr = '0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9' + + let ABI = ['function initialize(address[],address,address,address,address,address)'] + let iface = new ethers.utils.Interface(ABI) + + const DAI = '0x6b175474e89094c44da98b954eedeac495271d0f' + const USDT = '0xdac17f958d2ee523a2206206994597c13d831ec7' + const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' + const ACC_DAI = '0x9a7a9d980ed6239b89232c012e21f4c210f4bef1' + const ACC_USDT = '0x6D5Be15f9Aa170e207C043CDf8E0BaDbF2A48ed0' + const ACC_WETH = '0xe78388b4ce79068e89bf8aa7f218ef6b9ab0e9d0' + + const STETH = '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84' + const ACC_STETH = '0xdc24316b9ae028f1497c275eb9192a3ea0f67022' + + const dai = ethers.utils.parseUnits('10', 18) + const usdt = ethers.utils.parseUnits('10', 6) + const weth = ethers.utils.parseUnits('10', 18) + const Dai = ethers.utils.parseUnits('5000', 18) + const Usdt = ethers.utils.parseUnits('5000', 6) + const Weth = ethers.utils.parseUnits('1000', 18) + const steth = ethers.utils.parseUnits('1', 18) + const Steth = ethers.utils.parseUnits('100', 18) + + const _data = '0x' + + let _instaData = '0x' + + const token_dai = new ethers.Contract( + DAI, + IERC20__factory.abi, + ethers.provider, + ) + + const token_usdt = new ethers.Contract( + USDT, + IERC20__factory.abi, + ethers.provider, + ) + + const token_weth = new ethers.Contract( + WETH, + IERC20__factory.abi, + ethers.provider, + ) + + const token_steth = new ethers.Contract( + STETH, + IERC20__factory.abi, + ethers.provider, + ) + + beforeEach(async function () { + ;[signer] = await ethers.getSigners() + + ProxyA = new AaveImplementation__factory(signer) + proxyA = await ProxyA.deploy() + await proxyA.deployed() + // console.log("Aave proxy deployed at: ", proxyA.address); + + ProxyB = new BalancerImplementation__factory(signer) + proxyB = await ProxyB.deploy() + await proxyB.deployed() + // console.log("Balancer proxy deployed at: ", proxyB.address); + + + ProxyM = new MakerImplementation__factory(signer) + proxyM = await ProxyM.deploy() + await proxyM.deployed() + // console.log("Maker proxy deployed at: ", proxyM.address); + + ProxyU = new UniswapImplementation__factory(signer) + proxyU = await ProxyU.deploy() + await proxyU.deployed() + // console.log("Uniswap proxy deployed at: ", proxyU.address); + + + Aggregator = new InstaFlashAggregator__factory(signer) + aggregator = await Aggregator.deploy() + await aggregator.deployed() + // console.log("aggregator deployed at: ", aggregator.address); + + const data = iface.encodeFunctionData('initialize', [ + [ + '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643', // DAI + '0xf650C3d88D12dB855b8bf7D11Be6C55A4e07dCC9', // USDT + '0x39AA39c021dfbaE8faC545936693aC917d5E7563', // USDC + '0xe65cdb6479bac1e22340e4e755fae7e509ecd06c', // AAVE + '0x6c8c6b02e7b2be14d4fa6022dfd6d75921d90e4e', // BAT + '0x70e36f6bf80a52b3b46b3af8e106cc0ed743e8e4', // COMP + '0xface851a4921ce59e912d19329929ce6da6eb0c7', // LINK + '0x95b4ef2869ebd94beb4eee400a99824bf5dc325b', // MKR + '0x158079ee67fce2f58472a96584a73c7ab9ac95c1', // REP + '0x4b0181102a0112a2ef11abee5563bb4a3176c9d7', // SUSHI + '0x12392f67bdf24fae0af363c24ac620a2f67dad86', // TUSD + '0x35a18000230da775cac24873d00ff85bccded550', // UNI + '0xccf4429db6322d5c611ee964527d42e5d685dd6a', // WBTC2 + '0x80a2ae356fc9ef4305676f7a3e2ed04e12c33946', // YFI + '0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407', // ZRX + ],master,proxyA.address,proxyB.address,proxyM.address,proxyU.address + ]) + + Proxy = new InstaFlashAggregatorProxy__factory(signer) + proxy = await Proxy.deploy(aggregator.address, master, data) + await proxy.deployed() + // console.log("Proxy deployed at: ", proxy.address); + + Receiver = new InstaFlashReceiver__factory(signer) + receiver = await Receiver.deploy(proxy.address) + await receiver.deployed() + // console.log("receiver deployed at: ", receiver.address); + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_STETH, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.send('hardhat_setBalance', [ + proxy.address, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_DAI], + }) + + const signer_dai = await ethers.getSigner(ACC_DAI) + await token_dai.connect(signer_dai).transfer(receiver.address, dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_STETH], + }) + + const signer_steth = await ethers.getSigner(ACC_STETH) + await token_steth.connect(signer_steth).transfer(receiver.address, steth) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_STETH], + }) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [proxy.address], + }) + + const signer_fla = await ethers.getSigner(proxy.address) + await token_dai.connect(signer_fla).approve(aaveLendingAddr, 100) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [proxy.address], + }) + _instaData = '0x' + }) + + describe('Single token', async function () { + it('Should be able to take flashLoan of a single token from AAVE', async function () { + await receiver.flashBorrow([DAI], [Dai], 1, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from MakerDAO', async function () { + await receiver.flashBorrow([DAI], [Dai], 2, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from Compound(MakerDAO)', async function () { + await receiver.flashBorrow([DAI], [Dai], 3, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from AAVE(MakerDAO)', async function () { + await receiver.flashBorrow([DAI], [Dai], 4, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from Balancer', async function () { + await receiver.flashBorrow([DAI], [Dai], 5, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from Compound(Balancer)', async function () { + await receiver.flashBorrow([DAI], [Dai], 6, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from AAVE(Balancer)', async function () { + await receiver.flashBorrow([DAI], [Dai], 7, _data, _instaData) + }) + it('Should be able to take flashLoan of a steth token from AAVE(Balancer)', async function () { + await receiver.flashBorrow([STETH], [Steth], 5, _data, _instaData) + }) + describe('FLA Route', async function () { + beforeEach(async function () { + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_DAI], + }) + + const signer_dai = await ethers.getSigner(ACC_DAI) + await token_dai.connect(signer_dai).transfer(proxy.address, Dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) + }) + + it('Should be able to take flashLoan of a single token from FLA', async function () { + await receiver.flashBorrow([DAI], [Dai], 9, _data, _instaData) + }) + }) + describe('Uniswap Route', async function () { + beforeEach(async function () { + _instaData = await ethers.utils.defaultAbiCoder.encode( + ['tuple(address, address, uint24)'], + [[DAI, USDT, '500']], + ) + }) + it('Should be able to take flashLoan of a single token from Uniswap', async function () { + await receiver.flashBorrow([DAI], [Dai], 8, _data, _instaData) + }) + }) + }) + + describe('Multi token', async function () { + beforeEach(async function () { + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_USDT, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_WETH, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_USDT], + }) + + const signer_usdt = await ethers.getSigner(ACC_USDT) + await token_usdt.connect(signer_usdt).transfer(receiver.address, usdt) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDT], + }) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_WETH], + }) + + const signer_weth = await ethers.getSigner(ACC_WETH) + await token_weth.connect(signer_weth).transfer(receiver.address, weth) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_WETH], + }) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [proxy.address], + }) + + const signer_fla = await ethers.getSigner(proxy.address) + await token_usdt.connect(signer_fla).approve(aaveLendingAddr, 100) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [proxy.address], + }) + _instaData = '0x' + }) + + it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 1, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from MakerDAO', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 2, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from Compound(MakerDAO)', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 3, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from AAVE(MakerDAO)', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 4, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple sorted tokens together from Balancer', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 5, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple unsorted tokens together from Balancer', async function () { + await receiver.flashBorrow( + [USDT, DAI, WETH], + [Usdt, Dai, Weth], + 5, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from Compound(Balancer)', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 6, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens together from AAVE(Balancer)', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 7, + _data, + _instaData, + ) + }) + describe('FLA Route', async function () { + beforeEach(async function () { + await hre.network.provider.send('hardhat_setBalance', [ + ACC_USDT, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_WETH, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_USDT], + }) + + const signer_usdt = await ethers.getSigner(ACC_USDT) + await token_usdt.connect(signer_usdt).transfer(proxy.address, Usdt) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDT], + }) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_WETH], + }) + + const signer_weth = await ethers.getSigner(ACC_WETH) + await token_weth.connect(signer_weth).transfer(proxy.address, Weth) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_WETH], + }) + }) + + it('Should be able to take flashLoan of multiple tokens together from FLA', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 9, + _data, + _instaData, + ) + }) + }) + describe('Uniswap Route', async function () { + beforeEach(async function () { + _instaData = await ethers.utils.defaultAbiCoder.encode( + ['tuple(address, address, uint24)'], + [[USDT, DAI, '500']], + ) + }) + it('Should be able to take flashLoan of multiple unsorted tokens together from Uniswap', async function () { + await receiver.flashBorrow( + [USDT, DAI], + [Usdt, Dai], + 8, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens sorted together from Uniswap', async function () { + await receiver.flashBorrow( + [DAI, USDT], + [Dai, Usdt], + 8, + _data, + _instaData, + ) + }) + }) + }) +}) From 2afdaa0487087fd45ecaa2a30457ef5ca65a77e1 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 29 May 2022 22:40:25 +0530 Subject: [PATCH 25/36] added route 9 - polygon --- .../aggregator/polygon/flashloan/helpers.sol | 2 + .../aggregator/polygon/flashloan/main.sol | 66 +++++++++++++++++-- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/contracts/aggregator/polygon/flashloan/helpers.sol b/contracts/aggregator/polygon/flashloan/helpers.sol index d1eeb83f..78df0a25 100644 --- a/contracts/aggregator/polygon/flashloan/helpers.sol +++ b/contracts/aggregator/polygon/flashloan/helpers.sol @@ -210,6 +210,8 @@ contract Helper is HelpersCommon, Variables { .getFlashLoanFeePercentage() ) * 100; + } else if (_route == 9) { + BPS_ = InstaFeeBPS; } else { revert("Invalid source"); } diff --git a/contracts/aggregator/polygon/flashloan/main.sol b/contracts/aggregator/polygon/flashloan/main.sol index 61a642a8..b2b9a6a0 100644 --- a/contracts/aggregator/polygon/flashloan/main.sol +++ b/contracts/aggregator/polygon/flashloan/main.sol @@ -8,6 +8,7 @@ pragma solidity ^0.8.0; import "./helpers.sol"; import "@openzeppelin/contracts/utils/Address.sol"; +import "hardhat/console.sol"; contract FlashAggregatorPolygon is Helper { using SafeERC20 for IERC20; @@ -70,6 +71,54 @@ contract FlashAggregatorPolygon is Helper { spell(UNISWAP_IMPL, msg.data); } + function routeFLA( + address _receiverAddress, + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal reentrancy returns (bool) {//TODO: doubt + + FlashloanVariables memory instaLoanVariables_; + instaLoanVariables_._tokens = _tokens; + instaLoanVariables_._amounts = _amounts; + instaLoanVariables_._instaFees = calculateFees( + _amounts, + calculateFeeBPS(9) + ); + instaLoanVariables_._iniBals = calculateBalances( + _tokens, + address(this) + ); + console.log("token: ", instaLoanVariables_._tokens[0]); + console.log("balance this: ", IERC20(instaLoanVariables_._tokens[0]).balanceOf(address(this))); + safeTransfer(instaLoanVariables_, _receiverAddress); + + if (checkIfDsa(_receiverAddress)) { + Address.functionCall( + _receiverAddress, + _data, + "DSA-flashloan-fallback-failed" + ); + } else { + require(InstaFlashReceiverInterface(_receiverAddress).executeOperation( + _tokens, + _amounts, + instaLoanVariables_._instaFees, + _receiverAddress, + _data + ), "invalid flashloan execution"); + } + + instaLoanVariables_._finBals = calculateBalances( + _tokens, + address(this) + ); + validateFlashloan(instaLoanVariables_); + + status = 1; + return true; + } + /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -95,6 +144,10 @@ contract FlashAggregatorPolygon is Helper { spell(UNISWAP_IMPL, msg.data); } else if (_route == 2 || _route == 3 || _route == 4 || _route == 6) { revert("this route is only for mainnet"); + } else if (_route == 9) { + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + routeFLA(msg.sender, _tokens, _amounts, _data); } else { revert("route-does-not-exist"); } @@ -107,11 +160,12 @@ contract FlashAggregatorPolygon is Helper { * @notice Function to get the list of available routes. */ function getRoutes() public pure returns (uint16[] memory routes_) { - routes_ = new uint16[](4); + routes_ = new uint16[](5); routes_[0] = 1; routes_[1] = 5; routes_[2] = 7; routes_[3] = 8; + routes_[4] = 9; } /** @@ -149,11 +203,11 @@ contract InstaFlashAggregatorPolygon is FlashAggregatorPolygon { /** * @dev Function created for testing upgradable implementations */ - // function initialize(address aave, address balancer, address uniswap) public { - // AAVE_IMPL = aave; - // BALANCER_IMPL = balancer; - // UNISWAP_IMPL = uniswap; - // } + function initialize(address aave, address balancer, address uniswap) public { + AAVE_IMPL = aave; + BALANCER_IMPL = balancer; + UNISWAP_IMPL = uniswap; + } receive() external payable {} } From a92298fde0cd6a438cceafdf074c61f784362fd7 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 29 May 2022 22:40:43 +0530 Subject: [PATCH 26/36] testcases added - polygon --- test/polygon/updatedFlash.ts | 224 +++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 test/polygon/updatedFlash.ts diff --git a/test/polygon/updatedFlash.ts b/test/polygon/updatedFlash.ts new file mode 100644 index 00000000..3f287a26 --- /dev/null +++ b/test/polygon/updatedFlash.ts @@ -0,0 +1,224 @@ +const hre = require('hardhat') +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +const { ethers } = hre + +import { + InstaFlashAggregatorPolygon__factory, + IERC20__factory, + InstaFlashReceiver__factory, + InstaFlashReceiver, + InstaFlashAggregatorProxy__factory, + UniswapImplementationPolygon__factory, + BalancerImplementationPolygon__factory, + AaveImplementationPolygon__factory +} from '../../typechain' + +describe('FlashLoan', function () { + let Aggregator, + aggregator, + Receiver, + receiver: InstaFlashReceiver, + implUniswap, + ImplUniswap, + implBalancer, + ImplBalancer, + implAave, + ImplAave, + proxyAddr = "0xB2A7F20D10A006B0bEA86Ce42F2524Fde5D6a0F4", + admin = "0x90cf378a297c7ef6dabed36ea5e112c6646bb3a4", + adminSigner + + let signer: SignerWithAddress + + const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' + + let ABI = ['function initialize(address aave, address balancer, address uniswap)'] + let iface = new ethers.utils.Interface(ABI) + + const DAI = '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063' + const USDT = '0xc2132d05d31c914a87c6611c10748aeb04b58e8f' + const ACC_DAI = '0x4a35582a710e1f4b2030a3f826da20bfb6703c09' + const ACC_USDT = '0x0d0707963952f2fba59dd06f2b425ace40b492fe' + //dai < usdt + + const dai = ethers.utils.parseUnits('1000', 18) + const usdt = ethers.utils.parseUnits('1000', 6) + const Dai = ethers.utils.parseUnits('10', 18) + const Usdt = ethers.utils.parseUnits('100', 6) + + const _data = '0x' + + let _instaData = '0x' + + beforeEach(async function () { + ;[signer] = await ethers.getSigners() + Aggregator = new InstaFlashAggregatorPolygon__factory(signer) + aggregator = await Aggregator.deploy() + await aggregator.deployed() + console.log("aggregator deployed at: ", aggregator.address); + + ImplAave = new AaveImplementationPolygon__factory(signer) + implAave = await ImplAave.deploy() + await implAave.deployed() + console.log("implAave deployed at: ", implAave.address); + + ImplBalancer = new BalancerImplementationPolygon__factory(signer) + implBalancer = await ImplBalancer.deploy() + await implBalancer.deployed() + console.log("implBalancer deployed at: ", implBalancer.address); + + ImplUniswap = new UniswapImplementationPolygon__factory(signer) + implUniswap = await ImplUniswap.deploy() + await implUniswap.deployed() + console.log("implUniswap deployed at: ", implUniswap.address); + + const proxy = new ethers.Contract( + proxyAddr, + InstaFlashAggregatorProxy__factory.abi, + ethers.provider, + ) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [admin], + }) + + adminSigner = await ethers.getSigner(admin); + + await hre.network.provider.send('hardhat_setBalance', [ + admin, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + const data = iface.encodeFunctionData('initialize', [implAave.address, implBalancer.address,implUniswap.address]) + await proxy.connect(adminSigner).upgradeToAndCall(aggregator.address, data); + + Receiver = new InstaFlashReceiver__factory(signer) + receiver = await Receiver.deploy(proxy.address) + await receiver.deployed() + console.log("receiver deployed at: ", receiver.address); + + const token_dai = new ethers.Contract( + DAI, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_DAI], + }) + + const signer_dai = await ethers.getSigner(ACC_DAI) + await token_dai.connect(signer_dai).transfer(receiver.address, dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) + _instaData = '0x' + }) + + describe('Single token', async function () { + // it('Should be able to take flashLoan of a single token from AAVE', async function () { + // await receiver.flashBorrow([DAI], [Dai], 1, _data, _instaData) + // }) + // it('Should be able to take flashLoan of a single token from Balancer', async function () { + // await receiver.flashBorrow([DAI], [Dai], 5, _data, _instaData) + // }) + // it('Should be able to take flashLoan of a single token from AAVE(Balancer)', async function () { + // await receiver.flashBorrow([DAI], [Dai], 7, _data, _instaData) + // }) + it("Should be able to take flashLoan of a single token from FLA", async function () { + await receiver.flashBorrow([DAI], [Dai], 9, _data, _instaData) + }) + + // describe('Uniswap Route', async function () { + // beforeEach(async function () { + // _instaData = await ethers.utils.defaultAbiCoder.encode( + // ['tuple(address, address, uint24)'], + // [[DAI, USDT, '500']], + // ) + // }) + // it('Should be able to take flashLoan of a single token from Uniswap', async function () { + // await receiver.flashBorrow([DAI], [Dai], 8, _data, _instaData) + // }) + // }) + }) + + describe('Multi token', async function () { + beforeEach(async function () { + const token = new ethers.Contract( + USDT, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_USDT, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_USDT], + }) + + const signer_usdt = await ethers.getSigner(ACC_USDT) + await token.connect(signer_usdt).transfer(receiver.address, usdt) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDT], + }) + _instaData = '0x' + }) + // it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { + // await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 1, _data, _instaData) + // }) + // it('Should be able to take flashLoan of multiple sorted tokens together from Balancer', async function () { + // await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 5, _data, _instaData) + // }) + // it('Should be able to take flashLoan of multiple unsorted tokens together from Balancer', async function () { + // await receiver.flashBorrow([USDT, DAI], [Usdt, Dai], 5, _data, _instaData) + // }) + // it('Should be able to take flashLoan of multiple tokens together from AAVE(Balancer)', async function () { + // await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 7, _data, _instaData) + // }) + it("Should be able to take flashLoan of multiple tokens together from FLA", async function () { + await receiver.flashBorrow([USDT, DAI], [Usdt, Dai], 9, _data, _instaData); + }) + + // describe('Uniswap Route', async function () { + // beforeEach(async function () { + // _instaData = await ethers.utils.defaultAbiCoder.encode( + // ['tuple(address, address, uint24)'], + // [[USDT, DAI, '500']], + // ) + // }) + // it('Should be able to take flashLoan of multiple unsorted tokens together from Uniswap', async function () { + // await receiver.flashBorrow( + // [USDT, DAI], + // [Usdt, Dai], + // 8, + // _data, + // _instaData, + // ) + // }) + // it('Should be able to take flashLoan of multiple tokens sorted together from Uniswap', async function () { + // await receiver.flashBorrow( + // [DAI, USDT], + // [Dai, Usdt], + // 8, + // _data, + // _instaData, + // ) + // }) + // }) + }) +}) From 4d72798e092891d3774e6f2dea097503054c664d Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 30 May 2022 17:06:44 +0530 Subject: [PATCH 27/36] minor updates --- .../aggregator/polygon/flashloan/main.sol | 13 +- test/polygon/updatedFlash.ts | 117 +++++++++--------- 2 files changed, 64 insertions(+), 66 deletions(-) diff --git a/contracts/aggregator/polygon/flashloan/main.sol b/contracts/aggregator/polygon/flashloan/main.sol index b2b9a6a0..3b426134 100644 --- a/contracts/aggregator/polygon/flashloan/main.sol +++ b/contracts/aggregator/polygon/flashloan/main.sol @@ -8,7 +8,6 @@ pragma solidity ^0.8.0; import "./helpers.sol"; import "@openzeppelin/contracts/utils/Address.sol"; -import "hardhat/console.sol"; contract FlashAggregatorPolygon is Helper { using SafeERC20 for IERC20; @@ -89,8 +88,6 @@ contract FlashAggregatorPolygon is Helper { _tokens, address(this) ); - console.log("token: ", instaLoanVariables_._tokens[0]); - console.log("balance this: ", IERC20(instaLoanVariables_._tokens[0]).balanceOf(address(this))); safeTransfer(instaLoanVariables_, _receiverAddress); if (checkIfDsa(_receiverAddress)) { @@ -203,11 +200,11 @@ contract InstaFlashAggregatorPolygon is FlashAggregatorPolygon { /** * @dev Function created for testing upgradable implementations */ - function initialize(address aave, address balancer, address uniswap) public { - AAVE_IMPL = aave; - BALANCER_IMPL = balancer; - UNISWAP_IMPL = uniswap; - } + // function initialize(address aave, address balancer, address uniswap) public { + // AAVE_IMPL = aave; + // BALANCER_IMPL = balancer; + // UNISWAP_IMPL = uniswap; + // } receive() external payable {} } diff --git a/test/polygon/updatedFlash.ts b/test/polygon/updatedFlash.ts index 3f287a26..14347194 100644 --- a/test/polygon/updatedFlash.ts +++ b/test/polygon/updatedFlash.ts @@ -125,30 +125,30 @@ describe('FlashLoan', function () { }) describe('Single token', async function () { - // it('Should be able to take flashLoan of a single token from AAVE', async function () { - // await receiver.flashBorrow([DAI], [Dai], 1, _data, _instaData) - // }) - // it('Should be able to take flashLoan of a single token from Balancer', async function () { - // await receiver.flashBorrow([DAI], [Dai], 5, _data, _instaData) - // }) - // it('Should be able to take flashLoan of a single token from AAVE(Balancer)', async function () { - // await receiver.flashBorrow([DAI], [Dai], 7, _data, _instaData) - // }) + it('Should be able to take flashLoan of a single token from AAVE', async function () { + await receiver.flashBorrow([DAI], [Dai], 1, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from Balancer', async function () { + await receiver.flashBorrow([DAI], [Dai], 5, _data, _instaData) + }) + it('Should be able to take flashLoan of a single token from AAVE(Balancer)', async function () { + await receiver.flashBorrow([DAI], [Dai], 7, _data, _instaData) + }) it("Should be able to take flashLoan of a single token from FLA", async function () { await receiver.flashBorrow([DAI], [Dai], 9, _data, _instaData) }) - // describe('Uniswap Route', async function () { - // beforeEach(async function () { - // _instaData = await ethers.utils.defaultAbiCoder.encode( - // ['tuple(address, address, uint24)'], - // [[DAI, USDT, '500']], - // ) - // }) - // it('Should be able to take flashLoan of a single token from Uniswap', async function () { - // await receiver.flashBorrow([DAI], [Dai], 8, _data, _instaData) - // }) - // }) + describe('Uniswap Route', async function () { + beforeEach(async function () { + _instaData = await ethers.utils.defaultAbiCoder.encode( + ['tuple(address, address, uint24)'], + [[DAI, USDT, '500']], + ) + }) + it('Should be able to take flashLoan of a single token from Uniswap', async function () { + await receiver.flashBorrow([DAI], [Dai], 8, _data, _instaData) + }) + }) }) describe('Multi token', async function () { @@ -171,6 +171,7 @@ describe('FlashLoan', function () { const signer_usdt = await ethers.getSigner(ACC_USDT) await token.connect(signer_usdt).transfer(receiver.address, usdt) + await token.connect(signer_usdt).transfer(proxyAddr, usdt) await hre.network.provider.request({ method: 'hardhat_stopImpersonatingAccount', @@ -178,47 +179,47 @@ describe('FlashLoan', function () { }) _instaData = '0x' }) - // it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { - // await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 1, _data, _instaData) - // }) - // it('Should be able to take flashLoan of multiple sorted tokens together from Balancer', async function () { - // await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 5, _data, _instaData) - // }) - // it('Should be able to take flashLoan of multiple unsorted tokens together from Balancer', async function () { - // await receiver.flashBorrow([USDT, DAI], [Usdt, Dai], 5, _data, _instaData) - // }) - // it('Should be able to take flashLoan of multiple tokens together from AAVE(Balancer)', async function () { - // await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 7, _data, _instaData) - // }) + it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { + await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 1, _data, _instaData) + }) + it('Should be able to take flashLoan of multiple sorted tokens together from Balancer', async function () { + await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 5, _data, _instaData) + }) + it('Should be able to take flashLoan of multiple unsorted tokens together from Balancer', async function () { + await receiver.flashBorrow([USDT, DAI], [Usdt, Dai], 5, _data, _instaData) + }) + it('Should be able to take flashLoan of multiple tokens together from AAVE(Balancer)', async function () { + await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 7, _data, _instaData) + }) it("Should be able to take flashLoan of multiple tokens together from FLA", async function () { await receiver.flashBorrow([USDT, DAI], [Usdt, Dai], 9, _data, _instaData); }) - // describe('Uniswap Route', async function () { - // beforeEach(async function () { - // _instaData = await ethers.utils.defaultAbiCoder.encode( - // ['tuple(address, address, uint24)'], - // [[USDT, DAI, '500']], - // ) - // }) - // it('Should be able to take flashLoan of multiple unsorted tokens together from Uniswap', async function () { - // await receiver.flashBorrow( - // [USDT, DAI], - // [Usdt, Dai], - // 8, - // _data, - // _instaData, - // ) - // }) - // it('Should be able to take flashLoan of multiple tokens sorted together from Uniswap', async function () { - // await receiver.flashBorrow( - // [DAI, USDT], - // [Dai, Usdt], - // 8, - // _data, - // _instaData, - // ) - // }) - // }) + describe('Uniswap Route', async function () { + beforeEach(async function () { + _instaData = await ethers.utils.defaultAbiCoder.encode( + ['tuple(address, address, uint24)'], + [[USDT, DAI, '500']], + ) + }) + it('Should be able to take flashLoan of multiple unsorted tokens together from Uniswap', async function () { + await receiver.flashBorrow( + [USDT, DAI], + [Usdt, Dai], + 8, + _data, + _instaData, + ) + }) + it('Should be able to take flashLoan of multiple tokens sorted together from Uniswap', async function () { + await receiver.flashBorrow( + [DAI, USDT], + [Dai, Usdt], + 8, + _data, + _instaData, + ) + }) + }) }) }) From e110eb3e29f3c57ca3143f7de75a3721958002c2 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 30 May 2022 22:14:00 +0530 Subject: [PATCH 28/36] route 9 added- Arbitrum --- .../aggregator/arbitrum/flashloan/helpers.sol | 2 + .../aggregator/arbitrum/flashloan/main.sol | 53 ++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/contracts/aggregator/arbitrum/flashloan/helpers.sol b/contracts/aggregator/arbitrum/flashloan/helpers.sol index 2ac4bd41..f6197213 100644 --- a/contracts/aggregator/arbitrum/flashloan/helpers.sol +++ b/contracts/aggregator/arbitrum/flashloan/helpers.sol @@ -141,6 +141,8 @@ contract Helper is HelpersCommon, Variables { .getFlashLoanFeePercentage() ) * 100; + } else if (_route == 9) { + BPS_ = InstaFeeBPS; } else { revert("Invalid source"); } diff --git a/contracts/aggregator/arbitrum/flashloan/main.sol b/contracts/aggregator/arbitrum/flashloan/main.sol index 93e89cdc..f6db4bc0 100644 --- a/contracts/aggregator/arbitrum/flashloan/main.sol +++ b/contracts/aggregator/arbitrum/flashloan/main.sol @@ -48,6 +48,52 @@ contract FlashAggregatorArbitrum is Helper { spell(UNISWAP_IMPL, msg.data); } + function routeFLA( + address _receiverAddress, + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal reentrancy returns (bool) {//TODO: doubt + + FlashloanVariables memory instaLoanVariables_; + instaLoanVariables_._tokens = _tokens; + instaLoanVariables_._amounts = _amounts; + instaLoanVariables_._instaFees = calculateFees( + _amounts, + calculateFeeBPS(9) + ); + instaLoanVariables_._iniBals = calculateBalances( + _tokens, + address(this) + ); + safeTransfer(instaLoanVariables_, _receiverAddress); + + if (checkIfDsa(_receiverAddress)) { + Address.functionCall( + _receiverAddress, + _data, + "DSA-flashloan-fallback-failed" + ); + } else { + require(InstaFlashReceiverInterface(_receiverAddress).executeOperation( + _tokens, + _amounts, + instaLoanVariables_._instaFees, + _receiverAddress, + _data + ), "invalid flashloan execution"); + } + + instaLoanVariables_._finBals = calculateBalances( + _tokens, + address(this) + ); + validateFlashloan(instaLoanVariables_); + + status = 1; + return true; + } + /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -69,6 +115,10 @@ contract FlashAggregatorArbitrum is Helper { spell(BALANCER_IMPL, msg.data); } else if (_route == 8) { spell(UNISWAP_IMPL, msg.data); + } else if (_route == 9) { + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + routeFLA(msg.sender, _tokens, _amounts, _data); } else { revert("route-does-not-exist"); } @@ -81,9 +131,10 @@ contract FlashAggregatorArbitrum is Helper { * @notice Function to get the list of available routes. */ function getRoutes() public pure returns (uint16[] memory routes_) { - routes_ = new uint16[](2); + routes_ = new uint16[](3); routes_[0] = 5; routes_[1] = 8; + routes_[2] = 9; } /** From 8e8ec285b1813adc35713da0cdd4c4ac8506edd4 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 30 May 2022 22:14:19 +0530 Subject: [PATCH 29/36] testcases added - arbitrum --- test/arbitrum/updatedFlash.ts | 217 ++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 test/arbitrum/updatedFlash.ts diff --git a/test/arbitrum/updatedFlash.ts b/test/arbitrum/updatedFlash.ts new file mode 100644 index 00000000..e34fe4e4 --- /dev/null +++ b/test/arbitrum/updatedFlash.ts @@ -0,0 +1,217 @@ +const hre = require('hardhat') +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +const { ethers } = hre + +import { + BalancerImplementationArbitrum__factory, + UniswapImplementationArbitrum__factory, + InstaFlashAggregatorProxy__factory, + IERC20__factory, + InstaFlashReceiver__factory, + InstaFlashReceiver, + InstaFlashAggregatorArbitrum__factory, + } from '../../typechain' + + describe('FlashLoan', function () { + let Aggregator, + aggregator, + Receiver, + receiver: InstaFlashReceiver, + BalancerImp, + UniswapImp, + balancerImpl, + uniswapImpl, + proxyAddr = "0x1f882522DF99820dF8e586b6df8bAae2b91a782d", + admin = "0x82D57efa1cE59A0cA3492e189c72B360c7a1Dcdd", + adminSigner; + + let signer: SignerWithAddress + + const master = '0xa8c31E39e40E6765BEdBd83D92D6AA0B33f1CCC5' + const aaveLendingAddr = '0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9' + + let iface = new ethers.utils.Interface(["function initialize(address bImp,address uImp)"]); + + const USDC = "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8"; + const USDT = "0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9"; + const ACC_USDC = "0xce2cc46682e9c6d5f174af598fb4931a9c0be68e"; + const ACC_USDT = "0x0db3fe3b770c95a0b99d1ed6f2627933466c0dd8"; + //usdt < usdc + + const usdc = ethers.utils.parseUnits("10", 6); + const usdt = ethers.utils.parseUnits("10", 6); + const Usdc = ethers.utils.parseUnits("5000", 6); + const Usdt = ethers.utils.parseUnits("5000", 6); + + const _data = '0x' + + let _instaData = '0x' + + beforeEach('Should set up', async function () { + ;[signer] = await ethers.getSigners() + + Aggregator = new InstaFlashAggregatorArbitrum__factory(signer) + aggregator = await Aggregator.deploy() + await aggregator.deployed() + console.log("aggregator: ", aggregator.address) + + BalancerImp = new BalancerImplementationArbitrum__factory(signer) + balancerImpl = await BalancerImp.deploy() + await balancerImpl.deployed() + console.log("balancerImpl: ", balancerImpl.address) + + UniswapImp = new UniswapImplementationArbitrum__factory(signer) + uniswapImpl = await UniswapImp.deploy() + await uniswapImpl.deployed() + console.log("uniswapImpl: ", uniswapImpl.address) + + const proxy = new ethers.Contract( + proxyAddr, + InstaFlashAggregatorProxy__factory.abi, + ethers.provider, + ) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [admin], + }) + + adminSigner = await ethers.getSigner(admin); + + await hre.network.provider.send('hardhat_setBalance', [ + admin, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + const dataNew = await iface.encodeFunctionData('initialize', [balancerImpl.address,uniswapImpl.address]) + console.log("dataNew: ", dataNew) + await proxy.connect(adminSigner).upgradeToAndCall(aggregator.address, dataNew); + + Receiver = new InstaFlashReceiver__factory(signer); + receiver = await Receiver.deploy(proxyAddr); + await receiver.deployed(); + console.log("receiver: ", receiver.address) + + const token_usdc = new ethers.Contract( + USDC, + IERC20__factory.abi, + ethers.provider + ); + + await hre.network.provider.send("hardhat_setBalance", [ + ACC_USDC, + ethers.utils.parseEther("10.0").toHexString(), + ]); + + await hre.network.provider.request({ + method: "hardhat_impersonateAccount", + params: [ACC_USDC], + }); + + const signer_usdc = await ethers.getSigner(ACC_USDC); + await token_usdc.connect(signer_usdc).transfer(receiver.address, usdc); + await token_usdc.connect(signer_usdc).transfer(proxyAddr, Usdc); + + await hre.network.provider.request({ + method: "hardhat_stopImpersonatingAccount", + params: [ACC_USDC], + }); + _instaData = "0x"; + }) + + describe("Single token", async function () { + it("Should be able to take flashLoan of a single token from Balancer", async function () { + await receiver.flashBorrow([USDC], [Usdc], 5, _data, _instaData); + }); + it("Should be able to take flashLoan of a single token from FLA", async function () { + await receiver.flashBorrow([USDC], [Usdc], 9, _data, _instaData) + }) + }); + + describe("Uniswap Route", async function () { + beforeEach(async function () { + _instaData = await ethers.utils.defaultAbiCoder.encode( + ["tuple(address, address, uint24)"], + [[USDT, USDC, "500"]] + ); + }); + it("Should be able to take flashLoan of a single token from Uniswap", async function () { + await receiver.flashBorrow([USDC], [Usdc], 8, _data, _instaData); + }); + }); + + describe("Multi token", async function () { + beforeEach(async function () { + const token = new ethers.Contract( + USDT, + IERC20__factory.abi, + ethers.provider + ); + + await hre.network.provider.send("hardhat_setBalance", [ + ACC_USDT, + ethers.utils.parseEther("10.0").toHexString(), + ]); + + await hre.network.provider.request({ + method: "hardhat_impersonateAccount", + params: [ACC_USDT], + }); + + const signer_usdt = await ethers.getSigner(ACC_USDT); + await token.connect(signer_usdt).transfer(receiver.address, usdt); + await token.connect(signer_usdt).transfer(proxyAddr, Usdt); + + await hre.network.provider.request({ + method: "hardhat_stopImpersonatingAccount", + params: [ACC_USDT], + }); + _instaData = "0x"; + }); + it("Should be able to take flashLoan of multiple sorted tokens together from Balancer", async function () { + await receiver.flashBorrow( + [USDT, USDC], + [Usdt, Usdc], + 5, + _data, + _instaData + ); + }); + it("Should be able to take flashLoan of multiple unsorted tokens together from Balancer", async function () { + await receiver.flashBorrow( + [USDC, USDT], + [Usdc, Usdt], + 5, + _data, + _instaData + ); + }); + it("Should be able to take flashLoan of multiple tokens together from FLA", async function () { + await receiver.flashBorrow( + [USDT, USDC], + [Usdt, Usdc], + 9, + _data, + _instaData + ); + }); + + describe("Uniswap Route", async function () { + beforeEach(async function () { + _instaData = await ethers.utils.defaultAbiCoder.encode( + ["tuple(address, address, uint24)"], + [[USDT, USDC, "500"]] + ); + }); + it("Should be able to take flashLoan of multiple tokens together from Uniswap", async function () { + await receiver.flashBorrow( + [USDT, USDC], + [Usdt, Usdc], + 8, + _data, + _instaData + ); + }); + }); + }); + }) From 3d13e8a5253e2fbec2277aa7d18d398accfcd5d5 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 31 May 2022 01:18:40 +0530 Subject: [PATCH 30/36] route 9 added - Avalanche --- .../avalanche/flashloan/helpers.sol | 2 + .../aggregator/avalanche/flashloan/main.sol | 53 ++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/contracts/aggregator/avalanche/flashloan/helpers.sol b/contracts/aggregator/avalanche/flashloan/helpers.sol index 7392e3dd..fc3cc0a2 100644 --- a/contracts/aggregator/avalanche/flashloan/helpers.sol +++ b/contracts/aggregator/avalanche/flashloan/helpers.sol @@ -83,6 +83,8 @@ contract Helper is HelpersCommon, Variables { function calculateFeeBPS(uint256 _route) public view returns(uint256 BPS_){ if (_route == 1) { BPS_ = aaveLending.FLASHLOAN_PREMIUM_TOTAL(); + } else if (_route == 9) { + BPS_ = InstaFeeBPS; } else { revert("Invalid source"); } diff --git a/contracts/aggregator/avalanche/flashloan/main.sol b/contracts/aggregator/avalanche/flashloan/main.sol index 642a0cc0..6f632ed3 100644 --- a/contracts/aggregator/avalanche/flashloan/main.sol +++ b/contracts/aggregator/avalanche/flashloan/main.sol @@ -37,6 +37,52 @@ contract FlashAggregatorAvalanche is Helper { return (abi.decode(response_, (bool))); } + function routeFLA( + address _receiverAddress, + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal reentrancy returns (bool) {//TODO: doubt + + FlashloanVariables memory instaLoanVariables_; + instaLoanVariables_._tokens = _tokens; + instaLoanVariables_._amounts = _amounts; + instaLoanVariables_._instaFees = calculateFees( + _amounts, + calculateFeeBPS(9) + ); + instaLoanVariables_._iniBals = calculateBalances( + _tokens, + address(this) + ); + safeTransfer(instaLoanVariables_, _receiverAddress); + + if (checkIfDsa(_receiverAddress)) { + Address.functionCall( + _receiverAddress, + _data, + "DSA-flashloan-fallback-failed" + ); + } else { + require(InstaFlashReceiverInterface(_receiverAddress).executeOperation( + _tokens, + _amounts, + instaLoanVariables_._instaFees, + _receiverAddress, + _data + ), "invalid flashloan execution"); + } + + instaLoanVariables_._finBals = calculateBalances( + _tokens, + address(this) + ); + validateFlashloan(instaLoanVariables_); + + status = 1; + return true; + } + /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -59,6 +105,10 @@ contract FlashAggregatorAvalanche is Helper { if (_route == 1) { spell(AAVE_IMPL, msg.data); + } else if (_route == 9) { + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + routeFLA(msg.sender, _tokens, _amounts, _data); } else if (_route == 2) { revert("this route is only for mainnet"); } else if (_route == 3) { @@ -90,8 +140,9 @@ contract FlashAggregatorAvalanche is Helper { * @notice Function to get the list of available routes. */ function getRoutes() public pure returns (uint16[] memory routes_) { - routes_ = new uint16[](1); + routes_ = new uint16[](2); routes_[0] = 1; + routes_[1] = 9; } /** From e506911903828db3dea3b2ccbabb2b42de8d4d92 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 31 May 2022 01:19:00 +0530 Subject: [PATCH 31/36] testcases added - Avalanche --- test/avalanche/updatedFlash.ts | 147 +++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 test/avalanche/updatedFlash.ts diff --git a/test/avalanche/updatedFlash.ts b/test/avalanche/updatedFlash.ts new file mode 100644 index 00000000..f2fb9f7f --- /dev/null +++ b/test/avalanche/updatedFlash.ts @@ -0,0 +1,147 @@ +const hre = require('hardhat') +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +const { ethers } = hre + +import { + InstaFlashAggregatorAvalanche__factory, + IERC20__factory, + InstaFlashReceiver__factory, + InstaFlashReceiver, + InstaFlashAggregatorProxy__factory, + InstaFlashAggregatorProxy, + AaveImplementationAvalanche, + AaveImplementationAvalanche__factory +} from '../../typechain' + +describe('FlashLoan', function () { + let Aggregator, + aggregator, + Receiver, + receiver: InstaFlashReceiver, + Proxy, + proxy: InstaFlashAggregatorProxy, + ImplAave, + implAave, + proxyAddr = "0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19", + admin = "0x7b0990a249a215c9a88ebec3849920e29725f2d0", + adminSigner + + let signer: SignerWithAddress + + const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' + + let ABI = ['function initialize(address aave)'] + let iface = new ethers.utils.Interface(ABI) + + const DAI = '0xd586e7f844cea2f87f50152665bcbc2c279d8d70' + const USDT = '0xc7198437980c041c805a1edcba50c1ce5db95118' + const ACC_DAI = '0xed2a7edd7413021d440b09d654f3b87712abab66' + const ACC_USDT = '0xed2a7edd7413021d440b09d654f3b87712abab66' + + const dai = ethers.utils.parseUnits('10', 18) + const usdt = ethers.utils.parseUnits('10', 6) + const Dai = ethers.utils.parseUnits('5000', 18) + const Usdt = ethers.utils.parseUnits('5000', 6) + + const zeroAddr = + '0x0000000000000000000000000000000000000000000000000000000000000000' + const _data = '0x' + let _instaData = '' + + + beforeEach(async function () { + ;[signer] = await ethers.getSigners() + Aggregator = new InstaFlashAggregatorAvalanche__factory(signer) + aggregator = await Aggregator.deploy() + await aggregator.deployed() + console.log("aggregator: ", aggregator.address) + + ImplAave = new AaveImplementationAvalanche__factory(signer) + implAave = await ImplAave.deploy() + await implAave.deployed() + console.log("implAave: ", implAave.address) + + const data = iface.encodeFunctionData('initialize',[implAave.address]) + + Proxy = new InstaFlashAggregatorProxy__factory(signer) + proxy = await Proxy.deploy(aggregator.address, master, data) + await proxy.deployed() + console.log("proxy: ", proxy.address) + + Receiver = new InstaFlashReceiver__factory(signer) + receiver = await Receiver.deploy(proxy.address) + await receiver.deployed() + console.log("receiver: ", receiver.address) + + const token_dai = new ethers.Contract( + DAI, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_DAI], + }) + + const signer_dai = await ethers.getSigner(ACC_DAI) + await token_dai.connect(signer_dai).transfer(receiver.address, dai) + await token_dai.connect(signer_dai).transfer(proxy.address, Dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) + _instaData = '0x' + }) + + describe('Single token', async function () { + it('Should be able to take flashLoan of a single token from AAVE', async function () { + await receiver.flashBorrow([DAI], [Dai], 1, zeroAddr,_instaData) + }) + it('Should be able to take flashLoan of a single token from FLA', async function () { + await receiver.flashBorrow([DAI], [Dai], 9, zeroAddr, _instaData) + }) + }) + + describe('Multi token', async function () { + beforeEach(async function () { + const token = new ethers.Contract( + USDT, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_USDT, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_USDT], + }) + + const signer_usdt = await ethers.getSigner(ACC_USDT) + await token.connect(signer_usdt).transfer(receiver.address, usdt) + await token.connect(signer_usdt).transfer(proxy.address, Usdt) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDT], + }) + _instaData = '0x' + }) + it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { + await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 1, zeroAddr,_instaData ) + }) + it('Should be able to take flashLoan of multiple tokens together from FLA', async function () { + await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 9, _data, _instaData ) + }) + }) +}) From 66a2a5d28b8c03e12c479fd34836432357d66640 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 31 May 2022 01:24:35 +0530 Subject: [PATCH 32/36] route 9 added - optimism --- .../aggregator/optimism/flashloan/helpers.sol | 17 ++++++ .../aggregator/optimism/flashloan/main.sol | 57 ++++++++++++++++++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/contracts/aggregator/optimism/flashloan/helpers.sol b/contracts/aggregator/optimism/flashloan/helpers.sol index a4d92c3e..cb5ab880 100644 --- a/contracts/aggregator/optimism/flashloan/helpers.sol +++ b/contracts/aggregator/optimism/flashloan/helpers.sol @@ -122,6 +122,23 @@ contract Helper is HelpersCommon, Variables { } } + /** + * @dev Returns fee for the passed route in BPS. + * @notice Returns fee for the passed route in BPS. 1 BPS == 0.01%. + * @param _route route number for flashloan. + */ + function calculateFeeBPS(uint256 _route) public view returns(uint256 BPS_){ + if (_route == 9) { + BPS_ = InstaFeeBPS; + } else { + revert("Invalid source"); + } + + if (BPS_ < InstaFeeBPS) { + BPS_ = InstaFeeBPS; + } + } + /** * @dev Returns to true if the passed address is a DSA else returns false. * @notice Returns to true if the passed address is a DSA else returns false. diff --git a/contracts/aggregator/optimism/flashloan/main.sol b/contracts/aggregator/optimism/flashloan/main.sol index 6a91dc5f..2b779f70 100644 --- a/contracts/aggregator/optimism/flashloan/main.sol +++ b/contracts/aggregator/optimism/flashloan/main.sol @@ -35,6 +35,52 @@ contract FlashAggregatorOptimism is Helper { spell(UNISWAP_IMPL, msg.data); } + function routeFLA( + address _receiverAddress, + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal reentrancy returns (bool) {//TODO: doubt + + FlashloanVariables memory instaLoanVariables_; + instaLoanVariables_._tokens = _tokens; + instaLoanVariables_._amounts = _amounts; + instaLoanVariables_._instaFees = calculateFees( + _amounts, + calculateFeeBPS(9) + ); + instaLoanVariables_._iniBals = calculateBalances( + _tokens, + address(this) + ); + safeTransfer(instaLoanVariables_, _receiverAddress); + + if (checkIfDsa(_receiverAddress)) { + Address.functionCall( + _receiverAddress, + _data, + "DSA-flashloan-fallback-failed" + ); + } else { + require(InstaFlashReceiverInterface(_receiverAddress).executeOperation( + _tokens, + _amounts, + instaLoanVariables_._instaFees, + _receiverAddress, + _data + ), "invalid flashloan execution"); + } + + instaLoanVariables_._finBals = calculateBalances( + _tokens, + address(this) + ); + validateFlashloan(instaLoanVariables_); + + status = 1; + return true; + } + /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -51,7 +97,13 @@ contract FlashAggregatorOptimism is Helper { bytes calldata _instadata ) external { require(_tokens.length == _amounts.length, "array-lengths-not-same"); - spell(UNISWAP_IMPL, msg.data); + if (_route == 8) { + spell(UNISWAP_IMPL, msg.data); + } else if (_route == 9) { + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + routeFLA(msg.sender, _tokens, _amounts, _data); + } emit LogFlashloan(msg.sender, _route, _tokens, _amounts); } @@ -61,8 +113,9 @@ contract FlashAggregatorOptimism is Helper { * @notice Function to get the list of available routes. */ function getRoutes() public pure returns (uint16[] memory routes_) { - routes_ = new uint16[](1); + routes_ = new uint16[](2); routes_[0] = 8; + routes_[1] = 9; } /** From 153a7b002e303e8ee7f990940e0d6d8a1e9a05e0 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 31 May 2022 01:24:55 +0530 Subject: [PATCH 33/36] testcases added - optimism --- test/optimism/updatedFlash.ts | 167 ++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 test/optimism/updatedFlash.ts diff --git a/test/optimism/updatedFlash.ts b/test/optimism/updatedFlash.ts new file mode 100644 index 00000000..22c1e849 --- /dev/null +++ b/test/optimism/updatedFlash.ts @@ -0,0 +1,167 @@ +const hre = require('hardhat') +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +const { ethers } = hre + +import { + InstaFlashAggregatorOptimism__factory, + IERC20__factory, + InstaFlashReceiver__factory, + InstaFlashReceiver, + InstaFlashAggregatorProxy__factory, + UniswapImplementationOptimism, + UniswapImplementationOptimism__factory +} from '../../typechain' + +describe('FlashLoan', function () { + let Aggregator, + aggregator, + Receiver, + receiver: InstaFlashReceiver, + implUniswap : UniswapImplementationOptimism, + ImplUniswap, + proxyAddr = "0x84E6b05A089d5677A702cF61dc14335b4bE5b282", + admin = "0xd4e5e20ef32b4750d4cd185a8e970b89851e7775", + adminSigner + + let signer: SignerWithAddress + + const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' + + let ABI = ['function initialize(address)'] + let iface = new ethers.utils.Interface(ABI) + + const DAI = '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1' + const USDT = '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58' + const ACC_DAI = '0xadb35413ec50e0afe41039eac8b930d313e94fa4' + const ACC_USDT = '0x9d39fc627a6d9d9f8c831c16995b209548cc3401' + + const dai = ethers.utils.parseUnits('1000', 18) + const usdt = ethers.utils.parseUnits('1000', 6) + const Dai = ethers.utils.parseUnits('5000', 18) + const Usdt = ethers.utils.parseUnits('5000', 6) + + const _data = '0x' + + let _instaData = '0x' + + beforeEach(async function () { + ;[signer] = await ethers.getSigners() + Aggregator = new InstaFlashAggregatorOptimism__factory(signer) + aggregator = await Aggregator.deploy() + await aggregator.deployed() + + ImplUniswap = new UniswapImplementationOptimism__factory(signer) + implUniswap = await ImplUniswap.deploy() + await implUniswap.deployed() + + const proxy = new ethers.Contract( + proxyAddr, + InstaFlashAggregatorProxy__factory.abi, + ethers.provider, + ) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [admin], + }) + + adminSigner = await ethers.getSigner(admin); + + await hre.network.provider.send('hardhat_setBalance', [ + admin, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + const data = iface.encodeFunctionData('initialize',[implUniswap.address]) + console.log("data: ", data) + await proxy.connect(adminSigner).upgradeToAndCall(aggregator.address, data); + + Receiver = new InstaFlashReceiver__factory(signer) + receiver = await Receiver.deploy(proxy.address) + await receiver.deployed() + + const token_dai = new ethers.Contract( + DAI, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_DAI], + }) + + const signer_dai = await ethers.getSigner(ACC_DAI) + await token_dai.connect(signer_dai).transfer(receiver.address, dai) + await token_dai.connect(signer_dai).transfer(proxyAddr, Dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) + + _instaData = await ethers.utils.defaultAbiCoder.encode( + ['tuple(address, address, uint24)'], + [[USDT, DAI, '500']], + ) + }) + + describe('Single token', async function () { + it('Should be able to take flashLoan of a single token from Uniswap', async function () { + await receiver.flashBorrow([DAI], [Dai], 8, _data, _instaData) + }) + it("Should be able to take flashLoan of a single token from FLA", async function () { + await receiver.flashBorrow([DAI], [Dai], 9, _data, _instaData) + }) + }) + + describe('Multi token', async function () { + beforeEach(async function () { + const token = new ethers.Contract( + USDT, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_USDT, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_USDT], + }) + + const signer_usdt = await ethers.getSigner(ACC_USDT) + await token.connect(signer_usdt).transfer(receiver.address, usdt) + await token.connect(signer_usdt).transfer(proxyAddr, Usdt) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDT], + }) + _instaData = await ethers.utils.defaultAbiCoder.encode( + ['tuple(address, address, uint24)'], + [[USDT, DAI, '500']], + ) + }) + it('Should be able to take flashLoan of multiple tokens together from Uniswap', async function () { + await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 8, _data, _instaData) + }) + it("Should be able to take flashLoan of multiple tokens together from FLA", async function () { + await receiver.flashBorrow( + [USDT, DAI], + [Usdt, Dai], + 9, + _data, + _instaData + ); + }) + }) +}) From f0e5ac1d0c343ff810be5d867facfde884947448 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 31 May 2022 19:03:15 +0530 Subject: [PATCH 34/36] updated changes - mainnet --- .../aggregator/mainnet/flashloan/main.sol | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/contracts/aggregator/mainnet/flashloan/main.sol b/contracts/aggregator/mainnet/flashloan/main.sol index 33d072ef..4280507f 100644 --- a/contracts/aggregator/mainnet/flashloan/main.sol +++ b/contracts/aggregator/mainnet/flashloan/main.sol @@ -8,6 +8,7 @@ pragma solidity ^0.8.0; import "./helpers.sol"; import "@openzeppelin/contracts/utils/Address.sol"; +import "hardhat/console.sol"; contract AdminModule is Helper { @@ -154,36 +155,37 @@ contract FlashAggregator is Setups { } function routeFLA( + address _receiverAddress, address[] memory _tokens, uint256[] memory _amounts, bytes memory _data - ) internal returns (bool) { + ) internal reentrancy returns (bool) {//TODO: doubt FlashloanVariables memory instaLoanVariables_; instaLoanVariables_._tokens = _tokens; instaLoanVariables_._amounts = _amounts; instaLoanVariables_._instaFees = calculateFees( _amounts, - calculateFeeBPS(9, msg.sender) + calculateFeeBPS(9, _receiverAddress) ); instaLoanVariables_._iniBals = calculateBalances( _tokens, address(this) ); - safeTransfer(instaLoanVariables_, msg.sender); + safeTransfer(instaLoanVariables_, _receiverAddress); - if (checkIfDsa(msg.sender)) { + if (checkIfDsa(_receiverAddress)) { Address.functionCall( - msg.sender, + _receiverAddress, _data, "DSA-flashloan-fallback-failed" ); } else { - require(InstaFlashReceiverInterface(msg.sender).executeOperation( + require(InstaFlashReceiverInterface(_receiverAddress).executeOperation( _tokens, _amounts, instaLoanVariables_._instaFees, - msg.sender, + _receiverAddress, _data ), "invalid flashloan execution"); } @@ -194,6 +196,7 @@ contract FlashAggregator is Setups { ); validateFlashloan(instaLoanVariables_); + status = 1; return true; } @@ -233,7 +236,7 @@ contract FlashAggregator is Setups { } else if (_route == 9) { (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); - routeFLA(_tokens, _amounts, _data); + routeFLA(msg.sender, _tokens, _amounts, _data); } else { revert("route-does-not-exist"); } @@ -287,29 +290,25 @@ contract InstaFlashAggregator is FlashAggregator { /* Deprecated */ - function initialize(address[] memory _ctokens, address owner_, address aave, address balancer, address maker,address uniswap) public { - require(status == 0, "cannot-call-again"); - require(stETHStatus == 0, "only-once"); - require(ownerStatus == 0, "only-once"); - IERC20(daiTokenAddr).safeApprove(address(makerLending), type(uint256).max); - addTokenToCToken(_ctokens); - address[] memory cTokens_ = new address[](2); - cTokens_[0] = cethTokenAddr; - cTokens_[1] = cdaiTokenAddr; - uint256[] memory errors_ = troller.enterMarkets(cTokens_); - for(uint256 j = 0; j < errors_.length; j++){ - require(errors_[j] == 0, "Comptroller.enterMarkets failed."); - } - IERC20(stEthTokenAddr).approve(address(wstEthToken), type(uint256).max); - owner = owner_; - ownerStatus = 1; - stETHStatus = 1; - status = 1; - AAVE_IMPL = aave; - BALANCER_IMPL = balancer; - MAKER_IMPL = maker; - UNISWAP_IMPL = uniswap; - } + // function initialize(address[] memory _ctokens, address owner_) public { + // require(status == 0, "cannot-call-again"); + // require(stETHStatus == 0, "only-once"); + // require(ownerStatus == 0, "only-once"); + // IERC20(daiTokenAddr).safeApprove(address(makerLending), type(uint256).max); + // addTokenToCToken(_ctokens); + // address[] memory cTokens_ = new address[](2); + // cTokens_[0] = cethTokenAddr; + // cTokens_[1] = cdaiTokenAddr; + // uint256[] memory errors_ = troller.enterMarkets(cTokens_); + // for(uint256 j = 0; j < errors_.length; j++){ + // require(errors_[j] == 0, "Comptroller.enterMarkets failed."); + // } + // IERC20(stEthTokenAddr).approve(address(wstEthToken), type(uint256).max); + // owner = owner_; + // ownerStatus = 1; + // stETHStatus = 1; + // status = 1; + // } receive() external payable {} } From fba997dd0d9e79cd56a187f3ab47b16adac8c085 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 31 May 2022 19:04:08 +0530 Subject: [PATCH 35/36] updated testcases -mainnet --- test/mainnet/updatedFlash.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/mainnet/updatedFlash.ts b/test/mainnet/updatedFlash.ts index adabdf21..70da7ef1 100644 --- a/test/mainnet/updatedFlash.ts +++ b/test/mainnet/updatedFlash.ts @@ -435,6 +435,22 @@ describe('FlashLoan', function () { method: 'hardhat_stopImpersonatingAccount', params: [ACC_WETH], }) + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_DAI], + }) + + const signer_dai = await ethers.getSigner(ACC_DAI) + await token_dai.connect(signer_dai).transfer(proxy.address, Dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) }) it('Should be able to take flashLoan of multiple tokens together from FLA', async function () { From bf09018acbcd112c9f40836116d0f2e2c98ac39d Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Wed, 1 Jun 2022 03:00:13 +0530 Subject: [PATCH 36/36] minor updates --- .../mainnet/flashloan/implFLA/main.sol | 223 -------- .../aggregator/mainnet/flashloan/main.sol | 1 - contracts/misc/InstaReceiver.sol | 1 + test/arbitrum/newFlashloan.ts | 19 +- test/arbitrum/updatedFlash.ts | 217 -------- test/avalanche/newFlashloan.ts | 16 +- test/avalanche/updatedFlash.ts | 147 ------ test/mainnet/newFlash.ts | 147 ++++-- test/mainnet/updatedFlash.ts | 493 ------------------ test/optimism/newFlash.ts | 15 +- test/optimism/updatedFlash.ts | 167 ------ test/polygon/newFlashloan.ts | 13 +- test/polygon/updatedFlash.ts | 225 -------- 13 files changed, 162 insertions(+), 1522 deletions(-) delete mode 100644 contracts/aggregator/mainnet/flashloan/implFLA/main.sol delete mode 100644 test/arbitrum/updatedFlash.ts delete mode 100644 test/avalanche/updatedFlash.ts delete mode 100644 test/mainnet/updatedFlash.ts delete mode 100644 test/optimism/updatedFlash.ts delete mode 100644 test/polygon/updatedFlash.ts diff --git a/contracts/aggregator/mainnet/flashloan/implFLA/main.sol b/contracts/aggregator/mainnet/flashloan/implFLA/main.sol deleted file mode 100644 index 3ef59eae..00000000 --- a/contracts/aggregator/mainnet/flashloan/implFLA/main.sol +++ /dev/null @@ -1,223 +0,0 @@ -//SPDX-License-Identifier: Unlicense -pragma solidity ^0.8.0; -import "../helpers.sol"; - -contract FLAImplementation is Helper { - - /** - * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. - * @notice Main function for flashloan for all routes. Calls the middle functions according to routes. - * @param _tokens token addresses for flashloan. - * @param _amounts list of amounts for the corresponding assets. - * @param _route route for flashloan. - * @param _data extra data passed. - */ - function flashLoan( - address[] memory _tokens, - uint256[] memory _amounts, - uint256 _route, - bytes calldata _data, - bytes calldata // kept for future use by instadapp. Currently not used anywhere. - ) external reentrancy { - require(_route == 9, "invalid-FLA-route"); - (_tokens, _amounts) = bubbleSort(_tokens, _amounts); - validateTokens(_tokens); - routeFLA(_tokens, _amounts, _data); - } - - function routeFLA( - address[] memory _tokens, - uint256[] memory _amounts, - bytes memory _data - ) internal returns (bool) { - - FlashloanVariables memory instaLoanVariables_; - instaLoanVariables_._tokens = _tokens; - instaLoanVariables_._amounts = _amounts; - instaLoanVariables_._instaFees = calculateFees( - _amounts, - calculateFeeBPS(9, msg.sender) - ); - instaLoanVariables_._iniBals = calculateBalances( - _tokens, - address(this) - ); - safeTransfer(instaLoanVariables_, msg.sender); - - if (checkIfDsa(msg.sender)) { - Address.functionCall( - msg.sender, - _data, - "DSA-flashloan-fallback-failed" - ); - } else { - require(InstaFlashReceiverInterface(msg.sender).executeOperation( - _tokens, - _amounts, - instaLoanVariables_._instaFees, - msg.sender, - _data - ), "invalid flashloan execution"); - } - - instaLoanVariables_._finBals = calculateBalances( - _tokens, - address(this) - ); - validateFlashloan(instaLoanVariables_); - - return true; - } - -// function routeFLA( -// address[] memory _tokens, -// uint256[] memory _amounts, -// bytes memory _data -// ) internal { -// bytes memory data_ = abi.encode(msg.sender, _data); -// uint256 length_ = _tokens.length; -// uint256[] memory _modes = new uint256[](length_); -// for (uint256 i = 0; i < length_; i++) { -// _modes[i] = 0; -// } -// dataHash = bytes32(keccak256(data_)); -// aaveLending.flashLoan( -// address(this), -// _tokens, -// _amounts, -// _modes, -// address(0), -// data_, -// 3228 -// ); -// for (uint256 i = 0; i < length_; i++) { -// require(vaultFactory.tokenToVault(token) != address(0), 'FLASH_LENDER_UNSUPPORTED_CURRENCY'); -// } -// Vault vault = Vault(vaultFactory.tokenToVault(token)); -// require(vault.isPaused() == false, 'VAULT_IS_PAUSED'); -// require(amount > vault.minAmountForFlash(), 'FLASH_VALUE_IS_LESS_THAN_MIN_AMOUNT'); -// require( -// amount <= vault.stakedToken().balanceOf(address(vault)), -// 'AMOUNT_BIGGER_THAN_BALANCE' -// ); -// uint256 fee = _flashFee(token, amount); -// require(vault.transferToAccount(address(receiver), amount), 'FLASH_LENDER_TRANSFER_FAILED'); -// require( -// receiver.onFlashLoan(msg.sender, token, amount, fee, data) == CALLBACK_SUCCESS, -// 'FLASH_LENDER_CALLBACK_FAILED' -// ); -// require( -// ERC20(vault.stakedToken()).transferFrom( -// address(receiver), -// address(vault), -// amount + fee -// ), -// 'FLASH_LENDER_REPAY_FAILED' -// ); -// uint256 treasuryFee = vault.splitFees(fee); -// emit FlashLoan(address(receiver), token, amount, fee, treasuryFee); -// return true; -// } -// } - - -// /** -// * @dev Allows smartcontracts to access the liquidity of the pool within one transaction, -// * as long as the amount taken plus a fee is returned. -// * IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration. -// * For further details please visit https://developers.aave.com -// * @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface -// * @param assets The addresses of the assets being flash-borrowed -// * @param amounts The amounts amounts being flash-borrowed -// * @param modes Types of the debt to open if the flash loan is not returned: -// * 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver -// * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address -// * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address -// * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2 -// * @param params Variadic packed params to pass to the receiver as extra information -// * @param referralCode Code used to register the integrator originating the operation, for potential rewards. -// * 0 if the action is executed directly by the user, without any middle-man -// **/ -// function flashLoann( -// address receiverAddress, -// address[] calldata assets, -// uint256[] calldata amounts, -// uint256[] calldata modes, -// address onBehalfOf, -// bytes calldata params, -// uint16 referralCode -// ) override whenNotPaused { -// FlashLoanLocalVars memory vars; - -// ValidationLogic.validateFlashloan(assets, amounts); - -// address[] memory aTokenAddresses = new address[](assets.length); -// uint256[] memory premiums = new uint256[](assets.length); - -// vars.receiver = IFlashLoanReceiver(receiverAddress); - -// for (vars.i = 0; vars.i < assets.length; vars.i++) { -// aTokenAddresses[vars.i] = _reserves[assets[vars.i]].aTokenAddress; - -// premiums[vars.i] = amounts[vars.i].mul(FLASHLOAN_PREMIUM_TOTAL).div(10000); - -// IAToken(aTokenAddresses[vars.i]).transferUnderlyingTo(receiverAddress, amounts[vars.i]); -// } - -// require( -// vars.receiver.executeOperation(assets, amounts, premiums, msg.sender, params), -// Errors.LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN -// ); - -// for (vars.i = 0; vars.i < assets.length; vars.i++) { -// vars.currentAsset = assets[vars.i]; -// vars.currentAmount = amounts[vars.i]; -// vars.currentPremium = premiums[vars.i]; -// vars.currentATokenAddress = aTokenAddresses[vars.i]; -// vars.currentAmountPlusPremium = vars.currentAmount.add(vars.currentPremium); - -// if (DataTypes.InterestRateMode(modes[vars.i]) == DataTypes.InterestRateMode.NONE) { -// _reserves[vars.currentAsset].updateState(); -// _reserves[vars.currentAsset].cumulateToLiquidityIndex( -// IERC20(vars.currentATokenAddress).totalSupply(), -// vars.currentPremium -// ); -// _reserves[vars.currentAsset].updateInterestRates( -// vars.currentAsset, -// vars.currentATokenAddress, -// vars.currentAmountPlusPremium, -// 0 -// ); - -// IERC20(vars.currentAsset).safeTransferFrom( -// receiverAddress, -// vars.currentATokenAddress, -// vars.currentAmountPlusPremium -// ); -// } else { -// // If the user chose to not return the funds, the system checks if there is enough collateral and -// // eventually opens a debt position -// _executeBorrow( -// ExecuteBorrowParams( -// vars.currentAsset, -// msg.sender, -// onBehalfOf, -// vars.currentAmount, -// modes[vars.i], -// vars.currentATokenAddress, -// referralCode, -// false -// ) -// ); -// } -// emit FlashLoan( -// receiverAddress, -// msg.sender, -// vars.currentAsset, -// vars.currentAmount, -// vars.currentPremium, -// referralCode -// ); -// } -// } -} \ No newline at end of file diff --git a/contracts/aggregator/mainnet/flashloan/main.sol b/contracts/aggregator/mainnet/flashloan/main.sol index 4280507f..088269d1 100644 --- a/contracts/aggregator/mainnet/flashloan/main.sol +++ b/contracts/aggregator/mainnet/flashloan/main.sol @@ -8,7 +8,6 @@ pragma solidity ^0.8.0; import "./helpers.sol"; import "@openzeppelin/contracts/utils/Address.sol"; -import "hardhat/console.sol"; contract AdminModule is Helper { diff --git a/contracts/misc/InstaReceiver.sol b/contracts/misc/InstaReceiver.sol index 2ae239fd..61333919 100644 --- a/contracts/misc/InstaReceiver.sol +++ b/contracts/misc/InstaReceiver.sol @@ -45,6 +45,7 @@ contract InstaFlashReceiver { amounts[i] + premiums[i] ); } + return true; } constructor(address flashloan_) { diff --git a/test/arbitrum/newFlashloan.ts b/test/arbitrum/newFlashloan.ts index 11b0b53b..d338a00d 100644 --- a/test/arbitrum/newFlashloan.ts +++ b/test/arbitrum/newFlashloan.ts @@ -53,17 +53,14 @@ import { Aggregator = new InstaFlashAggregatorArbitrum__factory(signer) aggregator = await Aggregator.deploy() await aggregator.deployed() - console.log("aggregator: ", aggregator.address) BalancerImp = new BalancerImplementationArbitrum__factory(signer) balancerImpl = await BalancerImp.deploy() await balancerImpl.deployed() - console.log("balancerImpl: ", balancerImpl.address) UniswapImp = new UniswapImplementationArbitrum__factory(signer) uniswapImpl = await UniswapImp.deploy() await uniswapImpl.deployed() - console.log("uniswapImpl: ", uniswapImpl.address) const proxy = new ethers.Contract( proxyAddr, @@ -84,13 +81,11 @@ import { ]) const dataNew = await iface.encodeFunctionData('initialize', [balancerImpl.address,uniswapImpl.address]) - console.log("dataNew: ", dataNew) await proxy.connect(adminSigner).upgradeToAndCall(aggregator.address, dataNew); Receiver = new InstaFlashReceiver__factory(signer); receiver = await Receiver.deploy(proxyAddr); await receiver.deployed(); - console.log("receiver: ", receiver.address) const token_usdc = new ethers.Contract( USDC, @@ -110,6 +105,7 @@ import { const signer_usdc = await ethers.getSigner(ACC_USDC); await token_usdc.connect(signer_usdc).transfer(receiver.address, usdc); + await token_usdc.connect(signer_usdc).transfer(proxyAddr, Usdc); await hre.network.provider.request({ method: "hardhat_stopImpersonatingAccount", @@ -122,6 +118,9 @@ import { it("Should be able to take flashLoan of a single token from Balancer", async function () { await receiver.flashBorrow([USDC], [Usdc], 5, _data, _instaData); }); + it("Should be able to take flashLoan of a single token from FLA", async function () { + await receiver.flashBorrow([USDC], [Usdc], 9, _data, _instaData) + }) }); describe("Uniswap Route", async function () { @@ -156,6 +155,7 @@ import { const signer_usdt = await ethers.getSigner(ACC_USDT); await token.connect(signer_usdt).transfer(receiver.address, usdt); + await token.connect(signer_usdt).transfer(proxyAddr, Usdt); await hre.network.provider.request({ method: "hardhat_stopImpersonatingAccount", @@ -181,6 +181,15 @@ import { _instaData ); }); + it("Should be able to take flashLoan of multiple tokens together from FLA", async function () { + await receiver.flashBorrow( + [USDT, USDC], + [Usdt, Usdc], + 9, + _data, + _instaData + ); + }) describe("Uniswap Route", async function () { beforeEach(async function () { diff --git a/test/arbitrum/updatedFlash.ts b/test/arbitrum/updatedFlash.ts deleted file mode 100644 index e34fe4e4..00000000 --- a/test/arbitrum/updatedFlash.ts +++ /dev/null @@ -1,217 +0,0 @@ -const hre = require('hardhat') -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -const { ethers } = hre - -import { - BalancerImplementationArbitrum__factory, - UniswapImplementationArbitrum__factory, - InstaFlashAggregatorProxy__factory, - IERC20__factory, - InstaFlashReceiver__factory, - InstaFlashReceiver, - InstaFlashAggregatorArbitrum__factory, - } from '../../typechain' - - describe('FlashLoan', function () { - let Aggregator, - aggregator, - Receiver, - receiver: InstaFlashReceiver, - BalancerImp, - UniswapImp, - balancerImpl, - uniswapImpl, - proxyAddr = "0x1f882522DF99820dF8e586b6df8bAae2b91a782d", - admin = "0x82D57efa1cE59A0cA3492e189c72B360c7a1Dcdd", - adminSigner; - - let signer: SignerWithAddress - - const master = '0xa8c31E39e40E6765BEdBd83D92D6AA0B33f1CCC5' - const aaveLendingAddr = '0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9' - - let iface = new ethers.utils.Interface(["function initialize(address bImp,address uImp)"]); - - const USDC = "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8"; - const USDT = "0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9"; - const ACC_USDC = "0xce2cc46682e9c6d5f174af598fb4931a9c0be68e"; - const ACC_USDT = "0x0db3fe3b770c95a0b99d1ed6f2627933466c0dd8"; - //usdt < usdc - - const usdc = ethers.utils.parseUnits("10", 6); - const usdt = ethers.utils.parseUnits("10", 6); - const Usdc = ethers.utils.parseUnits("5000", 6); - const Usdt = ethers.utils.parseUnits("5000", 6); - - const _data = '0x' - - let _instaData = '0x' - - beforeEach('Should set up', async function () { - ;[signer] = await ethers.getSigners() - - Aggregator = new InstaFlashAggregatorArbitrum__factory(signer) - aggregator = await Aggregator.deploy() - await aggregator.deployed() - console.log("aggregator: ", aggregator.address) - - BalancerImp = new BalancerImplementationArbitrum__factory(signer) - balancerImpl = await BalancerImp.deploy() - await balancerImpl.deployed() - console.log("balancerImpl: ", balancerImpl.address) - - UniswapImp = new UniswapImplementationArbitrum__factory(signer) - uniswapImpl = await UniswapImp.deploy() - await uniswapImpl.deployed() - console.log("uniswapImpl: ", uniswapImpl.address) - - const proxy = new ethers.Contract( - proxyAddr, - InstaFlashAggregatorProxy__factory.abi, - ethers.provider, - ) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [admin], - }) - - adminSigner = await ethers.getSigner(admin); - - await hre.network.provider.send('hardhat_setBalance', [ - admin, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - const dataNew = await iface.encodeFunctionData('initialize', [balancerImpl.address,uniswapImpl.address]) - console.log("dataNew: ", dataNew) - await proxy.connect(adminSigner).upgradeToAndCall(aggregator.address, dataNew); - - Receiver = new InstaFlashReceiver__factory(signer); - receiver = await Receiver.deploy(proxyAddr); - await receiver.deployed(); - console.log("receiver: ", receiver.address) - - const token_usdc = new ethers.Contract( - USDC, - IERC20__factory.abi, - ethers.provider - ); - - await hre.network.provider.send("hardhat_setBalance", [ - ACC_USDC, - ethers.utils.parseEther("10.0").toHexString(), - ]); - - await hre.network.provider.request({ - method: "hardhat_impersonateAccount", - params: [ACC_USDC], - }); - - const signer_usdc = await ethers.getSigner(ACC_USDC); - await token_usdc.connect(signer_usdc).transfer(receiver.address, usdc); - await token_usdc.connect(signer_usdc).transfer(proxyAddr, Usdc); - - await hre.network.provider.request({ - method: "hardhat_stopImpersonatingAccount", - params: [ACC_USDC], - }); - _instaData = "0x"; - }) - - describe("Single token", async function () { - it("Should be able to take flashLoan of a single token from Balancer", async function () { - await receiver.flashBorrow([USDC], [Usdc], 5, _data, _instaData); - }); - it("Should be able to take flashLoan of a single token from FLA", async function () { - await receiver.flashBorrow([USDC], [Usdc], 9, _data, _instaData) - }) - }); - - describe("Uniswap Route", async function () { - beforeEach(async function () { - _instaData = await ethers.utils.defaultAbiCoder.encode( - ["tuple(address, address, uint24)"], - [[USDT, USDC, "500"]] - ); - }); - it("Should be able to take flashLoan of a single token from Uniswap", async function () { - await receiver.flashBorrow([USDC], [Usdc], 8, _data, _instaData); - }); - }); - - describe("Multi token", async function () { - beforeEach(async function () { - const token = new ethers.Contract( - USDT, - IERC20__factory.abi, - ethers.provider - ); - - await hre.network.provider.send("hardhat_setBalance", [ - ACC_USDT, - ethers.utils.parseEther("10.0").toHexString(), - ]); - - await hre.network.provider.request({ - method: "hardhat_impersonateAccount", - params: [ACC_USDT], - }); - - const signer_usdt = await ethers.getSigner(ACC_USDT); - await token.connect(signer_usdt).transfer(receiver.address, usdt); - await token.connect(signer_usdt).transfer(proxyAddr, Usdt); - - await hre.network.provider.request({ - method: "hardhat_stopImpersonatingAccount", - params: [ACC_USDT], - }); - _instaData = "0x"; - }); - it("Should be able to take flashLoan of multiple sorted tokens together from Balancer", async function () { - await receiver.flashBorrow( - [USDT, USDC], - [Usdt, Usdc], - 5, - _data, - _instaData - ); - }); - it("Should be able to take flashLoan of multiple unsorted tokens together from Balancer", async function () { - await receiver.flashBorrow( - [USDC, USDT], - [Usdc, Usdt], - 5, - _data, - _instaData - ); - }); - it("Should be able to take flashLoan of multiple tokens together from FLA", async function () { - await receiver.flashBorrow( - [USDT, USDC], - [Usdt, Usdc], - 9, - _data, - _instaData - ); - }); - - describe("Uniswap Route", async function () { - beforeEach(async function () { - _instaData = await ethers.utils.defaultAbiCoder.encode( - ["tuple(address, address, uint24)"], - [[USDT, USDC, "500"]] - ); - }); - it("Should be able to take flashLoan of multiple tokens together from Uniswap", async function () { - await receiver.flashBorrow( - [USDT, USDC], - [Usdt, Usdc], - 8, - _data, - _instaData - ); - }); - }); - }); - }) diff --git a/test/avalanche/newFlashloan.ts b/test/avalanche/newFlashloan.ts index 54e58fcf..8fde294d 100644 --- a/test/avalanche/newFlashloan.ts +++ b/test/avalanche/newFlashloan.ts @@ -8,6 +8,7 @@ import { InstaFlashReceiver__factory, InstaFlashReceiver, InstaFlashAggregatorProxy__factory, + InstaFlashAggregatorProxy, AaveImplementationAvalanche, AaveImplementationAvalanche__factory } from '../../typechain' @@ -18,7 +19,7 @@ describe('FlashLoan', function () { Receiver, receiver: InstaFlashReceiver, Proxy, - proxy, + proxy: InstaFlashAggregatorProxy, ImplAave, implAave, proxyAddr = "0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19", @@ -44,6 +45,7 @@ describe('FlashLoan', function () { const zeroAddr = '0x0000000000000000000000000000000000000000000000000000000000000000' + const _data = '0x' let _instaData = '' @@ -52,24 +54,20 @@ describe('FlashLoan', function () { Aggregator = new InstaFlashAggregatorAvalanche__factory(signer) aggregator = await Aggregator.deploy() await aggregator.deployed() - console.log("aggregator: ", aggregator.address) ImplAave = new AaveImplementationAvalanche__factory(signer) implAave = await ImplAave.deploy() await implAave.deployed() - console.log("implAave: ", implAave.address) const data = iface.encodeFunctionData('initialize',[implAave.address]) Proxy = new InstaFlashAggregatorProxy__factory(signer) proxy = await Proxy.deploy(aggregator.address, master, data) await proxy.deployed() - console.log("proxy: ", proxy.address) Receiver = new InstaFlashReceiver__factory(signer) receiver = await Receiver.deploy(proxy.address) await receiver.deployed() - console.log("receiver: ", receiver.address) const token_dai = new ethers.Contract( DAI, @@ -89,6 +87,7 @@ describe('FlashLoan', function () { const signer_dai = await ethers.getSigner(ACC_DAI) await token_dai.connect(signer_dai).transfer(receiver.address, dai) + await token_dai.connect(signer_dai).transfer(proxy.address, Dai) await hre.network.provider.request({ method: 'hardhat_stopImpersonatingAccount', @@ -101,6 +100,9 @@ describe('FlashLoan', function () { it('Should be able to take flashLoan of a single token from AAVE', async function () { await receiver.flashBorrow([DAI], [Dai], 1, zeroAddr,_instaData) }) + it('Should be able to take flashLoan of a single token from FLA', async function () { + await receiver.flashBorrow([DAI], [Dai], 9, zeroAddr, _instaData) + }) }) describe('Multi token', async function () { @@ -123,6 +125,7 @@ describe('FlashLoan', function () { const signer_usdt = await ethers.getSigner(ACC_USDT) await token.connect(signer_usdt).transfer(receiver.address, usdt) + await token.connect(signer_usdt).transfer(proxy.address, Usdt) await hre.network.provider.request({ method: 'hardhat_stopImpersonatingAccount', @@ -133,5 +136,8 @@ describe('FlashLoan', function () { it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 1, zeroAddr,_instaData ) }) + it('Should be able to take flashLoan of multiple tokens together from FLA', async function () { + await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 9, _data, _instaData ) + }) }) }) diff --git a/test/avalanche/updatedFlash.ts b/test/avalanche/updatedFlash.ts deleted file mode 100644 index f2fb9f7f..00000000 --- a/test/avalanche/updatedFlash.ts +++ /dev/null @@ -1,147 +0,0 @@ -const hre = require('hardhat') -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -const { ethers } = hre - -import { - InstaFlashAggregatorAvalanche__factory, - IERC20__factory, - InstaFlashReceiver__factory, - InstaFlashReceiver, - InstaFlashAggregatorProxy__factory, - InstaFlashAggregatorProxy, - AaveImplementationAvalanche, - AaveImplementationAvalanche__factory -} from '../../typechain' - -describe('FlashLoan', function () { - let Aggregator, - aggregator, - Receiver, - receiver: InstaFlashReceiver, - Proxy, - proxy: InstaFlashAggregatorProxy, - ImplAave, - implAave, - proxyAddr = "0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19", - admin = "0x7b0990a249a215c9a88ebec3849920e29725f2d0", - adminSigner - - let signer: SignerWithAddress - - const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' - - let ABI = ['function initialize(address aave)'] - let iface = new ethers.utils.Interface(ABI) - - const DAI = '0xd586e7f844cea2f87f50152665bcbc2c279d8d70' - const USDT = '0xc7198437980c041c805a1edcba50c1ce5db95118' - const ACC_DAI = '0xed2a7edd7413021d440b09d654f3b87712abab66' - const ACC_USDT = '0xed2a7edd7413021d440b09d654f3b87712abab66' - - const dai = ethers.utils.parseUnits('10', 18) - const usdt = ethers.utils.parseUnits('10', 6) - const Dai = ethers.utils.parseUnits('5000', 18) - const Usdt = ethers.utils.parseUnits('5000', 6) - - const zeroAddr = - '0x0000000000000000000000000000000000000000000000000000000000000000' - const _data = '0x' - let _instaData = '' - - - beforeEach(async function () { - ;[signer] = await ethers.getSigners() - Aggregator = new InstaFlashAggregatorAvalanche__factory(signer) - aggregator = await Aggregator.deploy() - await aggregator.deployed() - console.log("aggregator: ", aggregator.address) - - ImplAave = new AaveImplementationAvalanche__factory(signer) - implAave = await ImplAave.deploy() - await implAave.deployed() - console.log("implAave: ", implAave.address) - - const data = iface.encodeFunctionData('initialize',[implAave.address]) - - Proxy = new InstaFlashAggregatorProxy__factory(signer) - proxy = await Proxy.deploy(aggregator.address, master, data) - await proxy.deployed() - console.log("proxy: ", proxy.address) - - Receiver = new InstaFlashReceiver__factory(signer) - receiver = await Receiver.deploy(proxy.address) - await receiver.deployed() - console.log("receiver: ", receiver.address) - - const token_dai = new ethers.Contract( - DAI, - IERC20__factory.abi, - ethers.provider, - ) - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_DAI, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_DAI], - }) - - const signer_dai = await ethers.getSigner(ACC_DAI) - await token_dai.connect(signer_dai).transfer(receiver.address, dai) - await token_dai.connect(signer_dai).transfer(proxy.address, Dai) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_DAI], - }) - _instaData = '0x' - }) - - describe('Single token', async function () { - it('Should be able to take flashLoan of a single token from AAVE', async function () { - await receiver.flashBorrow([DAI], [Dai], 1, zeroAddr,_instaData) - }) - it('Should be able to take flashLoan of a single token from FLA', async function () { - await receiver.flashBorrow([DAI], [Dai], 9, zeroAddr, _instaData) - }) - }) - - describe('Multi token', async function () { - beforeEach(async function () { - const token = new ethers.Contract( - USDT, - IERC20__factory.abi, - ethers.provider, - ) - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_USDT, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_USDT], - }) - - const signer_usdt = await ethers.getSigner(ACC_USDT) - await token.connect(signer_usdt).transfer(receiver.address, usdt) - await token.connect(signer_usdt).transfer(proxy.address, Usdt) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_USDT], - }) - _instaData = '0x' - }) - it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { - await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 1, zeroAddr,_instaData ) - }) - it('Should be able to take flashLoan of multiple tokens together from FLA', async function () { - await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 9, _data, _instaData ) - }) - }) -}) diff --git a/test/mainnet/newFlash.ts b/test/mainnet/newFlash.ts index 7bf674e9..fbb78264 100644 --- a/test/mainnet/newFlash.ts +++ b/test/mainnet/newFlash.ts @@ -69,35 +69,52 @@ describe('FlashLoan', function () { let _instaData = '0x' + const token_steth = new ethers.Contract( + STETH, + IERC20__factory.abi, + ethers.provider, + ) + + const token_dai = new ethers.Contract( + DAI, + IERC20__factory.abi, + ethers.provider, + ) + + const token_usdt = new ethers.Contract( + USDT, + IERC20__factory.abi, + ethers.provider, + ) + + const token_weth = new ethers.Contract( + WETH, + IERC20__factory.abi, + ethers.provider, + ) + beforeEach(async function () { ;[signer] = await ethers.getSigners() ProxyA = new AaveImplementation__factory(signer) proxyA = await ProxyA.deploy() await proxyA.deployed() - console.log("Aave proxy deployed at: ", proxyA.address); ProxyB = new BalancerImplementation__factory(signer) proxyB = await ProxyB.deploy() await proxyB.deployed() - console.log("Balancer proxy deployed at: ", proxyB.address); - ProxyM = new MakerImplementation__factory(signer) proxyM = await ProxyM.deploy() await proxyM.deployed() - console.log("Maker proxy deployed at: ", proxyM.address); ProxyU = new UniswapImplementation__factory(signer) proxyU = await ProxyU.deploy() await proxyU.deployed() - console.log("Uniswap proxy deployed at: ", proxyU.address); - Aggregator = new InstaFlashAggregator__factory(signer) aggregator = await Aggregator.deploy() await aggregator.deployed() - console.log("aggregator deployed at: ", aggregator.address); const data = iface.encodeFunctionData('initialize', [ [ @@ -122,24 +139,10 @@ describe('FlashLoan', function () { Proxy = new InstaFlashAggregatorProxy__factory(signer) proxy = await Proxy.deploy(aggregator.address, master, data) await proxy.deployed() - console.log("Proxy deployed at: ", proxy.address); Receiver = new InstaFlashReceiver__factory(signer) receiver = await Receiver.deploy(proxy.address) await receiver.deployed() - console.log("receiver deployed at: ", receiver.address); - - const token_steth = new ethers.Contract( - STETH, - IERC20__factory.abi, - ethers.provider, - ) - - const token_dai = new ethers.Contract( - DAI, - IERC20__factory.abi, - ethers.provider, - ) await hre.network.provider.send('hardhat_setBalance', [ ACC_DAI, @@ -222,7 +225,32 @@ describe('FlashLoan', function () { }) it('Should be able to take flashLoan of a steth token from AAVE(Balancer)', async function () { await receiver.flashBorrow([STETH], [Steth], 5, _data, _instaData) + }) + describe('FLA Route', async function () { + beforeEach(async function () { + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_DAI], + }) + + const signer_dai = await ethers.getSigner(ACC_DAI) + await token_dai.connect(signer_dai).transfer(proxy.address, Dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) + }) + + it('Should be able to take flashLoan of a single token from FLA', async function () { + await receiver.flashBorrow([DAI], [Dai], 9, _data, _instaData) }) + }) describe('Uniswap Route', async function () { beforeEach(async function () { _instaData = await ethers.utils.defaultAbiCoder.encode( @@ -238,18 +266,7 @@ describe('FlashLoan', function () { describe('Multi token', async function () { beforeEach(async function () { - const token_usdt = new ethers.Contract( - USDT, - IERC20__factory.abi, - ethers.provider, - ) - - const token_weth = new ethers.Contract( - WETH, - IERC20__factory.abi, - ethers.provider, - ) - + await hre.network.provider.send('hardhat_setBalance', [ ACC_USDT, ethers.utils.parseEther('10.0').toHexString(), @@ -373,6 +390,70 @@ describe('FlashLoan', function () { _instaData, ) }) + describe('FLA Route', async function () { + beforeEach(async function () { + await hre.network.provider.send('hardhat_setBalance', [ + ACC_USDT, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.send('hardhat_setBalance', [ + ACC_WETH, + ethers.utils.parseEther('10.0').toHexString(), + ]) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_USDT], + }) + + const signer_usdt = await ethers.getSigner(ACC_USDT) + await token_usdt.connect(signer_usdt).transfer(proxy.address, Usdt) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDT], + }) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_WETH], + }) + + const signer_weth = await ethers.getSigner(ACC_WETH) + await token_weth.connect(signer_weth).transfer(proxy.address, Weth) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_WETH], + }) + await hre.network.provider.send('hardhat_setBalance', [ + ACC_DAI, + ethers.utils.parseEther('10.0').toHexString(), + ]) + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_DAI], + }) + + const signer_dai = await ethers.getSigner(ACC_DAI) + await token_dai.connect(signer_dai).transfer(proxy.address, Dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) + }) + it('Should be able to take flashLoan of multiple tokens together from FLA', async function () { + await receiver.flashBorrow( + [DAI, USDT, WETH], + [Dai, Usdt, Weth], + 9, + _data, + _instaData, + ) + }) + }) describe('Uniswap Route', async function () { beforeEach(async function () { _instaData = await ethers.utils.defaultAbiCoder.encode( diff --git a/test/mainnet/updatedFlash.ts b/test/mainnet/updatedFlash.ts deleted file mode 100644 index 70da7ef1..00000000 --- a/test/mainnet/updatedFlash.ts +++ /dev/null @@ -1,493 +0,0 @@ -const hre = require('hardhat') -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -const { ethers } = hre - -import { - InstaFlashAggregator__factory, - IERC20__factory, - InstaFlashReceiver__factory, - InstaFlashReceiver, - InstaFlashAggregatorProxy__factory, - InstaFlashAggregatorProxy, - AaveImplementation__factory, - BalancerImplementation__factory, - MakerImplementation__factory, - UniswapImplementation__factory, - AaveImplementation, - BalancerImplementation, - MakerImplementation, - UniswapImplementation -} from '../../typechain' - -describe('FlashLoan', function () { - let Aggregator, - aggregator, - Receiver, - receiver: InstaFlashReceiver, - Proxy, - proxy: InstaFlashAggregatorProxy, - proxyA : AaveImplementation, - proxyB : BalancerImplementation, - proxyM : MakerImplementation, - proxyU : UniswapImplementation, - ProxyA, - ProxyB, - ProxyM, - ProxyU, - admin = "0xb208CDF8e1c319d0019397dceC8E0bA3Fb9A149F", - proxyAddr = "0x619Ad2D02dBeE6ebA3CDbDA3F98430410e892882", - adminSigner - - let signer: SignerWithAddress - - const master = '0xa8c31E39e40E6765BEdBd83D92D6AA0B33f1CCC5' - const aaveLendingAddr = '0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9' - - let ABI = ['function initialize(address[],address,address,address,address,address)'] - let iface = new ethers.utils.Interface(ABI) - - const DAI = '0x6b175474e89094c44da98b954eedeac495271d0f' - const USDT = '0xdac17f958d2ee523a2206206994597c13d831ec7' - const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' - const ACC_DAI = '0x9a7a9d980ed6239b89232c012e21f4c210f4bef1' - const ACC_USDT = '0x6D5Be15f9Aa170e207C043CDf8E0BaDbF2A48ed0' - const ACC_WETH = '0xe78388b4ce79068e89bf8aa7f218ef6b9ab0e9d0' - - const STETH = '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84' - const ACC_STETH = '0xdc24316b9ae028f1497c275eb9192a3ea0f67022' - - const dai = ethers.utils.parseUnits('10', 18) - const usdt = ethers.utils.parseUnits('10', 6) - const weth = ethers.utils.parseUnits('10', 18) - const Dai = ethers.utils.parseUnits('5000', 18) - const Usdt = ethers.utils.parseUnits('5000', 6) - const Weth = ethers.utils.parseUnits('1000', 18) - const steth = ethers.utils.parseUnits('1', 18) - const Steth = ethers.utils.parseUnits('100', 18) - - const _data = '0x' - - let _instaData = '0x' - - const token_dai = new ethers.Contract( - DAI, - IERC20__factory.abi, - ethers.provider, - ) - - const token_usdt = new ethers.Contract( - USDT, - IERC20__factory.abi, - ethers.provider, - ) - - const token_weth = new ethers.Contract( - WETH, - IERC20__factory.abi, - ethers.provider, - ) - - const token_steth = new ethers.Contract( - STETH, - IERC20__factory.abi, - ethers.provider, - ) - - beforeEach(async function () { - ;[signer] = await ethers.getSigners() - - ProxyA = new AaveImplementation__factory(signer) - proxyA = await ProxyA.deploy() - await proxyA.deployed() - // console.log("Aave proxy deployed at: ", proxyA.address); - - ProxyB = new BalancerImplementation__factory(signer) - proxyB = await ProxyB.deploy() - await proxyB.deployed() - // console.log("Balancer proxy deployed at: ", proxyB.address); - - - ProxyM = new MakerImplementation__factory(signer) - proxyM = await ProxyM.deploy() - await proxyM.deployed() - // console.log("Maker proxy deployed at: ", proxyM.address); - - ProxyU = new UniswapImplementation__factory(signer) - proxyU = await ProxyU.deploy() - await proxyU.deployed() - // console.log("Uniswap proxy deployed at: ", proxyU.address); - - - Aggregator = new InstaFlashAggregator__factory(signer) - aggregator = await Aggregator.deploy() - await aggregator.deployed() - // console.log("aggregator deployed at: ", aggregator.address); - - const data = iface.encodeFunctionData('initialize', [ - [ - '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643', // DAI - '0xf650C3d88D12dB855b8bf7D11Be6C55A4e07dCC9', // USDT - '0x39AA39c021dfbaE8faC545936693aC917d5E7563', // USDC - '0xe65cdb6479bac1e22340e4e755fae7e509ecd06c', // AAVE - '0x6c8c6b02e7b2be14d4fa6022dfd6d75921d90e4e', // BAT - '0x70e36f6bf80a52b3b46b3af8e106cc0ed743e8e4', // COMP - '0xface851a4921ce59e912d19329929ce6da6eb0c7', // LINK - '0x95b4ef2869ebd94beb4eee400a99824bf5dc325b', // MKR - '0x158079ee67fce2f58472a96584a73c7ab9ac95c1', // REP - '0x4b0181102a0112a2ef11abee5563bb4a3176c9d7', // SUSHI - '0x12392f67bdf24fae0af363c24ac620a2f67dad86', // TUSD - '0x35a18000230da775cac24873d00ff85bccded550', // UNI - '0xccf4429db6322d5c611ee964527d42e5d685dd6a', // WBTC2 - '0x80a2ae356fc9ef4305676f7a3e2ed04e12c33946', // YFI - '0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407', // ZRX - ],master,proxyA.address,proxyB.address,proxyM.address,proxyU.address - ]) - - Proxy = new InstaFlashAggregatorProxy__factory(signer) - proxy = await Proxy.deploy(aggregator.address, master, data) - await proxy.deployed() - // console.log("Proxy deployed at: ", proxy.address); - - Receiver = new InstaFlashReceiver__factory(signer) - receiver = await Receiver.deploy(proxy.address) - await receiver.deployed() - // console.log("receiver deployed at: ", receiver.address); - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_DAI, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_STETH, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.send('hardhat_setBalance', [ - proxy.address, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_DAI], - }) - - const signer_dai = await ethers.getSigner(ACC_DAI) - await token_dai.connect(signer_dai).transfer(receiver.address, dai) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_DAI], - }) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_STETH], - }) - - const signer_steth = await ethers.getSigner(ACC_STETH) - await token_steth.connect(signer_steth).transfer(receiver.address, steth) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_STETH], - }) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [proxy.address], - }) - - const signer_fla = await ethers.getSigner(proxy.address) - await token_dai.connect(signer_fla).approve(aaveLendingAddr, 100) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [proxy.address], - }) - _instaData = '0x' - }) - - describe('Single token', async function () { - it('Should be able to take flashLoan of a single token from AAVE', async function () { - await receiver.flashBorrow([DAI], [Dai], 1, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from MakerDAO', async function () { - await receiver.flashBorrow([DAI], [Dai], 2, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from Compound(MakerDAO)', async function () { - await receiver.flashBorrow([DAI], [Dai], 3, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from AAVE(MakerDAO)', async function () { - await receiver.flashBorrow([DAI], [Dai], 4, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from Balancer', async function () { - await receiver.flashBorrow([DAI], [Dai], 5, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from Compound(Balancer)', async function () { - await receiver.flashBorrow([DAI], [Dai], 6, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from AAVE(Balancer)', async function () { - await receiver.flashBorrow([DAI], [Dai], 7, _data, _instaData) - }) - it('Should be able to take flashLoan of a steth token from AAVE(Balancer)', async function () { - await receiver.flashBorrow([STETH], [Steth], 5, _data, _instaData) - }) - describe('FLA Route', async function () { - beforeEach(async function () { - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_DAI, - ethers.utils.parseEther('10.0').toHexString(), - ]) - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_DAI], - }) - - const signer_dai = await ethers.getSigner(ACC_DAI) - await token_dai.connect(signer_dai).transfer(proxy.address, Dai) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_DAI], - }) - }) - - it('Should be able to take flashLoan of a single token from FLA', async function () { - await receiver.flashBorrow([DAI], [Dai], 9, _data, _instaData) - }) - }) - describe('Uniswap Route', async function () { - beforeEach(async function () { - _instaData = await ethers.utils.defaultAbiCoder.encode( - ['tuple(address, address, uint24)'], - [[DAI, USDT, '500']], - ) - }) - it('Should be able to take flashLoan of a single token from Uniswap', async function () { - await receiver.flashBorrow([DAI], [Dai], 8, _data, _instaData) - }) - }) - }) - - describe('Multi token', async function () { - beforeEach(async function () { - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_USDT, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_WETH, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_USDT], - }) - - const signer_usdt = await ethers.getSigner(ACC_USDT) - await token_usdt.connect(signer_usdt).transfer(receiver.address, usdt) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_USDT], - }) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_WETH], - }) - - const signer_weth = await ethers.getSigner(ACC_WETH) - await token_weth.connect(signer_weth).transfer(receiver.address, weth) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_WETH], - }) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [proxy.address], - }) - - const signer_fla = await ethers.getSigner(proxy.address) - await token_usdt.connect(signer_fla).approve(aaveLendingAddr, 100) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [proxy.address], - }) - _instaData = '0x' - }) - - it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 1, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple tokens together from MakerDAO', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 2, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple tokens together from Compound(MakerDAO)', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 3, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple tokens together from AAVE(MakerDAO)', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 4, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple sorted tokens together from Balancer', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 5, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple unsorted tokens together from Balancer', async function () { - await receiver.flashBorrow( - [USDT, DAI, WETH], - [Usdt, Dai, Weth], - 5, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple tokens together from Compound(Balancer)', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 6, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple tokens together from AAVE(Balancer)', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 7, - _data, - _instaData, - ) - }) - describe('FLA Route', async function () { - beforeEach(async function () { - await hre.network.provider.send('hardhat_setBalance', [ - ACC_USDT, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_WETH, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_USDT], - }) - - const signer_usdt = await ethers.getSigner(ACC_USDT) - await token_usdt.connect(signer_usdt).transfer(proxy.address, Usdt) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_USDT], - }) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_WETH], - }) - - const signer_weth = await ethers.getSigner(ACC_WETH) - await token_weth.connect(signer_weth).transfer(proxy.address, Weth) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_WETH], - }) - await hre.network.provider.send('hardhat_setBalance', [ - ACC_DAI, - ethers.utils.parseEther('10.0').toHexString(), - ]) - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_DAI], - }) - - const signer_dai = await ethers.getSigner(ACC_DAI) - await token_dai.connect(signer_dai).transfer(proxy.address, Dai) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_DAI], - }) - }) - - it('Should be able to take flashLoan of multiple tokens together from FLA', async function () { - await receiver.flashBorrow( - [DAI, USDT, WETH], - [Dai, Usdt, Weth], - 9, - _data, - _instaData, - ) - }) - }) - describe('Uniswap Route', async function () { - beforeEach(async function () { - _instaData = await ethers.utils.defaultAbiCoder.encode( - ['tuple(address, address, uint24)'], - [[USDT, DAI, '500']], - ) - }) - it('Should be able to take flashLoan of multiple unsorted tokens together from Uniswap', async function () { - await receiver.flashBorrow( - [USDT, DAI], - [Usdt, Dai], - 8, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple tokens sorted together from Uniswap', async function () { - await receiver.flashBorrow( - [DAI, USDT], - [Dai, Usdt], - 8, - _data, - _instaData, - ) - }) - }) - }) -}) diff --git a/test/optimism/newFlash.ts b/test/optimism/newFlash.ts index 6ced1dc8..243a6c83 100644 --- a/test/optimism/newFlash.ts +++ b/test/optimism/newFlash.ts @@ -73,7 +73,6 @@ describe('FlashLoan', function () { ]) const data = iface.encodeFunctionData('initialize',[implUniswap.address]) - console.log("data: ", data) await proxy.connect(adminSigner).upgradeToAndCall(aggregator.address, data); Receiver = new InstaFlashReceiver__factory(signer) @@ -98,6 +97,7 @@ describe('FlashLoan', function () { const signer_dai = await ethers.getSigner(ACC_DAI) await token_dai.connect(signer_dai).transfer(receiver.address, dai) + await token_dai.connect(signer_dai).transfer(proxyAddr, Dai) await hre.network.provider.request({ method: 'hardhat_stopImpersonatingAccount', @@ -114,6 +114,9 @@ describe('FlashLoan', function () { it('Should be able to take flashLoan of a single token from Uniswap', async function () { await receiver.flashBorrow([DAI], [Dai], 8, _data, _instaData) }) + it("Should be able to take flashLoan of a single token from FLA", async function () { + await receiver.flashBorrow([DAI], [Dai], 9, _data, _instaData) + }) }) describe('Multi token', async function () { @@ -136,6 +139,7 @@ describe('FlashLoan', function () { const signer_usdt = await ethers.getSigner(ACC_USDT) await token.connect(signer_usdt).transfer(receiver.address, usdt) + await token.connect(signer_usdt).transfer(proxyAddr, Usdt) await hre.network.provider.request({ method: 'hardhat_stopImpersonatingAccount', @@ -149,5 +153,14 @@ describe('FlashLoan', function () { it('Should be able to take flashLoan of multiple tokens together from Uniswap', async function () { await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 8, _data, _instaData) }) + it("Should be able to take flashLoan of multiple tokens together from FLA", async function () { + await receiver.flashBorrow( + [USDT, DAI], + [Usdt, Dai], + 9, + _data, + _instaData + ); + }) }) }) diff --git a/test/optimism/updatedFlash.ts b/test/optimism/updatedFlash.ts deleted file mode 100644 index 22c1e849..00000000 --- a/test/optimism/updatedFlash.ts +++ /dev/null @@ -1,167 +0,0 @@ -const hre = require('hardhat') -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -const { ethers } = hre - -import { - InstaFlashAggregatorOptimism__factory, - IERC20__factory, - InstaFlashReceiver__factory, - InstaFlashReceiver, - InstaFlashAggregatorProxy__factory, - UniswapImplementationOptimism, - UniswapImplementationOptimism__factory -} from '../../typechain' - -describe('FlashLoan', function () { - let Aggregator, - aggregator, - Receiver, - receiver: InstaFlashReceiver, - implUniswap : UniswapImplementationOptimism, - ImplUniswap, - proxyAddr = "0x84E6b05A089d5677A702cF61dc14335b4bE5b282", - admin = "0xd4e5e20ef32b4750d4cd185a8e970b89851e7775", - adminSigner - - let signer: SignerWithAddress - - const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' - - let ABI = ['function initialize(address)'] - let iface = new ethers.utils.Interface(ABI) - - const DAI = '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1' - const USDT = '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58' - const ACC_DAI = '0xadb35413ec50e0afe41039eac8b930d313e94fa4' - const ACC_USDT = '0x9d39fc627a6d9d9f8c831c16995b209548cc3401' - - const dai = ethers.utils.parseUnits('1000', 18) - const usdt = ethers.utils.parseUnits('1000', 6) - const Dai = ethers.utils.parseUnits('5000', 18) - const Usdt = ethers.utils.parseUnits('5000', 6) - - const _data = '0x' - - let _instaData = '0x' - - beforeEach(async function () { - ;[signer] = await ethers.getSigners() - Aggregator = new InstaFlashAggregatorOptimism__factory(signer) - aggregator = await Aggregator.deploy() - await aggregator.deployed() - - ImplUniswap = new UniswapImplementationOptimism__factory(signer) - implUniswap = await ImplUniswap.deploy() - await implUniswap.deployed() - - const proxy = new ethers.Contract( - proxyAddr, - InstaFlashAggregatorProxy__factory.abi, - ethers.provider, - ) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [admin], - }) - - adminSigner = await ethers.getSigner(admin); - - await hre.network.provider.send('hardhat_setBalance', [ - admin, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - const data = iface.encodeFunctionData('initialize',[implUniswap.address]) - console.log("data: ", data) - await proxy.connect(adminSigner).upgradeToAndCall(aggregator.address, data); - - Receiver = new InstaFlashReceiver__factory(signer) - receiver = await Receiver.deploy(proxy.address) - await receiver.deployed() - - const token_dai = new ethers.Contract( - DAI, - IERC20__factory.abi, - ethers.provider, - ) - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_DAI, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_DAI], - }) - - const signer_dai = await ethers.getSigner(ACC_DAI) - await token_dai.connect(signer_dai).transfer(receiver.address, dai) - await token_dai.connect(signer_dai).transfer(proxyAddr, Dai) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_DAI], - }) - - _instaData = await ethers.utils.defaultAbiCoder.encode( - ['tuple(address, address, uint24)'], - [[USDT, DAI, '500']], - ) - }) - - describe('Single token', async function () { - it('Should be able to take flashLoan of a single token from Uniswap', async function () { - await receiver.flashBorrow([DAI], [Dai], 8, _data, _instaData) - }) - it("Should be able to take flashLoan of a single token from FLA", async function () { - await receiver.flashBorrow([DAI], [Dai], 9, _data, _instaData) - }) - }) - - describe('Multi token', async function () { - beforeEach(async function () { - const token = new ethers.Contract( - USDT, - IERC20__factory.abi, - ethers.provider, - ) - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_USDT, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_USDT], - }) - - const signer_usdt = await ethers.getSigner(ACC_USDT) - await token.connect(signer_usdt).transfer(receiver.address, usdt) - await token.connect(signer_usdt).transfer(proxyAddr, Usdt) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_USDT], - }) - _instaData = await ethers.utils.defaultAbiCoder.encode( - ['tuple(address, address, uint24)'], - [[USDT, DAI, '500']], - ) - }) - it('Should be able to take flashLoan of multiple tokens together from Uniswap', async function () { - await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 8, _data, _instaData) - }) - it("Should be able to take flashLoan of multiple tokens together from FLA", async function () { - await receiver.flashBorrow( - [USDT, DAI], - [Usdt, Dai], - 9, - _data, - _instaData - ); - }) - }) -}) diff --git a/test/polygon/newFlashloan.ts b/test/polygon/newFlashloan.ts index f25a4e0e..0f5b67bd 100644 --- a/test/polygon/newFlashloan.ts +++ b/test/polygon/newFlashloan.ts @@ -55,22 +55,18 @@ describe('FlashLoan', function () { Aggregator = new InstaFlashAggregatorPolygon__factory(signer) aggregator = await Aggregator.deploy() await aggregator.deployed() - console.log("aggregator deployed at: ", aggregator.address); ImplAave = new AaveImplementationPolygon__factory(signer) implAave = await ImplAave.deploy() await implAave.deployed() - console.log("implAave deployed at: ", implAave.address); ImplBalancer = new BalancerImplementationPolygon__factory(signer) implBalancer = await ImplBalancer.deploy() await implBalancer.deployed() - console.log("implBalancer deployed at: ", implBalancer.address); ImplUniswap = new UniswapImplementationPolygon__factory(signer) implUniswap = await ImplUniswap.deploy() await implUniswap.deployed() - console.log("implUniswap deployed at: ", implUniswap.address); const proxy = new ethers.Contract( proxyAddr, @@ -96,7 +92,6 @@ describe('FlashLoan', function () { Receiver = new InstaFlashReceiver__factory(signer) receiver = await Receiver.deploy(proxy.address) await receiver.deployed() - console.log("receiver deployed at: ", receiver.address); const token_dai = new ethers.Contract( DAI, @@ -116,6 +111,7 @@ describe('FlashLoan', function () { const signer_dai = await ethers.getSigner(ACC_DAI) await token_dai.connect(signer_dai).transfer(receiver.address, dai) + await token_dai.connect(signer_dai).transfer(proxyAddr, Dai) await hre.network.provider.request({ method: 'hardhat_stopImpersonatingAccount', @@ -134,6 +130,9 @@ describe('FlashLoan', function () { it('Should be able to take flashLoan of a single token from AAVE(Balancer)', async function () { await receiver.flashBorrow([DAI], [Dai], 7, _data, _instaData) }) + it("Should be able to take flashLoan of a single token from FLA", async function () { + await receiver.flashBorrow([DAI], [Dai], 9, _data, _instaData) + }) describe('Uniswap Route', async function () { beforeEach(async function () { @@ -168,6 +167,7 @@ describe('FlashLoan', function () { const signer_usdt = await ethers.getSigner(ACC_USDT) await token.connect(signer_usdt).transfer(receiver.address, usdt) + await token.connect(signer_usdt).transfer(proxyAddr, Usdt) await hre.network.provider.request({ method: 'hardhat_stopImpersonatingAccount', @@ -187,6 +187,9 @@ describe('FlashLoan', function () { it('Should be able to take flashLoan of multiple tokens together from AAVE(Balancer)', async function () { await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 7, _data, _instaData) }) + it("Should be able to take flashLoan of multiple tokens together from FLA", async function () { + await receiver.flashBorrow([USDT, DAI], [Usdt, Dai], 9, _data, _instaData); + }) describe('Uniswap Route', async function () { beforeEach(async function () { diff --git a/test/polygon/updatedFlash.ts b/test/polygon/updatedFlash.ts deleted file mode 100644 index 14347194..00000000 --- a/test/polygon/updatedFlash.ts +++ /dev/null @@ -1,225 +0,0 @@ -const hre = require('hardhat') -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -const { ethers } = hre - -import { - InstaFlashAggregatorPolygon__factory, - IERC20__factory, - InstaFlashReceiver__factory, - InstaFlashReceiver, - InstaFlashAggregatorProxy__factory, - UniswapImplementationPolygon__factory, - BalancerImplementationPolygon__factory, - AaveImplementationPolygon__factory -} from '../../typechain' - -describe('FlashLoan', function () { - let Aggregator, - aggregator, - Receiver, - receiver: InstaFlashReceiver, - implUniswap, - ImplUniswap, - implBalancer, - ImplBalancer, - implAave, - ImplAave, - proxyAddr = "0xB2A7F20D10A006B0bEA86Ce42F2524Fde5D6a0F4", - admin = "0x90cf378a297c7ef6dabed36ea5e112c6646bb3a4", - adminSigner - - let signer: SignerWithAddress - - const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' - - let ABI = ['function initialize(address aave, address balancer, address uniswap)'] - let iface = new ethers.utils.Interface(ABI) - - const DAI = '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063' - const USDT = '0xc2132d05d31c914a87c6611c10748aeb04b58e8f' - const ACC_DAI = '0x4a35582a710e1f4b2030a3f826da20bfb6703c09' - const ACC_USDT = '0x0d0707963952f2fba59dd06f2b425ace40b492fe' - //dai < usdt - - const dai = ethers.utils.parseUnits('1000', 18) - const usdt = ethers.utils.parseUnits('1000', 6) - const Dai = ethers.utils.parseUnits('10', 18) - const Usdt = ethers.utils.parseUnits('100', 6) - - const _data = '0x' - - let _instaData = '0x' - - beforeEach(async function () { - ;[signer] = await ethers.getSigners() - Aggregator = new InstaFlashAggregatorPolygon__factory(signer) - aggregator = await Aggregator.deploy() - await aggregator.deployed() - console.log("aggregator deployed at: ", aggregator.address); - - ImplAave = new AaveImplementationPolygon__factory(signer) - implAave = await ImplAave.deploy() - await implAave.deployed() - console.log("implAave deployed at: ", implAave.address); - - ImplBalancer = new BalancerImplementationPolygon__factory(signer) - implBalancer = await ImplBalancer.deploy() - await implBalancer.deployed() - console.log("implBalancer deployed at: ", implBalancer.address); - - ImplUniswap = new UniswapImplementationPolygon__factory(signer) - implUniswap = await ImplUniswap.deploy() - await implUniswap.deployed() - console.log("implUniswap deployed at: ", implUniswap.address); - - const proxy = new ethers.Contract( - proxyAddr, - InstaFlashAggregatorProxy__factory.abi, - ethers.provider, - ) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [admin], - }) - - adminSigner = await ethers.getSigner(admin); - - await hre.network.provider.send('hardhat_setBalance', [ - admin, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - const data = iface.encodeFunctionData('initialize', [implAave.address, implBalancer.address,implUniswap.address]) - await proxy.connect(adminSigner).upgradeToAndCall(aggregator.address, data); - - Receiver = new InstaFlashReceiver__factory(signer) - receiver = await Receiver.deploy(proxy.address) - await receiver.deployed() - console.log("receiver deployed at: ", receiver.address); - - const token_dai = new ethers.Contract( - DAI, - IERC20__factory.abi, - ethers.provider, - ) - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_DAI, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_DAI], - }) - - const signer_dai = await ethers.getSigner(ACC_DAI) - await token_dai.connect(signer_dai).transfer(receiver.address, dai) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_DAI], - }) - _instaData = '0x' - }) - - describe('Single token', async function () { - it('Should be able to take flashLoan of a single token from AAVE', async function () { - await receiver.flashBorrow([DAI], [Dai], 1, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from Balancer', async function () { - await receiver.flashBorrow([DAI], [Dai], 5, _data, _instaData) - }) - it('Should be able to take flashLoan of a single token from AAVE(Balancer)', async function () { - await receiver.flashBorrow([DAI], [Dai], 7, _data, _instaData) - }) - it("Should be able to take flashLoan of a single token from FLA", async function () { - await receiver.flashBorrow([DAI], [Dai], 9, _data, _instaData) - }) - - describe('Uniswap Route', async function () { - beforeEach(async function () { - _instaData = await ethers.utils.defaultAbiCoder.encode( - ['tuple(address, address, uint24)'], - [[DAI, USDT, '500']], - ) - }) - it('Should be able to take flashLoan of a single token from Uniswap', async function () { - await receiver.flashBorrow([DAI], [Dai], 8, _data, _instaData) - }) - }) - }) - - describe('Multi token', async function () { - beforeEach(async function () { - const token = new ethers.Contract( - USDT, - IERC20__factory.abi, - ethers.provider, - ) - - await hre.network.provider.send('hardhat_setBalance', [ - ACC_USDT, - ethers.utils.parseEther('10.0').toHexString(), - ]) - - await hre.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [ACC_USDT], - }) - - const signer_usdt = await ethers.getSigner(ACC_USDT) - await token.connect(signer_usdt).transfer(receiver.address, usdt) - await token.connect(signer_usdt).transfer(proxyAddr, usdt) - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [ACC_USDT], - }) - _instaData = '0x' - }) - it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { - await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 1, _data, _instaData) - }) - it('Should be able to take flashLoan of multiple sorted tokens together from Balancer', async function () { - await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 5, _data, _instaData) - }) - it('Should be able to take flashLoan of multiple unsorted tokens together from Balancer', async function () { - await receiver.flashBorrow([USDT, DAI], [Usdt, Dai], 5, _data, _instaData) - }) - it('Should be able to take flashLoan of multiple tokens together from AAVE(Balancer)', async function () { - await receiver.flashBorrow([DAI, USDT], [Dai, Usdt], 7, _data, _instaData) - }) - it("Should be able to take flashLoan of multiple tokens together from FLA", async function () { - await receiver.flashBorrow([USDT, DAI], [Usdt, Dai], 9, _data, _instaData); - }) - - describe('Uniswap Route', async function () { - beforeEach(async function () { - _instaData = await ethers.utils.defaultAbiCoder.encode( - ['tuple(address, address, uint24)'], - [[USDT, DAI, '500']], - ) - }) - it('Should be able to take flashLoan of multiple unsorted tokens together from Uniswap', async function () { - await receiver.flashBorrow( - [USDT, DAI], - [Usdt, Dai], - 8, - _data, - _instaData, - ) - }) - it('Should be able to take flashLoan of multiple tokens sorted together from Uniswap', async function () { - await receiver.flashBorrow( - [DAI, USDT], - [Dai, Usdt], - 8, - _data, - _instaData, - ) - }) - }) - }) -})