From 18c167fd313157dd4be9ff28898f66252df22ff5 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 20 Jun 2022 01:48:16 +0530 Subject: [PATCH 01/55] Aave v3 implementation added --- .../aggregator/fantom/flashloan/helpers.sol | 128 ++++++++++++++++++ .../fantom/flashloan/implAaveV3/main.sol | 104 ++++++++++++++ .../fantom/flashloan/interfaces.sol | 27 ++++ .../aggregator/fantom/flashloan/main.sol | 124 +++++++++++++++++ .../aggregator/fantom/flashloan/variables.sol | 35 +++++ 5 files changed, 418 insertions(+) create mode 100644 contracts/aggregator/fantom/flashloan/helpers.sol create mode 100644 contracts/aggregator/fantom/flashloan/implAaveV3/main.sol create mode 100644 contracts/aggregator/fantom/flashloan/interfaces.sol create mode 100644 contracts/aggregator/fantom/flashloan/main.sol create mode 100644 contracts/aggregator/fantom/flashloan/variables.sol diff --git a/contracts/aggregator/fantom/flashloan/helpers.sol b/contracts/aggregator/fantom/flashloan/helpers.sol new file mode 100644 index 00000000..9705f275 --- /dev/null +++ b/contracts/aggregator/fantom/flashloan/helpers.sol @@ -0,0 +1,128 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +import "./variables.sol"; +import "../../common/helpers.sol"; + +contract Helper is HelpersCommon, Variables { + using SafeERC20 for IERC20; + + /** + * @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 { + TokenInterface tokenContract_ = TokenInterface(token_); + try tokenContract_.approve(spender_, amount_) { + + } catch { + IERC20 token = IERC20(token_); + token.safeApprove(spender_, 0); + token.safeApprove(spender_, amount_); + } + } + + /** + * @dev Approves the tokens to the receiver address with allowance (amount + fee). + * @notice Approves the tokens to the receiver address with allowance (amount + fee). + * @param _instaLoanVariables struct which includes list of token addresses and amounts. + * @param _fees list of premiums/fees for the corresponding addresses for flashloan. + * @param _receiver address to which tokens have to be approved. + */ + function safeApprove( + FlashloanVariables memory _instaLoanVariables, + uint256[] memory _fees, + address _receiver + ) internal { + uint256 length_ = _instaLoanVariables._tokens.length; + require(length_ == _instaLoanVariables._amounts.length, "Lengths of parameters not same"); + require(length_ == _fees.length, "Lengths of parameters not same"); + for (uint i = 0; i < length_; i++) { + approve(_instaLoanVariables._tokens[i], _receiver, _instaLoanVariables._amounts[i] + _fees[i]); + } + } + + /** + * @dev Transfers the tokens to the receiver address. + * @notice Transfers the tokens to the receiver address. + * @param _instaLoanVariables struct which includes list of token addresses and amounts. + * @param _receiver address to which tokens have to be transferred. + */ + function safeTransfer( + FlashloanVariables memory _instaLoanVariables, + address _receiver + ) internal { + uint256 length_ = _instaLoanVariables._tokens.length; + require(length_ == _instaLoanVariables._amounts.length, "Lengths of parameters not same"); + for (uint i = 0; i < length_; i++) { + IERC20 token = IERC20(_instaLoanVariables._tokens[i]); + token.safeTransfer(_receiver, _instaLoanVariables._amounts[i]); + } + } + + /** + * @dev Validates if the receiver sent the correct amounts of funds. + * @notice Validates if the receiver sent the correct amounts of funds. + * @param _instaLoanVariables struct which includes list of initial balances, final balances and fees for the respective tokens. + */ + function validateFlashloan( + FlashloanVariables memory _instaLoanVariables + ) internal pure { + for (uint i = 0; i < _instaLoanVariables._iniBals.length; i++) { + require(_instaLoanVariables._iniBals[i] + _instaLoanVariables._instaFees[i] <= _instaLoanVariables._finBals[i], "amount-paid-less"); + } + } + + /** + * @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_ = aaveV3Lending.FLASHLOAN_PREMIUM_TOTAL(); + } 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. + * @param _account account to check for, if DSA. + */ + function checkIfDsa(address _account) internal view returns (bool) { + return instaList.accountID(_account) > 0; + } + + /** + * @dev better checking by double encoding the data. + * @notice better checking by double encoding the data. + * @param data_ data passed. + */ + modifier verifyDataHash(bytes memory data_) { + bytes32 dataHash_ = keccak256(data_); + require(dataHash_ == dataHash && dataHash_ != bytes32(0), "invalid-data-hash"); + require(status == 2, "already-entered"); + dataHash = bytes32(0); + _; + status = 1; + } + + /** + * @dev reentrancy gaurd. + * @notice reentrancy gaurd. + */ + modifier reentrancy { + require(status == 1, "already-entered"); + status = 2; + _; + require(status == 1, "already-entered"); + } +} \ No newline at end of file diff --git a/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol b/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol new file mode 100644 index 00000000..dadeeac4 --- /dev/null +++ b/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol @@ -0,0 +1,104 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +import "../helpers.sol"; + +contract AaveImplementationFantom 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-AAVE-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + routeAaveV3(_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 == aaveV3LendingAddr, "not-aave-sender"); + FlashloanVariables memory instaLoanVariables_; + + (uint256 route_, address sender_, bytes memory data_) = abi.decode( + _data, + (uint256, address, bytes) + ); + + instaLoanVariables_._tokens = _assets; + instaLoanVariables_._amounts = _amounts; + instaLoanVariables_._instaFees = calculateFees(_amounts, calculateFeeBPS(9)); + instaLoanVariables_._iniBals = calculateBalances(_assets, address(this)); + + safeApprove(instaLoanVariables_, _premiums, aaveV3LendingAddr); + 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 9. + * @notice Middle function for route 9. + * @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 routeAaveV3( + address[] memory _tokens, + uint256[] memory _amounts, + bytes memory _data + ) internal { + + bytes memory data_ = abi.encode(9, 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_)); + aaveV3Lending.flashLoan( + address(this), + _tokens, + _amounts, + _modes, + address(0), + data_, + 3228 + ); + } +} diff --git a/contracts/aggregator/fantom/flashloan/interfaces.sol b/contracts/aggregator/fantom/flashloan/interfaces.sol new file mode 100644 index 00000000..2f9cefe1 --- /dev/null +++ b/contracts/aggregator/fantom/flashloan/interfaces.sol @@ -0,0 +1,27 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +pragma experimental ABIEncoderV2; + +interface InstaFlashReceiverInterface { + function executeOperation( + address[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata premiums, + address initiator, + bytes calldata _data + ) external returns (bool); +} + +interface IAaveV3Lending { + function flashLoan( + address receiverAddress, + address[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata modes, + address onBehalfOf, + bytes calldata params, + uint16 referralCode + ) external; + + function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128); +} diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol new file mode 100644 index 00000000..4b83ada0 --- /dev/null +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -0,0 +1,124 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + +/** + * @title Flashloan. + * @dev Flashloan aggregator for Fantom. + */ +import "./helpers.sol"; + +contract FlashAggregatorFantom is Helper { + using SafeERC20 for IERC20; + + event LogFlashloan( + address indexed account, + uint256 indexed route, + address[] tokens, + uint256[] amounts + ); + + /** + * @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 returns (bool) { + bytes memory response_ = spell(AAVE_IMPL, msg.data); + return (abi.decode(response_, (bool))); + } + + /** + * @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 { + require(_tokens.length == _amounts.length, "array-lengths-not-same"); + + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + + if (_route == 1) { + revert("this route is only for mainnet, polygon, and avalanche"); + } else if (_route == 2) { + revert("this route is only for mainnet"); + } else if (_route == 3) { + revert("this route is only for mainnet"); + } else if (_route == 4) { + revert("this route is only for mainnet"); + } else if (_route == 5) { + revert("this route is only for mainnet, polygon and arbitrum"); + } else if (_route == 6) { + 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 if (_route == 9) { + spell(AAVE_IMPL, msg.data); + } else { + revert("route-does-not-exist"); + } + + emit LogFlashloan( + msg.sender, + _route, + _tokens, + _amounts + ); + } + + /** + * @dev Function to get the list of available routes. + * @notice Function to get the list of available routes. + */ + function getRoutes() public pure returns (uint16[] memory routes_) { + routes_ = new uint16[](1); + routes_[0] = 9; + } + + /** + * @dev Function to transfer fee to the treasury. + * @notice Function to transfer fee to the treasury. + * @param _tokens token addresses for transferring fee to treasury. + */ + function transferFeeToTreasury(address[] memory _tokens) public { + for (uint256 i = 0; i < _tokens.length; i++) { + IERC20 token_ = IERC20(_tokens[i]); + uint decimals_ = TokenInterface(_tokens[i]).decimals(); + uint amtToSub_ = decimals_ == 18 ? 1e10 : decimals_ > 12 ? 10000 : decimals_ > 7 ? 100 : 10; + uint amtToTransfer_ = token_.balanceOf(address(this)) > amtToSub_ ? (token_.balanceOf(address(this)) - amtToSub_) : 0; + if (amtToTransfer_ > 0) token_.safeTransfer(treasuryAddr, amtToTransfer_); + } + } +} + +contract InstaFlashAggregatorFantom is FlashAggregatorFantom { + + function initialize(address aave) public { + require(status == 0, "cannot-call-again"); + status = 1; + AAVE_IMPL = aave; + } + + receive() external payable {} +} \ No newline at end of file diff --git a/contracts/aggregator/fantom/flashloan/variables.sol b/contracts/aggregator/fantom/flashloan/variables.sol new file mode 100644 index 00000000..4eb2b4d6 --- /dev/null +++ b/contracts/aggregator/fantom/flashloan/variables.sol @@ -0,0 +1,35 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + +import "./interfaces.sol"; +import "../../common/interface.sol"; + +contract ConstantVariables { + + address public constant aaveV3LendingAddr = 0x794a61358D6845594F94dc1DB02A252b5b4814aD; + IAaveV3Lending public constant aaveV3Lending = IAaveV3Lending(aaveV3LendingAddr); + + address public constant treasuryAddr = 0x6C4061A00F8739d528b185CC683B6400E0cd396a; + address private constant instaListAddr = 0x10e166c3FAF887D8a61dE6c25039231eE694E926; + ListInterface public constant instaList = ListInterface(instaListAddr); + + uint256 public constant InstaFeeBPS = 5; // in BPS; 1 BPS = 0.01% + +} + +contract Variables is ConstantVariables { + + bytes32 internal dataHash; + // if 1 then can enter flashlaon, if 2 then callback + uint internal status; + + struct FlashloanVariables { + address[] _tokens; + uint256[] _amounts; + uint256[] _iniBals; + uint256[] _finBals; + uint256[] _instaFees; + } + + address internal AAVE_IMPL; +} From 9364f29d989ecae8592f66f8eafa51d7f4947e01 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 20 Jun 2022 01:48:42 +0530 Subject: [PATCH 02/55] Aave v3 testcases added --- test/fantom/flashloan.ts | 153 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 test/fantom/flashloan.ts diff --git a/test/fantom/flashloan.ts b/test/fantom/flashloan.ts new file mode 100644 index 00000000..31968a0f --- /dev/null +++ b/test/fantom/flashloan.ts @@ -0,0 +1,153 @@ +const hre = require('hardhat') +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +const { ethers } = hre + +import { + InstaFlashAggregatorFantom, + InstaFlashAggregatorFantom__factory, + IERC20__factory, + IERC20, + InstaFlashReceiver__factory, + InstaFlashReceiver, + InstaFlashAggregatorProxy, + InstaFlashAggregatorProxy__factory, + AaveImplementationFantom, + AaveImplementationFantom__factory +} from '../../typechain' + +describe('FlashLoan', function () { + let Aggregator, + aggregator, + Receiver, + receiver: InstaFlashReceiver, + Proxy, + proxy, + ImplAave, + implAave; + + let signer: SignerWithAddress + + const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' + + let ABI = ['function initialize(address)'] + let iface = new ethers.utils.Interface(ABI) + + const DAI = '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E' + const USDC = '0x04068DA6C83AFCFA0e13ba15A6696662335D5B75' + const ACC_DAI = '0x1c664Bafc646510684Ba1588798c67fe22a8c7cf' + const ACC_USDC = '0x1c664Bafc646510684Ba1588798c67fe22a8c7cf' + + const dai = ethers.utils.parseUnits('10', 18) + const usdc = ethers.utils.parseUnits('10', 6) + const Dai = ethers.utils.parseUnits('5000', 18) + const Usdc = ethers.utils.parseUnits('5000', 6) + + const zeroAddr = + '0x0000000000000000000000000000000000000000000000000000000000000000' + + let _instaData = '' + + + beforeEach(async function () { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + //@ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url, + blockNumber: 36529195 + } + } + ] + }); + + ;[signer] = await ethers.getSigners() + Aggregator = new InstaFlashAggregatorFantom__factory(signer) + aggregator = await Aggregator.deploy() + await aggregator.deployed() + console.log("aggregator deployed at: ", aggregator.address) + + ImplAave = new AaveImplementationFantom__factory(signer) + implAave = await ImplAave.deploy() + await implAave.deployed() + console.log("implAave deployed at: ", 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 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, + 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) + console.log(await token_dai.connect(signer_dai).balanceOf(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 V3', async function () { + await receiver.flashBorrow([DAI], [Dai], 9, zeroAddr,_instaData) + }) + }) + + describe('Multi token', async function () { + beforeEach(async function () { + const token = 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.connect(signer_usdc).transfer(receiver.address, usdc) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDC], + }) + _instaData = '0x' + }) + it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { + await receiver.flashBorrow([DAI, USDC], [Dai, Usdc], 9, zeroAddr,_instaData ) + }) + }) +}) From d973f67024d742f757944037789c748d0cad6545 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 20 Jun 2022 03:20:15 +0530 Subject: [PATCH 03/55] Fantom resolver added --- contracts/resolver/fantom/helpers.sol | 75 +++++++++++++++++++++ contracts/resolver/fantom/interfaces.sol | 36 ++++++++++ contracts/resolver/fantom/main.sol | 83 ++++++++++++++++++++++++ contracts/resolver/fantom/variables.sol | 14 ++++ 4 files changed, 208 insertions(+) create mode 100644 contracts/resolver/fantom/helpers.sol create mode 100644 contracts/resolver/fantom/interfaces.sol create mode 100644 contracts/resolver/fantom/main.sol create mode 100644 contracts/resolver/fantom/variables.sol diff --git a/contracts/resolver/fantom/helpers.sol b/contracts/resolver/fantom/helpers.sol new file mode 100644 index 00000000..7ed52bd7 --- /dev/null +++ b/contracts/resolver/fantom/helpers.sol @@ -0,0 +1,75 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + +import {Variables} from "./variables.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract Helper is Variables { + function getAaveV3Availability( + address[] memory _tokens, + uint256[] memory _amounts + ) internal view returns (bool) { + uint length = _tokens.length; + for (uint256 i = 0; i < length; i++) { + IERC20 token_ = IERC20(_tokens[i]); + (, , , , , , , , bool isActive, ) = aaveV3DataProvider + .getReserveConfigurationData(_tokens[i]); + (address aTokenAddr, , ) = aaveV3DataProvider + .getReserveTokensAddresses(_tokens[i]); + if (isActive == false) return false; + if (token_.balanceOf(aTokenAddr) < _amounts[i]) return false; + } + return true; + } + + function getRoutesWithAvailability( + uint16[] memory _routes, + address[] memory _tokens, + uint256[] memory _amounts + ) internal view returns (uint16[] memory) { + uint16[] memory routesWithAvailability_ = new uint16[](7); + uint256 j = 0; + for (uint256 i = 0; i < _routes.length; i++) { + if (_routes[i] == 9) { + if (getAaveV3Availability(_tokens, _amounts)) { + routesWithAvailability_[j] = _routes[i]; + j++; + } + } else { + require(false, "invalid-route"); + } + } + return routesWithAvailability_; + } + + 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); + } + + 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"); + } + } +} diff --git a/contracts/resolver/fantom/interfaces.sol b/contracts/resolver/fantom/interfaces.sol new file mode 100644 index 00000000..1f11b9ef --- /dev/null +++ b/contracts/resolver/fantom/interfaces.sol @@ -0,0 +1,36 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + +interface InstaFlashloanAggregatorInterface { + function getRoutes() external pure returns (uint16[] memory); + + function calculateFeeBPS(uint256 _route) external view returns (uint256); +} + +interface IAaveV3DataProvider { + + function getReserveConfigurationData(address asset) + external + view + returns ( + uint256, + uint256, + uint256, + uint256, + uint256, + bool, + bool, + bool, + bool, + bool + ); + + function getReserveTokensAddresses(address asset) + external + view + returns ( + address, + address, + address + ); +} diff --git a/contracts/resolver/fantom/main.sol b/contracts/resolver/fantom/main.sol new file mode 100644 index 00000000..ae8dfb88 --- /dev/null +++ b/contracts/resolver/fantom/main.sol @@ -0,0 +1,83 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {Helper} from "./helpers.sol"; + +import {InstaFlashloanAggregatorInterface} from "./interfaces.sol"; + +contract FlashResolverFantom is Helper { + function getRoutesInfo() + public + view + returns (uint16[] memory routes_, uint256[] memory fees_) + { + routes_ = InstaFlashloanAggregatorInterface(flashloanAggregatorAddr).getRoutes(); + fees_ = new uint256[](routes_.length); + for (uint256 i = 0; i < routes_.length; i++) { + fees_[i] = InstaFlashloanAggregatorInterface(flashloanAggregatorAddr).calculateFeeBPS(routes_[i]); + } + } + + function getBestRoutes(address[] memory _tokens, uint256[] memory _amounts) + public + view + returns (uint16[] memory, uint256) + { + require(_tokens.length == _amounts.length, "array-lengths-not-same"); + + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + + uint16[] memory bRoutes_; + uint256 feeBPS_; + uint16[] memory routes_ = InstaFlashloanAggregatorInterface(flashloanAggregatorAddr).getRoutes(); + uint16[] memory routesWithAvailability_ = getRoutesWithAvailability( + routes_, + _tokens, + _amounts + ); + uint16 j = 0; + bRoutes_ = new uint16[](routes_.length); + feeBPS_ = type(uint256).max; + for (uint256 i = 0; i < routesWithAvailability_.length; i++) { + if (routesWithAvailability_[i] != 0) { + uint256 routeFeeBPS_ = InstaFlashloanAggregatorInterface(flashloanAggregatorAddr).calculateFeeBPS( + routesWithAvailability_[i] + ); + if (feeBPS_ > routeFeeBPS_) { + feeBPS_ = routeFeeBPS_; + bRoutes_[0] = routesWithAvailability_[i]; + j = 1; + } else if (feeBPS_ == routeFeeBPS_) { + bRoutes_[j] = routesWithAvailability_[i]; + j++; + } + } + } + uint16[] memory bestRoutes_ = new uint16[](j); + for (uint256 i = 0; i < j; i++) { + bestRoutes_[i] = bRoutes_[i]; + } + return (bestRoutes_, feeBPS_); + } + + function getData(address[] memory _tokens, uint256[] memory _amounts) + public + view + returns ( + uint16[] memory routes_, + uint256[] memory fees_, + uint16[] memory bestRoutes_, + uint256 bestFee_ + ) + { + (routes_, fees_) = getRoutesInfo(); + (bestRoutes_, bestFee_) = getBestRoutes(_tokens, _amounts); + return (routes_, fees_, bestRoutes_, bestFee_); + } +} + +contract InstaFlashloanResolverFantom is FlashResolverFantom { + receive() external payable {} +} diff --git a/contracts/resolver/fantom/variables.sol b/contracts/resolver/fantom/variables.sol new file mode 100644 index 00000000..6a4dbb30 --- /dev/null +++ b/contracts/resolver/fantom/variables.sol @@ -0,0 +1,14 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + +import "./interfaces.sol"; + +contract Variables { + IAaveV3DataProvider public constant aaveV3DataProvider = + IAaveV3DataProvider(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654); + + address public flashloanAggregatorAddr = + 0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19;//TODO: update + InstaFlashloanAggregatorInterface public flashloanAggregator = + InstaFlashloanAggregatorInterface(flashloanAggregatorAddr); +} From 0b5a8dd4653610674f79cacbdbaca067a7397441 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 20 Jun 2022 03:20:41 +0530 Subject: [PATCH 04/55] Resolver testcases added --- test/fantom/resolver.ts | 75 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 test/fantom/resolver.ts diff --git a/test/fantom/resolver.ts b/test/fantom/resolver.ts new file mode 100644 index 00000000..8dad7179 --- /dev/null +++ b/test/fantom/resolver.ts @@ -0,0 +1,75 @@ +const hre = require('hardhat') +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +const { ethers } = hre + +import { + InstaFlashAggregatorFantom__factory, + InstaFlashAggregatorProxy__factory, + AaveImplementationFantom__factory, + InstaFlashloanResolverFantom, + InstaFlashloanResolverFantom__factory, +} from '../../typechain' + +describe('Resolver', function () { + let Resolver, resolver: InstaFlashloanResolverFantom + let signer: SignerWithAddress + + const DAI = '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E' + const USDC = '0x04068DA6C83AFCFA0e13ba15A6696662335D5B75' + + const Dai = ethers.utils.parseUnits('5000', 18) + const Usdc = ethers.utils.parseUnits('5000', 6) + + const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' + + // let ABI = ['function initialize(address)'] + // let iface = new ethers.utils.Interface(ABI) + + beforeEach(async function () { + ;[signer] = await ethers.getSigners() + // let Aggregator, + // aggregator, + // Proxy, + // proxy, + // ImplAave, + // implAave; + + // Aggregator = new InstaFlashAggregatorFantom__factory(signer) + // aggregator = await Aggregator.deploy() + // await aggregator.deployed() + // console.log("aggregator deployed at: ", aggregator.address) + + // ImplAave = new AaveImplementationFantom__factory(signer) + // implAave = await ImplAave.deploy() + // await implAave.deployed() + // console.log("implAave deployed at: ", 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 at: ',proxy.address) + + Resolver = new InstaFlashloanResolverFantom__factory(signer) + resolver = await Resolver.deploy() + await resolver.deployed() + console.log("resolver deployed at: ", resolver.address) + + // await resolver.initialize(proxy.address) + }) + + it('Should be able to return routes info', async function () { + console.log((await resolver.getRoutesInfo()).toString()) + }) + + it('Should be able to return the best route for flashloan', async function () { + console.log( + (await resolver.getBestRoutes([DAI, USDC], [Dai, Usdc])).toString(), + ) + }) + + it('Should be able to return all the data for flashloan', async function () { + console.log((await resolver.getData([DAI, USDC], [Dai, Usdc])).toString()) + }) +}) \ No newline at end of file From f6688401ac1d553e6ce8fcc9dce378ef0383d84f Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 20 Jun 2022 03:21:33 +0530 Subject: [PATCH 05/55] common helpers and interface added --- contracts/aggregator/common/helpers.sol | 131 ++++++++++++++++++++++ contracts/aggregator/common/interface.sol | 35 ++++++ 2 files changed, 166 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..e1ba1740 --- /dev/null +++ b/contracts/aggregator/common/helpers.sol @@ -0,0 +1,131 @@ +//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); + } + + /** + * @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); + } +} 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 ea740e483197a254bec83a9684a29c63982c6236 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 20 Jun 2022 03:22:29 +0530 Subject: [PATCH 06/55] hardhat & test script updated --- hardhat.config.ts | 13 +++++++++++-- scripts/run-tests.ts | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 01fbd4f6..7a2a924f 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -26,6 +26,7 @@ const chainIds = { avalanche: 43114, polygon: 137, optimism: 10, + fantom: 250, }; // Ensure that we have all the environment variables we need. @@ -59,6 +60,7 @@ function getNetworkUrl(networkType: string) { else if (networkType === "polygon") return `https://polygon-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; else if (networkType === "arbitrum") return `https://arb-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; else if (networkType === "optimism") return `https://opt-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; + else if (networkType === "fantom") return `https://rpc.ankr.com/fantom`; else return `https://eth-mainnet.alchemyapi.io/v2/${alchemyApiKey}`; } @@ -67,6 +69,7 @@ function getBlockNumber(networkType: string) { else if (networkType === "polygon") return 25941254; else if (networkType === "arbitrum") return 7719792; else if (networkType === "optimism") return 4346343; + else if (networkType === "fantom") return 40887910; else return 14456907; } @@ -128,7 +131,13 @@ const config: HardhatUserConfig = { chainId: 10, accounts: [`0x${process.env.PRIVATE_KEY}`], gasPrice: 1000000, - } + }, + fantom_mainnet: { + url: `https://rpc.ankr.com/fantom`, + chainId: 250, + accounts: [`0x${process.env.PRIVATE_KEY}`], + gasPrice: 210011000000, + }, }, paths: { artifacts: "./artifacts", @@ -166,7 +175,7 @@ const config: HardhatUserConfig = { target: "ethers-v5", }, mocha: { - timeout: 10000 * 10000, + timeout: 100000 * 100000, }, etherscan: { apiKey: `${process.env.SCAN_API_KEY}` diff --git a/scripts/run-tests.ts b/scripts/run-tests.ts index bd5901c5..85998887 100644 --- a/scripts/run-tests.ts +++ b/scripts/run-tests.ts @@ -12,7 +12,7 @@ async function testRunner() { name: "chain", message: "What chain do you want to run tests on?", type: "list", - choices: ["mainnet", "polygon", "avalanche", "arbitrum", "optimism"], + choices: ["mainnet", "polygon", "avalanche", "arbitrum", "optimism", "fantom"], }, ]); const testsPath = join(__dirname, "../test", chain); From 9069c5319c1af6efc5977e7a33105aa426c07b6f Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 20 Jun 2022 05:11:37 +0530 Subject: [PATCH 07/55] Fla route added --- .../aggregator/fantom/flashloan/helpers.sol | 2 + .../aggregator/fantom/flashloan/main.sol | 63 ++++++++++++++++++- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/helpers.sol b/contracts/aggregator/fantom/flashloan/helpers.sol index 9705f275..2be06940 100644 --- a/contracts/aggregator/fantom/flashloan/helpers.sol +++ b/contracts/aggregator/fantom/flashloan/helpers.sol @@ -83,6 +83,8 @@ contract Helper is HelpersCommon, Variables { function calculateFeeBPS(uint256 _route) public view returns(uint256 BPS_){ if (_route == 9) { BPS_ = aaveV3Lending.FLASHLOAN_PREMIUM_TOTAL(); + } else if (_route == 10){ + BPS_ = InstaFeeBPS; } else { revert("Invalid source"); } diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 4b83ada0..979da13d 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -6,6 +6,7 @@ pragma solidity ^0.8.0; * @dev Flashloan aggregator for Fantom. */ import "./helpers.sol"; +import "hardhat/console.sol"; contract FlashAggregatorFantom is Helper { using SafeERC20 for IERC20; @@ -37,6 +38,57 @@ contract FlashAggregatorFantom 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 + + console.log("Inside routefla"); + + FlashloanVariables memory instaLoanVariables_; + instaLoanVariables_._tokens = _tokens; + instaLoanVariables_._amounts = _amounts; + instaLoanVariables_._instaFees = calculateFees( + _amounts, + calculateFeeBPS(10) + ); + console.log("AAVE_IMPL: ", AAVE_IMPL); + instaLoanVariables_._iniBals = calculateBalances( + _tokens, + address(this) + ); + console.log("_iniBals: ", instaLoanVariables_._iniBals[0]); + 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) + ); + console.log("_finBals: ", instaLoanVariables_._finBals[0]); + 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. @@ -75,6 +127,10 @@ contract FlashAggregatorFantom is Helper { revert("this route is only for arbitrum, polygon and optimism"); } else if (_route == 9) { spell(AAVE_IMPL, msg.data); + } else if (_route == 10){ + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + routeFLA(msg.sender, _tokens, _amounts, _data); } else { revert("route-does-not-exist"); } @@ -91,9 +147,11 @@ contract FlashAggregatorFantom is Helper { * @dev Function to get the list of available routes. * @notice Function to get the list of available routes. */ - function getRoutes() public pure returns (uint16[] memory routes_) { - routes_ = new uint16[](1); + function getRoutes() public view returns (uint16[] memory routes_) { + console.log("Inside getRoutes main"); + routes_ = new uint16[](2); routes_[0] = 9; + routes_[1] = 10; } /** @@ -118,6 +176,7 @@ contract InstaFlashAggregatorFantom is FlashAggregatorFantom { require(status == 0, "cannot-call-again"); status = 1; AAVE_IMPL = aave; + console.log("AAVE_IMPL: ", AAVE_IMPL); } receive() external payable {} From c911d33dee4cf572ae05973a000029ca6a2c31ce Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 20 Jun 2022 05:12:17 +0530 Subject: [PATCH 08/55] fla route - testcases --- test/fantom/flashloan.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/test/fantom/flashloan.ts b/test/fantom/flashloan.ts index 31968a0f..a075675e 100644 --- a/test/fantom/flashloan.ts +++ b/test/fantom/flashloan.ts @@ -21,7 +21,7 @@ describe('FlashLoan', function () { Receiver, receiver: InstaFlashReceiver, Proxy, - proxy, + proxy: InstaFlashAggregatorProxy, ImplAave, implAave; @@ -95,6 +95,10 @@ describe('FlashLoan', function () { ACC_DAI, 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', @@ -104,6 +108,7 @@ describe('FlashLoan', function () { const signer_dai = await ethers.getSigner(ACC_DAI) console.log(await token_dai.connect(signer_dai).balanceOf(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', @@ -117,6 +122,9 @@ describe('FlashLoan', function () { it('Should be able to take flashLoan of a single token from AAVE V3', async function () { await receiver.flashBorrow([DAI], [Dai], 9, zeroAddr,_instaData) }) + it('Should be able to take flashLoan of a single token from FLA', async function () { + await receiver.flashBorrow([DAI], [Dai], 10, zeroAddr, _instaData) + }) }) describe('Multi token', async function () { @@ -139,6 +147,7 @@ describe('FlashLoan', function () { const signer_usdc = await ethers.getSigner(ACC_USDC) await token.connect(signer_usdc).transfer(receiver.address, usdc) + await token.connect(signer_usdc).transfer(proxy.address, Usdc) await hre.network.provider.request({ method: 'hardhat_stopImpersonatingAccount', @@ -147,7 +156,10 @@ describe('FlashLoan', function () { _instaData = '0x' }) it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { - await receiver.flashBorrow([DAI, USDC], [Dai, Usdc], 9, zeroAddr,_instaData ) + await receiver.flashBorrow([DAI, USDC], [Dai, Usdc], 9, zeroAddr, _instaData ) + }) + it('Should be able to take flashLoan of multiple tokens together from FLA', async function () { + await receiver.flashBorrow([DAI, USDC], [Dai, Usdc], 10, zeroAddr, _instaData ) }) }) }) From 4cdde6caf9e014ab303ad1d591682fa3dce4a589 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 20 Jun 2022 05:12:50 +0530 Subject: [PATCH 09/55] receiver updated: minor fix --- contracts/misc/InstaReceiver.sol | 1 + 1 file changed, 1 insertion(+) 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_) { From 07ad9932f1ae36d2c565ed68da2f63c73b88d060 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Mon, 20 Jun 2022 05:35:15 +0530 Subject: [PATCH 10/55] Resolver updated - fla route --- contracts/resolver/fantom/helpers.sol | 17 +++++++++++++++++ contracts/resolver/fantom/main.sol | 8 ++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/contracts/resolver/fantom/helpers.sol b/contracts/resolver/fantom/helpers.sol index 7ed52bd7..0a876f2c 100644 --- a/contracts/resolver/fantom/helpers.sol +++ b/contracts/resolver/fantom/helpers.sol @@ -22,6 +22,18 @@ contract Helper is Variables { return true; } + function getFlaAvailability( + address[] memory _tokens, + uint256[] memory _amounts + ) internal view returns (bool) { + uint length = _tokens.length; + for (uint256 i = 0; i < length; i++) { + IERC20 token_ = IERC20(_tokens[i]); + if (token_.balanceOf(flashloanAggregatorAddr) < _amounts[i]) return false; + } + return true; + } + function getRoutesWithAvailability( uint16[] memory _routes, address[] memory _tokens, @@ -35,6 +47,11 @@ contract Helper is Variables { routesWithAvailability_[j] = _routes[i]; j++; } + } else if (_routes[i] == 10) { + if (getFlaAvailability(_tokens, _amounts)) { + routesWithAvailability_[j] = _routes[i]; + j++; + } } else { require(false, "invalid-route"); } diff --git a/contracts/resolver/fantom/main.sol b/contracts/resolver/fantom/main.sol index ae8dfb88..667f1570 100644 --- a/contracts/resolver/fantom/main.sol +++ b/contracts/resolver/fantom/main.sol @@ -12,10 +12,10 @@ contract FlashResolverFantom is Helper { view returns (uint16[] memory routes_, uint256[] memory fees_) { - routes_ = InstaFlashloanAggregatorInterface(flashloanAggregatorAddr).getRoutes(); + routes_ = flashloanAggregator.getRoutes(); fees_ = new uint256[](routes_.length); for (uint256 i = 0; i < routes_.length; i++) { - fees_[i] = InstaFlashloanAggregatorInterface(flashloanAggregatorAddr).calculateFeeBPS(routes_[i]); + fees_[i] = flashloanAggregator.calculateFeeBPS(routes_[i]); } } @@ -31,7 +31,7 @@ contract FlashResolverFantom is Helper { uint16[] memory bRoutes_; uint256 feeBPS_; - uint16[] memory routes_ = InstaFlashloanAggregatorInterface(flashloanAggregatorAddr).getRoutes(); + uint16[] memory routes_ = flashloanAggregator.getRoutes(); uint16[] memory routesWithAvailability_ = getRoutesWithAvailability( routes_, _tokens, @@ -42,7 +42,7 @@ contract FlashResolverFantom is Helper { feeBPS_ = type(uint256).max; for (uint256 i = 0; i < routesWithAvailability_.length; i++) { if (routesWithAvailability_[i] != 0) { - uint256 routeFeeBPS_ = InstaFlashloanAggregatorInterface(flashloanAggregatorAddr).calculateFeeBPS( + uint256 routeFeeBPS_ = flashloanAggregator.calculateFeeBPS( routesWithAvailability_[i] ); if (feeBPS_ > routeFeeBPS_) { From fa19dacb00978a6313d6420edd44f32ab95dd865 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 21 Jun 2022 16:35:42 +0530 Subject: [PATCH 11/55] Removed logs --- contracts/aggregator/fantom/flashloan/main.sol | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 979da13d..558a4e8c 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -6,7 +6,6 @@ pragma solidity ^0.8.0; * @dev Flashloan aggregator for Fantom. */ import "./helpers.sol"; -import "hardhat/console.sol"; contract FlashAggregatorFantom is Helper { using SafeERC20 for IERC20; @@ -45,7 +44,6 @@ contract FlashAggregatorFantom is Helper { bytes memory _data ) internal reentrancy returns (bool) {//TODO: doubt - console.log("Inside routefla"); FlashloanVariables memory instaLoanVariables_; instaLoanVariables_._tokens = _tokens; @@ -54,12 +52,11 @@ contract FlashAggregatorFantom is Helper { _amounts, calculateFeeBPS(10) ); - console.log("AAVE_IMPL: ", AAVE_IMPL); + instaLoanVariables_._iniBals = calculateBalances( _tokens, address(this) ); - console.log("_iniBals: ", instaLoanVariables_._iniBals[0]); safeTransfer(instaLoanVariables_, _receiverAddress); if (checkIfDsa(_receiverAddress)) { @@ -82,7 +79,6 @@ contract FlashAggregatorFantom is Helper { _tokens, address(this) ); - console.log("_finBals: ", instaLoanVariables_._finBals[0]); validateFlashloan(instaLoanVariables_); status = 1; @@ -148,7 +144,6 @@ contract FlashAggregatorFantom is Helper { * @notice Function to get the list of available routes. */ function getRoutes() public view returns (uint16[] memory routes_) { - console.log("Inside getRoutes main"); routes_ = new uint16[](2); routes_[0] = 9; routes_[1] = 10; @@ -176,7 +171,6 @@ contract InstaFlashAggregatorFantom is FlashAggregatorFantom { require(status == 0, "cannot-call-again"); status = 1; AAVE_IMPL = aave; - console.log("AAVE_IMPL: ", AAVE_IMPL); } receive() external payable {} From 87f02cf8ad854456d40b05c004fd871ebe61a15a Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 21 Jun 2022 16:37:17 +0530 Subject: [PATCH 12/55] Revert "Removed logs" This reverts commit fa19dacb00978a6313d6420edd44f32ab95dd865. --- contracts/aggregator/fantom/flashloan/main.sol | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 558a4e8c..979da13d 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -6,6 +6,7 @@ pragma solidity ^0.8.0; * @dev Flashloan aggregator for Fantom. */ import "./helpers.sol"; +import "hardhat/console.sol"; contract FlashAggregatorFantom is Helper { using SafeERC20 for IERC20; @@ -44,6 +45,7 @@ contract FlashAggregatorFantom is Helper { bytes memory _data ) internal reentrancy returns (bool) {//TODO: doubt + console.log("Inside routefla"); FlashloanVariables memory instaLoanVariables_; instaLoanVariables_._tokens = _tokens; @@ -52,11 +54,12 @@ contract FlashAggregatorFantom is Helper { _amounts, calculateFeeBPS(10) ); - + console.log("AAVE_IMPL: ", AAVE_IMPL); instaLoanVariables_._iniBals = calculateBalances( _tokens, address(this) ); + console.log("_iniBals: ", instaLoanVariables_._iniBals[0]); safeTransfer(instaLoanVariables_, _receiverAddress); if (checkIfDsa(_receiverAddress)) { @@ -79,6 +82,7 @@ contract FlashAggregatorFantom is Helper { _tokens, address(this) ); + console.log("_finBals: ", instaLoanVariables_._finBals[0]); validateFlashloan(instaLoanVariables_); status = 1; @@ -144,6 +148,7 @@ contract FlashAggregatorFantom is Helper { * @notice Function to get the list of available routes. */ function getRoutes() public view returns (uint16[] memory routes_) { + console.log("Inside getRoutes main"); routes_ = new uint16[](2); routes_[0] = 9; routes_[1] = 10; @@ -171,6 +176,7 @@ contract InstaFlashAggregatorFantom is FlashAggregatorFantom { require(status == 0, "cannot-call-again"); status = 1; AAVE_IMPL = aave; + console.log("AAVE_IMPL: ", AAVE_IMPL); } receive() external payable {} From 80a4c95e6f9130ab156b6c0deb249adb2680bff9 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Tue, 21 Jun 2022 16:38:04 +0530 Subject: [PATCH 13/55] code refactored Co-authored-by: Vaibhav Khanna <55931792+Vaibhav20201@users.noreply.github.com> --- contracts/aggregator/fantom/flashloan/main.sol | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 979da13d..a39f6bb2 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -109,23 +109,7 @@ contract FlashAggregatorFantom is Helper { (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); - if (_route == 1) { - revert("this route is only for mainnet, polygon, and avalanche"); - } else if (_route == 2) { - revert("this route is only for mainnet"); - } else if (_route == 3) { - revert("this route is only for mainnet"); - } else if (_route == 4) { - revert("this route is only for mainnet"); - } else if (_route == 5) { - revert("this route is only for mainnet, polygon and arbitrum"); - } else if (_route == 6) { - 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 if (_route == 9) { + if (_route == 9) { spell(AAVE_IMPL, msg.data); } else if (_route == 10){ (_tokens, _amounts) = bubbleSort(_tokens, _amounts); From bcddc8e3acf6b464fdbd7a1f2b8cb2d12b5c43a3 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Tue, 21 Jun 2022 16:48:16 +0530 Subject: [PATCH 14/55] route var removed Co-authored-by: Vaibhav Khanna <55931792+Vaibhav20201@users.noreply.github.com> --- contracts/aggregator/fantom/flashloan/implAaveV3/main.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol b/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol index dadeeac4..83228a52 100644 --- a/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol +++ b/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol @@ -46,9 +46,9 @@ contract AaveImplementationFantom is Helper { require(msg.sender == aaveV3LendingAddr, "not-aave-sender"); FlashloanVariables memory instaLoanVariables_; - (uint256 route_, address sender_, bytes memory data_) = abi.decode( + (address sender_, bytes memory data_) = abi.decode( _data, - (uint256, address, bytes) + (address, bytes) ); instaLoanVariables_._tokens = _assets; From 9a8043abdc1e8f7482d3b22997be520416d2eb26 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Tue, 21 Jun 2022 16:48:30 +0530 Subject: [PATCH 15/55] Update contracts/aggregator/fantom/flashloan/implAaveV3/main.sol Co-authored-by: Vaibhav Khanna <55931792+Vaibhav20201@users.noreply.github.com> --- contracts/aggregator/fantom/flashloan/implAaveV3/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol b/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol index 83228a52..8b68509d 100644 --- a/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol +++ b/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol @@ -84,7 +84,7 @@ contract AaveImplementationFantom is Helper { bytes memory _data ) internal { - bytes memory data_ = abi.encode(9, msg.sender, _data); + 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++) { From 12fcaa64bccf7f269f59ecd50ac5544738f37c3b Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 21 Jun 2022 17:49:39 +0530 Subject: [PATCH 16/55] transferFee updated + added admin module --- .../aggregator/fantom/flashloan/main.sol | 68 ++++++++++++++++--- .../aggregator/fantom/flashloan/variables.sol | 4 ++ 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index a39f6bb2..47afc363 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -8,7 +8,36 @@ pragma solidity ^0.8.0; import "./helpers.sol"; import "hardhat/console.sol"; -contract FlashAggregatorFantom is Helper { +contract AdminModule is Helper { + event updateOwnerLog(address indexed oldOwner, address indexed newOwner); + + event updateWhitelistLog( + address indexed account, + bool indexed isWhitelisted_ + ); + + /** + * @dev owner gaurd. + * @notice owner gaurd. + */ + modifier onlyOwner() { + require(msg.sender == owner, "not-owner"); + _; + } + + /** + * @dev Update owner. + * @notice Update owner. + * @param newOwner_ address of new owner. + */ + function updateOwner(address newOwner_) external onlyOwner { + address oldOwner_ = owner; + owner = newOwner_; + emit updateOwnerLog(oldOwner_, newOwner_); + } +} + +contract FlashAggregatorFantom is AdminModule { using SafeERC20 for IERC20; event LogFlashloan( @@ -17,6 +46,12 @@ contract FlashAggregatorFantom is Helper { address[] tokens, uint256[] amounts ); + + event LogCollectRevenue( + address to, + address[] tokens, + uint256[] amounts + ); /** * @dev Callback function for aave flashloan. @@ -140,26 +175,39 @@ contract FlashAggregatorFantom is Helper { /** * @dev Function to transfer fee to the treasury. - * @notice Function to transfer fee to the treasury. + * @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 { + * @param _to treasury address. + */ + 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]); - uint decimals_ = TokenInterface(_tokens[i]).decimals(); - uint amtToSub_ = decimals_ == 18 ? 1e10 : decimals_ > 12 ? 10000 : decimals_ > 7 ? 100 : 10; - uint amtToTransfer_ = token_.balanceOf(address(this)) > amtToSub_ ? (token_.balanceOf(address(this)) - amtToSub_) : 0; - if (amtToTransfer_ > 0) token_.safeTransfer(treasuryAddr, amtToTransfer_); + uint256 decimals_ = TokenInterface(_tokens[i]).decimals(); + uint256 amtToSub_ = decimals_ == 18 ? 1e10 : decimals_ > 12 + ? 10000 + : decimals_ > 7 + ? 100 + : 10; + _amts[i] = token_.balanceOf(address(this)) > amtToSub_ + ? (token_.balanceOf(address(this)) - amtToSub_) + : 0; + if (_amts[i] > 0) + token_.safeTransfer(_to, _amts[i]); } + emit LogCollectRevenue(_to, _tokens, _amts); } } contract InstaFlashAggregatorFantom is FlashAggregatorFantom { - function initialize(address aave) public { + function initialize(address owner_, address aave_) public { require(status == 0, "cannot-call-again"); + require(ownerStatus == 0, "only-once"); + owner = owner_; + ownerStatus = 1; status = 1; - AAVE_IMPL = aave; + AAVE_IMPL = aave_; console.log("AAVE_IMPL: ", AAVE_IMPL); } diff --git a/contracts/aggregator/fantom/flashloan/variables.sol b/contracts/aggregator/fantom/flashloan/variables.sol index 4eb2b4d6..c1b1aaec 100644 --- a/contracts/aggregator/fantom/flashloan/variables.sol +++ b/contracts/aggregator/fantom/flashloan/variables.sol @@ -19,6 +19,10 @@ contract ConstantVariables { contract Variables is ConstantVariables { + address public owner; + + uint256 internal ownerStatus; + bytes32 internal dataHash; // if 1 then can enter flashlaon, if 2 then callback uint internal status; From d45e8edf36e49d167426e7e1f6e98bd1c16d75fb Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 21 Jun 2022 18:33:20 +0530 Subject: [PATCH 17/55] removed logs --- contracts/aggregator/fantom/flashloan/main.sol | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 47afc363..a50b4757 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -6,7 +6,6 @@ pragma solidity ^0.8.0; * @dev Flashloan aggregator for Fantom. */ import "./helpers.sol"; -import "hardhat/console.sol"; contract AdminModule is Helper { event updateOwnerLog(address indexed oldOwner, address indexed newOwner); @@ -80,8 +79,6 @@ contract FlashAggregatorFantom is AdminModule { bytes memory _data ) internal reentrancy returns (bool) {//TODO: doubt - console.log("Inside routefla"); - FlashloanVariables memory instaLoanVariables_; instaLoanVariables_._tokens = _tokens; instaLoanVariables_._amounts = _amounts; @@ -89,12 +86,11 @@ contract FlashAggregatorFantom is AdminModule { _amounts, calculateFeeBPS(10) ); - console.log("AAVE_IMPL: ", AAVE_IMPL); instaLoanVariables_._iniBals = calculateBalances( _tokens, address(this) ); - console.log("_iniBals: ", instaLoanVariables_._iniBals[0]); + safeTransfer(instaLoanVariables_, _receiverAddress); if (checkIfDsa(_receiverAddress)) { @@ -117,7 +113,7 @@ contract FlashAggregatorFantom is AdminModule { _tokens, address(this) ); - console.log("_finBals: ", instaLoanVariables_._finBals[0]); + validateFlashloan(instaLoanVariables_); status = 1; @@ -166,8 +162,7 @@ contract FlashAggregatorFantom is AdminModule { * @dev Function to get the list of available routes. * @notice Function to get the list of available routes. */ - function getRoutes() public view returns (uint16[] memory routes_) { - console.log("Inside getRoutes main"); + function getRoutes() public pure returns (uint16[] memory routes_) { routes_ = new uint16[](2); routes_[0] = 9; routes_[1] = 10; @@ -208,7 +203,6 @@ contract InstaFlashAggregatorFantom is FlashAggregatorFantom { ownerStatus = 1; status = 1; AAVE_IMPL = aave_; - console.log("AAVE_IMPL: ", AAVE_IMPL); } receive() external payable {} From 0cda7c589b758d9362d23f57c13834de7af88b46 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Wed, 22 Jun 2022 03:11:15 +0530 Subject: [PATCH 18/55] Added flaImpl --- .../fantom/flashloan/implFLA/main.sol | 76 +++++++++++++++++++ .../aggregator/fantom/flashloan/main.sol | 58 ++------------ .../aggregator/fantom/flashloan/variables.sol | 1 + hardhat.config.ts | 4 +- 4 files changed, 84 insertions(+), 55 deletions(-) create mode 100644 contracts/aggregator/fantom/flashloan/implFLA/main.sol diff --git a/contracts/aggregator/fantom/flashloan/implFLA/main.sol b/contracts/aggregator/fantom/flashloan/implFLA/main.sol new file mode 100644 index 00000000..e93d90ff --- /dev/null +++ b/contracts/aggregator/fantom/flashloan/implFLA/main.sol @@ -0,0 +1,76 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +import "../helpers.sol"; + +contract FLAImplementationFantom 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 == 10, "invalid-FLA-route"); + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + routeFLA(msg.sender, _tokens, _amounts, _data); + } + + function routeFLA( + address _receiverAddress, + 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(10) + ); + 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; + } +} diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index a50b4757..7e079e4c 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -72,54 +72,6 @@ contract FlashAggregatorFantom is AdminModule { 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(10) - ); - 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. @@ -128,7 +80,7 @@ contract FlashAggregatorFantom is AdminModule { * @param _route route for flashloan. * @param _data extra data passed. */ - function flashLoan( + function flashLoan( address[] memory _tokens, uint256[] memory _amounts, uint256 _route, @@ -140,12 +92,11 @@ contract FlashAggregatorFantom is AdminModule { (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); + if (_route == 9) { spell(AAVE_IMPL, msg.data); } else if (_route == 10){ - (_tokens, _amounts) = bubbleSort(_tokens, _amounts); - validateTokens(_tokens); - routeFLA(msg.sender, _tokens, _amounts, _data); + spell(FLA_IMPL, msg.data); } else { revert("route-does-not-exist"); } @@ -196,13 +147,14 @@ contract FlashAggregatorFantom is AdminModule { contract InstaFlashAggregatorFantom is FlashAggregatorFantom { - function initialize(address owner_, address aave_) public { + function initialize(address owner_, address aave_, address fla_) public { require(status == 0, "cannot-call-again"); require(ownerStatus == 0, "only-once"); owner = owner_; ownerStatus = 1; status = 1; AAVE_IMPL = aave_; + FLA_IMPL = fla_; } receive() external payable {} diff --git a/contracts/aggregator/fantom/flashloan/variables.sol b/contracts/aggregator/fantom/flashloan/variables.sol index c1b1aaec..bbb1174d 100644 --- a/contracts/aggregator/fantom/flashloan/variables.sol +++ b/contracts/aggregator/fantom/flashloan/variables.sol @@ -36,4 +36,5 @@ contract Variables is ConstantVariables { } address internal AAVE_IMPL; + address internal FLA_IMPL; } diff --git a/hardhat.config.ts b/hardhat.config.ts index 7a2a924f..51ab2839 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -60,7 +60,7 @@ function getNetworkUrl(networkType: string) { else if (networkType === "polygon") return `https://polygon-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; else if (networkType === "arbitrum") return `https://arb-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; else if (networkType === "optimism") return `https://opt-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; - else if (networkType === "fantom") return `https://rpc.ankr.com/fantom`; + else if (networkType === "fantom") return `https://rpc.ftm.tools/`; else return `https://eth-mainnet.alchemyapi.io/v2/${alchemyApiKey}`; } @@ -69,7 +69,7 @@ function getBlockNumber(networkType: string) { else if (networkType === "polygon") return 25941254; else if (networkType === "arbitrum") return 7719792; else if (networkType === "optimism") return 4346343; - else if (networkType === "fantom") return 40887910; + else if (networkType === "fantom") return 40997910; else return 14456907; } From b33d9c6b639a157b8ef2a209306136fe460b208b Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 23 Jun 2022 01:07:26 +0530 Subject: [PATCH 19/55] removed spell --- contracts/aggregator/common/helpers.sol | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/contracts/aggregator/common/helpers.sol b/contracts/aggregator/common/helpers.sol index e1ba1740..3f929404 100644 --- a/contracts/aggregator/common/helpers.sol +++ b/contracts/aggregator/common/helpers.sol @@ -6,31 +6,6 @@ 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. From 5a7dd18bf52adb2b9219a5f7ac8a90a17f5556b2 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 23 Jun 2022 01:08:15 +0530 Subject: [PATCH 20/55] Added fallback and addNewRoutes func --- .../aggregator/fantom/flashloan/main.sol | 61 +++++++++---------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 7e079e4c..7f8d6285 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -1,11 +1,12 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; +import "./helpers.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; /** * @title Flashloan. * @dev Flashloan aggregator for Fantom. */ -import "./helpers.sol"; contract AdminModule is Helper { event updateOwnerLog(address indexed oldOwner, address indexed newOwner); @@ -51,26 +52,6 @@ contract FlashAggregatorFantom is AdminModule { address[] tokens, uint256[] amounts ); - - /** - * @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 returns (bool) { - bytes memory response_ = spell(AAVE_IMPL, msg.data); - return (abi.decode(response_, (bool))); - } /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -91,15 +72,10 @@ contract FlashAggregatorFantom is AdminModule { (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); + + implToCall = routeToImpl[_route]; - - if (_route == 9) { - spell(AAVE_IMPL, msg.data); - } else if (_route == 10){ - spell(FLA_IMPL, msg.data); - } else { - revert("route-does-not-exist"); - } + Address.functionDelegateCall(implToCall, msg.data, "call-to-impl-failed"); emit LogFlashloan( msg.sender, @@ -143,19 +119,38 @@ contract FlashAggregatorFantom is AdminModule { } emit LogCollectRevenue(_to, _tokens, _amts); } + + /** + * @dev Function to add new routes. + * @notice Function to add new routes and implementations. + * @param _routes routes to add. + * @param _impls implementations for their respective routes. + */ + function addNewRoutes(uint256[] memory _routes, address[] memory _impls) public onlyOwner { + require(_routes.length == _impls.length, "lengths-dont-match"); + uint length = _routes.length; + for (uint256 i = 0; i < length; i++) { + routeToImpl[_routes[i]] = _impls[i]; + } + } } contract InstaFlashAggregatorFantom is FlashAggregatorFantom { - function initialize(address owner_, address aave_, address fla_) public { + function initialize(address owner_, address aave_) public { require(status == 0, "cannot-call-again"); require(ownerStatus == 0, "only-once"); owner = owner_; ownerStatus = 1; status = 1; - AAVE_IMPL = aave_; - FLA_IMPL = fla_; + routeToImpl[9] = aave_; + // routeToImpl[10] = fla_; + } + + // Fallback function + fallback(bytes calldata input) external payable returns (bytes memory output) { + output = Address.functionDelegateCall(implToCall, input, "fallback-impl-call-failed"); } receive() external payable {} -} \ No newline at end of file +} From b2b93bbeca14d61ac13754950cd5b9673817e3bd Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 23 Jun 2022 01:08:49 +0530 Subject: [PATCH 21/55] added routeToImpl mapping --- contracts/aggregator/fantom/flashloan/implAaveV3/main.sol | 1 + contracts/aggregator/fantom/flashloan/implFLA/main.sol | 1 + contracts/aggregator/fantom/flashloan/variables.sol | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol b/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol index 8b68509d..fa746ab4 100644 --- a/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol +++ b/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol @@ -68,6 +68,7 @@ contract AaveImplementationFantom is Helper { instaLoanVariables_._finBals = calculateBalances(_assets, address(this)); validateFlashloan(instaLoanVariables_); + delete(implToCall); return true; } diff --git a/contracts/aggregator/fantom/flashloan/implFLA/main.sol b/contracts/aggregator/fantom/flashloan/implFLA/main.sol index e93d90ff..4dc406df 100644 --- a/contracts/aggregator/fantom/flashloan/implFLA/main.sol +++ b/contracts/aggregator/fantom/flashloan/implFLA/main.sol @@ -71,6 +71,7 @@ contract FLAImplementationFantom is Helper { validateFlashloan(instaLoanVariables_); status = 1; + delete(implToCall); return true; } } diff --git a/contracts/aggregator/fantom/flashloan/variables.sol b/contracts/aggregator/fantom/flashloan/variables.sol index bbb1174d..0fae4807 100644 --- a/contracts/aggregator/fantom/flashloan/variables.sol +++ b/contracts/aggregator/fantom/flashloan/variables.sol @@ -35,6 +35,6 @@ contract Variables is ConstantVariables { uint256[] _instaFees; } - address internal AAVE_IMPL; - address internal FLA_IMPL; + mapping (uint256 => address) public routeToImpl; + address internal implToCall; } From f35dc554375ab5389574f729d2118d3ec1ce578c Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 23 Jun 2022 01:09:14 +0530 Subject: [PATCH 22/55] updated testcases --- hardhat.config.ts | 2 +- test/fantom/flashloan.ts | 40 +++++++++++++++++++++++++++------------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 51ab2839..36e8f80c 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -69,7 +69,7 @@ function getBlockNumber(networkType: string) { else if (networkType === "polygon") return 25941254; else if (networkType === "arbitrum") return 7719792; else if (networkType === "optimism") return 4346343; - else if (networkType === "fantom") return 40997910; + else if (networkType === "fantom") return 41079980; else return 14456907; } diff --git a/test/fantom/flashloan.ts b/test/fantom/flashloan.ts index a075675e..4aea2b21 100644 --- a/test/fantom/flashloan.ts +++ b/test/fantom/flashloan.ts @@ -5,6 +5,7 @@ const { ethers } = hre import { InstaFlashAggregatorFantom, InstaFlashAggregatorFantom__factory, + FlashAggregatorFantom__factory, IERC20__factory, IERC20, InstaFlashReceiver__factory, @@ -12,7 +13,9 @@ import { InstaFlashAggregatorProxy, InstaFlashAggregatorProxy__factory, AaveImplementationFantom, - AaveImplementationFantom__factory + AaveImplementationFantom__factory, + FLAImplementationFantom__factory, + FLAImplementationFantom } from '../../typechain' describe('FlashLoan', function () { @@ -23,13 +26,17 @@ describe('FlashLoan', function () { Proxy, proxy: InstaFlashAggregatorProxy, ImplAave, - implAave; + implAave, + ImplFLA, + implFLA: FLAImplementationFantom, + proxyNew: any; let signer: SignerWithAddress const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' + let masterSigner: any - let ABI = ['function initialize(address)'] + let ABI = ['function initialize(address,address)'] let iface = new ethers.utils.Interface(ABI) const DAI = '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E' @@ -66,24 +73,30 @@ describe('FlashLoan', function () { Aggregator = new InstaFlashAggregatorFantom__factory(signer) aggregator = await Aggregator.deploy() await aggregator.deployed() - console.log("aggregator deployed at: ", aggregator.address) ImplAave = new AaveImplementationFantom__factory(signer) implAave = await ImplAave.deploy() await implAave.deployed() - console.log("implAave deployed at: ", implAave.address) - const data = iface.encodeFunctionData('initialize', [implAave.address]) + ImplFLA = new FLAImplementationFantom__factory(signer) + implFLA = await ImplFLA.deploy() + await implFLA.deployed() + + const data = iface.encodeFunctionData('initialize', [signer.address, implAave.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) + + proxyNew = new ethers.Contract( + proxy.address, + FlashAggregatorFantom__factory.abi, + ethers.provider, + ) const token_dai = new ethers.Contract( DAI, @@ -106,7 +119,6 @@ describe('FlashLoan', function () { }) const signer_dai = await ethers.getSigner(ACC_DAI) - console.log(await token_dai.connect(signer_dai).balanceOf(ACC_DAI)); await token_dai.connect(signer_dai).transfer(receiver.address, dai) await token_dai.connect(signer_dai).transfer(proxy.address, Dai) @@ -122,8 +134,9 @@ describe('FlashLoan', function () { it('Should be able to take flashLoan of a single token from AAVE V3', async function () { await receiver.flashBorrow([DAI], [Dai], 9, zeroAddr,_instaData) }) - it('Should be able to take flashLoan of a single token from FLA', async function () { - await receiver.flashBorrow([DAI], [Dai], 10, zeroAddr, _instaData) + it('Should add new route and take flashloan', async function () { + await proxyNew.connect(signer).addNewRoutes(['10'],[implFLA.address]); + await receiver.flashBorrow([DAI], [Dai], 10, zeroAddr, _instaData); }) }) @@ -155,10 +168,11 @@ describe('FlashLoan', function () { }) _instaData = '0x' }) - it('Should be able to take flashLoan of multiple tokens together from AAVE', async function () { + it('Should be able to take flashLoan of multiple tokens together from AAVE V3', async function () { await receiver.flashBorrow([DAI, USDC], [Dai, Usdc], 9, zeroAddr, _instaData ) }) - it('Should be able to take flashLoan of multiple tokens together from FLA', async function () { + it('Should add new route and take flashloan and take flashLoan of multiple tokens from FLA', async function () { + await proxyNew.connect(signer).addNewRoutes(['10'],[implFLA.address]); await receiver.flashBorrow([DAI, USDC], [Dai, Usdc], 10, zeroAddr, _instaData ) }) }) From b10b35ad5efb1522542be44bd064c7de746bc8af Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 23 Jun 2022 02:51:06 +0530 Subject: [PATCH 23/55] Added functions to add, update and disable routes --- .../aggregator/fantom/flashloan/main.sol | 85 +++++++++++++++---- .../aggregator/fantom/flashloan/variables.sol | 2 + 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 7f8d6285..94932083 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -69,6 +69,7 @@ contract FlashAggregatorFantom is AdminModule { bytes calldata // kept for future use by instadapp. Currently not used anywhere. ) external { require(_tokens.length == _amounts.length, "array-lengths-not-same"); + require(routeStatus[_route] == true, "route-disabled"); (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); @@ -86,13 +87,48 @@ contract FlashAggregatorFantom is AdminModule { } /** - * @dev Function to get the list of available routes. - * @notice Function to get the list of available routes. - */ - function getRoutes() public pure returns (uint16[] memory routes_) { - routes_ = new uint16[](2); - routes_[0] = 9; - routes_[1] = 10; + * @dev Function to add new routes. + * @notice Function to add new routes and implementations. + * @param _routes routes to add. + * @param _impls implementations of their respective routes. + */ + function addNewRoutesAndEnable(uint256[] memory _routes, address[] memory _impls) public onlyOwner { + require(_routes.length == _impls.length, "lengths-dont-match"); + uint length = _routes.length; + for (uint256 i = 0; i < length; i++) { + require(routeToImpl[_routes[i]] == address(0), "route-already-exists"); + routeToImpl[_routes[i]] = _impls[i]; + routeStatus[_routes[i]] = true; + routes.push(_routes[i]); + } + } + + /** + * @dev Function to update existing routes. + * @notice Function to update existing routes and implementations. + * @param _routes routes to update. + * @param _impls implementations of their respective routes. + */ + function updateRouteImplementation(uint256[] memory _routes, address[] memory _impls) public onlyOwner { + require(_routes.length == _impls.length, "lengths-dont-match"); + uint length = _routes.length; + for (uint256 i = 0; i < length; i++) { + routeToImpl[_routes[i]] = _impls[i]; + } + } + + /** + * @dev Function to change route status. + * @notice Function to enable and disable routes. + * @param _routes routes those status we want to change. + * @param _statuses new statuses. + */ + function changeRouteStatus(uint256[] memory _routes, bool[] memory _statuses) public onlyOwner { + require(_routes.length == _statuses.length, "lengths-dont-match"); + uint length = _routes.length; + for (uint256 i = 0; i < length; i++) { + routeStatus[_routes[i]] = _statuses[i]; + } } /** @@ -121,16 +157,28 @@ contract FlashAggregatorFantom is AdminModule { } /** - * @dev Function to add new routes. - * @notice Function to add new routes and implementations. - * @param _routes routes to add. - * @param _impls implementations for their respective routes. - */ - function addNewRoutes(uint256[] memory _routes, address[] memory _impls) public onlyOwner { - require(_routes.length == _impls.length, "lengths-dont-match"); - uint length = _routes.length; - for (uint256 i = 0; i < length; i++) { - routeToImpl[_routes[i]] = _impls[i]; + * @dev Function to get the list of all routes. + * @notice Function to get the list of all routes. + */ + function getRoutes() public view returns (uint256[] memory routes_) { + uint length = routes.length; + routes_ = new uint256[](length); + for(uint i = 0; i < length; i++) { + routes_[i] = routes[i]; + } + } + + /** + * @dev Function to get the list of enabled routes. + * @notice Function to get the list of enabled routes. + */ + function getEnabledRoutes() public view returns (uint256[] memory routes_, bool[] memory routesBool_) { + routes_ = getRoutes(); + uint length = routes_.length; + routesBool_ = new bool[](length); + + for(uint i = 0; i < length; i++) { + routesBool_[i] = routeStatus[routes_[i]] == true ? true : false; } } } @@ -144,7 +192,8 @@ contract InstaFlashAggregatorFantom is FlashAggregatorFantom { ownerStatus = 1; status = 1; routeToImpl[9] = aave_; - // routeToImpl[10] = fla_; + routeStatus[9] = true; + routes.push(9); } // Fallback function diff --git a/contracts/aggregator/fantom/flashloan/variables.sol b/contracts/aggregator/fantom/flashloan/variables.sol index 0fae4807..5e44623f 100644 --- a/contracts/aggregator/fantom/flashloan/variables.sol +++ b/contracts/aggregator/fantom/flashloan/variables.sol @@ -36,5 +36,7 @@ contract Variables is ConstantVariables { } mapping (uint256 => address) public routeToImpl; + mapping (uint256 => bool) public routeStatus; address internal implToCall; + uint256[] public routes; } From d19d79082b02924170ee9515f92ea8afd755dd60 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 23 Jun 2022 02:52:04 +0530 Subject: [PATCH 24/55] minor update --- test/fantom/flashloan.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fantom/flashloan.ts b/test/fantom/flashloan.ts index 4aea2b21..58876a90 100644 --- a/test/fantom/flashloan.ts +++ b/test/fantom/flashloan.ts @@ -135,7 +135,7 @@ describe('FlashLoan', function () { await receiver.flashBorrow([DAI], [Dai], 9, zeroAddr,_instaData) }) it('Should add new route and take flashloan', async function () { - await proxyNew.connect(signer).addNewRoutes(['10'],[implFLA.address]); + await proxyNew.connect(signer).addNewRoutesAndEnable(['10'],[implFLA.address]); await receiver.flashBorrow([DAI], [Dai], 10, zeroAddr, _instaData); }) }) @@ -172,7 +172,7 @@ describe('FlashLoan', function () { await receiver.flashBorrow([DAI, USDC], [Dai, Usdc], 9, zeroAddr, _instaData ) }) it('Should add new route and take flashloan and take flashLoan of multiple tokens from FLA', async function () { - await proxyNew.connect(signer).addNewRoutes(['10'],[implFLA.address]); + await proxyNew.connect(signer).addNewRoutesAndEnable(['10'],[implFLA.address]); await receiver.flashBorrow([DAI, USDC], [Dai, Usdc], 10, zeroAddr, _instaData ) }) }) From e3c0ccd4971ea3079a0e74bb21735a43d0298f34 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 23 Jun 2022 03:01:24 +0530 Subject: [PATCH 25/55] code refactored --- .../aggregator/fantom/flashloan/helpers.sol | 76 +++++++-------- .../aggregator/fantom/flashloan/main.sol | 93 +++++++------------ .../aggregator/fantom/flashloan/variables.sol | 13 +-- 3 files changed, 77 insertions(+), 105 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/helpers.sol b/contracts/aggregator/fantom/flashloan/helpers.sol index 2be06940..61ba8a37 100644 --- a/contracts/aggregator/fantom/flashloan/helpers.sol +++ b/contracts/aggregator/fantom/flashloan/helpers.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "./variables.sol"; -import "../../common/helpers.sol"; +import './variables.sol'; +import '../../common/helpers.sol'; contract Helper is HelpersCommon, Variables { using SafeERC20 for IERC20; @@ -12,12 +12,14 @@ contract Helper is HelpersCommon, Variables { * @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_); @@ -30,16 +32,16 @@ contract Helper is HelpersCommon, Variables { * @param _instaLoanVariables struct which includes list of token addresses and amounts. * @param _fees list of premiums/fees for the corresponding addresses for flashloan. * @param _receiver address to which tokens have to be approved. - */ + */ function safeApprove( FlashloanVariables memory _instaLoanVariables, uint256[] memory _fees, address _receiver ) internal { uint256 length_ = _instaLoanVariables._tokens.length; - require(length_ == _instaLoanVariables._amounts.length, "Lengths of parameters not same"); - require(length_ == _fees.length, "Lengths of parameters not same"); - for (uint i = 0; i < length_; i++) { + require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); + require(length_ == _fees.length, 'Lengths of parameters not same'); + for (uint256 i = 0; i < length_; i++) { approve(_instaLoanVariables._tokens[i], _receiver, _instaLoanVariables._amounts[i] + _fees[i]); } } @@ -49,14 +51,11 @@ contract Helper is HelpersCommon, Variables { * @notice Transfers the tokens to the receiver address. * @param _instaLoanVariables struct which includes list of token addresses and amounts. * @param _receiver address to which tokens have to be transferred. - */ - function safeTransfer( - FlashloanVariables memory _instaLoanVariables, - address _receiver - ) internal { + */ + function safeTransfer(FlashloanVariables memory _instaLoanVariables, address _receiver) internal { uint256 length_ = _instaLoanVariables._tokens.length; - require(length_ == _instaLoanVariables._amounts.length, "Lengths of parameters not same"); - for (uint i = 0; i < length_; i++) { + require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); + for (uint256 i = 0; i < length_; i++) { IERC20 token = IERC20(_instaLoanVariables._tokens[i]); token.safeTransfer(_receiver, _instaLoanVariables._amounts[i]); } @@ -66,12 +65,13 @@ contract Helper is HelpersCommon, Variables { * @dev Validates if the receiver sent the correct amounts of funds. * @notice Validates if the receiver sent the correct amounts of funds. * @param _instaLoanVariables struct which includes list of initial balances, final balances and fees for the respective tokens. - */ - function validateFlashloan( - FlashloanVariables memory _instaLoanVariables - ) internal pure { - for (uint i = 0; i < _instaLoanVariables._iniBals.length; i++) { - require(_instaLoanVariables._iniBals[i] + _instaLoanVariables._instaFees[i] <= _instaLoanVariables._finBals[i], "amount-paid-less"); + */ + function validateFlashloan(FlashloanVariables memory _instaLoanVariables) internal pure { + for (uint256 i = 0; i < _instaLoanVariables._iniBals.length; i++) { + require( + _instaLoanVariables._iniBals[i] + _instaLoanVariables._instaFees[i] <= _instaLoanVariables._finBals[i], + 'amount-paid-less' + ); } } @@ -79,16 +79,16 @@ 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_){ + */ + function calculateFeeBPS(uint256 _route) public view returns (uint256 BPS_) { if (_route == 9) { BPS_ = aaveV3Lending.FLASHLOAN_PREMIUM_TOTAL(); - } else if (_route == 10){ + } else if (_route == 10) { BPS_ = InstaFeeBPS; } else { - revert("Invalid source"); + revert('Invalid source'); } - + if (BPS_ < InstaFeeBPS) { BPS_ = InstaFeeBPS; } @@ -98,7 +98,7 @@ contract Helper is HelpersCommon, Variables { * @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. * @param _account account to check for, if DSA. - */ + */ function checkIfDsa(address _account) internal view returns (bool) { return instaList.accountID(_account) > 0; } @@ -107,11 +107,11 @@ contract Helper is HelpersCommon, Variables { * @dev better checking by double encoding the data. * @notice better checking by double encoding the data. * @param data_ data passed. - */ + */ modifier verifyDataHash(bytes memory data_) { bytes32 dataHash_ = keccak256(data_); - require(dataHash_ == dataHash && dataHash_ != bytes32(0), "invalid-data-hash"); - require(status == 2, "already-entered"); + require(dataHash_ == dataHash && dataHash_ != bytes32(0), 'invalid-data-hash'); + require(status == 2, 'already-entered'); dataHash = bytes32(0); _; status = 1; @@ -120,11 +120,11 @@ contract Helper is HelpersCommon, Variables { /** * @dev reentrancy gaurd. * @notice reentrancy gaurd. - */ - modifier reentrancy { - require(status == 1, "already-entered"); + */ + modifier reentrancy() { + require(status == 1, 'already-entered'); status = 2; _; - require(status == 1, "already-entered"); + require(status == 1, 'already-entered'); } -} \ No newline at end of file +} diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 94932083..197f58c1 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "./helpers.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; +import './helpers.sol'; +import '@openzeppelin/contracts/utils/Address.sol'; /** * @title Flashloan. @@ -11,17 +11,14 @@ import "@openzeppelin/contracts/utils/Address.sol"; contract AdminModule is Helper { event updateOwnerLog(address indexed oldOwner, address indexed newOwner); - event updateWhitelistLog( - address indexed account, - bool indexed isWhitelisted_ - ); + event updateWhitelistLog(address indexed account, bool indexed isWhitelisted_); /** * @dev owner gaurd. * @notice owner gaurd. */ modifier onlyOwner() { - require(msg.sender == owner, "not-owner"); + require(msg.sender == owner, 'not-owner'); _; } @@ -40,18 +37,9 @@ contract AdminModule is Helper { contract FlashAggregatorFantom is AdminModule { using SafeERC20 for IERC20; - event LogFlashloan( - address indexed account, - uint256 indexed route, - address[] tokens, - uint256[] amounts - ); + event LogFlashloan(address indexed account, uint256 indexed route, address[] tokens, uint256[] amounts); - event LogCollectRevenue( - address to, - address[] tokens, - uint256[] amounts - ); + event LogCollectRevenue(address to, address[] tokens, uint256[] amounts); /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -60,30 +48,25 @@ contract FlashAggregatorFantom is AdminModule { * @param _amounts list of amounts for the corresponding assets. * @param _route route for flashloan. * @param _data extra data passed. - */ + */ function flashLoan( - address[] memory _tokens, + address[] memory _tokens, uint256[] memory _amounts, uint256 _route, bytes calldata _data, bytes calldata // kept for future use by instadapp. Currently not used anywhere. ) external { - require(_tokens.length == _amounts.length, "array-lengths-not-same"); - require(routeStatus[_route] == true, "route-disabled"); + require(_tokens.length == _amounts.length, 'array-lengths-not-same'); + require(routeStatus[_route] == true, 'route-disabled'); (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); - + implToCall = routeToImpl[_route]; - Address.functionDelegateCall(implToCall, msg.data, "call-to-impl-failed"); + Address.functionDelegateCall(implToCall, msg.data, 'call-to-impl-failed'); - emit LogFlashloan( - msg.sender, - _route, - _tokens, - _amounts - ); + emit LogFlashloan(msg.sender, _route, _tokens, _amounts); } /** @@ -93,10 +76,10 @@ contract FlashAggregatorFantom is AdminModule { * @param _impls implementations of their respective routes. */ function addNewRoutesAndEnable(uint256[] memory _routes, address[] memory _impls) public onlyOwner { - require(_routes.length == _impls.length, "lengths-dont-match"); - uint length = _routes.length; + require(_routes.length == _impls.length, 'lengths-dont-match'); + uint256 length = _routes.length; for (uint256 i = 0; i < length; i++) { - require(routeToImpl[_routes[i]] == address(0), "route-already-exists"); + require(routeToImpl[_routes[i]] == address(0), 'route-already-exists'); routeToImpl[_routes[i]] = _impls[i]; routeStatus[_routes[i]] = true; routes.push(_routes[i]); @@ -109,9 +92,9 @@ contract FlashAggregatorFantom is AdminModule { * @param _routes routes to update. * @param _impls implementations of their respective routes. */ - function updateRouteImplementation(uint256[] memory _routes, address[] memory _impls) public onlyOwner { - require(_routes.length == _impls.length, "lengths-dont-match"); - uint length = _routes.length; + function updateRouteImplementations(uint256[] memory _routes, address[] memory _impls) public onlyOwner { + require(_routes.length == _impls.length, 'lengths-dont-match'); + uint256 length = _routes.length; for (uint256 i = 0; i < length; i++) { routeToImpl[_routes[i]] = _impls[i]; } @@ -124,8 +107,8 @@ contract FlashAggregatorFantom is AdminModule { * @param _statuses new statuses. */ function changeRouteStatus(uint256[] memory _routes, bool[] memory _statuses) public onlyOwner { - require(_routes.length == _statuses.length, "lengths-dont-match"); - uint length = _routes.length; + require(_routes.length == _statuses.length, 'lengths-dont-match'); + uint256 length = _routes.length; for (uint256 i = 0; i < length; i++) { routeStatus[_routes[i]] = _statuses[i]; } @@ -142,16 +125,9 @@ contract FlashAggregatorFantom is AdminModule { for (uint256 i = 0; i < _tokens.length; i++) { IERC20 token_ = IERC20(_tokens[i]); uint256 decimals_ = TokenInterface(_tokens[i]).decimals(); - uint256 amtToSub_ = decimals_ == 18 ? 1e10 : decimals_ > 12 - ? 10000 - : decimals_ > 7 - ? 100 - : 10; - _amts[i] = token_.balanceOf(address(this)) > amtToSub_ - ? (token_.balanceOf(address(this)) - amtToSub_) - : 0; - if (_amts[i] > 0) - token_.safeTransfer(_to, _amts[i]); + uint256 amtToSub_ = decimals_ == 18 ? 1e10 : decimals_ > 12 ? 10000 : decimals_ > 7 ? 100 : 10; + _amts[i] = token_.balanceOf(address(this)) > amtToSub_ ? (token_.balanceOf(address(this)) - amtToSub_) : 0; + if (_amts[i] > 0) token_.safeTransfer(_to, _amts[i]); } emit LogCollectRevenue(_to, _tokens, _amts); } @@ -159,11 +135,11 @@ contract FlashAggregatorFantom is AdminModule { /** * @dev Function to get the list of all routes. * @notice Function to get the list of all routes. - */ + */ function getRoutes() public view returns (uint256[] memory routes_) { - uint length = routes.length; + uint256 length = routes.length; routes_ = new uint256[](length); - for(uint i = 0; i < length; i++) { + for (uint256 i = 0; i < length; i++) { routes_[i] = routes[i]; } } @@ -171,23 +147,22 @@ contract FlashAggregatorFantom is AdminModule { /** * @dev Function to get the list of enabled routes. * @notice Function to get the list of enabled routes. - */ + */ function getEnabledRoutes() public view returns (uint256[] memory routes_, bool[] memory routesBool_) { routes_ = getRoutes(); - uint length = routes_.length; + uint256 length = routes_.length; routesBool_ = new bool[](length); - for(uint i = 0; i < length; i++) { + for (uint256 i = 0; i < length; i++) { routesBool_[i] = routeStatus[routes_[i]] == true ? true : false; } } } contract InstaFlashAggregatorFantom is FlashAggregatorFantom { - function initialize(address owner_, address aave_) public { - require(status == 0, "cannot-call-again"); - require(ownerStatus == 0, "only-once"); + require(status == 0, 'cannot-call-again'); + require(ownerStatus == 0, 'only-once'); owner = owner_; ownerStatus = 1; status = 1; @@ -197,8 +172,8 @@ contract InstaFlashAggregatorFantom is FlashAggregatorFantom { } // Fallback function - fallback(bytes calldata input) external payable returns (bytes memory output) { - output = Address.functionDelegateCall(implToCall, input, "fallback-impl-call-failed"); + fallback(bytes calldata input) external payable returns (bytes memory output) { + output = Address.functionDelegateCall(implToCall, input, 'fallback-impl-call-failed'); } receive() external payable {} diff --git a/contracts/aggregator/fantom/flashloan/variables.sol b/contracts/aggregator/fantom/flashloan/variables.sol index 5e44623f..44b3ef3a 100644 --- a/contracts/aggregator/fantom/flashloan/variables.sol +++ b/contracts/aggregator/fantom/flashloan/variables.sol @@ -1,11 +1,10 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "./interfaces.sol"; -import "../../common/interface.sol"; +import './interfaces.sol'; +import '../../common/interface.sol'; contract ConstantVariables { - address public constant aaveV3LendingAddr = 0x794a61358D6845594F94dc1DB02A252b5b4814aD; IAaveV3Lending public constant aaveV3Lending = IAaveV3Lending(aaveV3LendingAddr); @@ -14,18 +13,16 @@ contract ConstantVariables { ListInterface public constant instaList = ListInterface(instaListAddr); uint256 public constant InstaFeeBPS = 5; // in BPS; 1 BPS = 0.01% - } contract Variables is ConstantVariables { - address public owner; uint256 internal ownerStatus; bytes32 internal dataHash; // if 1 then can enter flashlaon, if 2 then callback - uint internal status; + uint256 internal status; struct FlashloanVariables { address[] _tokens; @@ -35,8 +32,8 @@ contract Variables is ConstantVariables { uint256[] _instaFees; } - mapping (uint256 => address) public routeToImpl; - mapping (uint256 => bool) public routeStatus; + mapping(uint256 => address) public routeToImpl; + mapping(uint256 => bool) public routeStatus; address internal implToCall; uint256[] public routes; } From 1a3a3610ef743cedd457043f09550ae69531115f Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 24 Jun 2022 01:46:25 +0530 Subject: [PATCH 26/55] calculateFeeBPS added in implementations --- .../fantom/flashloan/implAaveV3/main.sol | 38 +++++++++++++++++-- .../fantom/flashloan/implFLA/main.sol | 15 +++++++- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol b/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol index fa746ab4..8d138e7c 100644 --- a/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol +++ b/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol @@ -1,8 +1,27 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "../helpers.sol"; +import "../helper.sol"; -contract AaveImplementationFantom is Helper { +interface IAaveV3Lending { + function flashLoan( + address receiverAddress, + address[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata modes, + address onBehalfOf, + bytes calldata params, + uint16 referralCode + ) external; + + function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128); +} + +contract Variables { + address public constant aaveV3LendingAddr = 0x794a61358D6845594F94dc1DB02A252b5b4814aD; + IAaveV3Lending public constant aaveV3Lending = IAaveV3Lending(aaveV3LendingAddr); +} + +contract AaveImplementationFantom is Helper, Variables { /** * @dev Main function for flashloan for all routes. Calls the middle functions according to routes. @@ -12,7 +31,7 @@ contract AaveImplementationFantom is Helper { * @param _route route for flashloan. * @param _data extra data passed. */ - function flashLoan( + function flashLoan( address[] memory _tokens, uint256[] memory _amounts, uint256 _route, @@ -25,6 +44,19 @@ contract AaveImplementationFantom is Helper { routeAaveV3(_tokens, _amounts, _data); } + /** + * @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_ = aaveV3Lending.FLASHLOAN_PREMIUM_TOTAL(); + } else { + revert('Invalid source'); + } + } + /** * @dev Callback function for aave flashloan. * @notice Callback function for aave flashloan. diff --git a/contracts/aggregator/fantom/flashloan/implFLA/main.sol b/contracts/aggregator/fantom/flashloan/implFLA/main.sol index 4dc406df..4341865a 100644 --- a/contracts/aggregator/fantom/flashloan/implFLA/main.sol +++ b/contracts/aggregator/fantom/flashloan/implFLA/main.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "../helpers.sol"; +import "../helper.sol"; contract FLAImplementationFantom is Helper { @@ -26,6 +26,19 @@ contract FLAImplementationFantom is Helper { routeFLA(msg.sender, _tokens, _amounts, _data); } + /** + * @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 == 10) { + BPS_ = InstaFeeBPS; + } else { + revert('Invalid source'); + } + } + function routeFLA( address _receiverAddress, address[] memory _tokens, From 8992343fc8f92448a65ebc43cd1f39d9cd923bcd Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 24 Jun 2022 01:53:46 +0530 Subject: [PATCH 27/55] created common contracts for all chains --- contracts/aggregator/common/helpers.sol | 130 ++++++++++--- .../common/{interface.sol => interfaces.sol} | 10 + contracts/aggregator/common/main.sol | 174 ++++++++++++++++++ .../flashloan => common}/variables.sol | 18 +- .../aggregator/fantom/flashloan/helper.sol | 15 ++ .../aggregator/fantom/flashloan/helpers.sol | 130 ------------- .../fantom/flashloan/implAaveV3/main.sol | 46 ++--- .../fantom/flashloan/implFLA/main.sol | 53 ++---- .../fantom/flashloan/interfaces.sol | 27 --- .../aggregator/fantom/flashloan/main.sol | 159 +--------------- .../aggregator/fantom/flashloan/variable.sol | 9 + 11 files changed, 359 insertions(+), 412 deletions(-) rename contracts/aggregator/common/{interface.sol => interfaces.sol} (75%) create mode 100644 contracts/aggregator/common/main.sol rename contracts/aggregator/{fantom/flashloan => common}/variables.sol (55%) create mode 100644 contracts/aggregator/fantom/flashloan/helper.sol delete mode 100644 contracts/aggregator/fantom/flashloan/helpers.sol delete mode 100644 contracts/aggregator/fantom/flashloan/interfaces.sol create mode 100644 contracts/aggregator/fantom/flashloan/variable.sol diff --git a/contracts/aggregator/common/helpers.sol b/contracts/aggregator/common/helpers.sol index 3f929404..2581c27f 100644 --- a/contracts/aggregator/common/helpers.sol +++ b/contracts/aggregator/common/helpers.sol @@ -1,22 +1,88 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; +import './variables.sol'; -contract HelpersCommon { +contract HelpersCommon is VariablesCommon { using SafeERC20 for IERC20; + /** + * @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 { + TokenInterface tokenContract_ = TokenInterface(token_); + try tokenContract_.approve(spender_, amount_) {} catch { + IERC20 token = IERC20(token_); + token.safeApprove(spender_, 0); + token.safeApprove(spender_, amount_); + } + } + + /** + * @dev Approves the tokens to the receiver address with allowance (amount + fee). + * @notice Approves the tokens to the receiver address with allowance (amount + fee). + * @param _instaLoanVariables struct which includes list of token addresses and amounts. + * @param _fees list of premiums/fees for the corresponding addresses for flashloan. + * @param _receiver address to which tokens have to be approved. + */ + function safeApprove( + FlashloanVariables memory _instaLoanVariables, + uint256[] memory _fees, + address _receiver + ) internal { + uint256 length_ = _instaLoanVariables._tokens.length; + require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); + require(length_ == _fees.length, 'Lengths of parameters not same'); + for (uint256 i = 0; i < length_; i++) { + approve(_instaLoanVariables._tokens[i], _receiver, _instaLoanVariables._amounts[i] + _fees[i]); + } + } + + /** + * @dev Transfers the tokens to the receiver address. + * @notice Transfers the tokens to the receiver address. + * @param _instaLoanVariables struct which includes list of token addresses and amounts. + * @param _receiver address to which tokens have to be transferred. + */ + function safeTransfer(FlashloanVariables memory _instaLoanVariables, address _receiver) internal { + uint256 length_ = _instaLoanVariables._tokens.length; + require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); + for (uint256 i = 0; i < length_; i++) { + IERC20 token = IERC20(_instaLoanVariables._tokens[i]); + token.safeTransfer(_receiver, _instaLoanVariables._amounts[i]); + } + } + + /** + * @dev Validates if the receiver sent the correct amounts of funds. + * @notice Validates if the receiver sent the correct amounts of funds. + * @param _instaLoanVariables struct which includes list of initial balances, final balances and fees for the respective tokens. + */ + function validateFlashloan(FlashloanVariables memory _instaLoanVariables) internal pure { + for (uint256 i = 0; i < _instaLoanVariables._iniBals.length; i++) { + require( + _instaLoanVariables._iniBals[i] + _instaLoanVariables._instaFees[i] <= _instaLoanVariables._finBals[i], + 'amount-paid-less' + ); + } + } + /** * @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) - { + 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++) { @@ -33,7 +99,7 @@ contract HelpersCommon { */ 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"); + require(_tokens[i] != _tokens[i + 1], 'non-unique-tokens'); } } @@ -43,11 +109,7 @@ contract HelpersCommon { * @param _amounts list of amounts. * @param _BPS fee in BPS. */ - function calculateFees(uint256[] memory _amounts, uint256 _BPS) - internal - pure - returns (uint256[] memory) - { + 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++) { @@ -70,12 +132,7 @@ contract HelpersCommon { 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], _tokens[j + 1], _amounts[j], _amounts[j + 1]) = ( _tokens[j + 1], _tokens[j], _amounts[j + 1], @@ -93,14 +150,35 @@ contract HelpersCommon { * @param _token0 address of token0. * @param _token1 address of token1. */ - function sortTokens(address _token0, address _token1) - internal - pure - returns (address, address) - { - if(_token1 < _token0) { + function sortTokens(address _token0, address _token1) internal pure returns (address, address) { + if (_token1 < _token0) { (_token0, _token1) = (_token1, _token0); } - return (_token0 , _token1); + return (_token0, _token1); + } + + /** + * @dev better checking by double encoding the data. + * @notice better checking by double encoding the data. + * @param data_ data passed. + */ + modifier verifyDataHash(bytes memory data_) { + bytes32 dataHash_ = keccak256(data_); + require(dataHash_ == dataHash && dataHash_ != bytes32(0), 'invalid-data-hash'); + require(status == 2, 'already-entered'); + dataHash = bytes32(0); + _; + status = 1; + } + + /** + * @dev reentrancy gaurd. + * @notice reentrancy gaurd. + */ + modifier reentrancy() { + require(status == 1, 'already-entered'); + status = 2; + _; + require(status == 1, 'already-entered'); } } diff --git a/contracts/aggregator/common/interface.sol b/contracts/aggregator/common/interfaces.sol similarity index 75% rename from contracts/aggregator/common/interface.sol rename to contracts/aggregator/common/interfaces.sol index b800be8a..5a88a056 100644 --- a/contracts/aggregator/common/interface.sol +++ b/contracts/aggregator/common/interfaces.sol @@ -2,6 +2,16 @@ pragma solidity ^0.8.0; pragma experimental ABIEncoderV2; +interface InstaFlashReceiverInterface { + function executeOperation( + address[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata premiums, + address initiator, + bytes calldata _data + ) external returns (bool); +} + interface IndexInterface { function master() external view returns (address); diff --git a/contracts/aggregator/common/main.sol b/contracts/aggregator/common/main.sol new file mode 100644 index 00000000..a97581b1 --- /dev/null +++ b/contracts/aggregator/common/main.sol @@ -0,0 +1,174 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +import './helpers.sol'; +import '@openzeppelin/contracts/utils/Address.sol'; + +/** + * @title Flashloan. + * @dev Common aggregator implementation for all chains. + */ + +contract AdminModule is HelpersCommon { + event updateOwnerLog(address indexed oldOwner, address indexed newOwner); + + event updateWhitelistLog(address indexed account, bool indexed isWhitelisted_); + + /** + * @dev owner gaurd. + * @notice owner gaurd. + */ + modifier onlyOwner() { + require(msg.sender == owner, 'not-owner'); + _; + } + + /** + * @dev Update owner. + * @notice Update owner. + * @param newOwner_ address of new owner. + */ + function updateOwner(address newOwner_) external onlyOwner { + address oldOwner_ = owner; + owner = newOwner_; + emit updateOwnerLog(oldOwner_, newOwner_); + } +} + +contract FlashAggregator is AdminModule { + using SafeERC20 for IERC20; + + event LogFlashloan(address indexed account, uint256 indexed route, address[] tokens, uint256[] amounts); + + event LogCollectRevenue(address to, address[] tokens, uint256[] amounts); + + /** + * @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 { + require(_tokens.length == _amounts.length, 'array-lengths-not-same'); + require(routeStatus[_route] == true, 'route-disabled'); + + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + + implToCall = routeToImpl[_route]; + + Address.functionDelegateCall(implToCall, msg.data, 'call-to-impl-failed'); + + emit LogFlashloan(msg.sender, _route, _tokens, _amounts); + } + + /** + * @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_) { + bytes memory _output = Address.functionStaticCall(implToCall, msg.data, 'calculateFeeBPS-call-failed'); + BPS_ = abi.decode(_output, (uint256)); + + if (BPS_ < InstaFeeBPS) { + BPS_ = InstaFeeBPS; + } + } + + /** + * @dev Function to add new routes. + * @notice Function to add new routes and implementations. + * @param _routes routes to add. + * @param _impls implementations of their respective routes. + */ + function addNewRoutesAndEnable(uint256[] memory _routes, address[] memory _impls) public onlyOwner { + require(_routes.length == _impls.length, 'lengths-dont-match'); + uint256 length = _routes.length; + for (uint256 i = 0; i < length; i++) { + require(routeToImpl[_routes[i]] == address(0), 'route-already-exists'); + routeToImpl[_routes[i]] = _impls[i]; + routeStatus[_routes[i]] = true; + routes.push(_routes[i]); + } + } + + /** + * @dev Function to update existing routes. + * @notice Function to update existing routes and implementations. + * @param _routes routes to update. + * @param _impls implementations of their respective routes. + */ + function updateRouteImplementations(uint256[] memory _routes, address[] memory _impls) public onlyOwner { + require(_routes.length == _impls.length, 'lengths-dont-match'); + uint256 length = _routes.length; + for (uint256 i = 0; i < length; i++) { + routeToImpl[_routes[i]] = _impls[i]; + } + } + + /** + * @dev Function to change route status. + * @notice Function to enable and disable routes. + * @param _routes routes those status we want to change. + * @param _statuses new statuses. + */ + function changeRouteStatus(uint256[] memory _routes, bool[] memory _statuses) public onlyOwner { + require(_routes.length == _statuses.length, 'lengths-dont-match'); + uint256 length = _routes.length; + for (uint256 i = 0; i < length; i++) { + routeStatus[_routes[i]] = _statuses[i]; + } + } + + /** + * @dev Function to get the list of all routes. + * @notice Function to get the list of all routes. + */ + function getRoutes() public view returns (uint256[] memory routes_) { + uint256 length = routes.length; + routes_ = new uint256[](length); + for (uint256 i = 0; i < length; i++) { + routes_[i] = routes[i]; + } + } + + /** + * @dev Function to get the list of enabled routes. + * @notice Function to get the list of enabled routes. + */ + function getEnabledRoutes() public view returns (uint256[] memory routes_, bool[] memory routesBool_) { + routes_ = getRoutes(); + uint256 length = routes_.length; + routesBool_ = new bool[](length); + + for (uint256 i = 0; i < length; i++) { + routesBool_[i] = routeStatus[routes_[i]] == true ? true : false; + } + } + + /** + * @dev Function to transfer fee to the treasury. + * @notice Function to transfer fee to the treasury. Will be called manually. + * @param _tokens token addresses for transferring fee to treasury. + * @param _to treasury address. + */ + 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(); + uint256 amtToSub_ = decimals_ == 18 ? 1e10 : decimals_ > 12 ? 10000 : decimals_ > 7 ? 100 : 10; + _amts[i] = token_.balanceOf(address(this)) > amtToSub_ ? (token_.balanceOf(address(this)) - amtToSub_) : 0; + if (_amts[i] > 0) token_.safeTransfer(_to, _amts[i]); + } + emit LogCollectRevenue(_to, _tokens, _amts); + } +} diff --git a/contracts/aggregator/fantom/flashloan/variables.sol b/contracts/aggregator/common/variables.sol similarity index 55% rename from contracts/aggregator/fantom/flashloan/variables.sol rename to contracts/aggregator/common/variables.sol index 44b3ef3a..f6f9ff85 100644 --- a/contracts/aggregator/fantom/flashloan/variables.sol +++ b/contracts/aggregator/common/variables.sol @@ -1,21 +1,8 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; - import './interfaces.sol'; -import '../../common/interface.sol'; - -contract ConstantVariables { - address public constant aaveV3LendingAddr = 0x794a61358D6845594F94dc1DB02A252b5b4814aD; - IAaveV3Lending public constant aaveV3Lending = IAaveV3Lending(aaveV3LendingAddr); - - address public constant treasuryAddr = 0x6C4061A00F8739d528b185CC683B6400E0cd396a; - address private constant instaListAddr = 0x10e166c3FAF887D8a61dE6c25039231eE694E926; - ListInterface public constant instaList = ListInterface(instaListAddr); - - uint256 public constant InstaFeeBPS = 5; // in BPS; 1 BPS = 0.01% -} -contract Variables is ConstantVariables { +contract VariablesCommon { address public owner; uint256 internal ownerStatus; @@ -34,6 +21,9 @@ contract Variables is ConstantVariables { mapping(uint256 => address) public routeToImpl; mapping(uint256 => bool) public routeStatus; + mapping(uint256 => uint256) public routeToFee; address internal implToCall; uint256[] public routes; + + uint256 public constant InstaFeeBPS = 5; // in BPS; 1 BPS = 0.01% } diff --git a/contracts/aggregator/fantom/flashloan/helper.sol b/contracts/aggregator/fantom/flashloan/helper.sol new file mode 100644 index 00000000..5472654d --- /dev/null +++ b/contracts/aggregator/fantom/flashloan/helper.sol @@ -0,0 +1,15 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +import '../../common/helpers.sol'; +import './variable.sol'; + +contract Helper is ConstantVariables, HelpersCommon { + /** + * @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. + * @param _account account to check for, if DSA. + */ + function checkIfDsa(address _account) internal view returns (bool) { + return instaList.accountID(_account) > 0; + } +} diff --git a/contracts/aggregator/fantom/flashloan/helpers.sol b/contracts/aggregator/fantom/flashloan/helpers.sol deleted file mode 100644 index 61ba8a37..00000000 --- a/contracts/aggregator/fantom/flashloan/helpers.sol +++ /dev/null @@ -1,130 +0,0 @@ -//SPDX-License-Identifier: Unlicense -pragma solidity ^0.8.0; -import './variables.sol'; -import '../../common/helpers.sol'; - -contract Helper is HelpersCommon, Variables { - using SafeERC20 for IERC20; - - /** - * @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 { - TokenInterface tokenContract_ = TokenInterface(token_); - try tokenContract_.approve(spender_, amount_) {} catch { - IERC20 token = IERC20(token_); - token.safeApprove(spender_, 0); - token.safeApprove(spender_, amount_); - } - } - - /** - * @dev Approves the tokens to the receiver address with allowance (amount + fee). - * @notice Approves the tokens to the receiver address with allowance (amount + fee). - * @param _instaLoanVariables struct which includes list of token addresses and amounts. - * @param _fees list of premiums/fees for the corresponding addresses for flashloan. - * @param _receiver address to which tokens have to be approved. - */ - function safeApprove( - FlashloanVariables memory _instaLoanVariables, - uint256[] memory _fees, - address _receiver - ) internal { - uint256 length_ = _instaLoanVariables._tokens.length; - require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); - require(length_ == _fees.length, 'Lengths of parameters not same'); - for (uint256 i = 0; i < length_; i++) { - approve(_instaLoanVariables._tokens[i], _receiver, _instaLoanVariables._amounts[i] + _fees[i]); - } - } - - /** - * @dev Transfers the tokens to the receiver address. - * @notice Transfers the tokens to the receiver address. - * @param _instaLoanVariables struct which includes list of token addresses and amounts. - * @param _receiver address to which tokens have to be transferred. - */ - function safeTransfer(FlashloanVariables memory _instaLoanVariables, address _receiver) internal { - uint256 length_ = _instaLoanVariables._tokens.length; - require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); - for (uint256 i = 0; i < length_; i++) { - IERC20 token = IERC20(_instaLoanVariables._tokens[i]); - token.safeTransfer(_receiver, _instaLoanVariables._amounts[i]); - } - } - - /** - * @dev Validates if the receiver sent the correct amounts of funds. - * @notice Validates if the receiver sent the correct amounts of funds. - * @param _instaLoanVariables struct which includes list of initial balances, final balances and fees for the respective tokens. - */ - function validateFlashloan(FlashloanVariables memory _instaLoanVariables) internal pure { - for (uint256 i = 0; i < _instaLoanVariables._iniBals.length; i++) { - require( - _instaLoanVariables._iniBals[i] + _instaLoanVariables._instaFees[i] <= _instaLoanVariables._finBals[i], - 'amount-paid-less' - ); - } - } - - /** - * @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_ = aaveV3Lending.FLASHLOAN_PREMIUM_TOTAL(); - } else if (_route == 10) { - 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. - * @param _account account to check for, if DSA. - */ - function checkIfDsa(address _account) internal view returns (bool) { - return instaList.accountID(_account) > 0; - } - - /** - * @dev better checking by double encoding the data. - * @notice better checking by double encoding the data. - * @param data_ data passed. - */ - modifier verifyDataHash(bytes memory data_) { - bytes32 dataHash_ = keccak256(data_); - require(dataHash_ == dataHash && dataHash_ != bytes32(0), 'invalid-data-hash'); - require(status == 2, 'already-entered'); - dataHash = bytes32(0); - _; - status = 1; - } - - /** - * @dev reentrancy gaurd. - * @notice reentrancy gaurd. - */ - modifier reentrancy() { - require(status == 1, 'already-entered'); - status = 2; - _; - require(status == 1, 'already-entered'); - } -} diff --git a/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol b/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol index 8d138e7c..df6f613d 100644 --- a/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol +++ b/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "../helper.sol"; +import '../helper.sol'; interface IAaveV3Lending { function flashLoan( @@ -22,7 +22,6 @@ contract Variables { } contract AaveImplementationFantom is Helper, Variables { - /** * @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. @@ -30,15 +29,15 @@ contract AaveImplementationFantom is Helper, Variables { * @param _amounts list of amounts for the corresponding assets. * @param _route route for flashloan. * @param _data extra data passed. - */ + */ function flashLoan( - address[] memory _tokens, + 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-AAVE-route"); + require(_route == 9, 'invalid-AAVE-route'); (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); routeAaveV3(_tokens, _amounts, _data); @@ -48,7 +47,7 @@ contract AaveImplementationFantom is Helper, 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_ = aaveV3Lending.FLASHLOAN_PREMIUM_TOTAL(); @@ -65,7 +64,7 @@ contract AaveImplementationFantom is Helper, Variables { * @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, @@ -73,15 +72,11 @@ contract AaveImplementationFantom is Helper, Variables { address _initiator, bytes memory _data ) external verifyDataHash(_data) returns (bool) { - - require(_initiator == address(this), "not-same-sender"); - require(msg.sender == aaveV3LendingAddr, "not-aave-sender"); + require(_initiator == address(this), 'not-same-sender'); + require(msg.sender == aaveV3LendingAddr, 'not-aave-sender'); FlashloanVariables memory instaLoanVariables_; - (address sender_, bytes memory data_) = abi.decode( - _data, - (address, bytes) - ); + (address sender_, bytes memory data_) = abi.decode(_data, (address, bytes)); instaLoanVariables_._tokens = _assets; instaLoanVariables_._amounts = _amounts; @@ -92,15 +87,21 @@ contract AaveImplementationFantom is Helper, Variables { safeTransfer(instaLoanVariables_, sender_); if (checkIfDsa(sender_)) { - Address.functionCall(sender_, data_, "DSA-flashloan-fallback-failed"); + Address.functionCall(sender_, data_, 'DSA-flashloan-fallback-failed'); } else { - InstaFlashReceiverInterface(sender_).executeOperation(_assets, _amounts, instaLoanVariables_._instaFees, sender_, data_); + InstaFlashReceiverInterface(sender_).executeOperation( + _assets, + _amounts, + instaLoanVariables_._instaFees, + sender_, + data_ + ); } instaLoanVariables_._finBals = calculateBalances(_assets, address(this)); validateFlashloan(instaLoanVariables_); - delete(implToCall); + delete (implToCall); return true; } @@ -116,7 +117,6 @@ contract AaveImplementationFantom is Helper, Variables { 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_); @@ -124,14 +124,6 @@ contract AaveImplementationFantom is Helper, Variables { _modes[i] = 0; } dataHash = bytes32(keccak256(data_)); - aaveV3Lending.flashLoan( - address(this), - _tokens, - _amounts, - _modes, - address(0), - data_, - 3228 - ); + aaveV3Lending.flashLoan(address(this), _tokens, _amounts, _modes, address(0), data_, 3228); } } diff --git a/contracts/aggregator/fantom/flashloan/implFLA/main.sol b/contracts/aggregator/fantom/flashloan/implFLA/main.sol index 4341865a..5338a6f0 100644 --- a/contracts/aggregator/fantom/flashloan/implFLA/main.sol +++ b/contracts/aggregator/fantom/flashloan/implFLA/main.sol @@ -1,9 +1,8 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "../helper.sol"; +import '../helper.sol'; contract FLAImplementationFantom 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. @@ -11,16 +10,15 @@ contract FLAImplementationFantom is Helper { * @param _amounts list of amounts for the corresponding assets. * @param _route route for flashloan. * @param _data extra data passed. - */ - function flashLoan( - address[] memory _tokens, + */ + 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 == 10, "invalid-FLA-route"); + require(_route == 10, 'invalid-FLA-route'); (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); routeFLA(msg.sender, _tokens, _amounts, _data); @@ -30,7 +28,7 @@ contract FLAImplementationFantom is Helper { * @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 == 10) { BPS_ = InstaFeeBPS; @@ -45,41 +43,30 @@ contract FLAImplementationFantom is Helper { uint256[] memory _amounts, bytes memory _data ) internal returns (bool) { - FlashloanVariables memory instaLoanVariables_; instaLoanVariables_._tokens = _tokens; instaLoanVariables_._amounts = _amounts; - instaLoanVariables_._instaFees = calculateFees( - _amounts, - calculateFeeBPS(10) - ); - instaLoanVariables_._iniBals = calculateBalances( - _tokens, - address(this) - ); + instaLoanVariables_._instaFees = calculateFees(_amounts, calculateFeeBPS(10)); + instaLoanVariables_._iniBals = calculateBalances(_tokens, address(this)); safeTransfer(instaLoanVariables_, _receiverAddress); if (checkIfDsa(_receiverAddress)) { - Address.functionCall( - _receiverAddress, - _data, - "DSA-flashloan-fallback-failed" - ); + Address.functionCall(_receiverAddress, _data, 'DSA-flashloan-fallback-failed'); } else { - require(InstaFlashReceiverInterface(_receiverAddress).executeOperation( - _tokens, - _amounts, - instaLoanVariables_._instaFees, - _receiverAddress, - _data - ), "invalid flashloan execution"); + require( + InstaFlashReceiverInterface(_receiverAddress).executeOperation( + _tokens, + _amounts, + instaLoanVariables_._instaFees, + _receiverAddress, + _data + ), + 'invalid flashloan execution' + ); } - instaLoanVariables_._finBals = calculateBalances( - _tokens, - address(this) - ); + instaLoanVariables_._finBals = calculateBalances(_tokens, address(this)); validateFlashloan(instaLoanVariables_); diff --git a/contracts/aggregator/fantom/flashloan/interfaces.sol b/contracts/aggregator/fantom/flashloan/interfaces.sol deleted file mode 100644 index 2f9cefe1..00000000 --- a/contracts/aggregator/fantom/flashloan/interfaces.sol +++ /dev/null @@ -1,27 +0,0 @@ -//SPDX-License-Identifier: Unlicense -pragma solidity ^0.8.0; -pragma experimental ABIEncoderV2; - -interface InstaFlashReceiverInterface { - function executeOperation( - address[] calldata assets, - uint256[] calldata amounts, - uint256[] calldata premiums, - address initiator, - bytes calldata _data - ) external returns (bool); -} - -interface IAaveV3Lending { - function flashLoan( - address receiverAddress, - address[] calldata assets, - uint256[] calldata amounts, - uint256[] calldata modes, - address onBehalfOf, - bytes calldata params, - uint16 referralCode - ) external; - - function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128); -} diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 197f58c1..16ff5439 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -1,165 +1,14 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import './helpers.sol'; -import '@openzeppelin/contracts/utils/Address.sol'; +import './helper.sol'; +import '../../common/main.sol'; /** * @title Flashloan. * @dev Flashloan aggregator for Fantom. */ -contract AdminModule is Helper { - event updateOwnerLog(address indexed oldOwner, address indexed newOwner); - - event updateWhitelistLog(address indexed account, bool indexed isWhitelisted_); - - /** - * @dev owner gaurd. - * @notice owner gaurd. - */ - modifier onlyOwner() { - require(msg.sender == owner, 'not-owner'); - _; - } - - /** - * @dev Update owner. - * @notice Update owner. - * @param newOwner_ address of new owner. - */ - function updateOwner(address newOwner_) external onlyOwner { - address oldOwner_ = owner; - owner = newOwner_; - emit updateOwnerLog(oldOwner_, newOwner_); - } -} - -contract FlashAggregatorFantom is AdminModule { - using SafeERC20 for IERC20; - - event LogFlashloan(address indexed account, uint256 indexed route, address[] tokens, uint256[] amounts); - - event LogCollectRevenue(address to, address[] tokens, uint256[] amounts); - - /** - * @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 { - require(_tokens.length == _amounts.length, 'array-lengths-not-same'); - require(routeStatus[_route] == true, 'route-disabled'); - - (_tokens, _amounts) = bubbleSort(_tokens, _amounts); - validateTokens(_tokens); - - implToCall = routeToImpl[_route]; - - Address.functionDelegateCall(implToCall, msg.data, 'call-to-impl-failed'); - - emit LogFlashloan(msg.sender, _route, _tokens, _amounts); - } - - /** - * @dev Function to add new routes. - * @notice Function to add new routes and implementations. - * @param _routes routes to add. - * @param _impls implementations of their respective routes. - */ - function addNewRoutesAndEnable(uint256[] memory _routes, address[] memory _impls) public onlyOwner { - require(_routes.length == _impls.length, 'lengths-dont-match'); - uint256 length = _routes.length; - for (uint256 i = 0; i < length; i++) { - require(routeToImpl[_routes[i]] == address(0), 'route-already-exists'); - routeToImpl[_routes[i]] = _impls[i]; - routeStatus[_routes[i]] = true; - routes.push(_routes[i]); - } - } - - /** - * @dev Function to update existing routes. - * @notice Function to update existing routes and implementations. - * @param _routes routes to update. - * @param _impls implementations of their respective routes. - */ - function updateRouteImplementations(uint256[] memory _routes, address[] memory _impls) public onlyOwner { - require(_routes.length == _impls.length, 'lengths-dont-match'); - uint256 length = _routes.length; - for (uint256 i = 0; i < length; i++) { - routeToImpl[_routes[i]] = _impls[i]; - } - } - - /** - * @dev Function to change route status. - * @notice Function to enable and disable routes. - * @param _routes routes those status we want to change. - * @param _statuses new statuses. - */ - function changeRouteStatus(uint256[] memory _routes, bool[] memory _statuses) public onlyOwner { - require(_routes.length == _statuses.length, 'lengths-dont-match'); - uint256 length = _routes.length; - for (uint256 i = 0; i < length; i++) { - routeStatus[_routes[i]] = _statuses[i]; - } - } - - /** - * @dev Function to transfer fee to the treasury. - * @notice Function to transfer fee to the treasury. Will be called manually. - * @param _tokens token addresses for transferring fee to treasury. - * @param _to treasury address. - */ - 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(); - uint256 amtToSub_ = decimals_ == 18 ? 1e10 : decimals_ > 12 ? 10000 : decimals_ > 7 ? 100 : 10; - _amts[i] = token_.balanceOf(address(this)) > amtToSub_ ? (token_.balanceOf(address(this)) - amtToSub_) : 0; - if (_amts[i] > 0) token_.safeTransfer(_to, _amts[i]); - } - emit LogCollectRevenue(_to, _tokens, _amts); - } - - /** - * @dev Function to get the list of all routes. - * @notice Function to get the list of all routes. - */ - function getRoutes() public view returns (uint256[] memory routes_) { - uint256 length = routes.length; - routes_ = new uint256[](length); - for (uint256 i = 0; i < length; i++) { - routes_[i] = routes[i]; - } - } - - /** - * @dev Function to get the list of enabled routes. - * @notice Function to get the list of enabled routes. - */ - function getEnabledRoutes() public view returns (uint256[] memory routes_, bool[] memory routesBool_) { - routes_ = getRoutes(); - uint256 length = routes_.length; - routesBool_ = new bool[](length); - - for (uint256 i = 0; i < length; i++) { - routesBool_[i] = routeStatus[routes_[i]] == true ? true : false; - } - } -} - -contract InstaFlashAggregatorFantom is FlashAggregatorFantom { +contract InstaFlashAggregatorFantom is FlashAggregator { function initialize(address owner_, address aave_) public { require(status == 0, 'cannot-call-again'); require(ownerStatus == 0, 'only-once'); @@ -172,7 +21,7 @@ contract InstaFlashAggregatorFantom is FlashAggregatorFantom { } // Fallback function - fallback(bytes calldata input) external payable returns (bytes memory output) { + fallback() external payable { output = Address.functionDelegateCall(implToCall, input, 'fallback-impl-call-failed'); } diff --git a/contracts/aggregator/fantom/flashloan/variable.sol b/contracts/aggregator/fantom/flashloan/variable.sol new file mode 100644 index 00000000..4b8e8ebc --- /dev/null +++ b/contracts/aggregator/fantom/flashloan/variable.sol @@ -0,0 +1,9 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +import '../../common/variables.sol'; + +contract ConstantVariables { + address public constant treasuryAddr = 0x6C4061A00F8739d528b185CC683B6400E0cd396a; + address private constant instaListAddr = 0x10e166c3FAF887D8a61dE6c25039231eE694E926; + ListInterface public constant instaList = ListInterface(instaListAddr); +} From 7c71aaddc0d1f635ab639d5f623487122fd9e2e8 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 24 Jun 2022 22:32:21 +0530 Subject: [PATCH 28/55] refactored code --- contracts/aggregator/common/main.sol | 119 +++++++----------- .../{ => implementations}/implAaveV3/main.sol | 3 +- .../{ => implementations}/implFLA/main.sol | 3 +- .../aggregator/fantom/flashloan/main.sol | 42 ++++++- 4 files changed, 84 insertions(+), 83 deletions(-) rename contracts/aggregator/fantom/flashloan/{ => implementations}/implAaveV3/main.sol (98%) rename contracts/aggregator/fantom/flashloan/{ => implementations}/implFLA/main.sol (98%) diff --git a/contracts/aggregator/common/main.sol b/contracts/aggregator/common/main.sol index a97581b1..7a85b874 100644 --- a/contracts/aggregator/common/main.sol +++ b/contracts/aggregator/common/main.sol @@ -9,10 +9,14 @@ import '@openzeppelin/contracts/utils/Address.sol'; */ contract AdminModule is HelpersCommon { + using SafeERC20 for IERC20; + event updateOwnerLog(address indexed oldOwner, address indexed newOwner); event updateWhitelistLog(address indexed account, bool indexed isWhitelisted_); + event LogCollectRevenue(address to, address[] tokens, uint256[] amounts); + /** * @dev owner gaurd. * @notice owner gaurd. @@ -32,56 +36,6 @@ contract AdminModule is HelpersCommon { owner = newOwner_; emit updateOwnerLog(oldOwner_, newOwner_); } -} - -contract FlashAggregator is AdminModule { - using SafeERC20 for IERC20; - - event LogFlashloan(address indexed account, uint256 indexed route, address[] tokens, uint256[] amounts); - - event LogCollectRevenue(address to, address[] tokens, uint256[] amounts); - - /** - * @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 { - require(_tokens.length == _amounts.length, 'array-lengths-not-same'); - require(routeStatus[_route] == true, 'route-disabled'); - - (_tokens, _amounts) = bubbleSort(_tokens, _amounts); - validateTokens(_tokens); - - implToCall = routeToImpl[_route]; - - Address.functionDelegateCall(implToCall, msg.data, 'call-to-impl-failed'); - - emit LogFlashloan(msg.sender, _route, _tokens, _amounts); - } - - /** - * @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_) { - bytes memory _output = Address.functionStaticCall(implToCall, msg.data, 'calculateFeeBPS-call-failed'); - BPS_ = abi.decode(_output, (uint256)); - - if (BPS_ < InstaFeeBPS) { - BPS_ = InstaFeeBPS; - } - } /** * @dev Function to add new routes. @@ -128,32 +82,6 @@ contract FlashAggregator is AdminModule { } } - /** - * @dev Function to get the list of all routes. - * @notice Function to get the list of all routes. - */ - function getRoutes() public view returns (uint256[] memory routes_) { - uint256 length = routes.length; - routes_ = new uint256[](length); - for (uint256 i = 0; i < length; i++) { - routes_[i] = routes[i]; - } - } - - /** - * @dev Function to get the list of enabled routes. - * @notice Function to get the list of enabled routes. - */ - function getEnabledRoutes() public view returns (uint256[] memory routes_, bool[] memory routesBool_) { - routes_ = getRoutes(); - uint256 length = routes_.length; - routesBool_ = new bool[](length); - - for (uint256 i = 0; i < length; i++) { - routesBool_[i] = routeStatus[routes_[i]] == true ? true : false; - } - } - /** * @dev Function to transfer fee to the treasury. * @notice Function to transfer fee to the treasury. Will be called manually. @@ -172,3 +100,42 @@ contract FlashAggregator is AdminModule { emit LogCollectRevenue(_to, _tokens, _amts); } } + +contract FlashAggregator is AdminModule { + + /** + * @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_) { + bytes memory _output = Address.functionStaticCall(routeToImpl[_route], msg.data, 'calculateFeeBPS-call-failed'); + BPS_ = abi.decode(_output, (uint256)); + + if (BPS_ < InstaFeeBPS) { + BPS_ = InstaFeeBPS; + } + } + + /** + * @dev Function to get the list of all routes. + * @notice Function to get the list of all routes. + */ + function getRoutes() public view returns (uint256[] memory) { + return routes; + } + + /** + * @dev Function to get the list of enabled routes. + * @notice Function to get the list of enabled routes. + */ + function getEnabledRoutes() public view returns (uint256[] memory routesAll_, bool[] memory routesBool_) { + routesAll_ = getRoutes(); + uint256 length = routesAll_.length; + routesBool_ = new bool[](length); + + for (uint256 i = 0; i < length; i++) { + routesBool_[i] = routeStatus[routesAll_[i]] == true ? true : false; + } + } +} diff --git a/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol b/contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol similarity index 98% rename from contracts/aggregator/fantom/flashloan/implAaveV3/main.sol rename to contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol index df6f613d..79146428 100644 --- a/contracts/aggregator/fantom/flashloan/implAaveV3/main.sol +++ b/contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import '../helper.sol'; +import '../../helper.sol'; interface IAaveV3Lending { function flashLoan( @@ -101,7 +101,6 @@ contract AaveImplementationFantom is Helper, Variables { instaLoanVariables_._finBals = calculateBalances(_assets, address(this)); validateFlashloan(instaLoanVariables_); - delete (implToCall); return true; } diff --git a/contracts/aggregator/fantom/flashloan/implFLA/main.sol b/contracts/aggregator/fantom/flashloan/implementations/implFLA/main.sol similarity index 98% rename from contracts/aggregator/fantom/flashloan/implFLA/main.sol rename to contracts/aggregator/fantom/flashloan/implementations/implFLA/main.sol index 5338a6f0..e32cfd3b 100644 --- a/contracts/aggregator/fantom/flashloan/implFLA/main.sol +++ b/contracts/aggregator/fantom/flashloan/implementations/implFLA/main.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import '../helper.sol'; +import '../../helper.sol'; contract FLAImplementationFantom is Helper { /** @@ -71,7 +71,6 @@ contract FLAImplementationFantom is Helper { validateFlashloan(instaLoanVariables_); status = 1; - delete(implToCall); return true; } } diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 16ff5439..01c3fa2c 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -8,8 +8,41 @@ import '../../common/main.sol'; * @dev Flashloan aggregator for Fantom. */ -contract InstaFlashAggregatorFantom is FlashAggregator { - function initialize(address owner_, address aave_) public { +contract FlashAggregatorFantom is FlashAggregator { + event LogFlashloan(address indexed account, uint256 indexed route, address[] tokens, uint256[] amounts); + + /** + * @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 { + require(_tokens.length == _amounts.length, 'array-lengths-not-same'); + require(routeStatus[_route] == true, 'route-disabled'); + + (_tokens, _amounts) = bubbleSort(_tokens, _amounts); + validateTokens(_tokens); + + implToCall = routeToImpl[_route]; + + Address.functionDelegateCall(implToCall, msg.data, 'call-to-impl-failed'); + + delete implToCall; + emit LogFlashloan(msg.sender, _route, _tokens, _amounts); + } +} + +contract InstaFlashAggregatorFantom is FlashAggregatorFantom { + function initialize(address owner_, address aave_, address fla_) public { require(status == 0, 'cannot-call-again'); require(ownerStatus == 0, 'only-once'); owner = owner_; @@ -18,10 +51,13 @@ contract InstaFlashAggregatorFantom is FlashAggregator { routeToImpl[9] = aave_; routeStatus[9] = true; routes.push(9); + routeToImpl[10] = fla_; + routeStatus[10] = true; + routes.push(10); } // Fallback function - fallback() external payable { + fallback(bytes calldata input) external payable returns (bytes memory output) { output = Address.functionDelegateCall(implToCall, input, 'fallback-impl-call-failed'); } From 1ef3d1815209683e902849da5aeec98a27ba16d3 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 24 Jun 2022 22:36:45 +0530 Subject: [PATCH 29/55] Added implementations in resolver contracts --- contracts/resolver/fantom/helpers.sol | 63 ++++++------------- .../fantom/implementations/aaveV3Resolver.sol | 54 ++++++++++++++++ .../fantom/implementations/flaResolver.sol | 24 +++++++ contracts/resolver/fantom/interfaces.sol | 30 +-------- contracts/resolver/fantom/main.sol | 14 +++-- contracts/resolver/fantom/variables.sol | 4 +- 6 files changed, 109 insertions(+), 80 deletions(-) create mode 100644 contracts/resolver/fantom/implementations/aaveV3Resolver.sol create mode 100644 contracts/resolver/fantom/implementations/flaResolver.sol diff --git a/contracts/resolver/fantom/helpers.sol b/contracts/resolver/fantom/helpers.sol index 0a876f2c..87912dee 100644 --- a/contracts/resolver/fantom/helpers.sol +++ b/contracts/resolver/fantom/helpers.sol @@ -1,64 +1,37 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; - -import {Variables} from "./variables.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { Variables } from "./variables.sol"; +import '@openzeppelin/contracts/utils/Address.sol'; +import { InstaFlashloanAggregatorInterface } from "./interfaces.sol"; contract Helper is Variables { - function getAaveV3Availability( - address[] memory _tokens, - uint256[] memory _amounts - ) internal view returns (bool) { - uint length = _tokens.length; - for (uint256 i = 0; i < length; i++) { - IERC20 token_ = IERC20(_tokens[i]); - (, , , , , , , , bool isActive, ) = aaveV3DataProvider - .getReserveConfigurationData(_tokens[i]); - (address aTokenAddr, , ) = aaveV3DataProvider - .getReserveTokensAddresses(_tokens[i]); - if (isActive == false) return false; - if (token_.balanceOf(aTokenAddr) < _amounts[i]) return false; - } - return true; - } - - function getFlaAvailability( - address[] memory _tokens, - uint256[] memory _amounts - ) internal view returns (bool) { - uint length = _tokens.length; - for (uint256 i = 0; i < length; i++) { - IERC20 token_ = IERC20(_tokens[i]); - if (token_.balanceOf(flashloanAggregatorAddr) < _amounts[i]) return false; - } - return true; - } function getRoutesWithAvailability( - uint16[] memory _routes, address[] memory _tokens, uint256[] memory _amounts - ) internal view returns (uint16[] memory) { - uint16[] memory routesWithAvailability_ = new uint16[](7); + ) internal view returns (uint16[] memory) { + (uint256[] memory _routesAll, bool[] memory routesBool) = flashloanAggregator.getEnabledRoutes(); + uint256 length = _routesAll.length; uint256 j = 0; - for (uint256 i = 0; i < _routes.length; i++) { - if (_routes[i] == 9) { - if (getAaveV3Availability(_tokens, _amounts)) { - routesWithAvailability_[j] = _routes[i]; + uint16[] memory routesWithAvailability_ = new uint16[](length); + for(uint256 i = 0; i < length; i++) { + if(routesBool[i] == true) { + if(getAvailability(_routesAll[i], _tokens, _amounts)) { + routesWithAvailability_[j] = uint16(_routesAll[i]); j++; + } else { + require(false, "invalid-route-2"); } - } else if (_routes[i] == 10) { - if (getFlaAvailability(_tokens, _amounts)) { - routesWithAvailability_[j] = _routes[i]; - j++; - } - } else { - require(false, "invalid-route"); } } return routesWithAvailability_; } + function getAvailability( uint256 _route, address[] memory _tokens, uint256[] memory _amounts) public view returns (bool) { + bytes memory _output = Address.functionStaticCall(routeToResolver[_route], abi.encodeWithSelector(this.getAvailability.selector, _route,_tokens,_amounts), 'getAvailability-call-failed'); + return abi.decode(_output, (bool)); + } + function bubbleSort(address[] memory _tokens, uint256[] memory _amounts) internal pure diff --git a/contracts/resolver/fantom/implementations/aaveV3Resolver.sol b/contracts/resolver/fantom/implementations/aaveV3Resolver.sol new file mode 100644 index 00000000..b564cfa2 --- /dev/null +++ b/contracts/resolver/fantom/implementations/aaveV3Resolver.sol @@ -0,0 +1,54 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface IAaveV3DataProvider { + + function getReserveConfigurationData(address asset) + external + view + returns ( + uint256, + uint256, + uint256, + uint256, + uint256, + bool, + bool, + bool, + bool, + bool + ); + + function getReserveTokensAddresses(address asset) + external + view + returns ( + address, + address, + address + ); +} + +contract Variable { + IAaveV3DataProvider public constant aaveV3DataProvider = + IAaveV3DataProvider(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654); +} + +contract AaveV3Resolver is Variable { + function getAvailability( uint256 _route, address[] memory _tokens, uint256[] memory _amounts) public view returns (bool) { + require(_route == 9, 'invalid-route'); + uint length = _tokens.length; + for (uint256 i = 0; i < length; i++) { + IERC20 token_ = IERC20(_tokens[i]); + (, , , , , , , , bool isActive, ) = aaveV3DataProvider + .getReserveConfigurationData(_tokens[i]); + (address aTokenAddr, , ) = aaveV3DataProvider + .getReserveTokensAddresses(_tokens[i]); + if (isActive == false) return false; + if (token_.balanceOf(aTokenAddr) < _amounts[i]) return false; + } + return true; + } +} diff --git a/contracts/resolver/fantom/implementations/flaResolver.sol b/contracts/resolver/fantom/implementations/flaResolver.sol new file mode 100644 index 00000000..a6a0fea1 --- /dev/null +++ b/contracts/resolver/fantom/implementations/flaResolver.sol @@ -0,0 +1,24 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract FLAResolver { + + address public flashloanAggregatorAddr = + 0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19;//todo: update + + function initialize(address fla) public { + flashloanAggregatorAddr = fla; + } + + function getAvailability( uint256 _route, address[] memory _tokens, uint256[] memory _amounts) public view returns (bool) { + require(_route == 10, 'invalid-route'); + uint length = _tokens.length; + for (uint256 i = 0; i < length; i++) { + IERC20 token_ = IERC20(_tokens[i]); + if (token_.balanceOf(flashloanAggregatorAddr) < _amounts[i]) return false; + } + return true; + } +} diff --git a/contracts/resolver/fantom/interfaces.sol b/contracts/resolver/fantom/interfaces.sol index 1f11b9ef..161fcadb 100644 --- a/contracts/resolver/fantom/interfaces.sol +++ b/contracts/resolver/fantom/interfaces.sol @@ -4,33 +4,7 @@ pragma solidity ^0.8.0; interface InstaFlashloanAggregatorInterface { function getRoutes() external pure returns (uint16[] memory); - function calculateFeeBPS(uint256 _route) external view returns (uint256); -} - -interface IAaveV3DataProvider { + function getEnabledRoutes() external view returns (uint256[] memory routes_, bool[] memory routesBool_); - function getReserveConfigurationData(address asset) - external - view - returns ( - uint256, - uint256, - uint256, - uint256, - uint256, - bool, - bool, - bool, - bool, - bool - ); - - function getReserveTokensAddresses(address asset) - external - view - returns ( - address, - address, - address - ); + function calculateFeeBPS(uint256 _route) external view returns (uint256); } diff --git a/contracts/resolver/fantom/main.sol b/contracts/resolver/fantom/main.sol index 667f1570..2480dcf9 100644 --- a/contracts/resolver/fantom/main.sol +++ b/contracts/resolver/fantom/main.sol @@ -2,9 +2,8 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {Helper} from "./helpers.sol"; - -import {InstaFlashloanAggregatorInterface} from "./interfaces.sol"; +import { Helper } from "./helpers.sol"; +import { InstaFlashloanAggregatorInterface } from "./interfaces.sol"; contract FlashResolverFantom is Helper { function getRoutesInfo() @@ -33,7 +32,6 @@ contract FlashResolverFantom is Helper { uint256 feeBPS_; uint16[] memory routes_ = flashloanAggregator.getRoutes(); uint16[] memory routesWithAvailability_ = getRoutesWithAvailability( - routes_, _tokens, _amounts ); @@ -79,5 +77,13 @@ contract FlashResolverFantom is Helper { } contract InstaFlashloanResolverFantom is FlashResolverFantom { + + // function initialize(address aggregator, uint256[] memory _routes, address[] memory impls) public { + // flashloanAggregatorAddr = aggregator; + // uint256 length = _routes.length; + // for(uint i = 0; i < length; i++) { + // routeToResolver[_routes[i]] = impls[i]; + // } + // } receive() external payable {} } diff --git a/contracts/resolver/fantom/variables.sol b/contracts/resolver/fantom/variables.sol index 6a4dbb30..dcb03fdb 100644 --- a/contracts/resolver/fantom/variables.sol +++ b/contracts/resolver/fantom/variables.sol @@ -4,11 +4,9 @@ pragma solidity ^0.8.0; import "./interfaces.sol"; contract Variables { - IAaveV3DataProvider public constant aaveV3DataProvider = - IAaveV3DataProvider(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654); - address public flashloanAggregatorAddr = 0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19;//TODO: update InstaFlashloanAggregatorInterface public flashloanAggregator = InstaFlashloanAggregatorInterface(flashloanAggregatorAddr); + mapping (uint256 => address) routeToResolver; } From 0608c2744b4f0ab186fa28c30b0f71eb7d30b329 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Fri, 24 Jun 2022 22:49:00 +0530 Subject: [PATCH 30/55] Added admin module & func to update impls --- contracts/resolver/fantom/main.sol | 54 ++++++++++ contracts/resolver/fantom/variables.sol | 1 + test/fantom/flashloan.ts | 10 +- test/fantom/resolver.ts | 128 ++++++++++++++++++++---- 4 files changed, 166 insertions(+), 27 deletions(-) diff --git a/contracts/resolver/fantom/main.sol b/contracts/resolver/fantom/main.sol index 2480dcf9..47952c72 100644 --- a/contracts/resolver/fantom/main.sol +++ b/contracts/resolver/fantom/main.sol @@ -5,6 +5,60 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { Helper } from "./helpers.sol"; import { InstaFlashloanAggregatorInterface } from "./interfaces.sol"; +contract AdminModule is Helper { + + event updateOwnerLog(address indexed oldOwner, address indexed newOwner); + + /** + * @dev owner gaurd. + * @notice owner gaurd. + */ + modifier onlyOwner() { + require(msg.sender == owner, 'not-owner'); + _; + } + + /** + * @dev Update owner. + * @notice Update owner. + * @param newOwner_ address of new owner. + */ + function updateOwner(address newOwner_) external onlyOwner { + address oldOwner_ = owner; + owner = newOwner_; + emit updateOwnerLog(oldOwner_, newOwner_); + } + + /** + * @dev Function to add new routes. + * @notice Function to add new routes and implementations. + * @param _routes routes to add. + * @param _resolverImpls implementations of their respective routes. + */ + function addNewRoutes(uint256[] memory _routes, address[] memory _resolverImpls) public onlyOwner { + require(_routes.length == _resolverImpls.length, 'lengths-dont-match'); + uint256 length = _routes.length; + for (uint256 i = 0; i < length; i++) { + require(routeToResolver[_routes[i]] == address(0), 'route-already-added'); + routeToResolver[_routes[i]] = _resolverImpls[i]; + } + } + + /** + * @dev Function to update existing routes. + * @notice Function to update existing routes and implementations. + * @param _routes routes to update. + * @param _resolverImpls implementations of their respective routes. + */ + function updateResolverImplementations(uint256[] memory _routes, address[] memory _resolverImpls) public onlyOwner { + require(_routes.length == _resolverImpls.length, 'lengths-dont-match'); + uint256 length = _routes.length; + for (uint256 i = 0; i < length; i++) { + routeToResolver[_routes[i]] = _resolverImpls[i]; + } + } +} + contract FlashResolverFantom is Helper { function getRoutesInfo() public diff --git a/contracts/resolver/fantom/variables.sol b/contracts/resolver/fantom/variables.sol index dcb03fdb..4ba75971 100644 --- a/contracts/resolver/fantom/variables.sol +++ b/contracts/resolver/fantom/variables.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.0; import "./interfaces.sol"; contract Variables { + address public owner; address public flashloanAggregatorAddr = 0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19;//TODO: update InstaFlashloanAggregatorInterface public flashloanAggregator = diff --git a/test/fantom/flashloan.ts b/test/fantom/flashloan.ts index 58876a90..134bc174 100644 --- a/test/fantom/flashloan.ts +++ b/test/fantom/flashloan.ts @@ -15,7 +15,7 @@ import { AaveImplementationFantom, AaveImplementationFantom__factory, FLAImplementationFantom__factory, - FLAImplementationFantom + FLAImplementationFantom, } from '../../typechain' describe('FlashLoan', function () { @@ -36,7 +36,7 @@ describe('FlashLoan', function () { const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' let masterSigner: any - let ABI = ['function initialize(address,address)'] + let ABI = ['function initialize(address,address,address)'] let iface = new ethers.utils.Interface(ABI) const DAI = '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E' @@ -82,7 +82,7 @@ describe('FlashLoan', function () { implFLA = await ImplFLA.deploy() await implFLA.deployed() - const data = iface.encodeFunctionData('initialize', [signer.address, implAave.address]) + const data = iface.encodeFunctionData('initialize', [signer.address, implAave.address, implFLA.address]) Proxy = new InstaFlashAggregatorProxy__factory(signer) proxy = await Proxy.deploy(aggregator.address, master, data) @@ -135,7 +135,7 @@ describe('FlashLoan', function () { await receiver.flashBorrow([DAI], [Dai], 9, zeroAddr,_instaData) }) it('Should add new route and take flashloan', async function () { - await proxyNew.connect(signer).addNewRoutesAndEnable(['10'],[implFLA.address]); + // await proxyNew.connect(signer).addNewRoutesAndEnable(['10'],[implFLA.address]); await receiver.flashBorrow([DAI], [Dai], 10, zeroAddr, _instaData); }) }) @@ -172,7 +172,7 @@ describe('FlashLoan', function () { await receiver.flashBorrow([DAI, USDC], [Dai, Usdc], 9, zeroAddr, _instaData ) }) it('Should add new route and take flashloan and take flashLoan of multiple tokens from FLA', async function () { - await proxyNew.connect(signer).addNewRoutesAndEnable(['10'],[implFLA.address]); + // await proxyNew.connect(signer).addNewRoutesAndEnable(['10'],[implFLA.address]); await receiver.flashBorrow([DAI, USDC], [Dai, Usdc], 10, zeroAddr, _instaData ) }) }) diff --git a/test/fantom/resolver.ts b/test/fantom/resolver.ts index 8dad7179..b6d971ea 100644 --- a/test/fantom/resolver.ts +++ b/test/fantom/resolver.ts @@ -8,6 +8,12 @@ import { AaveImplementationFantom__factory, InstaFlashloanResolverFantom, InstaFlashloanResolverFantom__factory, + AaveV3Resolver__factory, + AaveV3Resolver, + FLAImplementationFantom__factory, + FLAResolver, + FLAResolver__factory, + IERC20__factory, } from '../../typechain' describe('Resolver', function () { @@ -20,43 +26,121 @@ describe('Resolver', function () { const Dai = ethers.utils.parseUnits('5000', 18) const Usdc = ethers.utils.parseUnits('5000', 6) + const ACC_DAI = '0x1c664Bafc646510684Ba1588798c67fe22a8c7cf' + const ACC_USDC = '0x1c664Bafc646510684Ba1588798c67fe22a8c7cf' + const master = '0xa9061100d29C3C562a2e2421eb035741C1b42137' - // let ABI = ['function initialize(address)'] - // let iface = new ethers.utils.Interface(ABI) + let ABI = ['function initialize(address,address,address)'] + let iface = new ethers.utils.Interface(ABI) beforeEach(async function () { ;[signer] = await ethers.getSigners() - // let Aggregator, - // aggregator, - // Proxy, - // proxy, - // ImplAave, - // implAave; - - // Aggregator = new InstaFlashAggregatorFantom__factory(signer) - // aggregator = await Aggregator.deploy() - // await aggregator.deployed() + let Aggregator, + aggregator, + Proxy, + proxy, + AaveV3, + aaveV3, + ImplAave, + implAave, + ImplFLA, + implFLA, + FLA, + fla; + + Aggregator = new InstaFlashAggregatorFantom__factory(signer) + aggregator = await Aggregator.deploy() + await aggregator.deployed() // console.log("aggregator deployed at: ", aggregator.address) - // ImplAave = new AaveImplementationFantom__factory(signer) - // implAave = await ImplAave.deploy() - // await implAave.deployed() + ImplAave = new AaveImplementationFantom__factory(signer) + implAave = await ImplAave.deploy() + await implAave.deployed() // console.log("implAave deployed at: ", implAave.address) - // const data = iface.encodeFunctionData('initialize', [implAave.address]) + ImplFLA = new FLAImplementationFantom__factory(signer) + implFLA = await ImplFLA.deploy() + await implFLA.deployed() + // console.log("implFLA deployed at: ", implFLA.address) + + const data = iface.encodeFunctionData('initialize', [signer.address, implAave.address, implFLA.address]) - // Proxy = new InstaFlashAggregatorProxy__factory(signer) - // proxy = await Proxy.deploy(aggregator.address, master, data) - // await proxy.deployed() + Proxy = new InstaFlashAggregatorProxy__factory(signer) + proxy = await Proxy.deploy(aggregator.address, master, data) + await proxy.deployed() // console.log('Proxy at: ',proxy.address) + AaveV3 = new AaveV3Resolver__factory(signer) + aaveV3 = await AaveV3.deploy() + await aaveV3.deployed() + // console.log('aaveV3 at: ', aaveV3.address) + + FLA = new FLAResolver__factory(signer) + fla = await FLA.deploy() + await fla.deployed() + // console.log('fla at: ', fla.address) + + await fla.connect(signer).initialize(proxy.address) + Resolver = new InstaFlashloanResolverFantom__factory(signer) resolver = await Resolver.deploy() await resolver.deployed() - console.log("resolver deployed at: ", resolver.address) + // console.log("resolver deployed at: ", resolver.address) + + await resolver.connect(signer).initialize(proxy.address, ["9", "10"],[aaveV3.address, fla.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.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(proxy.address, Dai) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_DAI], + }) + + const token = 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.connect(signer_usdc).transfer(proxy.address, Usdc) - // await resolver.initialize(proxy.address) + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDC], + }) }) it('Should be able to return routes info', async function () { @@ -72,4 +156,4 @@ describe('Resolver', function () { it('Should be able to return all the data for flashloan', async function () { console.log((await resolver.getData([DAI, USDC], [Dai, Usdc])).toString()) }) -}) \ No newline at end of file +}) From 4b2dd2134588318dcc78fba705dd815a9ebe09da Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 26 Jun 2022 00:58:33 +0530 Subject: [PATCH 31/55] Removed routeToFee mapping --- contracts/aggregator/common/variables.sol | 1 - hardhat.config.ts | 2 +- package-lock.json | 2 ++ package.json | 2 ++ 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/aggregator/common/variables.sol b/contracts/aggregator/common/variables.sol index f6f9ff85..875d76ee 100644 --- a/contracts/aggregator/common/variables.sol +++ b/contracts/aggregator/common/variables.sol @@ -21,7 +21,6 @@ contract VariablesCommon { mapping(uint256 => address) public routeToImpl; mapping(uint256 => bool) public routeStatus; - mapping(uint256 => uint256) public routeToFee; address internal implToCall; uint256[] public routes; diff --git a/hardhat.config.ts b/hardhat.config.ts index 36e8f80c..18dc46fc 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -69,7 +69,7 @@ function getBlockNumber(networkType: string) { else if (networkType === "polygon") return 25941254; else if (networkType === "arbitrum") return 7719792; else if (networkType === "optimism") return 4346343; - else if (networkType === "fantom") return 41079980; + else if (networkType === "fantom") return 41229980; else return 14456907; } diff --git a/package-lock.json b/package-lock.json index 5d28191c..f8df3f3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,8 @@ "@types/mocha": "^9.0.0", "hardhat": "^2.6.7", "hardhat-gas-reporter": "^1.0.4", + "prettier": "^2.7.1", + "prettier-plugin-solidity": "^1.0.0-beta.19", "solidity-coverage": "^0.7.17", "ts-node": "^10.4.0" } diff --git a/package.json b/package.json index dee65610..674e3c14 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,8 @@ "@types/mocha": "^9.0.0", "hardhat": "^2.6.7", "hardhat-gas-reporter": "^1.0.4", + "prettier": "^2.7.1", + "prettier-plugin-solidity": "^1.0.0-beta.19", "solidity-coverage": "^0.7.17", "ts-node": "^10.4.0" } From ec1e9abe2a2c29f5096dc84e0148d19063f9cec5 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 26 Jun 2022 01:03:57 +0530 Subject: [PATCH 32/55] removed bubbleSort from main flashloan --- contracts/aggregator/fantom/flashloan/main.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 01c3fa2c..9b933380 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -29,9 +29,6 @@ contract FlashAggregatorFantom is FlashAggregator { require(_tokens.length == _amounts.length, 'array-lengths-not-same'); require(routeStatus[_route] == true, 'route-disabled'); - (_tokens, _amounts) = bubbleSort(_tokens, _amounts); - validateTokens(_tokens); - implToCall = routeToImpl[_route]; Address.functionDelegateCall(implToCall, msg.data, 'call-to-impl-failed'); From 5b33657c0e5310cae4b169e09037439f8c6d9abf Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Sun, 26 Jun 2022 01:16:52 +0530 Subject: [PATCH 33/55] updated getEnabledRoutes Co-authored-by: Vaibhav Khanna <55931792+Vaibhav20201@users.noreply.github.com> --- contracts/aggregator/common/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/aggregator/common/main.sol b/contracts/aggregator/common/main.sol index 7a85b874..2175011e 100644 --- a/contracts/aggregator/common/main.sol +++ b/contracts/aggregator/common/main.sol @@ -135,7 +135,7 @@ contract FlashAggregator is AdminModule { routesBool_ = new bool[](length); for (uint256 i = 0; i < length; i++) { - routesBool_[i] = routeStatus[routesAll_[i]] == true ? true : false; + routesBool_[i] = routeStatus[routesAll_[i]]; } } } From 95242249becf66738e635e547d2e7f9483fa628e Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 26 Jun 2022 01:56:27 +0530 Subject: [PATCH 34/55] updated getEnabledRoutes + resolver fixes --- contracts/aggregator/common/main.sol | 16 ++++++++++++---- contracts/resolver/fantom/helpers.sol | 18 ++++++++---------- contracts/resolver/fantom/interfaces.sol | 2 +- contracts/resolver/fantom/main.sol | 8 ++++---- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/contracts/aggregator/common/main.sol b/contracts/aggregator/common/main.sol index 2175011e..bdd4ecb0 100644 --- a/contracts/aggregator/common/main.sol +++ b/contracts/aggregator/common/main.sol @@ -129,13 +129,21 @@ contract FlashAggregator is AdminModule { * @dev Function to get the list of enabled routes. * @notice Function to get the list of enabled routes. */ - function getEnabledRoutes() public view returns (uint256[] memory routesAll_, bool[] memory routesBool_) { - routesAll_ = getRoutes(); + function getEnabledRoutes() public view returns (uint16[] memory routesEnabled_) { + uint256[] memory routesAll_ = getRoutes(); uint256 length = routesAll_.length; - routesBool_ = new bool[](length); + uint256 _count = 0; for (uint256 i = 0; i < length; i++) { - routesBool_[i] = routeStatus[routesAll_[i]]; + if(routeStatus[routesAll_[i]] == true) { + _count++; + } + } + + for (uint256 j = 0; j < _count; j++) { + if(routeStatus[routesAll_[j]]) { + routesEnabled_[j] = uint16(routesAll_[j]); + } } } } diff --git a/contracts/resolver/fantom/helpers.sol b/contracts/resolver/fantom/helpers.sol index 87912dee..f2d419ff 100644 --- a/contracts/resolver/fantom/helpers.sol +++ b/contracts/resolver/fantom/helpers.sol @@ -10,21 +10,19 @@ contract Helper is Variables { address[] memory _tokens, uint256[] memory _amounts ) internal view returns (uint16[] memory) { - (uint256[] memory _routesAll, bool[] memory routesBool) = flashloanAggregator.getEnabledRoutes(); + (uint16[] memory _routesAll) = flashloanAggregator.getEnabledRoutes(); uint256 length = _routesAll.length; uint256 j = 0; - uint16[] memory routesWithAvailability_ = new uint16[](length); + uint16[] memory _routesWithAvailability = new uint16[](length); for(uint256 i = 0; i < length; i++) { - if(routesBool[i] == true) { - if(getAvailability(_routesAll[i], _tokens, _amounts)) { - routesWithAvailability_[j] = uint16(_routesAll[i]); - j++; - } else { - require(false, "invalid-route-2"); - } + if(getAvailability(_routesAll[i], _tokens, _amounts)) { + _routesWithAvailability[j] = _routesAll[i]; + j++; + } else { + require(false, "invalid-route-2"); } } - return routesWithAvailability_; + return _routesWithAvailability; } function getAvailability( uint256 _route, address[] memory _tokens, uint256[] memory _amounts) public view returns (bool) { diff --git a/contracts/resolver/fantom/interfaces.sol b/contracts/resolver/fantom/interfaces.sol index 161fcadb..a07f4c24 100644 --- a/contracts/resolver/fantom/interfaces.sol +++ b/contracts/resolver/fantom/interfaces.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; interface InstaFlashloanAggregatorInterface { function getRoutes() external pure returns (uint16[] memory); - function getEnabledRoutes() external view returns (uint256[] memory routes_, bool[] memory routesBool_); + function getEnabledRoutes() external view returns (uint16[] memory _routes); function calculateFeeBPS(uint256 _route) external view returns (uint256); } diff --git a/contracts/resolver/fantom/main.sol b/contracts/resolver/fantom/main.sol index 47952c72..43b291bb 100644 --- a/contracts/resolver/fantom/main.sol +++ b/contracts/resolver/fantom/main.sol @@ -65,10 +65,10 @@ contract FlashResolverFantom is Helper { view returns (uint16[] memory routes_, uint256[] memory fees_) { - routes_ = flashloanAggregator.getRoutes(); + routes_ = flashloanAggregator.getEnabledRoutes(); fees_ = new uint256[](routes_.length); for (uint256 i = 0; i < routes_.length; i++) { - fees_[i] = flashloanAggregator.calculateFeeBPS(routes_[i]); + fees_[i] = flashloanAggregator.calculateFeeBPS(uint256(routes_[i])); } } @@ -84,7 +84,7 @@ contract FlashResolverFantom is Helper { uint16[] memory bRoutes_; uint256 feeBPS_; - uint16[] memory routes_ = flashloanAggregator.getRoutes(); + uint16[] memory routes_ = flashloanAggregator.getEnabledRoutes(); uint16[] memory routesWithAvailability_ = getRoutesWithAvailability( _tokens, _amounts @@ -95,7 +95,7 @@ contract FlashResolverFantom is Helper { for (uint256 i = 0; i < routesWithAvailability_.length; i++) { if (routesWithAvailability_[i] != 0) { uint256 routeFeeBPS_ = flashloanAggregator.calculateFeeBPS( - routesWithAvailability_[i] + uint256(routesWithAvailability_[i]) ); if (feeBPS_ > routeFeeBPS_) { feeBPS_ = routeFeeBPS_; From b1d66659ae7fae47e17885f3148531bb27dec069 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 26 Jun 2022 02:01:01 +0530 Subject: [PATCH 35/55] removed ownerStatus --- contracts/aggregator/common/variables.sol | 2 -- contracts/aggregator/fantom/flashloan/main.sol | 2 -- 2 files changed, 4 deletions(-) diff --git a/contracts/aggregator/common/variables.sol b/contracts/aggregator/common/variables.sol index 875d76ee..1a67a8f2 100644 --- a/contracts/aggregator/common/variables.sol +++ b/contracts/aggregator/common/variables.sol @@ -5,8 +5,6 @@ import './interfaces.sol'; contract VariablesCommon { address public owner; - uint256 internal ownerStatus; - bytes32 internal dataHash; // if 1 then can enter flashlaon, if 2 then callback uint256 internal status; diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 9b933380..76136908 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -41,9 +41,7 @@ contract FlashAggregatorFantom is FlashAggregator { contract InstaFlashAggregatorFantom is FlashAggregatorFantom { function initialize(address owner_, address aave_, address fla_) public { require(status == 0, 'cannot-call-again'); - require(ownerStatus == 0, 'only-once'); owner = owner_; - ownerStatus = 1; status = 1; routeToImpl[9] = aave_; routeStatus[9] = true; From 27027b139002c2480fc4f37c18e607afd1fca97f Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 26 Jun 2022 02:34:34 +0530 Subject: [PATCH 36/55] added deleteRoute --- contracts/aggregator/common/main.sol | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/contracts/aggregator/common/main.sol b/contracts/aggregator/common/main.sol index bdd4ecb0..32833273 100644 --- a/contracts/aggregator/common/main.sol +++ b/contracts/aggregator/common/main.sol @@ -64,6 +64,7 @@ contract AdminModule is HelpersCommon { require(_routes.length == _impls.length, 'lengths-dont-match'); uint256 length = _routes.length; for (uint256 i = 0; i < length; i++) { + require(routeToImpl[_routes[i]] != address(0), 'route-doesnt-exist'); routeToImpl[_routes[i]] = _impls[i]; } } @@ -82,6 +83,22 @@ contract AdminModule is HelpersCommon { } } + /** + * @dev Function to delete route. + * @notice Function to delete route. + * @param _route routes to delete. + */ + function deleteRoute(uint256 _route) public onlyOwner { + uint256 length = routes.length; + for (uint256 i = 0; i < length; i++) { + if(routes[i] == _route) { + delete routes[i]; + delete routeToImpl[_route]; + delete routeStatus[_route]; + } + } + } + /** * @dev Function to transfer fee to the treasury. * @notice Function to transfer fee to the treasury. Will be called manually. From 2d12a4cea573de207a1480ce24b393149102c6bb Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 26 Jun 2022 04:20:37 +0530 Subject: [PATCH 37/55] lint added --- contracts/aggregator/common/main.sol | 82 ++++++++++++++----- contracts/aggregator/common/variables.sol | 2 +- .../aggregator/fantom/flashloan/helper.sol | 4 +- .../implementations/implAaveV3/main.sol | 58 +++++++++---- .../implementations/implFLA/main.sol | 35 ++++++-- .../aggregator/fantom/flashloan/main.sol | 28 +++++-- .../aggregator/fantom/flashloan/variable.sol | 8 +- contracts/resolver/fantom/helpers.sol | 34 +++++--- .../fantom/implementations/aaveV3Resolver.sol | 11 ++- .../fantom/implementations/flaResolver.sol | 16 ++-- contracts/resolver/fantom/main.sol | 31 ++++--- contracts/resolver/fantom/variables.sol | 4 +- 12 files changed, 219 insertions(+), 94 deletions(-) diff --git a/contracts/aggregator/common/main.sol b/contracts/aggregator/common/main.sol index 32833273..3f9b98ca 100644 --- a/contracts/aggregator/common/main.sol +++ b/contracts/aggregator/common/main.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import './helpers.sol'; -import '@openzeppelin/contracts/utils/Address.sol'; +import "./helpers.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; /** * @title Flashloan. @@ -13,7 +13,10 @@ contract AdminModule is HelpersCommon { event updateOwnerLog(address indexed oldOwner, address indexed newOwner); - event updateWhitelistLog(address indexed account, bool indexed isWhitelisted_); + event updateWhitelistLog( + address indexed account, + bool indexed isWhitelisted_ + ); event LogCollectRevenue(address to, address[] tokens, uint256[] amounts); @@ -22,7 +25,7 @@ contract AdminModule is HelpersCommon { * @notice owner gaurd. */ modifier onlyOwner() { - require(msg.sender == owner, 'not-owner'); + require(msg.sender == owner, "not-owner"); _; } @@ -43,11 +46,17 @@ contract AdminModule is HelpersCommon { * @param _routes routes to add. * @param _impls implementations of their respective routes. */ - function addNewRoutesAndEnable(uint256[] memory _routes, address[] memory _impls) public onlyOwner { - require(_routes.length == _impls.length, 'lengths-dont-match'); + function addNewRoutesAndEnable( + uint256[] memory _routes, + address[] memory _impls + ) public onlyOwner { + require(_routes.length == _impls.length, "lengths-dont-match"); uint256 length = _routes.length; for (uint256 i = 0; i < length; i++) { - require(routeToImpl[_routes[i]] == address(0), 'route-already-exists'); + require( + routeToImpl[_routes[i]] == address(0), + "route-already-exists" + ); routeToImpl[_routes[i]] = _impls[i]; routeStatus[_routes[i]] = true; routes.push(_routes[i]); @@ -60,11 +69,17 @@ contract AdminModule is HelpersCommon { * @param _routes routes to update. * @param _impls implementations of their respective routes. */ - function updateRouteImplementations(uint256[] memory _routes, address[] memory _impls) public onlyOwner { - require(_routes.length == _impls.length, 'lengths-dont-match'); + function updateRouteImplementations( + uint256[] memory _routes, + address[] memory _impls + ) public onlyOwner { + require(_routes.length == _impls.length, "lengths-dont-match"); uint256 length = _routes.length; for (uint256 i = 0; i < length; i++) { - require(routeToImpl[_routes[i]] != address(0), 'route-doesnt-exist'); + require( + routeToImpl[_routes[i]] != address(0), + "route-doesnt-exist" + ); routeToImpl[_routes[i]] = _impls[i]; } } @@ -75,8 +90,11 @@ contract AdminModule is HelpersCommon { * @param _routes routes those status we want to change. * @param _statuses new statuses. */ - function changeRouteStatus(uint256[] memory _routes, bool[] memory _statuses) public onlyOwner { - require(_routes.length == _statuses.length, 'lengths-dont-match'); + function changeRouteStatus( + uint256[] memory _routes, + bool[] memory _statuses + ) public onlyOwner { + require(_routes.length == _statuses.length, "lengths-dont-match"); uint256 length = _routes.length; for (uint256 i = 0; i < length; i++) { routeStatus[_routes[i]] = _statuses[i]; @@ -91,7 +109,7 @@ contract AdminModule is HelpersCommon { function deleteRoute(uint256 _route) public onlyOwner { uint256 length = routes.length; for (uint256 i = 0; i < length; i++) { - if(routes[i] == _route) { + if (routes[i] == _route) { delete routes[i]; delete routeToImpl[_route]; delete routeStatus[_route]; @@ -105,13 +123,22 @@ contract AdminModule is HelpersCommon { * @param _tokens token addresses for transferring fee to treasury. * @param _to treasury address. */ - function transferFee(address[] memory _tokens, address _to) public onlyOwner { + 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(); - uint256 amtToSub_ = decimals_ == 18 ? 1e10 : decimals_ > 12 ? 10000 : decimals_ > 7 ? 100 : 10; - _amts[i] = token_.balanceOf(address(this)) > amtToSub_ ? (token_.balanceOf(address(this)) - amtToSub_) : 0; + uint256 amtToSub_ = decimals_ == 18 ? 1e10 : decimals_ > 12 + ? 10000 + : decimals_ > 7 + ? 100 + : 10; + _amts[i] = token_.balanceOf(address(this)) > amtToSub_ + ? (token_.balanceOf(address(this)) - amtToSub_) + : 0; if (_amts[i] > 0) token_.safeTransfer(_to, _amts[i]); } emit LogCollectRevenue(_to, _tokens, _amts); @@ -119,14 +146,21 @@ contract AdminModule is HelpersCommon { } contract FlashAggregator is AdminModule { - /** * @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_) { - bytes memory _output = Address.functionStaticCall(routeToImpl[_route], msg.data, 'calculateFeeBPS-call-failed'); + function calculateFeeBPS(uint256 _route) + public + view + returns (uint256 BPS_) + { + bytes memory _output = Address.functionStaticCall( + routeToImpl[_route], + msg.data, + "calculateFeeBPS-call-failed" + ); BPS_ = abi.decode(_output, (uint256)); if (BPS_ < InstaFeeBPS) { @@ -146,19 +180,23 @@ contract FlashAggregator is AdminModule { * @dev Function to get the list of enabled routes. * @notice Function to get the list of enabled routes. */ - function getEnabledRoutes() public view returns (uint16[] memory routesEnabled_) { + function getEnabledRoutes() + public + view + returns (uint16[] memory routesEnabled_) + { uint256[] memory routesAll_ = getRoutes(); uint256 length = routesAll_.length; uint256 _count = 0; for (uint256 i = 0; i < length; i++) { - if(routeStatus[routesAll_[i]] == true) { + if (routeStatus[routesAll_[i]] == true) { _count++; } } for (uint256 j = 0; j < _count; j++) { - if(routeStatus[routesAll_[j]]) { + if (routeStatus[routesAll_[j]]) { routesEnabled_[j] = uint16(routesAll_[j]); } } diff --git a/contracts/aggregator/common/variables.sol b/contracts/aggregator/common/variables.sol index 1a67a8f2..a5cec698 100644 --- a/contracts/aggregator/common/variables.sol +++ b/contracts/aggregator/common/variables.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import './interfaces.sol'; +import "./interfaces.sol"; contract VariablesCommon { address public owner; diff --git a/contracts/aggregator/fantom/flashloan/helper.sol b/contracts/aggregator/fantom/flashloan/helper.sol index 5472654d..fce398f9 100644 --- a/contracts/aggregator/fantom/flashloan/helper.sol +++ b/contracts/aggregator/fantom/flashloan/helper.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import '../../common/helpers.sol'; -import './variable.sol'; +import "../../common/helpers.sol"; +import "./variable.sol"; contract Helper is ConstantVariables, HelpersCommon { /** diff --git a/contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol b/contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol index 79146428..98e9a81a 100644 --- a/contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol +++ b/contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import '../../helper.sol'; +import "../../helper.sol"; interface IAaveV3Lending { function flashLoan( @@ -17,8 +17,10 @@ interface IAaveV3Lending { } contract Variables { - address public constant aaveV3LendingAddr = 0x794a61358D6845594F94dc1DB02A252b5b4814aD; - IAaveV3Lending public constant aaveV3Lending = IAaveV3Lending(aaveV3LendingAddr); + address public constant aaveV3LendingAddr = + 0x794a61358D6845594F94dc1DB02A252b5b4814aD; + IAaveV3Lending public constant aaveV3Lending = + IAaveV3Lending(aaveV3LendingAddr); } contract AaveImplementationFantom is Helper, Variables { @@ -37,7 +39,7 @@ contract AaveImplementationFantom is Helper, Variables { bytes calldata _data, bytes calldata // kept for future use by instadapp. Currently not used anywhere. ) external reentrancy { - require(_route == 9, 'invalid-AAVE-route'); + require(_route == 9, "invalid-AAVE-route"); (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); routeAaveV3(_tokens, _amounts, _data); @@ -48,11 +50,15 @@ contract AaveImplementationFantom is Helper, Variables { * @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_) { + function calculateFeeBPS(uint256 _route) + public + view + returns (uint256 BPS_) + { if (_route == 9) { BPS_ = aaveV3Lending.FLASHLOAN_PREMIUM_TOTAL(); } else { - revert('Invalid source'); + revert("Invalid source"); } } @@ -72,22 +78,35 @@ contract AaveImplementationFantom is Helper, Variables { address _initiator, bytes memory _data ) external verifyDataHash(_data) returns (bool) { - require(_initiator == address(this), 'not-same-sender'); - require(msg.sender == aaveV3LendingAddr, 'not-aave-sender'); + require(_initiator == address(this), "not-same-sender"); + require(msg.sender == aaveV3LendingAddr, "not-aave-sender"); FlashloanVariables memory instaLoanVariables_; - (address sender_, bytes memory data_) = abi.decode(_data, (address, bytes)); + (address sender_, bytes memory data_) = abi.decode( + _data, + (address, bytes) + ); instaLoanVariables_._tokens = _assets; instaLoanVariables_._amounts = _amounts; - instaLoanVariables_._instaFees = calculateFees(_amounts, calculateFeeBPS(9)); - instaLoanVariables_._iniBals = calculateBalances(_assets, address(this)); + instaLoanVariables_._instaFees = calculateFees( + _amounts, + calculateFeeBPS(9) + ); + instaLoanVariables_._iniBals = calculateBalances( + _assets, + address(this) + ); safeApprove(instaLoanVariables_, _premiums, aaveV3LendingAddr); safeTransfer(instaLoanVariables_, sender_); if (checkIfDsa(sender_)) { - Address.functionCall(sender_, data_, 'DSA-flashloan-fallback-failed'); + Address.functionCall( + sender_, + data_, + "DSA-flashloan-fallback-failed" + ); } else { InstaFlashReceiverInterface(sender_).executeOperation( _assets, @@ -98,7 +117,10 @@ contract AaveImplementationFantom is Helper, Variables { ); } - instaLoanVariables_._finBals = calculateBalances(_assets, address(this)); + instaLoanVariables_._finBals = calculateBalances( + _assets, + address(this) + ); validateFlashloan(instaLoanVariables_); return true; @@ -123,6 +145,14 @@ contract AaveImplementationFantom is Helper, Variables { _modes[i] = 0; } dataHash = bytes32(keccak256(data_)); - aaveV3Lending.flashLoan(address(this), _tokens, _amounts, _modes, address(0), data_, 3228); + aaveV3Lending.flashLoan( + address(this), + _tokens, + _amounts, + _modes, + address(0), + data_, + 3228 + ); } } diff --git a/contracts/aggregator/fantom/flashloan/implementations/implFLA/main.sol b/contracts/aggregator/fantom/flashloan/implementations/implFLA/main.sol index e32cfd3b..19475ef3 100644 --- a/contracts/aggregator/fantom/flashloan/implementations/implFLA/main.sol +++ b/contracts/aggregator/fantom/flashloan/implementations/implFLA/main.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import '../../helper.sol'; +import "../../helper.sol"; contract FLAImplementationFantom is Helper { /** @@ -18,7 +18,7 @@ contract FLAImplementationFantom is Helper { bytes calldata _data, bytes calldata // kept for future use by instadapp. Currently not used anywhere. ) external reentrancy { - require(_route == 10, 'invalid-FLA-route'); + require(_route == 10, "invalid-FLA-route"); (_tokens, _amounts) = bubbleSort(_tokens, _amounts); validateTokens(_tokens); routeFLA(msg.sender, _tokens, _amounts, _data); @@ -29,11 +29,15 @@ contract FLAImplementationFantom is Helper { * @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_) { + function calculateFeeBPS(uint256 _route) + public + view + returns (uint256 BPS_) + { if (_route == 10) { BPS_ = InstaFeeBPS; } else { - revert('Invalid source'); + revert("Invalid source"); } } @@ -46,13 +50,23 @@ contract FLAImplementationFantom is Helper { FlashloanVariables memory instaLoanVariables_; instaLoanVariables_._tokens = _tokens; instaLoanVariables_._amounts = _amounts; - instaLoanVariables_._instaFees = calculateFees(_amounts, calculateFeeBPS(10)); - instaLoanVariables_._iniBals = calculateBalances(_tokens, address(this)); + instaLoanVariables_._instaFees = calculateFees( + _amounts, + calculateFeeBPS(10) + ); + instaLoanVariables_._iniBals = calculateBalances( + _tokens, + address(this) + ); safeTransfer(instaLoanVariables_, _receiverAddress); if (checkIfDsa(_receiverAddress)) { - Address.functionCall(_receiverAddress, _data, 'DSA-flashloan-fallback-failed'); + Address.functionCall( + _receiverAddress, + _data, + "DSA-flashloan-fallback-failed" + ); } else { require( InstaFlashReceiverInterface(_receiverAddress).executeOperation( @@ -62,11 +76,14 @@ contract FLAImplementationFantom is Helper { _receiverAddress, _data ), - 'invalid flashloan execution' + "invalid flashloan execution" ); } - instaLoanVariables_._finBals = calculateBalances(_tokens, address(this)); + instaLoanVariables_._finBals = calculateBalances( + _tokens, + address(this) + ); validateFlashloan(instaLoanVariables_); diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 76136908..7d3ea87c 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import './helper.sol'; -import '../../common/main.sol'; +import "./helper.sol"; +import "../../common/main.sol"; /** * @title Flashloan. @@ -26,12 +26,16 @@ contract FlashAggregatorFantom is FlashAggregator { bytes calldata _data, bytes calldata // kept for future use by instadapp. Currently not used anywhere. ) external { - require(_tokens.length == _amounts.length, 'array-lengths-not-same'); - require(routeStatus[_route] == true, 'route-disabled'); + require(_tokens.length == _amounts.length, "array-lengths-not-same"); + require(routeStatus[_route] == true, "route-disabled"); implToCall = routeToImpl[_route]; - Address.functionDelegateCall(implToCall, msg.data, 'call-to-impl-failed'); + Address.functionDelegateCall( + implToCall, + msg.data, + "call-to-impl-failed" + ); delete implToCall; emit LogFlashloan(msg.sender, _route, _tokens, _amounts); @@ -39,8 +43,12 @@ contract FlashAggregatorFantom is FlashAggregator { } contract InstaFlashAggregatorFantom is FlashAggregatorFantom { - function initialize(address owner_, address aave_, address fla_) public { - require(status == 0, 'cannot-call-again'); + function initialize( + address owner_, + address aave_, + address fla_ + ) public { + require(status == 0, "cannot-call-again"); owner = owner_; status = 1; routeToImpl[9] = aave_; @@ -53,7 +61,11 @@ contract InstaFlashAggregatorFantom is FlashAggregatorFantom { // Fallback function fallback(bytes calldata input) external payable returns (bytes memory output) { - output = Address.functionDelegateCall(implToCall, input, 'fallback-impl-call-failed'); + output = Address.functionDelegateCall( + implToCall, + input, + "fallback-impl-call-failed" + ); } receive() external payable {} diff --git a/contracts/aggregator/fantom/flashloan/variable.sol b/contracts/aggregator/fantom/flashloan/variable.sol index 4b8e8ebc..edbcfe1e 100644 --- a/contracts/aggregator/fantom/flashloan/variable.sol +++ b/contracts/aggregator/fantom/flashloan/variable.sol @@ -1,9 +1,11 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import '../../common/variables.sol'; +import "../../common/variables.sol"; contract ConstantVariables { - address public constant treasuryAddr = 0x6C4061A00F8739d528b185CC683B6400E0cd396a; - address private constant instaListAddr = 0x10e166c3FAF887D8a61dE6c25039231eE694E926; + address public constant treasuryAddr = + 0x6C4061A00F8739d528b185CC683B6400E0cd396a; + address private constant instaListAddr = + 0x10e166c3FAF887D8a61dE6c25039231eE694E926; ListInterface public constant instaList = ListInterface(instaListAddr); } diff --git a/contracts/resolver/fantom/helpers.sol b/contracts/resolver/fantom/helpers.sol index f2d419ff..5ca3c393 100644 --- a/contracts/resolver/fantom/helpers.sol +++ b/contracts/resolver/fantom/helpers.sol @@ -1,32 +1,44 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import { Variables } from "./variables.sol"; -import '@openzeppelin/contracts/utils/Address.sol'; -import { InstaFlashloanAggregatorInterface } from "./interfaces.sol"; +import {Variables} from "./variables.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; +import {InstaFlashloanAggregatorInterface} from "./interfaces.sol"; contract Helper is Variables { - function getRoutesWithAvailability( address[] memory _tokens, uint256[] memory _amounts - ) internal view returns (uint16[] memory) { - (uint16[] memory _routesAll) = flashloanAggregator.getEnabledRoutes(); + ) internal view returns (uint16[] memory) { + uint16[] memory _routesAll = flashloanAggregator.getEnabledRoutes(); uint256 length = _routesAll.length; uint256 j = 0; uint16[] memory _routesWithAvailability = new uint16[](length); - for(uint256 i = 0; i < length; i++) { - if(getAvailability(_routesAll[i], _tokens, _amounts)) { + for (uint256 i = 0; i < length; i++) { + if (getAvailability(_routesAll[i], _tokens, _amounts)) { _routesWithAvailability[j] = _routesAll[i]; j++; } else { - require(false, "invalid-route-2"); + require(false, "invalid-route-2"); } } return _routesWithAvailability; } - function getAvailability( uint256 _route, address[] memory _tokens, uint256[] memory _amounts) public view returns (bool) { - bytes memory _output = Address.functionStaticCall(routeToResolver[_route], abi.encodeWithSelector(this.getAvailability.selector, _route,_tokens,_amounts), 'getAvailability-call-failed'); + function getAvailability( + uint256 _route, + address[] memory _tokens, + uint256[] memory _amounts + ) public view returns (bool) { + bytes memory _output = Address.functionStaticCall( + routeToResolver[_route], + abi.encodeWithSelector( + this.getAvailability.selector, + _route, + _tokens, + _amounts + ), + "getAvailability-call-failed" + ); return abi.decode(_output, (bool)); } diff --git a/contracts/resolver/fantom/implementations/aaveV3Resolver.sol b/contracts/resolver/fantom/implementations/aaveV3Resolver.sol index b564cfa2..61d7ca9e 100644 --- a/contracts/resolver/fantom/implementations/aaveV3Resolver.sol +++ b/contracts/resolver/fantom/implementations/aaveV3Resolver.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IAaveV3DataProvider { - function getReserveConfigurationData(address asset) external view @@ -37,9 +36,13 @@ contract Variable { } contract AaveV3Resolver is Variable { - function getAvailability( uint256 _route, address[] memory _tokens, uint256[] memory _amounts) public view returns (bool) { - require(_route == 9, 'invalid-route'); - uint length = _tokens.length; + function getAvailability( + uint256 _route, + address[] memory _tokens, + uint256[] memory _amounts + ) public view returns (bool) { + require(_route == 9, "invalid-route"); + uint256 length = _tokens.length; for (uint256 i = 0; i < length; i++) { IERC20 token_ = IERC20(_tokens[i]); (, , , , , , , , bool isActive, ) = aaveV3DataProvider diff --git a/contracts/resolver/fantom/implementations/flaResolver.sol b/contracts/resolver/fantom/implementations/flaResolver.sol index a6a0fea1..455fd9d6 100644 --- a/contracts/resolver/fantom/implementations/flaResolver.sol +++ b/contracts/resolver/fantom/implementations/flaResolver.sol @@ -4,20 +4,24 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract FLAResolver { - address public flashloanAggregatorAddr = - 0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19;//todo: update + 0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19; //todo: update function initialize(address fla) public { flashloanAggregatorAddr = fla; } - function getAvailability( uint256 _route, address[] memory _tokens, uint256[] memory _amounts) public view returns (bool) { - require(_route == 10, 'invalid-route'); - uint length = _tokens.length; + function getAvailability( + uint256 _route, + address[] memory _tokens, + uint256[] memory _amounts + ) public view returns (bool) { + require(_route == 10, "invalid-route"); + uint256 length = _tokens.length; for (uint256 i = 0; i < length; i++) { IERC20 token_ = IERC20(_tokens[i]); - if (token_.balanceOf(flashloanAggregatorAddr) < _amounts[i]) return false; + if (token_.balanceOf(flashloanAggregatorAddr) < _amounts[i]) + return false; } return true; } diff --git a/contracts/resolver/fantom/main.sol b/contracts/resolver/fantom/main.sol index 43b291bb..4df04cdb 100644 --- a/contracts/resolver/fantom/main.sol +++ b/contracts/resolver/fantom/main.sol @@ -2,11 +2,10 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { Helper } from "./helpers.sol"; -import { InstaFlashloanAggregatorInterface } from "./interfaces.sol"; +import {Helper} from "./helpers.sol"; +import {InstaFlashloanAggregatorInterface} from "./interfaces.sol"; contract AdminModule is Helper { - event updateOwnerLog(address indexed oldOwner, address indexed newOwner); /** @@ -14,7 +13,7 @@ contract AdminModule is Helper { * @notice owner gaurd. */ modifier onlyOwner() { - require(msg.sender == owner, 'not-owner'); + require(msg.sender == owner, "not-owner"); _; } @@ -35,12 +34,18 @@ contract AdminModule is Helper { * @param _routes routes to add. * @param _resolverImpls implementations of their respective routes. */ - function addNewRoutes(uint256[] memory _routes, address[] memory _resolverImpls) public onlyOwner { - require(_routes.length == _resolverImpls.length, 'lengths-dont-match'); + function addNewRoutes( + uint256[] memory _routes, + address[] memory _resolverImpls + ) public onlyOwner { + require(_routes.length == _resolverImpls.length, "lengths-dont-match"); uint256 length = _routes.length; for (uint256 i = 0; i < length; i++) { - require(routeToResolver[_routes[i]] == address(0), 'route-already-added'); - routeToResolver[_routes[i]] = _resolverImpls[i]; + require( + routeToResolver[_routes[i]] == address(0), + "route-already-added" + ); + routeToResolver[_routes[i]] = _resolverImpls[i]; } } @@ -50,11 +55,14 @@ contract AdminModule is Helper { * @param _routes routes to update. * @param _resolverImpls implementations of their respective routes. */ - function updateResolverImplementations(uint256[] memory _routes, address[] memory _resolverImpls) public onlyOwner { - require(_routes.length == _resolverImpls.length, 'lengths-dont-match'); + function updateResolverImplementations( + uint256[] memory _routes, + address[] memory _resolverImpls + ) public onlyOwner { + require(_routes.length == _resolverImpls.length, "lengths-dont-match"); uint256 length = _routes.length; for (uint256 i = 0; i < length; i++) { - routeToResolver[_routes[i]] = _resolverImpls[i]; + routeToResolver[_routes[i]] = _resolverImpls[i]; } } } @@ -131,7 +139,6 @@ contract FlashResolverFantom is Helper { } contract InstaFlashloanResolverFantom is FlashResolverFantom { - // function initialize(address aggregator, uint256[] memory _routes, address[] memory impls) public { // flashloanAggregatorAddr = aggregator; // uint256 length = _routes.length; diff --git a/contracts/resolver/fantom/variables.sol b/contracts/resolver/fantom/variables.sol index 4ba75971..f72c0c2e 100644 --- a/contracts/resolver/fantom/variables.sol +++ b/contracts/resolver/fantom/variables.sol @@ -6,8 +6,8 @@ import "./interfaces.sol"; contract Variables { address public owner; address public flashloanAggregatorAddr = - 0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19;//TODO: update + 0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19; //TODO: update InstaFlashloanAggregatorInterface public flashloanAggregator = InstaFlashloanAggregatorInterface(flashloanAggregatorAddr); - mapping (uint256 => address) routeToResolver; + mapping(uint256 => address) routeToResolver; } From c3d0f1f33cebcedc453fb4581d54bbc3b79dcf08 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 26 Jun 2022 17:31:18 +0530 Subject: [PATCH 38/55] minor fix --- contracts/aggregator/common/main.sol | 4 ---- .../fantom/flashloan/implementations/implAaveV3/main.sol | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/contracts/aggregator/common/main.sol b/contracts/aggregator/common/main.sol index 3f9b98ca..0fb45475 100644 --- a/contracts/aggregator/common/main.sol +++ b/contracts/aggregator/common/main.sol @@ -162,10 +162,6 @@ contract FlashAggregator is AdminModule { "calculateFeeBPS-call-failed" ); BPS_ = abi.decode(_output, (uint256)); - - if (BPS_ < InstaFeeBPS) { - BPS_ = InstaFeeBPS; - } } /** diff --git a/contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol b/contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol index 98e9a81a..93f3b666 100644 --- a/contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol +++ b/contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol @@ -60,6 +60,9 @@ contract AaveImplementationFantom is Helper, Variables { } else { revert("Invalid source"); } + if (BPS_ < InstaFeeBPS) { + BPS_ = InstaFeeBPS; + } } /** From e32696e23e720ae7d06e7a781fc7bb7180867277 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 26 Jun 2022 18:11:58 +0530 Subject: [PATCH 39/55] fixes --- contracts/aggregator/common/main.sol | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/contracts/aggregator/common/main.sol b/contracts/aggregator/common/main.sol index 0fb45475..8b45b598 100644 --- a/contracts/aggregator/common/main.sol +++ b/contracts/aggregator/common/main.sol @@ -191,9 +191,13 @@ contract FlashAggregator is AdminModule { } } - for (uint256 j = 0; j < _count; j++) { + routesEnabled_ = new uint16[](_count); + uint256 k = 0; + + for (uint256 j = 0; j < length; j++) { if (routeStatus[routesAll_[j]]) { - routesEnabled_[j] = uint16(routesAll_[j]); + routesEnabled_[k] = uint16(routesAll_[j]); + k++; } } } From 78c7605c5e5f0f121f58fb87db9905e1b3dd080b Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Sun, 26 Jun 2022 18:23:09 +0530 Subject: [PATCH 40/55] deleteRoute updated --- contracts/aggregator/common/main.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/aggregator/common/main.sol b/contracts/aggregator/common/main.sol index 8b45b598..1b65cd77 100644 --- a/contracts/aggregator/common/main.sol +++ b/contracts/aggregator/common/main.sol @@ -110,7 +110,8 @@ contract AdminModule is HelpersCommon { uint256 length = routes.length; for (uint256 i = 0; i < length; i++) { if (routes[i] == _route) { - delete routes[i]; + routes[i] = routes[length - 1]; + routes.pop(); delete routeToImpl[_route]; delete routeStatus[_route]; } From 18f9f02f4c6ac6ffda6e7cc3e1bdb8ca629e9d3b Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Mon, 27 Jun 2022 22:31:24 +0530 Subject: [PATCH 41/55] timeout updated Co-authored-by: Thrilok kumar --- hardhat.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 18dc46fc..33333870 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -175,7 +175,7 @@ const config: HardhatUserConfig = { target: "ethers-v5", }, mocha: { - timeout: 100000 * 100000, + timeout: 10000000 * 1000, // 10M sec }, etherscan: { apiKey: `${process.env.SCAN_API_KEY}` From b9292020ac8989d005617c6cbdba1979f89d9a9e Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Mon, 27 Jun 2022 22:32:00 +0530 Subject: [PATCH 42/55] implToCall renamed to fallbackImplementation Co-authored-by: Thrilok kumar --- contracts/aggregator/common/variables.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/aggregator/common/variables.sol b/contracts/aggregator/common/variables.sol index a5cec698..217e2bcb 100644 --- a/contracts/aggregator/common/variables.sol +++ b/contracts/aggregator/common/variables.sol @@ -19,7 +19,7 @@ contract VariablesCommon { mapping(uint256 => address) public routeToImpl; mapping(uint256 => bool) public routeStatus; - address internal implToCall; + address internal fallbackImplementation; uint256[] public routes; uint256 public constant InstaFeeBPS = 5; // in BPS; 1 BPS = 0.01% From f4a2fe1be61ca4a920d42f7f15b9bd1a0a4c9c01 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Mon, 27 Jun 2022 22:32:16 +0530 Subject: [PATCH 43/55] routeToImplementation renamed Co-authored-by: Thrilok kumar --- contracts/aggregator/common/variables.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/aggregator/common/variables.sol b/contracts/aggregator/common/variables.sol index 217e2bcb..12cd69a4 100644 --- a/contracts/aggregator/common/variables.sol +++ b/contracts/aggregator/common/variables.sol @@ -17,7 +17,7 @@ contract VariablesCommon { uint256[] _instaFees; } - mapping(uint256 => address) public routeToImpl; + mapping(uint256 => address) public routeToImplementation; mapping(uint256 => bool) public routeStatus; address internal fallbackImplementation; uint256[] public routes; From 05b0bcea5a5206c6a6d2034133fb5cbf505543b5 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Mon, 27 Jun 2022 22:33:10 +0530 Subject: [PATCH 44/55] Update contracts/aggregator/common/main.sol Co-authored-by: Thrilok kumar --- contracts/aggregator/common/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/aggregator/common/main.sol b/contracts/aggregator/common/main.sol index 1b65cd77..9a00e06d 100644 --- a/contracts/aggregator/common/main.sol +++ b/contracts/aggregator/common/main.sol @@ -4,7 +4,7 @@ import "./helpers.sol"; import "@openzeppelin/contracts/utils/Address.sol"; /** - * @title Flashloan. + * @title Flashloan Aggregator * @dev Common aggregator implementation for all chains. */ From 58c5a32397ef3a711cdbb4adf902e86011b78d39 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Mon, 27 Jun 2022 22:33:22 +0530 Subject: [PATCH 45/55] Update contracts/aggregator/common/main.sol Co-authored-by: Thrilok kumar --- contracts/aggregator/common/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/aggregator/common/main.sol b/contracts/aggregator/common/main.sol index 9a00e06d..83768232 100644 --- a/contracts/aggregator/common/main.sol +++ b/contracts/aggregator/common/main.sol @@ -146,7 +146,7 @@ contract AdminModule is HelpersCommon { } } -contract FlashAggregator is AdminModule { +contract FlashloanAggregator is AdminModule { /** * @dev Returns fee for the passed route in BPS. * @notice Returns fee for the passed route in BPS. 1 BPS == 0.01%. From 25acf39043e381ea4c0ddb24cff4abc5c4023a09 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 28 Jun 2022 02:20:58 +0530 Subject: [PATCH 46/55] contract structure changed --- contracts/aggregator/common/main.sol | 205 ------------------ .../aggregator/fantom/flashloan/helper.sol | 80 ++++++- .../aggregator/fantom/flashloan/main.sol | 154 ++++++++++++- .../implAaveV3 => routes/aaveV3}/main.sol | 4 +- .../implFLA => routes/fla}/main.sol | 0 .../aggregator/fantom/flashloan/variable.sol | 19 +- contracts/{aggregator => }/common/helpers.sol | 74 ------- .../{aggregator => }/common/interfaces.sol | 0 contracts/common/main.sol | 67 ++++++ .../{aggregator => }/common/variables.sol | 15 -- hardhat.config.ts | 2 +- 11 files changed, 312 insertions(+), 308 deletions(-) delete mode 100644 contracts/aggregator/common/main.sol rename contracts/aggregator/fantom/flashloan/{implementations/implAaveV3 => routes/aaveV3}/main.sol (98%) rename contracts/aggregator/fantom/flashloan/{implementations/implFLA => routes/fla}/main.sol (100%) rename contracts/{aggregator => }/common/helpers.sol (56%) rename contracts/{aggregator => }/common/interfaces.sol (100%) create mode 100644 contracts/common/main.sol rename contracts/{aggregator => }/common/variables.sol (53%) diff --git a/contracts/aggregator/common/main.sol b/contracts/aggregator/common/main.sol deleted file mode 100644 index 83768232..00000000 --- a/contracts/aggregator/common/main.sol +++ /dev/null @@ -1,205 +0,0 @@ -//SPDX-License-Identifier: Unlicense -pragma solidity ^0.8.0; -import "./helpers.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; - -/** - * @title Flashloan Aggregator - * @dev Common aggregator implementation for all chains. - */ - -contract AdminModule is HelpersCommon { - using SafeERC20 for IERC20; - - event updateOwnerLog(address indexed oldOwner, address indexed newOwner); - - event updateWhitelistLog( - address indexed account, - bool indexed isWhitelisted_ - ); - - event LogCollectRevenue(address to, address[] tokens, uint256[] amounts); - - /** - * @dev owner gaurd. - * @notice owner gaurd. - */ - modifier onlyOwner() { - require(msg.sender == owner, "not-owner"); - _; - } - - /** - * @dev Update owner. - * @notice Update owner. - * @param newOwner_ address of new owner. - */ - function updateOwner(address newOwner_) external onlyOwner { - address oldOwner_ = owner; - owner = newOwner_; - emit updateOwnerLog(oldOwner_, newOwner_); - } - - /** - * @dev Function to add new routes. - * @notice Function to add new routes and implementations. - * @param _routes routes to add. - * @param _impls implementations of their respective routes. - */ - function addNewRoutesAndEnable( - uint256[] memory _routes, - address[] memory _impls - ) public onlyOwner { - require(_routes.length == _impls.length, "lengths-dont-match"); - uint256 length = _routes.length; - for (uint256 i = 0; i < length; i++) { - require( - routeToImpl[_routes[i]] == address(0), - "route-already-exists" - ); - routeToImpl[_routes[i]] = _impls[i]; - routeStatus[_routes[i]] = true; - routes.push(_routes[i]); - } - } - - /** - * @dev Function to update existing routes. - * @notice Function to update existing routes and implementations. - * @param _routes routes to update. - * @param _impls implementations of their respective routes. - */ - function updateRouteImplementations( - uint256[] memory _routes, - address[] memory _impls - ) public onlyOwner { - require(_routes.length == _impls.length, "lengths-dont-match"); - uint256 length = _routes.length; - for (uint256 i = 0; i < length; i++) { - require( - routeToImpl[_routes[i]] != address(0), - "route-doesnt-exist" - ); - routeToImpl[_routes[i]] = _impls[i]; - } - } - - /** - * @dev Function to change route status. - * @notice Function to enable and disable routes. - * @param _routes routes those status we want to change. - * @param _statuses new statuses. - */ - function changeRouteStatus( - uint256[] memory _routes, - bool[] memory _statuses - ) public onlyOwner { - require(_routes.length == _statuses.length, "lengths-dont-match"); - uint256 length = _routes.length; - for (uint256 i = 0; i < length; i++) { - routeStatus[_routes[i]] = _statuses[i]; - } - } - - /** - * @dev Function to delete route. - * @notice Function to delete route. - * @param _route routes to delete. - */ - function deleteRoute(uint256 _route) public onlyOwner { - uint256 length = routes.length; - for (uint256 i = 0; i < length; i++) { - if (routes[i] == _route) { - routes[i] = routes[length - 1]; - routes.pop(); - delete routeToImpl[_route]; - delete routeStatus[_route]; - } - } - } - - /** - * @dev Function to transfer fee to the treasury. - * @notice Function to transfer fee to the treasury. Will be called manually. - * @param _tokens token addresses for transferring fee to treasury. - * @param _to treasury address. - */ - 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(); - uint256 amtToSub_ = decimals_ == 18 ? 1e10 : decimals_ > 12 - ? 10000 - : decimals_ > 7 - ? 100 - : 10; - _amts[i] = token_.balanceOf(address(this)) > amtToSub_ - ? (token_.balanceOf(address(this)) - amtToSub_) - : 0; - if (_amts[i] > 0) token_.safeTransfer(_to, _amts[i]); - } - emit LogCollectRevenue(_to, _tokens, _amts); - } -} - -contract FlashloanAggregator is AdminModule { - /** - * @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_) - { - bytes memory _output = Address.functionStaticCall( - routeToImpl[_route], - msg.data, - "calculateFeeBPS-call-failed" - ); - BPS_ = abi.decode(_output, (uint256)); - } - - /** - * @dev Function to get the list of all routes. - * @notice Function to get the list of all routes. - */ - function getRoutes() public view returns (uint256[] memory) { - return routes; - } - - /** - * @dev Function to get the list of enabled routes. - * @notice Function to get the list of enabled routes. - */ - function getEnabledRoutes() - public - view - returns (uint16[] memory routesEnabled_) - { - uint256[] memory routesAll_ = getRoutes(); - uint256 length = routesAll_.length; - uint256 _count = 0; - - for (uint256 i = 0; i < length; i++) { - if (routeStatus[routesAll_[i]] == true) { - _count++; - } - } - - routesEnabled_ = new uint16[](_count); - uint256 k = 0; - - for (uint256 j = 0; j < length; j++) { - if (routeStatus[routesAll_[j]]) { - routesEnabled_[k] = uint16(routesAll_[j]); - k++; - } - } - } -} diff --git a/contracts/aggregator/fantom/flashloan/helper.sol b/contracts/aggregator/fantom/flashloan/helper.sol index fce398f9..94628579 100644 --- a/contracts/aggregator/fantom/flashloan/helper.sol +++ b/contracts/aggregator/fantom/flashloan/helper.sol @@ -1,9 +1,11 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "../../common/helpers.sol"; +import "../../../common/helpers.sol"; import "./variable.sol"; -contract Helper is ConstantVariables, HelpersCommon { +contract Helper is Variables, HelpersCommon { + using SafeERC20 for IERC20; + /** * @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. @@ -12,4 +14,78 @@ contract Helper is ConstantVariables, HelpersCommon { function checkIfDsa(address _account) internal view returns (bool) { return instaList.accountID(_account) > 0; } + + /** + * @dev Approves the tokens to the receiver address with allowance (amount + fee). + * @notice Approves the tokens to the receiver address with allowance (amount + fee). + * @param _instaLoanVariables struct which includes list of token addresses and amounts. + * @param _fees list of premiums/fees for the corresponding addresses for flashloan. + * @param _receiver address to which tokens have to be approved. + */ + function safeApprove( + FlashloanVariables memory _instaLoanVariables, + uint256[] memory _fees, + address _receiver + ) internal { + uint256 length_ = _instaLoanVariables._tokens.length; + require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); + require(length_ == _fees.length, 'Lengths of parameters not same'); + for (uint256 i = 0; i < length_; i++) { + approve(_instaLoanVariables._tokens[i], _receiver, _instaLoanVariables._amounts[i] + _fees[i]); + } + } + + /** + * @dev Transfers the tokens to the receiver address. + * @notice Transfers the tokens to the receiver address. + * @param _instaLoanVariables struct which includes list of token addresses and amounts. + * @param _receiver address to which tokens have to be transferred. + */ + function safeTransfer(FlashloanVariables memory _instaLoanVariables, address _receiver) internal { + uint256 length_ = _instaLoanVariables._tokens.length; + require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); + for (uint256 i = 0; i < length_; i++) { + IERC20 token = IERC20(_instaLoanVariables._tokens[i]); + token.safeTransfer(_receiver, _instaLoanVariables._amounts[i]); + } + } + + /** + * @dev Validates if the receiver sent the correct amounts of funds. + * @notice Validates if the receiver sent the correct amounts of funds. + * @param _instaLoanVariables struct which includes list of initial balances, final balances and fees for the respective tokens. + */ + function validateFlashloan(FlashloanVariables memory _instaLoanVariables) internal pure { + for (uint256 i = 0; i < _instaLoanVariables._iniBals.length; i++) { + require( + _instaLoanVariables._iniBals[i] + _instaLoanVariables._instaFees[i] <= _instaLoanVariables._finBals[i], + 'amount-paid-less' + ); + } + } + + /** + * @dev better checking by double encoding the data. + * @notice better checking by double encoding the data. + * @param data_ data passed. + */ + modifier verifyDataHash(bytes memory data_) { + bytes32 dataHash_ = keccak256(data_); + require(dataHash_ == dataHash && dataHash_ != bytes32(0), 'invalid-data-hash'); + require(status == 2, 'already-entered'); + dataHash = bytes32(0); + _; + status = 1; + } + + /** + * @dev reentrancy gaurd. + * @notice reentrancy gaurd. + */ + modifier reentrancy() { + require(status == 1, 'already-entered'); + status = 2; + _; + require(status == 1, 'already-entered'); + } } diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 7d3ea87c..21d2c0f5 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -1,14 +1,152 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "./helper.sol"; -import "../../common/main.sol"; +import "../../../common/main.sol"; /** * @title Flashloan. * @dev Flashloan aggregator for Fantom. */ -contract FlashAggregatorFantom is FlashAggregator { +contract AdminModule is Helper { + using SafeERC20 for IERC20; + + event updateOwnerLog(address indexed oldOwner, address indexed newOwner); + + event updateWhitelistLog( + address indexed account, + bool indexed isWhitelisted_ + ); + + event LogCollectRevenue(address to, address[] tokens, uint256[] amounts); + + /** + * @dev owner gaurd. + * @notice owner gaurd. + */ + modifier onlyOwner() { + require(msg.sender == owner, "not-owner"); + _; + } + + /** + * @dev Update owner. + * @notice Update owner. + * @param newOwner_ address of new owner. + */ + function updateOwner(address newOwner_) external onlyOwner { + address oldOwner_ = owner; + owner = newOwner_; + emit updateOwnerLog(oldOwner_, newOwner_); + } + + /** + * @dev Function to add new routes. + * @notice Function to add new routes and implementations. + * @param _routes routes to add. + * @param _impls implementations of their respective routes. + */ + function addNewRoutesAndEnable( + uint256[] memory _routes, + address[] memory _impls + ) public onlyOwner { + require(_routes.length == _impls.length, "lengths-dont-match"); + uint256 length = _routes.length; + for (uint256 i = 0; i < length; i++) { + require( + routeToImplementation[_routes[i]] == address(0), + "route-already-exists" + ); + routeToImplementation[_routes[i]] = _impls[i]; + routeStatus[_routes[i]] = true; + routes.push(_routes[i]); + } + } + + /** + * @dev Function to update existing routes. + * @notice Function to update existing routes and implementations. + * @param _routes routes to update. + * @param _impls implementations of their respective routes. + */ + function updateRouteImplementations( + uint256[] memory _routes, + address[] memory _impls + ) public onlyOwner { + require(_routes.length == _impls.length, "lengths-dont-match"); + uint256 length = _routes.length; + for (uint256 i = 0; i < length; i++) { + require( + routeToImplementation[_routes[i]] != address(0), + "route-doesnt-exist" + ); + routeToImplementation[_routes[i]] = _impls[i]; + } + } + + /** + * @dev Function to change route status. + * @notice Function to enable and disable routes. + * @param _routes routes those status we want to change. + * @param _statuses new statuses. + */ + function changeRouteStatus( + uint256[] memory _routes, + bool[] memory _statuses + ) public onlyOwner { + require(_routes.length == _statuses.length, "lengths-dont-match"); + uint256 length = _routes.length; + for (uint256 i = 0; i < length; i++) { + routeStatus[_routes[i]] = _statuses[i]; + } + } + + /** + * @dev Function to delete route. + * @notice Function to delete route. + * @param _route routes to delete. + */ + function deleteRoute(uint256 _route) public onlyOwner { + uint256 length = routes.length; + for (uint256 i = 0; i < length; i++) { + if (routes[i] == _route) { + routes[i] = routes[length - 1]; + routes.pop(); + delete routeToImplementation[_route]; + delete routeStatus[_route]; + } + } + } + + /** + * @dev Function to transfer fee to the treasury. + * @notice Function to transfer fee to the treasury. Will be called manually. + * @param _tokens token addresses for transferring fee to treasury. + * @param _to treasury address. + */ + 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(); + uint256 amtToSub_ = decimals_ == 18 ? 1e10 : decimals_ > 12 + ? 10000 + : decimals_ > 7 + ? 100 + : 10; + _amts[i] = token_.balanceOf(address(this)) > amtToSub_ + ? (token_.balanceOf(address(this)) - amtToSub_) + : 0; + if (_amts[i] > 0) token_.safeTransfer(_to, _amts[i]); + } + emit LogCollectRevenue(_to, _tokens, _amts); + } +} + +contract FlashAggregatorFantom is FlashloanAggregator, AdminModule { event LogFlashloan(address indexed account, uint256 indexed route, address[] tokens, uint256[] amounts); /** @@ -29,15 +167,15 @@ contract FlashAggregatorFantom is FlashAggregator { require(_tokens.length == _amounts.length, "array-lengths-not-same"); require(routeStatus[_route] == true, "route-disabled"); - implToCall = routeToImpl[_route]; + fallbackImplementation = routeToImplementation[_route]; Address.functionDelegateCall( - implToCall, + fallbackImplementation, msg.data, "call-to-impl-failed" ); - delete implToCall; + delete fallbackImplementation; emit LogFlashloan(msg.sender, _route, _tokens, _amounts); } } @@ -51,10 +189,10 @@ contract InstaFlashAggregatorFantom is FlashAggregatorFantom { require(status == 0, "cannot-call-again"); owner = owner_; status = 1; - routeToImpl[9] = aave_; + routeToImplementation[9] = aave_; routeStatus[9] = true; routes.push(9); - routeToImpl[10] = fla_; + routeToImplementation[10] = fla_; routeStatus[10] = true; routes.push(10); } @@ -62,7 +200,7 @@ contract InstaFlashAggregatorFantom is FlashAggregatorFantom { // Fallback function fallback(bytes calldata input) external payable returns (bytes memory output) { output = Address.functionDelegateCall( - implToCall, + fallbackImplementation, input, "fallback-impl-call-failed" ); diff --git a/contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol b/contracts/aggregator/fantom/flashloan/routes/aaveV3/main.sol similarity index 98% rename from contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol rename to contracts/aggregator/fantom/flashloan/routes/aaveV3/main.sol index 93f3b666..1d0817fd 100644 --- a/contracts/aggregator/fantom/flashloan/implementations/implAaveV3/main.sol +++ b/contracts/aggregator/fantom/flashloan/routes/aaveV3/main.sol @@ -16,14 +16,14 @@ interface IAaveV3Lending { function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128); } -contract Variables { +contract AaveV3Variables { address public constant aaveV3LendingAddr = 0x794a61358D6845594F94dc1DB02A252b5b4814aD; IAaveV3Lending public constant aaveV3Lending = IAaveV3Lending(aaveV3LendingAddr); } -contract AaveImplementationFantom is Helper, Variables { +contract AaveImplementationFantom is Helper, AaveV3Variables { /** * @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. diff --git a/contracts/aggregator/fantom/flashloan/implementations/implFLA/main.sol b/contracts/aggregator/fantom/flashloan/routes/fla/main.sol similarity index 100% rename from contracts/aggregator/fantom/flashloan/implementations/implFLA/main.sol rename to contracts/aggregator/fantom/flashloan/routes/fla/main.sol diff --git a/contracts/aggregator/fantom/flashloan/variable.sol b/contracts/aggregator/fantom/flashloan/variable.sol index edbcfe1e..e2d83113 100644 --- a/contracts/aggregator/fantom/flashloan/variable.sol +++ b/contracts/aggregator/fantom/flashloan/variable.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "../../common/variables.sol"; +import "../../../common/variables.sol"; contract ConstantVariables { address public constant treasuryAddr = @@ -9,3 +9,20 @@ contract ConstantVariables { 0x10e166c3FAF887D8a61dE6c25039231eE694E926; ListInterface public constant instaList = ListInterface(instaListAddr); } + +contract Variables is ConstantVariables { + + bytes32 internal dataHash; + // if 1 then can enter flashlaon, if 2 then callback + uint256 internal status; + + struct FlashloanVariables { + address[] _tokens; + uint256[] _amounts; + uint256[] _iniBals; + uint256[] _finBals; + uint256[] _instaFees; + } + + address public owner; +} diff --git a/contracts/aggregator/common/helpers.sol b/contracts/common/helpers.sol similarity index 56% rename from contracts/aggregator/common/helpers.sol rename to contracts/common/helpers.sol index 2581c27f..db377912 100644 --- a/contracts/aggregator/common/helpers.sol +++ b/contracts/common/helpers.sol @@ -27,55 +27,6 @@ contract HelpersCommon is VariablesCommon { } } - /** - * @dev Approves the tokens to the receiver address with allowance (amount + fee). - * @notice Approves the tokens to the receiver address with allowance (amount + fee). - * @param _instaLoanVariables struct which includes list of token addresses and amounts. - * @param _fees list of premiums/fees for the corresponding addresses for flashloan. - * @param _receiver address to which tokens have to be approved. - */ - function safeApprove( - FlashloanVariables memory _instaLoanVariables, - uint256[] memory _fees, - address _receiver - ) internal { - uint256 length_ = _instaLoanVariables._tokens.length; - require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); - require(length_ == _fees.length, 'Lengths of parameters not same'); - for (uint256 i = 0; i < length_; i++) { - approve(_instaLoanVariables._tokens[i], _receiver, _instaLoanVariables._amounts[i] + _fees[i]); - } - } - - /** - * @dev Transfers the tokens to the receiver address. - * @notice Transfers the tokens to the receiver address. - * @param _instaLoanVariables struct which includes list of token addresses and amounts. - * @param _receiver address to which tokens have to be transferred. - */ - function safeTransfer(FlashloanVariables memory _instaLoanVariables, address _receiver) internal { - uint256 length_ = _instaLoanVariables._tokens.length; - require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); - for (uint256 i = 0; i < length_; i++) { - IERC20 token = IERC20(_instaLoanVariables._tokens[i]); - token.safeTransfer(_receiver, _instaLoanVariables._amounts[i]); - } - } - - /** - * @dev Validates if the receiver sent the correct amounts of funds. - * @notice Validates if the receiver sent the correct amounts of funds. - * @param _instaLoanVariables struct which includes list of initial balances, final balances and fees for the respective tokens. - */ - function validateFlashloan(FlashloanVariables memory _instaLoanVariables) internal pure { - for (uint256 i = 0; i < _instaLoanVariables._iniBals.length; i++) { - require( - _instaLoanVariables._iniBals[i] + _instaLoanVariables._instaFees[i] <= _instaLoanVariables._finBals[i], - 'amount-paid-less' - ); - } - } - /** * @dev Calculates the balances.. * @notice Calculates the balances of the account passed for the tokens. @@ -156,29 +107,4 @@ contract HelpersCommon is VariablesCommon { } return (_token0, _token1); } - - /** - * @dev better checking by double encoding the data. - * @notice better checking by double encoding the data. - * @param data_ data passed. - */ - modifier verifyDataHash(bytes memory data_) { - bytes32 dataHash_ = keccak256(data_); - require(dataHash_ == dataHash && dataHash_ != bytes32(0), 'invalid-data-hash'); - require(status == 2, 'already-entered'); - dataHash = bytes32(0); - _; - status = 1; - } - - /** - * @dev reentrancy gaurd. - * @notice reentrancy gaurd. - */ - modifier reentrancy() { - require(status == 1, 'already-entered'); - status = 2; - _; - require(status == 1, 'already-entered'); - } } diff --git a/contracts/aggregator/common/interfaces.sol b/contracts/common/interfaces.sol similarity index 100% rename from contracts/aggregator/common/interfaces.sol rename to contracts/common/interfaces.sol diff --git a/contracts/common/main.sol b/contracts/common/main.sol new file mode 100644 index 00000000..71fa5426 --- /dev/null +++ b/contracts/common/main.sol @@ -0,0 +1,67 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; +import "./helpers.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; + +/** + * @title Flashloan Aggregator + * @dev Common aggregator implementation for all chains. + */ + +contract FlashloanAggregator is HelpersCommon { + /** + * @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_) + { + bytes memory _output = Address.functionStaticCall( + routeToImplementation[_route], + msg.data, + "calculateFeeBPS-call-failed" + ); + BPS_ = abi.decode(_output, (uint256)); + } + + /** + * @dev Function to get the list of all routes. + * @notice Function to get the list of all routes. + */ + function getRoutes() public view returns (uint256[] memory) { + return routes; + } + + /** + * @dev Function to get the list of enabled routes. + * @notice Function to get the list of enabled routes. + */ + function getEnabledRoutes() + public + view + returns (uint16[] memory routesEnabled_) + { + uint256[] memory routesAll_ = getRoutes(); + uint256 length = routesAll_.length; + uint256 _count = 0; + + for (uint256 i = 0; i < length; i++) { + if (routeStatus[routesAll_[i]] == true) { + _count++; + } + } + + routesEnabled_ = new uint16[](_count); + uint256 k = 0; + + for (uint256 j = 0; j < length; j++) { + if (routeStatus[routesAll_[j]]) { + routesEnabled_[k] = uint16(routesAll_[j]); + k++; + } + } + } +} diff --git a/contracts/aggregator/common/variables.sol b/contracts/common/variables.sol similarity index 53% rename from contracts/aggregator/common/variables.sol rename to contracts/common/variables.sol index 12cd69a4..abcc6b9e 100644 --- a/contracts/aggregator/common/variables.sol +++ b/contracts/common/variables.sol @@ -3,24 +3,9 @@ pragma solidity ^0.8.0; import "./interfaces.sol"; contract VariablesCommon { - address public owner; - - bytes32 internal dataHash; - // if 1 then can enter flashlaon, if 2 then callback - uint256 internal status; - - struct FlashloanVariables { - address[] _tokens; - uint256[] _amounts; - uint256[] _iniBals; - uint256[] _finBals; - uint256[] _instaFees; - } - mapping(uint256 => address) public routeToImplementation; mapping(uint256 => bool) public routeStatus; address internal fallbackImplementation; uint256[] public routes; - uint256 public constant InstaFeeBPS = 5; // in BPS; 1 BPS = 0.01% } diff --git a/hardhat.config.ts b/hardhat.config.ts index 33333870..eec09e5a 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -69,7 +69,7 @@ function getBlockNumber(networkType: string) { else if (networkType === "polygon") return 25941254; else if (networkType === "arbitrum") return 7719792; else if (networkType === "optimism") return 4346343; - else if (networkType === "fantom") return 41229980; + else if (networkType === "fantom") return 41427580; else return 14456907; } From f88e19fb58fab68211d653987e6ed4100cdea256 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi <47134275+shriyatyagii@users.noreply.github.com> Date: Tue, 28 Jun 2022 18:34:50 +0530 Subject: [PATCH 47/55] Update contracts/aggregator/fantom/flashloan/variable.sol Co-authored-by: Thrilok kumar --- contracts/aggregator/fantom/flashloan/variable.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/variable.sol b/contracts/aggregator/fantom/flashloan/variable.sol index e2d83113..6dd1cb9f 100644 --- a/contracts/aggregator/fantom/flashloan/variable.sol +++ b/contracts/aggregator/fantom/flashloan/variable.sol @@ -5,9 +5,7 @@ import "../../../common/variables.sol"; contract ConstantVariables { address public constant treasuryAddr = 0x6C4061A00F8739d528b185CC683B6400E0cd396a; - address private constant instaListAddr = - 0x10e166c3FAF887D8a61dE6c25039231eE694E926; - ListInterface public constant instaList = ListInterface(instaListAddr); + ListInterface public constant instaList = ListInterface(0x10e166c3FAF887D8a61dE6c25039231eE694E926); } contract Variables is ConstantVariables { From bf1d9f3e2f4bc2ebfb060cc107139f678e83f60f Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Tue, 28 Jun 2022 18:58:59 +0530 Subject: [PATCH 48/55] Refactored code --- .../aggregator/fantom/flashloan/helper.sol | 105 +++++++-------- .../aggregator/fantom/flashloan/main.sol | 3 +- .../fantom/flashloan/routes/aaveV3/main.sol | 5 +- .../fantom/flashloan/routes/fla/main.sol | 1 + .../aggregator/fantom/flashloan/variable.sol | 40 ++++-- contracts/common/helpers.sol | 85 ++++++++++--- contracts/common/main.sol | 120 +++++++++--------- contracts/common/structs.sol | 12 ++ contracts/common/variablesV1.sol | 34 +++++ .../common/{variables.sol => variablesV2.sol} | 6 +- 10 files changed, 252 insertions(+), 159 deletions(-) create mode 100644 contracts/common/structs.sol create mode 100644 contracts/common/variablesV1.sol rename contracts/common/{variables.sol => variablesV2.sol} (66%) diff --git a/contracts/aggregator/fantom/flashloan/helper.sol b/contracts/aggregator/fantom/flashloan/helper.sol index 94628579..6e22eb1d 100644 --- a/contracts/aggregator/fantom/flashloan/helper.sol +++ b/contracts/aggregator/fantom/flashloan/helper.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import "../../../common/helpers.sol"; import "./variable.sol"; -contract Helper is Variables, HelpersCommon { +contract Helper is Variables, TokenHelpers, FlashloanHelpers { using SafeERC20 for IERC20; /** @@ -15,77 +15,60 @@ contract Helper is Variables, HelpersCommon { return instaList.accountID(_account) > 0; } - /** - * @dev Approves the tokens to the receiver address with allowance (amount + fee). - * @notice Approves the tokens to the receiver address with allowance (amount + fee). - * @param _instaLoanVariables struct which includes list of token addresses and amounts. - * @param _fees list of premiums/fees for the corresponding addresses for flashloan. - * @param _receiver address to which tokens have to be approved. + /** + * @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 safeApprove( - FlashloanVariables memory _instaLoanVariables, - uint256[] memory _fees, - address _receiver - ) internal { - uint256 length_ = _instaLoanVariables._tokens.length; - require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); - require(length_ == _fees.length, 'Lengths of parameters not same'); - for (uint256 i = 0; i < length_; i++) { - approve(_instaLoanVariables._tokens[i], _receiver, _instaLoanVariables._amounts[i] + _fees[i]); - } + function calculateFeeBPS(uint256 _route) + public + view + virtual + returns (uint256 BPS_) + { + bytes memory _output = Address.functionStaticCall( + routeToImplementation[_route], + msg.data, + "calculateFeeBPS-call-failed" + ); + BPS_ = abi.decode(_output, (uint256)); } /** - * @dev Transfers the tokens to the receiver address. - * @notice Transfers the tokens to the receiver address. - * @param _instaLoanVariables struct which includes list of token addresses and amounts. - * @param _receiver address to which tokens have to be transferred. + * @dev Function to get the list of all routes. + * @notice Function to get the list of all routes. */ - function safeTransfer(FlashloanVariables memory _instaLoanVariables, address _receiver) internal { - uint256 length_ = _instaLoanVariables._tokens.length; - require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); - for (uint256 i = 0; i < length_; i++) { - IERC20 token = IERC20(_instaLoanVariables._tokens[i]); - token.safeTransfer(_receiver, _instaLoanVariables._amounts[i]); - } + function getRoutes() public view returns (uint256[] memory) { + return routes; } /** - * @dev Validates if the receiver sent the correct amounts of funds. - * @notice Validates if the receiver sent the correct amounts of funds. - * @param _instaLoanVariables struct which includes list of initial balances, final balances and fees for the respective tokens. + * @dev Function to get the list of enabled routes. + * @notice Function to get the list of enabled routes. */ - function validateFlashloan(FlashloanVariables memory _instaLoanVariables) internal pure { - for (uint256 i = 0; i < _instaLoanVariables._iniBals.length; i++) { - require( - _instaLoanVariables._iniBals[i] + _instaLoanVariables._instaFees[i] <= _instaLoanVariables._finBals[i], - 'amount-paid-less' - ); + function getEnabledRoutes() + public + view + returns (uint16[] memory routesEnabled_) + { + uint256[] memory routesAll_ = getRoutes(); + uint256 length = routesAll_.length; + uint256 _count = 0; + + for (uint256 i = 0; i < length; i++) { + if (routeStatus[routesAll_[i]] == true) { + _count++; + } } - } - /** - * @dev better checking by double encoding the data. - * @notice better checking by double encoding the data. - * @param data_ data passed. - */ - modifier verifyDataHash(bytes memory data_) { - bytes32 dataHash_ = keccak256(data_); - require(dataHash_ == dataHash && dataHash_ != bytes32(0), 'invalid-data-hash'); - require(status == 2, 'already-entered'); - dataHash = bytes32(0); - _; - status = 1; - } + routesEnabled_ = new uint16[](_count); + uint256 k = 0; - /** - * @dev reentrancy gaurd. - * @notice reentrancy gaurd. - */ - modifier reentrancy() { - require(status == 1, 'already-entered'); - status = 2; - _; - require(status == 1, 'already-entered'); + for (uint256 j = 0; j < length; j++) { + if (routeStatus[routesAll_[j]]) { + routesEnabled_[k] = uint16(routesAll_[j]); + k++; + } + } } } diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index 21d2c0f5..fde3fe26 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -1,7 +1,6 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "./helper.sol"; -import "../../../common/main.sol"; /** * @title Flashloan. @@ -146,7 +145,7 @@ contract AdminModule is Helper { } } -contract FlashAggregatorFantom is FlashloanAggregator, AdminModule { +contract FlashAggregatorFantom is AdminModule { event LogFlashloan(address indexed account, uint256 indexed route, address[] tokens, uint256[] amounts); /** diff --git a/contracts/aggregator/fantom/flashloan/routes/aaveV3/main.sol b/contracts/aggregator/fantom/flashloan/routes/aaveV3/main.sol index 1d0817fd..2705582e 100644 --- a/contracts/aggregator/fantom/flashloan/routes/aaveV3/main.sol +++ b/contracts/aggregator/fantom/flashloan/routes/aaveV3/main.sol @@ -16,14 +16,14 @@ interface IAaveV3Lending { function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128); } -contract AaveV3Variables { +contract AaveV3ConstantVariables { address public constant aaveV3LendingAddr = 0x794a61358D6845594F94dc1DB02A252b5b4814aD; IAaveV3Lending public constant aaveV3Lending = IAaveV3Lending(aaveV3LendingAddr); } -contract AaveImplementationFantom is Helper, AaveV3Variables { +contract AaveV3RouteImplementationFantom is AaveV3ConstantVariables, 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. @@ -53,6 +53,7 @@ contract AaveImplementationFantom is Helper, AaveV3Variables { function calculateFeeBPS(uint256 _route) public view + override returns (uint256 BPS_) { if (_route == 9) { diff --git a/contracts/aggregator/fantom/flashloan/routes/fla/main.sol b/contracts/aggregator/fantom/flashloan/routes/fla/main.sol index 19475ef3..e1f0109a 100644 --- a/contracts/aggregator/fantom/flashloan/routes/fla/main.sol +++ b/contracts/aggregator/fantom/flashloan/routes/fla/main.sol @@ -32,6 +32,7 @@ contract FLAImplementationFantom is Helper { function calculateFeeBPS(uint256 _route) public view + override returns (uint256 BPS_) { if (_route == 10) { diff --git a/contracts/aggregator/fantom/flashloan/variable.sol b/contracts/aggregator/fantom/flashloan/variable.sol index e2d83113..6e979a2e 100644 --- a/contracts/aggregator/fantom/flashloan/variable.sol +++ b/contracts/aggregator/fantom/flashloan/variable.sol @@ -1,6 +1,10 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "../../../common/variables.sol"; + +import "../../../common/interfaces.sol"; +import "../../../common/variablesV1.sol"; +import "../../../common/variablesV2.sol"; +import "../../../common/structs.sol"; contract ConstantVariables { address public constant treasuryAddr = @@ -8,21 +12,29 @@ contract ConstantVariables { address private constant instaListAddr = 0x10e166c3FAF887D8a61dE6c25039231eE694E926; ListInterface public constant instaList = ListInterface(instaListAddr); + uint256 public constant InstaFeeBPS = 5; // in BPS; 1 BPS = 0.01% +} + +contract FantonVariablesV1 { + address public owner; } -contract Variables is ConstantVariables { +contract Variables is ConstantVariables, Structs, CommonVariablesV1, FantonVariablesV1, CommonVariablesV2 { + // ******** Stroage Variable layout ******* // - bytes32 internal dataHash; - // if 1 then can enter flashlaon, if 2 then callback - uint256 internal status; + /* CommonVariablesV1 + // bytes32 internal dataHash; + // uint256 internal status; + */ - struct FlashloanVariables { - address[] _tokens; - uint256[] _amounts; - uint256[] _iniBals; - uint256[] _finBals; - uint256[] _instaFees; - } + /* FantonVariablesV1 + // address public owner; + */ - address public owner; -} + /* CommonVariablesV2 + // mapping(uint256 => address) public routeToImplementation; + // mapping(uint256 => bool) public routeStatus; + // address internal fallbackImplementation; + // uint256[] public routes; + */ +} \ No newline at end of file diff --git a/contracts/common/helpers.sol b/contracts/common/helpers.sol index db377912..948bf330 100644 --- a/contracts/common/helpers.sol +++ b/contracts/common/helpers.sol @@ -2,9 +2,11 @@ pragma solidity ^0.8.0; import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; -import './variables.sol'; +import "./interfaces.sol"; +import "./variablesV2.sol"; +import "./structs.sol"; -contract HelpersCommon is VariablesCommon { +contract TokenHelpers is Structs { using SafeERC20 for IERC20; /** @@ -54,6 +56,70 @@ contract HelpersCommon is VariablesCommon { } } + /** + * @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); + } + + /** + * @dev Approves the tokens to the receiver address with allowance (amount + fee). + * @notice Approves the tokens to the receiver address with allowance (amount + fee). + * @param _instaLoanVariables struct which includes list of token addresses and amounts. + * @param _fees list of premiums/fees for the corresponding addresses for flashloan. + * @param _receiver address to which tokens have to be approved. + */ + function safeApprove( + FlashloanVariables memory _instaLoanVariables, + uint256[] memory _fees, + address _receiver + ) internal { + uint256 length_ = _instaLoanVariables._tokens.length; + require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); + require(length_ == _fees.length, 'Lengths of parameters not same'); + for (uint256 i = 0; i < length_; i++) { + approve(_instaLoanVariables._tokens[i], _receiver, _instaLoanVariables._amounts[i] + _fees[i]); + } + } + + /** + * @dev Transfers the tokens to the receiver address. + * @notice Transfers the tokens to the receiver address. + * @param _instaLoanVariables struct which includes list of token addresses and amounts. + * @param _receiver address to which tokens have to be transferred. + */ + function safeTransfer(FlashloanVariables memory _instaLoanVariables, address _receiver) internal { + uint256 length_ = _instaLoanVariables._tokens.length; + require(length_ == _instaLoanVariables._amounts.length, 'Lengths of parameters not same'); + for (uint256 i = 0; i < length_; i++) { + IERC20 token = IERC20(_instaLoanVariables._tokens[i]); + token.safeTransfer(_receiver, _instaLoanVariables._amounts[i]); + } + } + + /** + * @dev Validates if the receiver sent the correct amounts of funds. + * @notice Validates if the receiver sent the correct amounts of funds. + * @param _instaLoanVariables struct which includes list of initial balances, final balances and fees for the respective tokens. + */ + function validateFlashloan(FlashloanVariables memory _instaLoanVariables) internal pure { + for (uint256 i = 0; i < _instaLoanVariables._iniBals.length; i++) { + require( + _instaLoanVariables._iniBals[i] + _instaLoanVariables._instaFees[i] <= _instaLoanVariables._finBals[i], + 'amount-paid-less' + ); + } + } +} + +contract FlashloanHelpers { /** * @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%. @@ -94,17 +160,4 @@ contract HelpersCommon is VariablesCommon { } 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); - } -} +} \ No newline at end of file diff --git a/contracts/common/main.sol b/contracts/common/main.sol index 71fa5426..c0d5a192 100644 --- a/contracts/common/main.sol +++ b/contracts/common/main.sol @@ -1,67 +1,67 @@ -//SPDX-License-Identifier: Unlicense -pragma solidity ^0.8.0; -import "./helpers.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; +// //SPDX-License-Identifier: Unlicense +// pragma solidity ^0.8.0; +// import "./helpers.sol"; +// import "@openzeppelin/contracts/utils/Address.sol"; -/** - * @title Flashloan Aggregator - * @dev Common aggregator implementation for all chains. - */ +// /** +// * @title Flashloan Aggregator +// * @dev Common aggregator implementation for all chains. +// */ -contract FlashloanAggregator is HelpersCommon { - /** - * @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_) - { - bytes memory _output = Address.functionStaticCall( - routeToImplementation[_route], - msg.data, - "calculateFeeBPS-call-failed" - ); - BPS_ = abi.decode(_output, (uint256)); - } +// contract FlashloanAggregator is HelpersCommon { +// /** +// * @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_) +// { +// bytes memory _output = Address.functionStaticCall( +// routeToImplementation[_route], +// msg.data, +// "calculateFeeBPS-call-failed" +// ); +// BPS_ = abi.decode(_output, (uint256)); +// } - /** - * @dev Function to get the list of all routes. - * @notice Function to get the list of all routes. - */ - function getRoutes() public view returns (uint256[] memory) { - return routes; - } +// /** +// * @dev Function to get the list of all routes. +// * @notice Function to get the list of all routes. +// */ +// function getRoutes() public view returns (uint256[] memory) { +// return routes; +// } - /** - * @dev Function to get the list of enabled routes. - * @notice Function to get the list of enabled routes. - */ - function getEnabledRoutes() - public - view - returns (uint16[] memory routesEnabled_) - { - uint256[] memory routesAll_ = getRoutes(); - uint256 length = routesAll_.length; - uint256 _count = 0; +// /** +// * @dev Function to get the list of enabled routes. +// * @notice Function to get the list of enabled routes. +// */ +// function getEnabledRoutes() +// public +// view +// returns (uint16[] memory routesEnabled_) +// { +// uint256[] memory routesAll_ = getRoutes(); +// uint256 length = routesAll_.length; +// uint256 _count = 0; - for (uint256 i = 0; i < length; i++) { - if (routeStatus[routesAll_[i]] == true) { - _count++; - } - } +// for (uint256 i = 0; i < length; i++) { +// if (routeStatus[routesAll_[i]] == true) { +// _count++; +// } +// } - routesEnabled_ = new uint16[](_count); - uint256 k = 0; +// routesEnabled_ = new uint16[](_count); +// uint256 k = 0; - for (uint256 j = 0; j < length; j++) { - if (routeStatus[routesAll_[j]]) { - routesEnabled_[k] = uint16(routesAll_[j]); - k++; - } - } - } -} +// for (uint256 j = 0; j < length; j++) { +// if (routeStatus[routesAll_[j]]) { +// routesEnabled_[k] = uint16(routesAll_[j]); +// k++; +// } +// } +// } +// } diff --git a/contracts/common/structs.sol b/contracts/common/structs.sol new file mode 100644 index 00000000..faabcd6b --- /dev/null +++ b/contracts/common/structs.sol @@ -0,0 +1,12 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + +contract Structs { + struct FlashloanVariables { + address[] _tokens; + uint256[] _amounts; + uint256[] _iniBals; + uint256[] _finBals; + uint256[] _instaFees; + } +} diff --git a/contracts/common/variablesV1.sol b/contracts/common/variablesV1.sol new file mode 100644 index 00000000..9b1480ad --- /dev/null +++ b/contracts/common/variablesV1.sol @@ -0,0 +1,34 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + +contract CommonVariablesV1 { + + bytes32 internal dataHash; + // if 1 then can enter flashlaon, if 2 then callback + uint256 internal status; + + /** + * @dev better checking by double encoding the data. + * @notice better checking by double encoding the data. + * @param data_ data passed. + */ + modifier verifyDataHash(bytes memory data_) { + bytes32 dataHash_ = keccak256(data_); + require(dataHash_ == dataHash && dataHash_ != bytes32(0), 'invalid-data-hash'); + require(status == 2, 'already-entered'); + dataHash = bytes32(0); + _; + status = 1; + } + + /** + * @dev reentrancy gaurd. + * @notice reentrancy gaurd. + */ + modifier reentrancy() { + require(status == 1, 'already-entered'); + status = 2; + _; + require(status == 1, 'already-entered'); + } +} diff --git a/contracts/common/variables.sol b/contracts/common/variablesV2.sol similarity index 66% rename from contracts/common/variables.sol rename to contracts/common/variablesV2.sol index abcc6b9e..3853a318 100644 --- a/contracts/common/variables.sol +++ b/contracts/common/variablesV2.sol @@ -1,11 +1,9 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "./interfaces.sol"; -contract VariablesCommon { +contract CommonVariablesV2 { mapping(uint256 => address) public routeToImplementation; mapping(uint256 => bool) public routeStatus; address internal fallbackImplementation; uint256[] public routes; - uint256 public constant InstaFeeBPS = 5; // in BPS; 1 BPS = 0.01% -} +} \ No newline at end of file From b407e450b557295ca1bb4d24081a359d502ea3ba Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Tue, 28 Jun 2022 19:02:30 +0530 Subject: [PATCH 49/55] removed 1 file --- contracts/common/main.sol | 67 --------------------------------------- 1 file changed, 67 deletions(-) delete mode 100644 contracts/common/main.sol diff --git a/contracts/common/main.sol b/contracts/common/main.sol deleted file mode 100644 index c0d5a192..00000000 --- a/contracts/common/main.sol +++ /dev/null @@ -1,67 +0,0 @@ -// //SPDX-License-Identifier: Unlicense -// pragma solidity ^0.8.0; -// import "./helpers.sol"; -// import "@openzeppelin/contracts/utils/Address.sol"; - -// /** -// * @title Flashloan Aggregator -// * @dev Common aggregator implementation for all chains. -// */ - -// contract FlashloanAggregator is HelpersCommon { -// /** -// * @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_) -// { -// bytes memory _output = Address.functionStaticCall( -// routeToImplementation[_route], -// msg.data, -// "calculateFeeBPS-call-failed" -// ); -// BPS_ = abi.decode(_output, (uint256)); -// } - -// /** -// * @dev Function to get the list of all routes. -// * @notice Function to get the list of all routes. -// */ -// function getRoutes() public view returns (uint256[] memory) { -// return routes; -// } - -// /** -// * @dev Function to get the list of enabled routes. -// * @notice Function to get the list of enabled routes. -// */ -// function getEnabledRoutes() -// public -// view -// returns (uint16[] memory routesEnabled_) -// { -// uint256[] memory routesAll_ = getRoutes(); -// uint256 length = routesAll_.length; -// uint256 _count = 0; - -// for (uint256 i = 0; i < length; i++) { -// if (routeStatus[routesAll_[i]] == true) { -// _count++; -// } -// } - -// routesEnabled_ = new uint16[](_count); -// uint256 k = 0; - -// for (uint256 j = 0; j < length; j++) { -// if (routeStatus[routesAll_[j]]) { -// routesEnabled_[k] = uint16(routesAll_[j]); -// k++; -// } -// } -// } -// } From 9bf5170e02e35617e92a0419a66591a41a7df3d2 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Tue, 28 Jun 2022 19:13:40 +0530 Subject: [PATCH 50/55] minor change --- contracts/common/helpers.sol | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/contracts/common/helpers.sol b/contracts/common/helpers.sol index 948bf330..c420503a 100644 --- a/contracts/common/helpers.sol +++ b/contracts/common/helpers.sol @@ -103,23 +103,9 @@ contract TokenHelpers is Structs { token.safeTransfer(_receiver, _instaLoanVariables._amounts[i]); } } - - /** - * @dev Validates if the receiver sent the correct amounts of funds. - * @notice Validates if the receiver sent the correct amounts of funds. - * @param _instaLoanVariables struct which includes list of initial balances, final balances and fees for the respective tokens. - */ - function validateFlashloan(FlashloanVariables memory _instaLoanVariables) internal pure { - for (uint256 i = 0; i < _instaLoanVariables._iniBals.length; i++) { - require( - _instaLoanVariables._iniBals[i] + _instaLoanVariables._instaFees[i] <= _instaLoanVariables._finBals[i], - 'amount-paid-less' - ); - } - } } -contract FlashloanHelpers { +contract FlashloanHelpers is Structs { /** * @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%. @@ -160,4 +146,19 @@ contract FlashloanHelpers { } return (_tokens, _amounts); } + + + /** + * @dev Validates if the receiver sent the correct amounts of funds. + * @notice Validates if the receiver sent the correct amounts of funds. + * @param _instaLoanVariables struct which includes list of initial balances, final balances and fees for the respective tokens. + */ + function validateFlashloan(FlashloanVariables memory _instaLoanVariables) internal pure { + for (uint256 i = 0; i < _instaLoanVariables._iniBals.length; i++) { + require( + _instaLoanVariables._iniBals[i] + _instaLoanVariables._instaFees[i] <= _instaLoanVariables._finBals[i], + 'amount-paid-less' + ); + } + } } \ No newline at end of file From 537df139924f1aac61b6b05c8c30bb8bb01bd4b8 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Tue, 28 Jun 2022 20:07:03 +0530 Subject: [PATCH 51/55] moved onlyOwner modifier --- contracts/aggregator/fantom/flashloan/main.sol | 9 --------- contracts/aggregator/fantom/flashloan/variable.sol | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/main.sol b/contracts/aggregator/fantom/flashloan/main.sol index fde3fe26..c71197ab 100644 --- a/contracts/aggregator/fantom/flashloan/main.sol +++ b/contracts/aggregator/fantom/flashloan/main.sol @@ -19,15 +19,6 @@ contract AdminModule is Helper { event LogCollectRevenue(address to, address[] tokens, uint256[] amounts); - /** - * @dev owner gaurd. - * @notice owner gaurd. - */ - modifier onlyOwner() { - require(msg.sender == owner, "not-owner"); - _; - } - /** * @dev Update owner. * @notice Update owner. diff --git a/contracts/aggregator/fantom/flashloan/variable.sol b/contracts/aggregator/fantom/flashloan/variable.sol index 1f078155..68e785ee 100644 --- a/contracts/aggregator/fantom/flashloan/variable.sol +++ b/contracts/aggregator/fantom/flashloan/variable.sol @@ -15,6 +15,15 @@ contract ConstantVariables { contract FantonVariablesV1 { address public owner; + + /** + * @dev owner gaurd. + * @notice owner gaurd. + */ + modifier onlyOwner() { + require(msg.sender == owner, "not-owner"); + _; + } } contract Variables is ConstantVariables, Structs, CommonVariablesV1, FantonVariablesV1, CommonVariablesV2 { From 04fe872263506287db135c1ed76a7da769ff3400 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 28 Jun 2022 21:00:33 +0530 Subject: [PATCH 52/55] minor fix --- contracts/aggregator/fantom/flashloan/variable.sol | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/contracts/aggregator/fantom/flashloan/variable.sol b/contracts/aggregator/fantom/flashloan/variable.sol index 68e785ee..e1884e00 100644 --- a/contracts/aggregator/fantom/flashloan/variable.sol +++ b/contracts/aggregator/fantom/flashloan/variable.sol @@ -13,7 +13,7 @@ contract ConstantVariables { uint256 public constant InstaFeeBPS = 5; // in BPS; 1 BPS = 0.01% } -contract FantonVariablesV1 { +contract FantomVariablesV1 { address public owner; /** @@ -26,7 +26,7 @@ contract FantonVariablesV1 { } } -contract Variables is ConstantVariables, Structs, CommonVariablesV1, FantonVariablesV1, CommonVariablesV2 { +contract Variables is ConstantVariables, CommonVariablesV1, Structs, FantomVariablesV1, CommonVariablesV2 { // ******** Stroage Variable layout ******* // /* CommonVariablesV1 @@ -34,7 +34,11 @@ contract Variables is ConstantVariables, Structs, CommonVariablesV1, FantonVaria // uint256 internal status; */ - /* FantonVariablesV1 + /* Structs + FlashloanVariables; + */ + + /* FantomVariablesV1 // address public owner; */ From 441fd3ad12efbff2f6d913cd68d96a05d8e46a72 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 5 Jul 2022 17:37:54 +0400 Subject: [PATCH 53/55] minor edits --- contracts/resolver/fantom/helpers.sol | 16 +++--- contracts/resolver/fantom/interfaces.sol | 2 - contracts/resolver/fantom/main.sol | 19 +++---- .../aaveV3Resolver.sol => routes/aaveV3.sol} | 1 - .../flaResolver.sol => routes/fla.sol} | 3 +- contracts/resolver/fantom/variables.sol | 6 +-- test/fantom/resolver.ts | 50 +++---------------- 7 files changed, 26 insertions(+), 71 deletions(-) rename contracts/resolver/fantom/{implementations/aaveV3Resolver.sol => routes/aaveV3.sol} (99%) rename contracts/resolver/fantom/{implementations/flaResolver.sol => routes/fla.sol} (91%) diff --git a/contracts/resolver/fantom/helpers.sol b/contracts/resolver/fantom/helpers.sol index 5ca3c393..1efb9371 100644 --- a/contracts/resolver/fantom/helpers.sol +++ b/contracts/resolver/fantom/helpers.sol @@ -1,27 +1,27 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import {Variables} from "./variables.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; import {InstaFlashloanAggregatorInterface} from "./interfaces.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; contract Helper is Variables { - function getRoutesWithAvailability( + function getRoutesAndAvailability( address[] memory _tokens, uint256[] memory _amounts - ) internal view returns (uint16[] memory) { - uint16[] memory _routesAll = flashloanAggregator.getEnabledRoutes(); - uint256 length = _routesAll.length; + ) internal view returns (uint16[] memory routes_, uint16[] memory routesWithAvailability_) { + uint16[] memory _enabledRoutes = flashloanAggregator.getEnabledRoutes(); + uint256 length = _enabledRoutes.length; uint256 j = 0; uint16[] memory _routesWithAvailability = new uint16[](length); for (uint256 i = 0; i < length; i++) { - if (getAvailability(_routesAll[i], _tokens, _amounts)) { - _routesWithAvailability[j] = _routesAll[i]; + if (getAvailability(_enabledRoutes[i], _tokens, _amounts)) { + _routesWithAvailability[j] = _enabledRoutes[i]; j++; } else { require(false, "invalid-route-2"); } } - return _routesWithAvailability; + return (_enabledRoutes, _routesWithAvailability); } function getAvailability( diff --git a/contracts/resolver/fantom/interfaces.sol b/contracts/resolver/fantom/interfaces.sol index a07f4c24..bda3904f 100644 --- a/contracts/resolver/fantom/interfaces.sol +++ b/contracts/resolver/fantom/interfaces.sol @@ -3,8 +3,6 @@ pragma solidity ^0.8.0; interface InstaFlashloanAggregatorInterface { function getRoutes() external pure returns (uint16[] memory); - function getEnabledRoutes() external view returns (uint16[] memory _routes); - function calculateFeeBPS(uint256 _route) external view returns (uint256); } diff --git a/contracts/resolver/fantom/main.sol b/contracts/resolver/fantom/main.sol index 4df04cdb..f58e7f00 100644 --- a/contracts/resolver/fantom/main.sol +++ b/contracts/resolver/fantom/main.sol @@ -1,9 +1,9 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Helper} from "./helpers.sol"; import {InstaFlashloanAggregatorInterface} from "./interfaces.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract AdminModule is Helper { event updateOwnerLog(address indexed oldOwner, address indexed newOwner); @@ -92,11 +92,11 @@ contract FlashResolverFantom is Helper { uint16[] memory bRoutes_; uint256 feeBPS_; - uint16[] memory routes_ = flashloanAggregator.getEnabledRoutes(); - uint16[] memory routesWithAvailability_ = getRoutesWithAvailability( - _tokens, - _amounts - ); + ( + uint16[] memory routes_, + uint16[] memory routesWithAvailability_ + ) = getRoutesAndAvailability(_tokens, _amounts); + uint16 j = 0; bRoutes_ = new uint16[](routes_.length); feeBPS_ = type(uint256).max; @@ -139,12 +139,5 @@ contract FlashResolverFantom is Helper { } contract InstaFlashloanResolverFantom is FlashResolverFantom { - // function initialize(address aggregator, uint256[] memory _routes, address[] memory impls) public { - // flashloanAggregatorAddr = aggregator; - // uint256 length = _routes.length; - // for(uint i = 0; i < length; i++) { - // routeToResolver[_routes[i]] = impls[i]; - // } - // } receive() external payable {} } diff --git a/contracts/resolver/fantom/implementations/aaveV3Resolver.sol b/contracts/resolver/fantom/routes/aaveV3.sol similarity index 99% rename from contracts/resolver/fantom/implementations/aaveV3Resolver.sol rename to contracts/resolver/fantom/routes/aaveV3.sol index 61d7ca9e..d1dab9c9 100644 --- a/contracts/resolver/fantom/implementations/aaveV3Resolver.sol +++ b/contracts/resolver/fantom/routes/aaveV3.sol @@ -1,6 +1,5 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; - import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IAaveV3DataProvider { diff --git a/contracts/resolver/fantom/implementations/flaResolver.sol b/contracts/resolver/fantom/routes/fla.sol similarity index 91% rename from contracts/resolver/fantom/implementations/flaResolver.sol rename to contracts/resolver/fantom/routes/fla.sol index 455fd9d6..8767f2c4 100644 --- a/contracts/resolver/fantom/implementations/flaResolver.sol +++ b/contracts/resolver/fantom/routes/fla.sol @@ -1,11 +1,10 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; - import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract FLAResolver { address public flashloanAggregatorAddr = - 0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19; //todo: update + 0x22ed23Cc6EFf065AfDb7D5fF0CBf6886fd19aee1; function initialize(address fla) public { flashloanAggregatorAddr = fla; diff --git a/contracts/resolver/fantom/variables.sol b/contracts/resolver/fantom/variables.sol index f72c0c2e..3dab99b0 100644 --- a/contracts/resolver/fantom/variables.sol +++ b/contracts/resolver/fantom/variables.sol @@ -1,12 +1,12 @@ //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; - import "./interfaces.sol"; contract Variables { - address public owner; + address public owner = + 0x34Eb8e4B8789807540eB188459ccE082D642e846; address public flashloanAggregatorAddr = - 0x2b65731A085B55DBe6c7DcC8D717Ac36c00F6d19; //TODO: update + 0x22ed23Cc6EFf065AfDb7D5fF0CBf6886fd19aee1; InstaFlashloanAggregatorInterface public flashloanAggregator = InstaFlashloanAggregatorInterface(flashloanAggregatorAddr); mapping(uint256 => address) routeToResolver; diff --git a/test/fantom/resolver.ts b/test/fantom/resolver.ts index b6d971ea..efb4d188 100644 --- a/test/fantom/resolver.ts +++ b/test/fantom/resolver.ts @@ -5,7 +5,6 @@ const { ethers } = hre import { InstaFlashAggregatorFantom__factory, InstaFlashAggregatorProxy__factory, - AaveImplementationFantom__factory, InstaFlashloanResolverFantom, InstaFlashloanResolverFantom__factory, AaveV3Resolver__factory, @@ -17,9 +16,12 @@ import { } from '../../typechain' describe('Resolver', function () { + let AaveV3, aaveV3, FLA, fla; let Resolver, resolver: InstaFlashloanResolverFantom let signer: SignerWithAddress + const proxy = "0x22ed23Cc6EFf065AfDb7D5fF0CBf6886fd19aee1"; + const DAI = '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E' const USDC = '0x04068DA6C83AFCFA0e13ba15A6696662335D5B75' @@ -36,40 +38,6 @@ describe('Resolver', function () { beforeEach(async function () { ;[signer] = await ethers.getSigners() - let Aggregator, - aggregator, - Proxy, - proxy, - AaveV3, - aaveV3, - ImplAave, - implAave, - ImplFLA, - implFLA, - FLA, - fla; - - Aggregator = new InstaFlashAggregatorFantom__factory(signer) - aggregator = await Aggregator.deploy() - await aggregator.deployed() - // console.log("aggregator deployed at: ", aggregator.address) - - ImplAave = new AaveImplementationFantom__factory(signer) - implAave = await ImplAave.deploy() - await implAave.deployed() - // console.log("implAave deployed at: ", implAave.address) - - ImplFLA = new FLAImplementationFantom__factory(signer) - implFLA = await ImplFLA.deploy() - await implFLA.deployed() - // console.log("implFLA deployed at: ", implFLA.address) - - const data = iface.encodeFunctionData('initialize', [signer.address, implAave.address, implFLA.address]) - - Proxy = new InstaFlashAggregatorProxy__factory(signer) - proxy = await Proxy.deploy(aggregator.address, master, data) - await proxy.deployed() - // console.log('Proxy at: ',proxy.address) AaveV3 = new AaveV3Resolver__factory(signer) aaveV3 = await AaveV3.deploy() @@ -81,14 +49,12 @@ describe('Resolver', function () { await fla.deployed() // console.log('fla at: ', fla.address) - await fla.connect(signer).initialize(proxy.address) - Resolver = new InstaFlashloanResolverFantom__factory(signer) resolver = await Resolver.deploy() await resolver.deployed() - // console.log("resolver deployed at: ", resolver.address) + console.log("resolver deployed at: ", resolver.address) - await resolver.connect(signer).initialize(proxy.address, ["9", "10"],[aaveV3.address, fla.address]) + // await resolver.connect(signer).initialize(["9", "10"],[aaveV3.address, fla.address]) const token_dai = new ethers.Contract( DAI, @@ -101,7 +67,7 @@ describe('Resolver', function () { ethers.utils.parseEther('10.0').toHexString(), ]) await hre.network.provider.send('hardhat_setBalance', [ - proxy.address, + proxy, ethers.utils.parseEther('10.0').toHexString(), ]) @@ -111,7 +77,7 @@ describe('Resolver', function () { }) const signer_dai = await ethers.getSigner(ACC_DAI) - await token_dai.connect(signer_dai).transfer(proxy.address, Dai) + await token_dai.connect(signer_dai).transfer(proxy, Dai) await hre.network.provider.request({ method: 'hardhat_stopImpersonatingAccount', @@ -135,7 +101,7 @@ describe('Resolver', function () { }) const signer_usdc = await ethers.getSigner(ACC_USDC) - await token.connect(signer_usdc).transfer(proxy.address, Usdc) + await token.connect(signer_usdc).transfer(proxy, Usdc) await hre.network.provider.request({ method: 'hardhat_stopImpersonatingAccount', From bbc47f819f1b70f00ba3233f3ce951bb38564485 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 5 Jul 2022 18:01:44 +0400 Subject: [PATCH 54/55] minor fix --- contracts/resolver/fantom/main.sol | 2 +- hardhat.config.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/resolver/fantom/main.sol b/contracts/resolver/fantom/main.sol index f58e7f00..e8d2cd20 100644 --- a/contracts/resolver/fantom/main.sol +++ b/contracts/resolver/fantom/main.sol @@ -67,7 +67,7 @@ contract AdminModule is Helper { } } -contract FlashResolverFantom is Helper { +contract FlashResolverFantom is AdminModule { function getRoutesInfo() public view diff --git a/hardhat.config.ts b/hardhat.config.ts index eec09e5a..9a3d2df0 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -60,7 +60,7 @@ function getNetworkUrl(networkType: string) { else if (networkType === "polygon") return `https://polygon-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; else if (networkType === "arbitrum") return `https://arb-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; else if (networkType === "optimism") return `https://opt-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; - else if (networkType === "fantom") return `https://rpc.ftm.tools/`; + else if (networkType === "fantom") return `https://rpc.ankr.com/fantom`; else return `https://eth-mainnet.alchemyapi.io/v2/${alchemyApiKey}`; } @@ -69,7 +69,7 @@ function getBlockNumber(networkType: string) { else if (networkType === "polygon") return 25941254; else if (networkType === "arbitrum") return 7719792; else if (networkType === "optimism") return 4346343; - else if (networkType === "fantom") return 41427580; + else if (networkType === "fantom") return 42070000; else return 14456907; } From 9c773166d8db9a0b16cd9c588843bcb425180673 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 5 Jul 2022 18:18:36 +0400 Subject: [PATCH 55/55] minor update --- contracts/resolver/fantom/main.sol | 18 ++++++++++++++++++ contracts/resolver/fantom/variables.sol | 6 +++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/contracts/resolver/fantom/main.sol b/contracts/resolver/fantom/main.sol index e8d2cd20..1fddfb46 100644 --- a/contracts/resolver/fantom/main.sol +++ b/contracts/resolver/fantom/main.sol @@ -139,5 +139,23 @@ contract FlashResolverFantom is AdminModule { } contract InstaFlashloanResolverFantom is FlashResolverFantom { + function initialize( + address owner_, + uint256[] memory _routes, + address[] memory _resolverImpls + ) public { + require(status == 0, "cannot-call-again"); + require(_routes.length == _resolverImpls.length, "lengths-dont-match"); + owner = owner_; + uint256 length = _routes.length; + for (uint256 i = 0; i < length; i++) { + require( + routeToResolver[_routes[i]] == address(0), + "route-already-added" + ); + routeToResolver[_routes[i]] = _resolverImpls[i]; + } + status = 1; + } receive() external payable {} } diff --git a/contracts/resolver/fantom/variables.sol b/contracts/resolver/fantom/variables.sol index 3dab99b0..17e97700 100644 --- a/contracts/resolver/fantom/variables.sol +++ b/contracts/resolver/fantom/variables.sol @@ -3,11 +3,11 @@ pragma solidity ^0.8.0; import "./interfaces.sol"; contract Variables { - address public owner = - 0x34Eb8e4B8789807540eB188459ccE082D642e846; + uint256 internal status; + address public owner; address public flashloanAggregatorAddr = 0x22ed23Cc6EFf065AfDb7D5fF0CBf6886fd19aee1; InstaFlashloanAggregatorInterface public flashloanAggregator = InstaFlashloanAggregatorInterface(flashloanAggregatorAddr); - mapping(uint256 => address) routeToResolver; + mapping(uint256 => address) public routeToResolver; }