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..c71197ab 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. @@ -20,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. @@ -146,7 +136,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 6dd1cb9f..e1884e00 100644 --- a/contracts/aggregator/fantom/flashloan/variable.sol +++ b/contracts/aggregator/fantom/flashloan/variable.sol @@ -1,26 +1,51 @@ //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 = 0x6C4061A00F8739d528b185CC683B6400E0cd396a; ListInterface public constant instaList = ListInterface(0x10e166c3FAF887D8a61dE6c25039231eE694E926); + 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 - uint256 internal status; +contract FantomVariablesV1 { + address public owner; - struct FlashloanVariables { - address[] _tokens; - uint256[] _amounts; - uint256[] _iniBals; - uint256[] _finBals; - uint256[] _instaFees; + /** + * @dev owner gaurd. + * @notice owner gaurd. + */ + modifier onlyOwner() { + require(msg.sender == owner, "not-owner"); + _; } - - address public owner; } + +contract Variables is ConstantVariables, CommonVariablesV1, Structs, FantomVariablesV1, CommonVariablesV2 { + // ******** Stroage Variable layout ******* // + + /* CommonVariablesV1 + // bytes32 internal dataHash; + // uint256 internal status; + */ + + /* Structs + FlashloanVariables; + */ + + /* FantomVariablesV1 + // 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..c420503a 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,56 @@ 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]); + } + } +} + +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%. @@ -95,16 +147,18 @@ 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. + * @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 sortTokens(address _token0, address _token1) internal pure returns (address, address) { - if (_token1 < _token0) { - (_token0, _token1) = (_token1, _token0); + 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' + ); } - return (_token0, _token1); } -} +} \ No newline at end of file diff --git a/contracts/common/main.sol b/contracts/common/main.sol deleted file mode 100644 index 71fa5426..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++; - } - } - } -} 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