From d1d7b31724eb8b500afa1e33cbfa0fc5337962bc Mon Sep 17 00:00:00 2001 From: Mubaris NK Date: Sun, 21 Mar 2021 14:43:05 +0530 Subject: [PATCH] Add oneProto and refactor oneInch --- contracts/connectors/1inch/events.sol | 28 -- contracts/connectors/1inch/helpers.sol | 51 +--- contracts/connectors/1inch/interface.sol | 58 ---- contracts/connectors/1inch/main.sol | 310 +--------------------- contracts/connectors/1proto/events.sol | 22 ++ contracts/connectors/1proto/helpers.sol | 39 +++ contracts/connectors/1proto/interface.sol | 61 +++++ contracts/connectors/1proto/main.sol | 224 ++++++++++++++++ 8 files changed, 364 insertions(+), 429 deletions(-) create mode 100644 contracts/connectors/1proto/events.sol create mode 100644 contracts/connectors/1proto/helpers.sol create mode 100644 contracts/connectors/1proto/interface.sol create mode 100644 contracts/connectors/1proto/main.sol diff --git a/contracts/connectors/1inch/events.sol b/contracts/connectors/1inch/events.sol index 1f3bef7a..bec3b27a 100644 --- a/contracts/connectors/1inch/events.sol +++ b/contracts/connectors/1inch/events.sol @@ -9,32 +9,4 @@ contract Events { uint256 getId, uint256 setId ); - - event LogSellTwo( - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - uint256 getId, - uint256 setId - ); - - event LogSellMulti( - address[] tokens, - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - uint256 getId, - uint256 setId - ); - - event LogSellThree( - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - uint256 getId, - uint256 setId - ); } \ No newline at end of file diff --git a/contracts/connectors/1inch/helpers.sol b/contracts/connectors/1inch/helpers.sol index 3bd543d4..1aa7b6a1 100644 --- a/contracts/connectors/1inch/helpers.sol +++ b/contracts/connectors/1inch/helpers.sol @@ -3,55 +3,16 @@ pragma solidity ^0.7.0; import { TokenInterface } from "../../common/interfaces.sol"; import { DSMath } from "../../common/math.sol"; import { Basic } from "../../common/basic.sol"; -import { TokenInterface, OneProtoMappingInterface } from "./interface.sol"; abstract contract Helpers is DSMath, Basic { + /** + * @dev 1Inch Address + */ + address internal constant oneInchAddr = 0x111111125434b319222CdBf8C261674aDB56F3ae; /** - * @dev Return 1proto mapping Address + * @dev 1inch swap function sig */ - function getOneProtoMappingAddress() internal pure returns (address payable) { - return 0x8d0287AFa7755BB5f2eFe686AA8d4F0A7BC4AE7F; - } - - /** - * @dev Return 1proto Address - */ - function getOneProtoAddress() internal virtual view returns (address payable) { - return payable(OneProtoMappingInterface(getOneProtoMappingAddress()).oneProtoAddress()); - } - - /** - * @dev Return 1Inch Address - */ - function getOneInchAddress() internal pure returns (address) { - return 0x111111125434b319222CdBf8C261674aDB56F3ae; - } - - /** - * @dev Return 1inch swap function sig - */ - function getOneInchSig() internal pure returns (bytes4) { - return 0x90411a32; - } - - function getSlippageAmt( - TokenInterface _buyAddr, - TokenInterface _sellAddr, - uint _sellAmt, - uint unitAmt - ) internal view returns(uint _slippageAmt) { - (uint _buyDec, uint _sellDec) = getTokensDec(_buyAddr, _sellAddr); - uint _sellAmt18 = convertTo18(_sellDec, _sellAmt); - _slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18)); - } - - function convertToTokenInterface(address[] memory tokens) internal pure returns(TokenInterface[] memory) { - TokenInterface[] memory _tokens = new TokenInterface[](tokens.length); - for (uint i = 0; i < tokens.length; i++) { - _tokens[i] = TokenInterface(tokens[i]); - } - return _tokens; - } + bytes4 internal constant oneInchSig = 0x90411a32; } \ No newline at end of file diff --git a/contracts/connectors/1inch/interface.sol b/contracts/connectors/1inch/interface.sol index 8f8ca7de..f35b9277 100644 --- a/contracts/connectors/1inch/interface.sol +++ b/contracts/connectors/1inch/interface.sol @@ -20,64 +20,6 @@ interface OneInchInterace { returns (uint256 returnAmount); } -interface OneProtoInterface { - function swap( - TokenInterface fromToken, - TokenInterface destToken, - uint256 amount, - uint256 minReturn, - uint256[] calldata distribution, - uint256 flags // See contants in IOneSplit.sol - ) external payable returns(uint256); - - function swapMulti( - TokenInterface[] calldata tokens, - uint256 amount, - uint256 minReturn, - uint256[] calldata distribution, - uint256[] calldata flags - ) external payable returns(uint256 returnAmount); - - function getExpectedReturn( - TokenInterface fromToken, - TokenInterface destToken, - uint256 amount, - uint256 parts, - uint256 flags // See constants in IOneSplit.sol - ) - external - view - returns( - uint256 returnAmount, - uint256[] memory distribution - ); -} - -interface OneProtoMappingInterface { - function oneProtoAddress() external view returns(address); -} - -struct OneProtoData { - TokenInterface sellToken; - TokenInterface buyToken; - uint _sellAmt; - uint _buyAmt; - uint unitAmt; - uint[] distribution; - uint disableDexes; -} - -struct OneProtoMultiData { - address[] tokens; - TokenInterface sellToken; - TokenInterface buyToken; - uint _sellAmt; - uint _buyAmt; - uint unitAmt; - uint[] distribution; - uint[] disableDexes; -} - struct OneInchData { TokenInterface sellToken; TokenInterface buyToken; diff --git a/contracts/connectors/1inch/main.sol b/contracts/connectors/1inch/main.sol index beb16abd..fe98e8d5 100644 --- a/contracts/connectors/1inch/main.sol +++ b/contracts/connectors/1inch/main.sol @@ -4,88 +4,11 @@ pragma experimental ABIEncoderV2; // import files from common directory import { TokenInterface , MemoryInterface } from "../../common/interfaces.sol"; import { Stores } from "../../common/stores.sol"; -import { OneInchInterace, OneProtoInterface, OneProtoMappingInterface, OneProtoData, OneProtoMultiData, OneInchData } from "./interface.sol"; +import { OneInchInterace, OneInchData } from "./interface.sol"; import { Helpers } from "./helpers.sol"; import { Events } from "./events.sol"; - -abstract contract OneProtoResolver is Helpers, Events { - - /** - * @dev 1proto contract swap handler - * @param oneProtoContract - 1 proto contract - * @param oneProtoData - Struct with swap data defined in interfaces.sol - */ - function oneProtoSwap( - OneProtoInterface oneProtoContract, - OneProtoData memory oneProtoData - ) internal returns (uint buyAmt) { - TokenInterface _sellAddr = oneProtoData.sellToken; - TokenInterface _buyAddr = oneProtoData.buyToken; - uint _sellAmt = oneProtoData._sellAmt; - - uint _slippageAmt = getSlippageAmt(_buyAddr, _sellAddr, _sellAmt, oneProtoData.unitAmt); - - uint ethAmt; - if (address(_sellAddr) == ethAddr) { - ethAmt = _sellAmt; - } else { - _sellAddr.approve(address(oneProtoContract), _sellAmt); - } - - - uint initalBal = getTokenBal(_buyAddr); - oneProtoContract.swap{value: ethAmt}( - _sellAddr, - _buyAddr, - _sellAmt, - _slippageAmt, - oneProtoData.distribution, - oneProtoData.disableDexes - ); - uint finalBal = getTokenBal(_buyAddr); - - buyAmt = sub(finalBal, initalBal); - - require(_slippageAmt <= buyAmt, "Too much slippage"); - } - - - /** - * @dev 1proto contract multi swap handler - * @param oneProtoData - Struct with multiple swap data defined in interfaces.sol - */ - function oneProtoSwapMulti(OneProtoMultiData memory oneProtoData) internal returns (uint buyAmt) { - TokenInterface _sellAddr = oneProtoData.sellToken; - TokenInterface _buyAddr = oneProtoData.buyToken; - uint _sellAmt = oneProtoData._sellAmt; - uint _slippageAmt = getSlippageAmt(_buyAddr, _sellAddr, _sellAmt, oneProtoData.unitAmt); - - OneProtoInterface oneSplitContract = OneProtoInterface(getOneProtoAddress()); - uint ethAmt; - if (address(_sellAddr) == ethAddr) { - ethAmt = _sellAmt; - } else { - _sellAddr.approve(address(oneSplitContract), _sellAmt); - } - - uint initalBal = getTokenBal(_buyAddr); - oneSplitContract.swapMulti{value: ethAmt}( - convertToTokenInterface(oneProtoData.tokens), - _sellAmt, - _slippageAmt, - oneProtoData.distribution, - oneProtoData.disableDexes - ); - uint finalBal = getTokenBal(_buyAddr); - - buyAmt = sub(finalBal, initalBal); - - require(_slippageAmt <= buyAmt, "Too much slippage"); - } -} - -abstract contract OneInchResolver is OneProtoResolver { +abstract contract OneInchResolver is Helpers, Events { /** * @dev 1inch swap uses `.call()`. This function restrict it to call only swap/trade functionality * @param callData - calldata to extract the first 4 bytes for checking function signature @@ -97,7 +20,7 @@ abstract contract OneInchResolver is OneProtoResolver { assembly { sig := mload(add(_data, 32)) } - isOk = sig == getOneInchSig(); + isOk = sig == oneInchSig; } /** @@ -117,7 +40,7 @@ abstract contract OneInchResolver is OneProtoResolver { uint initalBal = getTokenBal(buyToken); // solium-disable-next-line security/no-call-value - (bool success, ) = address(getOneInchAddress()).call{value: ethAmt}(oneInchData.callData); + (bool success, ) = oneInchAddr.call{value: ethAmt}(oneInchData.callData); if (!success) revert("1Inch-swap-failed"); uint finalBal = getTokenBal(buyToken); @@ -129,106 +52,14 @@ abstract contract OneInchResolver is OneProtoResolver { } -abstract contract OneProtoResolverHelpers is OneInchResolver { - - /** - * @dev Gets the swapping data onchain for swaps and calls swap. - * @param oneProtoData - Struct with swap data defined in interfaces.sol - * @param getId Get token amount at this ID from `InstaMemory` Contract. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - function _sell( - OneProtoData memory oneProtoData, - uint256 getId, - uint256 setId - ) internal returns (OneProtoData memory) { - uint _sellAmt = getUint(getId, oneProtoData._sellAmt); - - oneProtoData._sellAmt = _sellAmt == uint(-1) ? - getTokenBal(oneProtoData.sellToken) : - _sellAmt; - - OneProtoInterface oneProtoContract = OneProtoInterface(getOneProtoAddress()); - - (, oneProtoData.distribution) = oneProtoContract.getExpectedReturn( - oneProtoData.sellToken, - oneProtoData.buyToken, - oneProtoData._sellAmt, - 5, - 0 - ); - - oneProtoData._buyAmt = oneProtoSwap( - oneProtoContract, - oneProtoData - ); - - setUint(setId, oneProtoData._buyAmt); - - return oneProtoData; - } - - /** - * @dev Gets the swapping data offchian for swaps and calls swap. - * @param oneProtoData - Struct with swap data defined in interfaces.sol - * @param getId Get token amount at this ID from `InstaMemory` Contract. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - function _sellTwo( - OneProtoData memory oneProtoData, - uint getId, - uint setId - ) internal returns (OneProtoData memory) { - uint _sellAmt = getUint(getId, oneProtoData._sellAmt); - - oneProtoData._sellAmt = _sellAmt == uint(-1) ? - getTokenBal(oneProtoData.sellToken) : - _sellAmt; - - oneProtoData._buyAmt = oneProtoSwap( - OneProtoInterface(getOneProtoAddress()), - oneProtoData - ); - - setUint(setId, oneProtoData._buyAmt); - - return oneProtoData; - } - - /** - * @dev Gets the swapping data offchian for swaps and calls swap. - * @param oneProtoData - Struct with multiple swap data defined in interfaces.sol - * @param getId Get token amount at this ID from `InstaMemory` Contract. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - function _sellMulti( - OneProtoMultiData memory oneProtoData, - uint getId, - uint setId - ) internal returns (OneProtoMultiData memory) { - uint _sellAmt = getUint(getId, oneProtoData._sellAmt); - - oneProtoData._sellAmt = _sellAmt == uint(-1) ? - getTokenBal(oneProtoData.sellToken) : - _sellAmt; - - oneProtoData._buyAmt = oneProtoSwapMulti(oneProtoData); - setUint(setId, oneProtoData._buyAmt); - - // emitLogSellMulti(oneProtoData, getId, setId); - - return oneProtoData; - } -} - -abstract contract OneInchResolverHelpers is OneProtoResolverHelpers { +abstract contract OneInchResolverHelpers is OneInchResolver { /** * @dev Gets the swapping data from 1inch's API. * @param oneInchData Struct with multiple swap data defined in interfaces.sol * @param setId Set token amount at this ID in `InstaMemory` Contract. */ - function _sellThree( + function _sell( OneInchData memory oneInchData, uint setId ) internal returns (OneInchData memory) { @@ -238,7 +69,7 @@ abstract contract OneInchResolverHelpers is OneProtoResolverHelpers { if (address(_sellAddr) == ethAddr) { ethAmt = oneInchData._sellAmt; } else { - TokenInterface(_sellAddr).approve(getOneInchAddress(), oneInchData._sellAmt); + TokenInterface(_sellAddr).approve(oneInchAddr, oneInchData._sellAmt); } require(checkOneInchSig(oneInchData.callData), "Not-swap-function"); @@ -252,124 +83,7 @@ abstract contract OneInchResolverHelpers is OneProtoResolverHelpers { } } -abstract contract OneProto is OneInchResolverHelpers { - /** - * @dev Sell ETH/ERC20_Token using 1proto. - * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAddr selling token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAmt selling token amount. - * @param unitAmt unit amount of buyAmt/sellAmt with slippage. - * @param getId Get token amount at this ID from `InstaMemory` Contract. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - function sell( - address buyAddr, - address sellAddr, - uint sellAmt, - uint unitAmt, - uint getId, - uint setId - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - OneProtoData memory oneProtoData = OneProtoData({ - buyToken: TokenInterface(buyAddr), - sellToken: TokenInterface(sellAddr), - _sellAmt: sellAmt, - unitAmt: unitAmt, - distribution: new uint[](0), - _buyAmt: 0, - disableDexes: 0 - }); - - oneProtoData = _sell(oneProtoData, getId, setId); - - _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode(buyAddr, sellAddr, oneProtoData._buyAmt, oneProtoData._sellAmt, getId, setId); - } - - /** - * @dev Sell ETH/ERC20_Token using 1proto using off-chain calculation. - * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAddr selling token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAmt selling token amount. - * @param unitAmt unit amount of buyAmt/sellAmt with slippage. - * @param distribution distribution of swap across different dex. - * @param disableDexes disable a dex. (To disable none: 0) - * @param getId Get token amount at this ID from `InstaMemory` Contract. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - function sellTwo( - address buyAddr, - address sellAddr, - uint sellAmt, - uint unitAmt, - uint[] calldata distribution, - uint disableDexes, - uint getId, - uint setId - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - OneProtoData memory oneProtoData = OneProtoData({ - buyToken: TokenInterface(buyAddr), - sellToken: TokenInterface(sellAddr), - _sellAmt: sellAmt, - unitAmt: unitAmt, - distribution: distribution, - disableDexes: disableDexes, - _buyAmt: 0 - }); - - oneProtoData = _sellTwo(oneProtoData, getId, setId); - - _eventName = "LogSellTwo(address,address,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode(buyAddr, sellAddr, oneProtoData._buyAmt, oneProtoData._sellAmt, getId, setId); - } - - /** - * @dev Sell ETH/ERC20_Token using 1proto using muliple token. - * @param tokens array of tokens. - * @param sellAmt selling token amount. - * @param unitAmt unit amount of buyAmt/sellAmt with slippage. - * @param distribution distribution of swap across different dex. - * @param disableDexes disable a dex. (To disable none: 0) - * @param getId Get token amount at this ID from `InstaMemory` Contract. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - function sellMulti( - address[] calldata tokens, - uint sellAmt, - uint unitAmt, - uint[] calldata distribution, - uint[] calldata disableDexes, - uint getId, - uint setId - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _length = tokens.length; - OneProtoMultiData memory oneProtoData = OneProtoMultiData({ - tokens: tokens, - buyToken: TokenInterface(address(tokens[_length - 1])), - sellToken: TokenInterface(address(tokens[0])), - unitAmt: unitAmt, - distribution: distribution, - disableDexes: disableDexes, - _sellAmt: sellAmt, - _buyAmt: 0 - }); - - oneProtoData = _sellMulti(oneProtoData, getId, setId); - - _eventName = "LogSellMulti(address[],address,address,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode( - tokens, - address(oneProtoData.buyToken), - address(oneProtoData.sellToken), - oneProtoData._buyAmt, - oneProtoData._sellAmt, - getId, - setId - ); - } -} - -abstract contract OneInch is OneProto { +abstract contract OneInch is OneInchResolverHelpers { /** * @dev Sell ETH/ERC20_Token using 1inch. * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) @@ -379,7 +93,7 @@ abstract contract OneInch is OneProto { * @param callData Data from 1inch API. * @param setId Set token amount at this ID in `InstaMemory` Contract. */ - function sellThree( + function sell( address buyAddr, address sellAddr, uint sellAmt, @@ -396,13 +110,13 @@ abstract contract OneInch is OneProto { _buyAmt: 0 }); - oneInchData = _sellThree(oneInchData, setId); + oneInchData = _sell(oneInchData, setId); - _eventName = "LogSellThree(address,address,uint256,uint256,uint256,uint256)"; + _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; _eventParam = abi.encode(buyAddr, sellAddr, oneInchData._buyAmt, oneInchData._sellAmt, 0, setId); } } contract ConnectV2OneInch is OneInch { - string public name = "1inch-1proto-v1"; + string public name = "1inch-v1"; } diff --git a/contracts/connectors/1proto/events.sol b/contracts/connectors/1proto/events.sol new file mode 100644 index 00000000..b8f9def9 --- /dev/null +++ b/contracts/connectors/1proto/events.sol @@ -0,0 +1,22 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogSell( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); + + event LogSellMulti( + address[] tokens, + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); +} \ No newline at end of file diff --git a/contracts/connectors/1proto/helpers.sol b/contracts/connectors/1proto/helpers.sol new file mode 100644 index 00000000..272709b5 --- /dev/null +++ b/contracts/connectors/1proto/helpers.sol @@ -0,0 +1,39 @@ +pragma solidity ^0.7.0; + +import { TokenInterface } from "../../common/interfaces.sol"; +import { DSMath } from "../../common/math.sol"; +import { Basic } from "../../common/basic.sol"; +import { TokenInterface, OneProtoMappingInterface } from "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + /** + * @dev 1proto mapping Address + */ + OneProtoMappingInterface constant internal oneProtoMapping = OneProtoMappingInterface(0x8d0287AFa7755BB5f2eFe686AA8d4F0A7BC4AE7F); + + /** + * @dev Return 1proto Address + */ + function getOneProtoAddress() internal virtual view returns (address payable) { + return payable(oneProtoMapping.oneProtoAddress()); + } + + function getSlippageAmt( + TokenInterface _buyAddr, + TokenInterface _sellAddr, + uint _sellAmt, + uint unitAmt + ) internal view returns(uint _slippageAmt) { + (uint _buyDec, uint _sellDec) = getTokensDec(_buyAddr, _sellAddr); + uint _sellAmt18 = convertTo18(_sellDec, _sellAmt); + _slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18)); + } + + function convertToTokenInterface(address[] memory tokens) internal pure returns(TokenInterface[] memory) { + TokenInterface[] memory _tokens = new TokenInterface[](tokens.length); + for (uint i = 0; i < tokens.length; i++) { + _tokens[i] = TokenInterface(tokens[i]); + } + return _tokens; + } +} \ No newline at end of file diff --git a/contracts/connectors/1proto/interface.sol b/contracts/connectors/1proto/interface.sol new file mode 100644 index 00000000..369d1399 --- /dev/null +++ b/contracts/connectors/1proto/interface.sol @@ -0,0 +1,61 @@ +pragma solidity ^0.7.0; + +import { TokenInterface } from "../../common/interfaces.sol"; + +interface OneProtoInterface { + function swap( + TokenInterface fromToken, + TokenInterface destToken, + uint256 amount, + uint256 minReturn, + uint256[] calldata distribution, + uint256 flags // See contants in IOneSplit.sol + ) external payable returns(uint256); + + function swapMulti( + TokenInterface[] calldata tokens, + uint256 amount, + uint256 minReturn, + uint256[] calldata distribution, + uint256[] calldata flags + ) external payable returns(uint256 returnAmount); + + function getExpectedReturn( + TokenInterface fromToken, + TokenInterface destToken, + uint256 amount, + uint256 parts, + uint256 flags // See constants in IOneSplit.sol + ) + external + view + returns( + uint256 returnAmount, + uint256[] memory distribution + ); +} + +interface OneProtoMappingInterface { + function oneProtoAddress() external view returns(address); +} + +struct OneProtoData { + TokenInterface sellToken; + TokenInterface buyToken; + uint _sellAmt; + uint _buyAmt; + uint unitAmt; + uint[] distribution; + uint disableDexes; +} + +struct OneProtoMultiData { + address[] tokens; + TokenInterface sellToken; + TokenInterface buyToken; + uint _sellAmt; + uint _buyAmt; + uint unitAmt; + uint[] distribution; + uint[] disableDexes; +} diff --git a/contracts/connectors/1proto/main.sol b/contracts/connectors/1proto/main.sol new file mode 100644 index 00000000..d84a6480 --- /dev/null +++ b/contracts/connectors/1proto/main.sol @@ -0,0 +1,224 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +import { TokenInterface , MemoryInterface } from "../../common/interfaces.sol"; +import { Stores } from "../../common/stores.sol"; +import { OneProtoInterface, OneProtoData, OneProtoMultiData } from "./interface.sol"; +import { Helpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract OneProtoResolver is Helpers, Events { + /** + * @dev 1proto contract swap handler + * @param oneProtoContract - 1 proto contract + * @param oneProtoData - Struct with swap data defined in interfaces.sol + */ + function oneProtoSwap( + OneProtoInterface oneProtoContract, + OneProtoData memory oneProtoData + ) internal returns (uint buyAmt) { + TokenInterface _sellAddr = oneProtoData.sellToken; + TokenInterface _buyAddr = oneProtoData.buyToken; + uint _sellAmt = oneProtoData._sellAmt; + + uint _slippageAmt = getSlippageAmt(_buyAddr, _sellAddr, _sellAmt, oneProtoData.unitAmt); + + uint ethAmt; + if (address(_sellAddr) == ethAddr) { + ethAmt = _sellAmt; + } else { + _sellAddr.approve(address(oneProtoContract), _sellAmt); + } + + + uint initalBal = getTokenBal(_buyAddr); + oneProtoContract.swap{value: ethAmt}( + _sellAddr, + _buyAddr, + _sellAmt, + _slippageAmt, + oneProtoData.distribution, + oneProtoData.disableDexes + ); + uint finalBal = getTokenBal(_buyAddr); + + buyAmt = sub(finalBal, initalBal); + + require(_slippageAmt <= buyAmt, "Too much slippage"); + } + + /** + * @dev 1proto contract multi swap handler + * @param oneProtoData - Struct with multiple swap data defined in interfaces.sol + */ + function oneProtoSwapMulti(OneProtoMultiData memory oneProtoData) internal returns (uint buyAmt) { + TokenInterface _sellAddr = oneProtoData.sellToken; + TokenInterface _buyAddr = oneProtoData.buyToken; + uint _sellAmt = oneProtoData._sellAmt; + uint _slippageAmt = getSlippageAmt(_buyAddr, _sellAddr, _sellAmt, oneProtoData.unitAmt); + + OneProtoInterface oneSplitContract = OneProtoInterface(getOneProtoAddress()); + uint ethAmt; + if (address(_sellAddr) == ethAddr) { + ethAmt = _sellAmt; + } else { + _sellAddr.approve(address(oneSplitContract), _sellAmt); + } + + uint initalBal = getTokenBal(_buyAddr); + oneSplitContract.swapMulti{value: ethAmt}( + convertToTokenInterface(oneProtoData.tokens), + _sellAmt, + _slippageAmt, + oneProtoData.distribution, + oneProtoData.disableDexes + ); + uint finalBal = getTokenBal(_buyAddr); + + buyAmt = sub(finalBal, initalBal); + + require(_slippageAmt <= buyAmt, "Too much slippage"); + } +} + +abstract contract OneProtoResolverHelpers is OneProtoResolver { + /** + * @dev Gets the swapping data offchian for swaps and calls swap. + * @param oneProtoData - Struct with swap data defined in interfaces.sol + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function _sell( + OneProtoData memory oneProtoData, + uint getId, + uint setId + ) internal returns (OneProtoData memory) { + uint _sellAmt = getUint(getId, oneProtoData._sellAmt); + + oneProtoData._sellAmt = _sellAmt == uint(-1) ? + getTokenBal(oneProtoData.sellToken) : + _sellAmt; + + oneProtoData._buyAmt = oneProtoSwap( + OneProtoInterface(getOneProtoAddress()), + oneProtoData + ); + + setUint(setId, oneProtoData._buyAmt); + + return oneProtoData; + } + + /** + * @dev Gets the swapping data offchian for swaps and calls swap. + * @param oneProtoData - Struct with multiple swap data defined in interfaces.sol + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function _sellMulti( + OneProtoMultiData memory oneProtoData, + uint getId, + uint setId + ) internal returns (OneProtoMultiData memory) { + uint _sellAmt = getUint(getId, oneProtoData._sellAmt); + + oneProtoData._sellAmt = _sellAmt == uint(-1) ? + getTokenBal(oneProtoData.sellToken) : + _sellAmt; + + oneProtoData._buyAmt = oneProtoSwapMulti(oneProtoData); + setUint(setId, oneProtoData._buyAmt); + + // emitLogSellMulti(oneProtoData, getId, setId); + + return oneProtoData; + } +} + +abstract contract OneProto is OneProtoResolverHelpers { + /** + * @dev Sell ETH/ERC20_Token using 1proto using off-chain calculation. + * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr selling token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAmt selling token amount. + * @param unitAmt unit amount of buyAmt/sellAmt with slippage. + * @param distribution distribution of swap across different dex. + * @param disableDexes disable a dex. (To disable none: 0) + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function sell( + address buyAddr, + address sellAddr, + uint sellAmt, + uint unitAmt, + uint[] calldata distribution, + uint disableDexes, + uint getId, + uint setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + OneProtoData memory oneProtoData = OneProtoData({ + buyToken: TokenInterface(buyAddr), + sellToken: TokenInterface(sellAddr), + _sellAmt: sellAmt, + unitAmt: unitAmt, + distribution: distribution, + disableDexes: disableDexes, + _buyAmt: 0 + }); + + oneProtoData = _sell(oneProtoData, getId, setId); + + _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(buyAddr, sellAddr, oneProtoData._buyAmt, oneProtoData._sellAmt, getId, setId); + } + + /** + * @dev Sell ETH/ERC20_Token using 1proto using muliple token. + * @param tokens array of tokens. + * @param sellAmt selling token amount. + * @param unitAmt unit amount of buyAmt/sellAmt with slippage. + * @param distribution distribution of swap across different dex. + * @param disableDexes disable a dex. (To disable none: 0) + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function sellMulti( + address[] calldata tokens, + uint sellAmt, + uint unitAmt, + uint[] calldata distribution, + uint[] calldata disableDexes, + uint getId, + uint setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _length = tokens.length; + OneProtoMultiData memory oneProtoData = OneProtoMultiData({ + tokens: tokens, + buyToken: TokenInterface(address(tokens[_length - 1])), + sellToken: TokenInterface(address(tokens[0])), + unitAmt: unitAmt, + distribution: distribution, + disableDexes: disableDexes, + _sellAmt: sellAmt, + _buyAmt: 0 + }); + + oneProtoData = _sellMulti(oneProtoData, getId, setId); + + _eventName = "LogSellMulti(address[],address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode( + tokens, + address(oneProtoData.buyToken), + address(oneProtoData.sellToken), + oneProtoData._buyAmt, + oneProtoData._sellAmt, + getId, + setId + ); + } +} + +contract ConnectV2OneProto is OneProto { + string public name = "1proto-v1"; +}