diff --git a/contracts/connectors/1inch.sol b/contracts/connectors/1inch.sol index 56aaa2f..6fbba60 100644 --- a/contracts/connectors/1inch.sol +++ b/contracts/connectors/1inch.sol @@ -26,44 +26,6 @@ interface OneInchInterace { returns (uint256 returnAmount); } -interface OneProtoInterface { - function swapWithReferral( - TokenInterface fromToken, - TokenInterface destToken, - uint256 amount, - uint256 minReturn, - uint256[] calldata distribution, - uint256 flags, // See contants in IOneSplit.sol - address referral, - uint256 feePercent - ) external payable returns(uint256); - - function swapWithReferralMulti( - TokenInterface[] calldata tokens, - uint256 amount, - uint256 minReturn, - uint256[] calldata distribution, - uint256[] calldata flags, - address referral, - uint256 feePercent - ) 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 - ); -} - - contract OneHelpers is Stores, DSMath { using SafeERC20 for IERC20; /** @@ -73,13 +35,6 @@ contract OneHelpers is Stores, DSMath { return 0x11111254369792b2Ca5d084aB5eEA397cA8fa48B; } - /** - * @dev Return 1proto Address - */ - function getOneProtoAddress() internal pure returns (address payable) { - return 0x50FDA034C0Ce7a8f7EFDAebDA7Aa7cA21CC1267e; - } - /** * @dev Return 1inch Token Taker Address */ @@ -115,25 +70,6 @@ contract OneHelpers is Stores, DSMath { sellDec = address(sellAddr) == getEthAddr() ? 18 : sellAddr.decimals(); } - 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; - } - function _transfer(address payable to, IERC20 token, uint _amt) internal { address(token) == getEthAddr() ? to.transfer(_amt) : @@ -171,111 +107,34 @@ contract Resolver is OneHelpers { isOk = sig == getOneInchSig(); } - struct OneProtoData { + struct OneInchData { TokenInterface sellToken; TokenInterface buyToken; uint _sellAmt; uint _buyAmt; uint unitAmt; + bytes callData; address feeCollector; uint256 feeAmount; - uint[] distribution; - uint disableDexes; - } - function oneProtoSwap(OneProtoInterface oneSplitContract, 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) == getEthAddr()) { - ethAmt = _sellAmt; - } else { - _sellAddr.approve(address(oneSplitContract), _sellAmt); - } - - uint initalBal = getTokenBal(_buyAddr); - - oneSplitContract.swapWithReferral.value(ethAmt)( - _sellAddr, - _buyAddr, - _sellAmt, - _slippageAmt, - oneProtoData.distribution, - oneProtoData.disableDexes, - getReferralAddr(), - 0 - ); - - uint finalBal = getTokenBal(_buyAddr); - buyAmt = sub(finalBal, initalBal); - - require(_slippageAmt <= buyAmt, "Too much slippage"); - } - - struct OneProtoMultiData { - address[] tokens; - TokenInterface sellToken; - TokenInterface buyToken; - uint _sellAmt; - uint _buyAmt; - uint unitAmt; - address feeCollector; - uint256 feeAmount; - uint[] distribution; - uint[] disableDexes; - } - function oneProtoSwapMulti(OneProtoMultiData memory oneProtoData) internal returns (uint buyAmt){ - OneProtoInterface oneSplitContract = OneProtoInterface(getOneProtoAddress()); - 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) == getEthAddr()) { - ethAmt = _sellAmt; - } else { - _sellAddr.approve(address(oneSplitContract), _sellAmt); - } - - uint initalBal = getTokenBal(_buyAddr); - oneSplitContract.swapWithReferralMulti.value(ethAmt)( - convertToTokenInterface(oneProtoData.tokens), - _sellAmt, - _slippageAmt, - oneProtoData.distribution, - oneProtoData.disableDexes, - getReferralAddr(), - 0 - ); - uint finalBal = getTokenBal(_buyAddr); - - buyAmt = sub(finalBal, initalBal); - - require(_slippageAmt <= buyAmt, "Too much slippage"); } function oneInchSwap( - TokenInterface _buyAddr, - TokenInterface _sellAddr, - bytes memory callData, - uint sellAmt, - uint unitAmt, + OneInchData memory oneInchData, uint ethAmt ) internal returns (uint buyAmt) { - (uint _buyDec, uint _sellDec) = getTokensDec(_buyAddr, _sellAddr); - uint _sellAmt18 = convertTo18(_sellDec, sellAmt); - uint _slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18)); - uint initalBal = getTokenBal(_buyAddr); + TokenInterface buyToken = oneInchData.buyToken; + (uint _buyDec, uint _sellDec) = getTokensDec(buyToken, oneInchData.sellToken); + uint _sellAmt18 = convertTo18(_sellDec, oneInchData._sellAmt); + uint _slippageAmt = convert18ToDec(_buyDec, wmul(oneInchData.unitAmt, _sellAmt18)); + + uint initalBal = getTokenBal(buyToken); // solium-disable-next-line security/no-call-value - (bool success, ) = address(getOneInchAddress()).call.value(ethAmt)(callData); + (bool success, ) = address(getOneInchAddress()).call.value(ethAmt)(oneInchData.callData); if (!success) revert("1Inch-swap-failed"); - uint finalBal = getTokenBal(_buyAddr); + uint finalBal = getTokenBal(buyToken); + buyAmt = sub(finalBal, initalBal); require(_slippageAmt <= buyAmt, "Too much slippage"); @@ -283,7 +142,7 @@ contract Resolver is OneHelpers { } -contract OneProtoEventResolver is Resolver { +contract OneInchEventResolver is Resolver { event LogSell( address indexed buyToken, address indexed sellToken, @@ -305,308 +164,97 @@ contract OneProtoEventResolver is Resolver { ); function emitLogSell( - OneProtoData memory oneProtoData, - uint256 getId, + OneInchData memory oneInchData, uint256 setId ) internal { bytes32 _eventCode; bytes memory _eventParam; - if (oneProtoData.feeCollector == address(0)) { + if (oneInchData.feeCollector == address(0)) { emit LogSell( - address(oneProtoData.buyToken), - address(oneProtoData.sellToken), - oneProtoData._buyAmt, - oneProtoData._sellAmt, - getId, + address(oneInchData.buyToken), + address(oneInchData.sellToken), + oneInchData._buyAmt, + oneInchData._sellAmt, + 0, setId ); _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)"); _eventParam = abi.encode( - address(oneProtoData.buyToken), - address(oneProtoData.sellToken), - oneProtoData._buyAmt, - oneProtoData._sellAmt, - getId, + address(oneInchData.buyToken), + address(oneInchData.sellToken), + oneInchData._buyAmt, + oneInchData._sellAmt, + 0, setId ); } else { emit LogSellFee( - address(oneProtoData.buyToken), - address(oneProtoData.sellToken), - oneProtoData._buyAmt, - oneProtoData._sellAmt, - oneProtoData.feeCollector, - oneProtoData.feeAmount, - getId, + address(oneInchData.buyToken), + address(oneInchData.sellToken), + oneInchData._buyAmt, + oneInchData._sellAmt, + oneInchData.feeCollector, + oneInchData.feeAmount, + 0, setId ); _eventCode = keccak256("LogSellFee(address,address,uint256,uint256,uint256,uint256)"); _eventParam = abi.encode( - address(oneProtoData.buyToken), - address(oneProtoData.sellToken), - oneProtoData._buyAmt, - oneProtoData._sellAmt, - oneProtoData.feeCollector, - oneProtoData.feeAmount, - getId, + address(oneInchData.buyToken), + address(oneInchData.sellToken), + oneInchData._buyAmt, + oneInchData._sellAmt, + oneInchData.feeCollector, + oneInchData.feeAmount, + 0, setId ); } emitEvent(_eventCode, _eventParam); } - - event LogSellTwo( - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - uint256 getId, - uint256 setId - ); - - event LogSellFeeTwo( - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - address indexed collector, - uint256 fee, - uint256 getId, - uint256 setId - ); - - function emitLogSellTwo( - OneProtoData memory oneProtoData, - uint256 getId, - uint256 setId - ) internal { - bytes32 _eventCode; - bytes memory _eventParam; - if (oneProtoData.feeCollector == address(0)) { - emit LogSellTwo( - address(oneProtoData.buyToken), - address(oneProtoData.sellToken), - oneProtoData._buyAmt, - oneProtoData._sellAmt, - getId, - setId - ); - _eventCode = keccak256("LogSellTwo(address,address,uint256,uint256,uint256,uint256)"); - _eventParam = abi.encode( - address(oneProtoData.buyToken), - address(oneProtoData.sellToken), - oneProtoData._buyAmt, - oneProtoData._sellAmt, - getId, - setId - ); - } else { - emit LogSellFeeTwo( - address(oneProtoData.buyToken), - address(oneProtoData.sellToken), - oneProtoData._buyAmt, - oneProtoData._sellAmt, - oneProtoData.feeCollector, - oneProtoData.feeAmount, - getId, - setId - ); - _eventCode = keccak256("LogSellFeeTwo(address,address,uint256,uint256,uint256,uint256)"); - _eventParam = abi.encode( - address(oneProtoData.buyToken), - address(oneProtoData.sellToken), - oneProtoData._buyAmt, - oneProtoData._sellAmt, - oneProtoData.feeCollector, - oneProtoData.feeAmount, - getId, - setId - ); - } - emitEvent(_eventCode, _eventParam); - } - - event LogSellMulti( - address[] tokens, - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - uint256 getId, - uint256 setId - ); - - event LogSellFeeMulti( - address[] tokens, - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - address indexed collector, - uint256 fee, - uint256 getId, - uint256 setId - ); - - function emitLogSellMulti( - OneProtoMultiData memory oneProtoData, - uint256 getId, - uint256 setId - ) internal { - bytes32 _eventCode; - bytes memory _eventParam; - if (oneProtoData.feeCollector == address(0)) { - emit LogSellMulti( - oneProtoData.tokens, - address(oneProtoData.buyToken), - address(oneProtoData.sellToken), - oneProtoData._buyAmt, - oneProtoData._sellAmt, - getId, - setId - ); - _eventCode = keccak256("LogSellMulti(address[],address,address,uint256,uint256,uint256,uint256)"); - _eventParam = abi.encode( - oneProtoData.tokens, - address(oneProtoData.buyToken), - address(oneProtoData.sellToken), - oneProtoData._buyAmt, - oneProtoData._sellAmt, - getId, - setId - ); - } else { - emit LogSellFeeMulti( - oneProtoData.tokens, - address(oneProtoData.buyToken), - address(oneProtoData.sellToken), - oneProtoData._buyAmt, - oneProtoData._sellAmt, - oneProtoData.feeCollector, - oneProtoData.feeAmount, - getId, - setId - ); - _eventCode = keccak256("LogSellFeeMulti(address[],address,address,uint256,uint256,uint256,uint256)"); - _eventParam = abi.encode( - oneProtoData.tokens, - address(oneProtoData.buyToken), - address(oneProtoData.sellToken), - oneProtoData._buyAmt, - oneProtoData._sellAmt, - oneProtoData.feeCollector, - oneProtoData.feeAmount, - getId, - setId - ); - } - emitEvent(_eventCode, _eventParam); - } - -} -contract OneProtoResolverHelpers is OneProtoEventResolver { - function _sell( - OneProtoData memory oneProtoData, - uint256 feePercent, - uint256 getId, - uint256 setId - ) internal { - uint _sellAmt = getUint(getId, oneProtoData._sellAmt); - - oneProtoData._sellAmt = _sellAmt == uint(-1) ? - getTokenBal(oneProtoData.sellToken) : - _sellAmt; - - OneProtoInterface oneSplitContract = OneProtoInterface(getOneProtoAddress()); - - (, oneProtoData.distribution) = oneSplitContract.getExpectedReturn( - oneProtoData.sellToken, - oneProtoData.buyToken, - oneProtoData._sellAmt, - 5, - 0 - ); - - oneProtoData._buyAmt = oneProtoSwap( - oneSplitContract, - oneProtoData - ); - - (uint feeAmount, uint leftBuyAmt) = takeFee( - address(oneProtoData.buyToken), - oneProtoData._buyAmt, - oneProtoData.feeCollector, - feePercent - ); - setUint(setId, leftBuyAmt); - oneProtoData.feeAmount = feeAmount; - - emitLogSell(oneProtoData, getId, setId); - } - - function _sellTwo( - OneProtoData memory oneProtoData, - uint256 feePercent, - uint getId, - uint setId - ) internal { - uint _sellAmt = getUint(getId, oneProtoData._sellAmt); - - oneProtoData._sellAmt = _sellAmt == uint(-1) ? - getTokenBal(oneProtoData.sellToken) : - _sellAmt; - - oneProtoData._buyAmt = oneProtoSwap( - OneProtoInterface(getOneProtoAddress()), - oneProtoData - ); - - (uint feeAmount, uint leftBuyAmt) = takeFee( - address(oneProtoData.buyToken), - oneProtoData._buyAmt, - oneProtoData.feeCollector, - feePercent - ); - setUint(setId, leftBuyAmt); - oneProtoData.feeAmount = feeAmount; - - emitLogSellTwo(oneProtoData, getId, setId); - } - - function _sellMulti( - OneProtoMultiData memory oneProtoData, - uint256 feePercent, - uint getId, - uint setId - ) internal { - uint _sellAmt = getUint(getId, oneProtoData._sellAmt); - - oneProtoData._sellAmt = _sellAmt == uint(-1) ? - getTokenBal(oneProtoData.sellToken) : - _sellAmt; - - oneProtoData._buyAmt = oneProtoSwapMulti(oneProtoData); - uint leftBuyAmt; - (oneProtoData.feeAmount, leftBuyAmt) = takeFee( - address(oneProtoData.buyToken), - oneProtoData._buyAmt, - oneProtoData.feeCollector, - feePercent - ); - setUint(setId, leftBuyAmt); - - emitLogSellMulti(oneProtoData, getId, setId); - } } -contract OneProtoResolver is OneProtoResolverHelpers { +contract OneInchResolverHelpers is OneInchEventResolver { + function _sell ( + OneInchData memory oneInchData, + uint feePercent, + uint setId + ) internal { + TokenInterface _buyAddr = oneInchData.buyToken; + TokenInterface _sellAddr = oneInchData.sellToken; + + uint ethAmt; + if (address(_sellAddr) == getEthAddr()) { + ethAmt = oneInchData._sellAmt; + } else { + TokenInterface(_sellAddr).approve(getOneInchTokenTaker(), oneInchData._sellAmt); + } + + require(checkOneInchSig(oneInchData.callData), "Not-swap-function"); + + uint buyAmt = oneInchSwap(oneInchData, ethAmt); + + (uint feeAmount, uint leftBuyAmt) = takeFee( + address(_buyAddr), + buyAmt, + oneInchData.feeCollector, + feePercent + ); + setUint(setId, leftBuyAmt); + oneInchData.feeAmount = feeAmount; + + emitLogSell(oneInchData, setId); + } +} + +contract OneInchResolver is OneInchResolverHelpers { /** - * @dev Sell ETH/ERC20_Token using 1proto. + * @dev Sell ETH/ERC20_Token using 1inch. * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param sellAddr selling token amount.(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 callData Data from 1inch API. * @param setId Set token amount at this ID in `InstaMemory` Contract. */ function sell( @@ -614,290 +262,35 @@ contract OneProtoResolver is OneProtoResolverHelpers { address sellAddr, uint sellAmt, uint unitAmt, - uint getId, + bytes calldata callData, uint setId ) external payable { - OneProtoData memory oneProtoData = OneProtoData({ + OneInchData memory oneInchData = OneInchData({ buyToken: TokenInterface(buyAddr), sellToken: TokenInterface(sellAddr), unitAmt: unitAmt, - distribution: new uint[](0), + callData: callData, feeCollector: address(0), _sellAmt: sellAmt, _buyAmt: 0, - disableDexes: 0, feeAmount: 0 }); - _sell(oneProtoData, 0, getId, setId); - + _sell(oneInchData, 0, setId); } /** - * @dev Sell ETH/ERC20_Token using 1proto. + * @dev Sell ETH/ERC20_Token using 1inch. * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param sellAddr selling token amount.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param sellAmt selling token amount. * @param unitAmt unit amount of buyAmt/sellAmt with slippage. + * @param callData Data from 1inch API. * @param feeCollector Fee amount to transfer. * @param feePercent Fee percentage on buyAmt. - * @param getId Get token amount at this ID from `InstaMemory` Contract. * @param setId Set token amount at this ID in `InstaMemory` Contract. */ function sellFee( - address buyAddr, - address sellAddr, - uint sellAmt, - uint unitAmt, - address feeCollector, - uint feePercent, - uint getId, - uint setId - ) external payable { - require(feePercent > 0 && feePercent <= 2*10*16, "Fee more than 2%"); - require(feeCollector != address(0), "feeCollector is not vaild address"); - - OneProtoData memory oneProtoData = OneProtoData({ - buyToken: TokenInterface(buyAddr), - sellToken: TokenInterface(sellAddr), - unitAmt: unitAmt, - distribution: new uint[](0), - feeCollector: feeCollector, - _sellAmt: sellAmt, - _buyAmt: 0, - disableDexes: 0, - feeAmount: 0 - }); - - _sell(oneProtoData, feePercent, getId, setId); - } - - /** - * @dev Sell ETH/ERC20_Token using 1proto. - * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAddr selling token amount.(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 { - OneProtoData memory oneProtoData = OneProtoData({ - buyToken: TokenInterface(buyAddr), - sellToken: TokenInterface(sellAddr), - unitAmt: unitAmt, - distribution: distribution, - disableDexes: disableDexes, - _sellAmt: sellAmt, - feeCollector: address(0), - _buyAmt: 0, - feeAmount: 0 - }); - - _sellTwo(oneProtoData, 0, getId, setId); - } - - - /** - * @dev Sell ETH/ERC20_Token using 1proto. - * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAddr selling token amount.(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 feeCollector Fee amount to transfer. - * @param feePercent Fee percentage on buyAmt. - * @param getId Get token amount at this ID from `InstaMemory` Contract. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - function sellFeeTwo( - address buyAddr, - address sellAddr, - uint sellAmt, - uint unitAmt, - uint[] calldata distribution, - uint disableDexes, - address feeCollector, - uint feePercent, - uint getId, - uint setId - ) external payable { - require(feePercent > 0 && feePercent <= 2*10*16, "Fee more than 2%"); - require(feeCollector != address(0), "feeCollector is not vaild address"); - OneProtoData memory oneProtoData = OneProtoData({ - buyToken: TokenInterface(buyAddr), - sellToken: TokenInterface(sellAddr), - unitAmt: unitAmt, - distribution: distribution, - disableDexes: disableDexes, - feeCollector: feeCollector, - _sellAmt: sellAmt, - _buyAmt: 0, - feeAmount: 0 - }); - - _sellTwo(oneProtoData, feePercent, getId, setId); - } - - /** - * @dev Sell ETH/ERC20_Token using 1proto using muliple token. - * @param tokens buying 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 sellMulti( - address[] calldata tokens, - uint sellAmt, - uint unitAmt, - uint[] calldata distribution, - uint[] calldata disableDexes, - uint getId, - uint setId - ) external payable { - OneProtoMultiData memory oneProtoData = OneProtoMultiData({ - tokens: tokens, - buyToken: TokenInterface(address(tokens[tokens.length - 1])), - sellToken: TokenInterface(address(tokens[0])), - unitAmt: unitAmt, - distribution: distribution, - disableDexes: disableDexes, - _sellAmt: sellAmt, - feeCollector: address(0), - _buyAmt: 0, - feeAmount: 0 - }); - - _sellMulti(oneProtoData, 0, getId, setId); - } - - /** - * @dev Sell ETH/ERC20_Token using 1proto using muliple token. - * @param tokens buying 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 feeCollector Fee amount to transfer. - * @param feePercent Fee percentage on buyAmt. - * @param getId Get token amount at this ID from `InstaMemory` Contract. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - function sellFeeMulti( - address[] calldata tokens, - uint sellAmt, - uint unitAmt, - uint[] calldata distribution, - uint[] calldata disableDexes, - address feeCollector, - uint feePercent, - uint getId, - uint setId - ) external payable { - require(feePercent > 0 && feePercent <= 2*10*16, "Fee more than 2%"); - require(feeCollector != address(0), "feeCollector is not vaild address"); - TokenInterface buyToken = TokenInterface(address(tokens[tokens.length-1])); - OneProtoMultiData memory oneProtoData = OneProtoMultiData({ - tokens: tokens, - buyToken: buyToken, - sellToken: TokenInterface(address(tokens[0])), - unitAmt: unitAmt, - distribution: distribution, - feeCollector: feeCollector, - disableDexes: disableDexes, - _sellAmt: sellAmt, - _buyAmt: 0, - feeAmount: 0 - }); - - _sellMulti(oneProtoData, feePercent, getId, setId); - } -} -contract OneInchResolver is OneProtoResolver { - event LogSellThree( - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - uint256 getId, - uint256 setId - ); - - /** - * @dev Sell ETH/ERC20_Token using 1split. - * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAddr selling token amount.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAmt selling token amount. - * @param unitAmt unit amount of buyAmt/sellAmt with slippage. - * @param callData Data from 1inch API. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - function sellThree( - address buyAddr, - address sellAddr, - uint sellAmt, - uint unitAmt, - bytes calldata callData, - uint setId - ) external payable { - TokenInterface _buyAddr = TokenInterface(buyAddr); - TokenInterface _sellAddr = TokenInterface(sellAddr); - - uint ethAmt; - if (address(_sellAddr) == getEthAddr()) { - ethAmt = sellAmt; - } else { - TokenInterface(_sellAddr).approve(getOneInchTokenTaker(), sellAmt); - } - - require(checkOneInchSig(callData), "Not-swap-function"); - - uint buyAmt = oneInchSwap(_buyAddr, _sellAddr, callData, sellAmt, unitAmt, ethAmt); - - setUint(setId, buyAmt); - - emit LogSellThree(address(_buyAddr), address(_sellAddr), buyAmt, sellAmt, 0, setId); - bytes32 _eventCode = keccak256("LogSellThree(address,address,uint256,uint256,uint256,uint256)"); - bytes memory _eventParam = abi.encode(address(_buyAddr), address(_sellAddr), buyAmt, sellAmt, 0, setId); - emitEvent(_eventCode, _eventParam); - } - - event LogSellFeeThree( - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - address indexed collector, - uint256 fee, - uint256 getId, - uint256 setId - ); - - /** - * @dev Sell ETH/ERC20_Token using 1split. - * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAddr selling token amount.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAmt selling token amount. - * @param unitAmt unit amount of buyAmt/sellAmt with slippage. - * @param callData Data from 1inch API. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - function sellFeeThree( address buyAddr, address sellAddr, uint sellAmt, @@ -910,52 +303,21 @@ contract OneInchResolver is OneProtoResolver { require(feePercent > 0 && feePercent <= 2*10*16, "Fee more than 2%"); require(feeCollector != address(0), "feeCollector is not vaild address"); - TokenInterface _buyAddr = TokenInterface(buyAddr); - TokenInterface _sellAddr = TokenInterface(sellAddr); + OneInchData memory oneInchData = OneInchData({ + buyToken: TokenInterface(buyAddr), + sellToken: TokenInterface(sellAddr), + _sellAmt: sellAmt, + unitAmt: unitAmt, + callData: callData, + feeCollector: feeCollector, + _buyAmt: 0, + feeAmount: 0 + }); - uint ethAmt; - if (address(_sellAddr) == getEthAddr()) { - ethAmt = sellAmt; - } else { - TokenInterface(_sellAddr).approve(getOneInchTokenTaker(), sellAmt); - } - - require(checkOneInchSig(callData), "Not-swap-function"); - - uint buyAmt = oneInchSwap(_buyAddr, _sellAddr, callData, sellAmt, unitAmt, ethAmt); - - (uint feeAmount, uint leftBuyAmt) = takeFee( - address(_buyAddr), - buyAmt, - feeCollector, - feePercent - ); - setUint(setId, leftBuyAmt); - - emit LogSellFeeThree( - address(_buyAddr), - address(_sellAddr), - buyAmt, - sellAmt, - feeCollector, - feeAmount, - 0, - setId - ); - bytes32 _eventCode = keccak256("LogSellThree(address,address,uint256,uint256,uint256,uint256)"); - bytes memory _eventParam = abi.encode( - address(_buyAddr), - address(_sellAddr), - buyAmt, - sellAmt, - feeCollector, - feeAmount, - 0, - setId - ); - emitEvent(_eventCode, _eventParam); + _sell(oneInchData, feePercent, setId); } } + contract ConnectOne is OneInchResolver { - string public name = "1Inch-1proto-v1"; + string public name = "1Inch-v1"; } \ No newline at end of file diff --git a/contracts/connectors/1proto.sol b/contracts/connectors/1proto.sol new file mode 100644 index 0000000..4c7ab74 --- /dev/null +++ b/contracts/connectors/1proto.sol @@ -0,0 +1,763 @@ +pragma solidity ^0.6.0; + +// import files from common directory +import { TokenInterface , MemoryInterface, EventInterface} from "../common/interfaces.sol"; +import { Stores } from "../common/stores.sol"; +import { DSMath } from "../common/math.sol"; + +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + + +interface OneProtoInterface { + function swapWithReferral( + TokenInterface fromToken, + TokenInterface destToken, + uint256 amount, + uint256 minReturn, + uint256[] calldata distribution, + uint256 flags, // See contants in IOneSplit.sol + address referral, + uint256 feePercent + ) external payable returns(uint256); + + function swapWithReferralMulti( + TokenInterface[] calldata tokens, + uint256 amount, + uint256 minReturn, + uint256[] calldata distribution, + uint256[] calldata flags, + address referral, + uint256 feePercent + ) 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 + ); +} + + +contract OneHelpers is Stores, DSMath { + using SafeERC20 for IERC20; + + /** + * @dev Return 1proto Address + */ + function getOneProtoAddress() internal pure returns (address payable) { + return 0x50FDA034C0Ce7a8f7EFDAebDA7Aa7cA21CC1267e; + } + + function getReferralAddr() internal pure returns (address) { + return 0xa7615CD307F323172331865181DC8b80a2834324; // TODO - change address + } + + function convert18ToDec(uint _dec, uint256 _amt) internal pure returns (uint256 amt) { + amt = (_amt / 10 ** (18 - _dec)); + } + + function convertTo18(uint _dec, uint256 _amt) internal pure returns (uint256 amt) { + amt = mul(_amt, 10 ** (18 - _dec)); + } + + function getTokenBal(TokenInterface token) internal view returns(uint _amt) { + _amt = address(token) == getEthAddr() ? address(this).balance : token.balanceOf(address(this)); + } + + function getTokensDec(TokenInterface buyAddr, TokenInterface sellAddr) internal view returns(uint buyDec, uint sellDec) { + buyDec = address(buyAddr) == getEthAddr() ? 18 : buyAddr.decimals(); + sellDec = address(sellAddr) == getEthAddr() ? 18 : sellAddr.decimals(); + } + + 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; + } + + function _transfer(address payable to, IERC20 token, uint _amt) internal { + address(token) == getEthAddr() ? + to.transfer(_amt) : + token.safeTransfer(to, _amt); + } + + function takeFee( + address token, + uint amount, + address feeCollector, + uint feePercent + ) internal returns (uint leftAmt, uint feeAmount){ + if (feeCollector != address(0)) { + feeAmount = wmul(amount, feePercent); + leftAmt = sub(amount, feeAmount); + uint feeCollectorAmt = wmul(feeAmount, 3 * 10 ** 17); + uint restAmt = sub(feeAmount, feeCollectorAmt); + _transfer(payable(feeCollector), IERC20(token), feeCollectorAmt); + _transfer(payable(getReferralAddr()), IERC20(token), restAmt); + } else { + leftAmt = amount; + } + } +} + + +contract Resolver is OneHelpers { + struct OneProtoData { + TokenInterface sellToken; + TokenInterface buyToken; + uint _sellAmt; + uint _buyAmt; + uint unitAmt; + address feeCollector; + uint256 feeAmount; + uint[] distribution; + uint disableDexes; + } + function oneProtoSwap(OneProtoInterface oneSplitContract, 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) == getEthAddr()) { + ethAmt = _sellAmt; + } else { + _sellAddr.approve(address(oneSplitContract), _sellAmt); + } + + uint initalBal = getTokenBal(_buyAddr); + + oneSplitContract.swapWithReferral.value(ethAmt)( + _sellAddr, + _buyAddr, + _sellAmt, + _slippageAmt, + oneProtoData.distribution, + oneProtoData.disableDexes, + getReferralAddr(), + 0 + ); + + uint finalBal = getTokenBal(_buyAddr); + buyAmt = sub(finalBal, initalBal); + + require(_slippageAmt <= buyAmt, "Too much slippage"); + } + + struct OneProtoMultiData { + address[] tokens; + TokenInterface sellToken; + TokenInterface buyToken; + uint _sellAmt; + uint _buyAmt; + uint unitAmt; + address feeCollector; + uint256 feeAmount; + uint[] distribution; + uint[] disableDexes; + } + function oneProtoSwapMulti(OneProtoMultiData memory oneProtoData) internal returns (uint buyAmt){ + OneProtoInterface oneSplitContract = OneProtoInterface(getOneProtoAddress()); + 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) == getEthAddr()) { + ethAmt = _sellAmt; + } else { + _sellAddr.approve(address(oneSplitContract), _sellAmt); + } + + uint initalBal = getTokenBal(_buyAddr); + oneSplitContract.swapWithReferralMulti.value(ethAmt)( + convertToTokenInterface(oneProtoData.tokens), + _sellAmt, + _slippageAmt, + oneProtoData.distribution, + oneProtoData.disableDexes, + getReferralAddr(), + 0 + ); + uint finalBal = getTokenBal(_buyAddr); + + buyAmt = sub(finalBal, initalBal); + + require(_slippageAmt <= buyAmt, "Too much slippage"); + } +} + +contract OneProtoEventResolver is Resolver { + event LogSell( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); + + event LogSellFee( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + address indexed collector, + uint256 fee, + uint256 getId, + uint256 setId + ); + + function emitLogSell( + OneProtoData memory oneProtoData, + uint256 getId, + uint256 setId + ) internal { + bytes32 _eventCode; + bytes memory _eventParam; + if (oneProtoData.feeCollector == address(0)) { + emit LogSell( + address(oneProtoData.buyToken), + address(oneProtoData.sellToken), + oneProtoData._buyAmt, + oneProtoData._sellAmt, + getId, + setId + ); + _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)"); + _eventParam = abi.encode( + address(oneProtoData.buyToken), + address(oneProtoData.sellToken), + oneProtoData._buyAmt, + oneProtoData._sellAmt, + getId, + setId + ); + } else { + emit LogSellFee( + address(oneProtoData.buyToken), + address(oneProtoData.sellToken), + oneProtoData._buyAmt, + oneProtoData._sellAmt, + oneProtoData.feeCollector, + oneProtoData.feeAmount, + getId, + setId + ); + _eventCode = keccak256("LogSellFee(address,address,uint256,uint256,uint256,uint256)"); + _eventParam = abi.encode( + address(oneProtoData.buyToken), + address(oneProtoData.sellToken), + oneProtoData._buyAmt, + oneProtoData._sellAmt, + oneProtoData.feeCollector, + oneProtoData.feeAmount, + getId, + setId + ); + } + emitEvent(_eventCode, _eventParam); + } + + event LogSellTwo( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); + + event LogSellFeeTwo( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + address indexed collector, + uint256 fee, + uint256 getId, + uint256 setId + ); + + function emitLogSellTwo( + OneProtoData memory oneProtoData, + uint256 getId, + uint256 setId + ) internal { + bytes32 _eventCode; + bytes memory _eventParam; + if (oneProtoData.feeCollector == address(0)) { + emit LogSellTwo( + address(oneProtoData.buyToken), + address(oneProtoData.sellToken), + oneProtoData._buyAmt, + oneProtoData._sellAmt, + getId, + setId + ); + _eventCode = keccak256("LogSellTwo(address,address,uint256,uint256,uint256,uint256)"); + _eventParam = abi.encode( + address(oneProtoData.buyToken), + address(oneProtoData.sellToken), + oneProtoData._buyAmt, + oneProtoData._sellAmt, + getId, + setId + ); + } else { + emit LogSellFeeTwo( + address(oneProtoData.buyToken), + address(oneProtoData.sellToken), + oneProtoData._buyAmt, + oneProtoData._sellAmt, + oneProtoData.feeCollector, + oneProtoData.feeAmount, + getId, + setId + ); + _eventCode = keccak256("LogSellFeeTwo(address,address,uint256,uint256,uint256,uint256)"); + _eventParam = abi.encode( + address(oneProtoData.buyToken), + address(oneProtoData.sellToken), + oneProtoData._buyAmt, + oneProtoData._sellAmt, + oneProtoData.feeCollector, + oneProtoData.feeAmount, + getId, + setId + ); + } + emitEvent(_eventCode, _eventParam); + } + + event LogSellMulti( + address[] tokens, + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); + + event LogSellFeeMulti( + address[] tokens, + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + address indexed collector, + uint256 fee, + uint256 getId, + uint256 setId + ); + + function emitLogSellMulti( + OneProtoMultiData memory oneProtoData, + uint256 getId, + uint256 setId + ) internal { + bytes32 _eventCode; + bytes memory _eventParam; + if (oneProtoData.feeCollector == address(0)) { + emit LogSellMulti( + oneProtoData.tokens, + address(oneProtoData.buyToken), + address(oneProtoData.sellToken), + oneProtoData._buyAmt, + oneProtoData._sellAmt, + getId, + setId + ); + _eventCode = keccak256("LogSellMulti(address[],address,address,uint256,uint256,uint256,uint256)"); + _eventParam = abi.encode( + oneProtoData.tokens, + address(oneProtoData.buyToken), + address(oneProtoData.sellToken), + oneProtoData._buyAmt, + oneProtoData._sellAmt, + getId, + setId + ); + } else { + emit LogSellFeeMulti( + oneProtoData.tokens, + address(oneProtoData.buyToken), + address(oneProtoData.sellToken), + oneProtoData._buyAmt, + oneProtoData._sellAmt, + oneProtoData.feeCollector, + oneProtoData.feeAmount, + getId, + setId + ); + _eventCode = keccak256("LogSellFeeMulti(address[],address,address,uint256,uint256,uint256,uint256)"); + _eventParam = abi.encode( + oneProtoData.tokens, + address(oneProtoData.buyToken), + address(oneProtoData.sellToken), + oneProtoData._buyAmt, + oneProtoData._sellAmt, + oneProtoData.feeCollector, + oneProtoData.feeAmount, + getId, + setId + ); + } + emitEvent(_eventCode, _eventParam); + } + +} +contract OneProtoResolverHelpers is OneProtoEventResolver { + function _sell( + OneProtoData memory oneProtoData, + uint256 feePercent, + uint256 getId, + uint256 setId + ) internal { + uint _sellAmt = getUint(getId, oneProtoData._sellAmt); + + oneProtoData._sellAmt = _sellAmt == uint(-1) ? + getTokenBal(oneProtoData.sellToken) : + _sellAmt; + + OneProtoInterface oneSplitContract = OneProtoInterface(getOneProtoAddress()); + + (, oneProtoData.distribution) = oneSplitContract.getExpectedReturn( + oneProtoData.sellToken, + oneProtoData.buyToken, + oneProtoData._sellAmt, + 5, + 0 + ); + + oneProtoData._buyAmt = oneProtoSwap( + oneSplitContract, + oneProtoData + ); + + (uint feeAmount, uint leftBuyAmt) = takeFee( + address(oneProtoData.buyToken), + oneProtoData._buyAmt, + oneProtoData.feeCollector, + feePercent + ); + setUint(setId, leftBuyAmt); + oneProtoData.feeAmount = feeAmount; + + emitLogSell(oneProtoData, getId, setId); + } + + function _sellTwo( + OneProtoData memory oneProtoData, + uint256 feePercent, + uint getId, + uint setId + ) internal { + uint _sellAmt = getUint(getId, oneProtoData._sellAmt); + + oneProtoData._sellAmt = _sellAmt == uint(-1) ? + getTokenBal(oneProtoData.sellToken) : + _sellAmt; + + oneProtoData._buyAmt = oneProtoSwap( + OneProtoInterface(getOneProtoAddress()), + oneProtoData + ); + + (uint feeAmount, uint leftBuyAmt) = takeFee( + address(oneProtoData.buyToken), + oneProtoData._buyAmt, + oneProtoData.feeCollector, + feePercent + ); + setUint(setId, leftBuyAmt); + oneProtoData.feeAmount = feeAmount; + + emitLogSellTwo(oneProtoData, getId, setId); + } + + function _sellMulti( + OneProtoMultiData memory oneProtoData, + uint256 feePercent, + uint getId, + uint setId + ) internal { + uint _sellAmt = getUint(getId, oneProtoData._sellAmt); + + oneProtoData._sellAmt = _sellAmt == uint(-1) ? + getTokenBal(oneProtoData.sellToken) : + _sellAmt; + + oneProtoData._buyAmt = oneProtoSwapMulti(oneProtoData); + uint leftBuyAmt; + (oneProtoData.feeAmount, leftBuyAmt) = takeFee( + address(oneProtoData.buyToken), + oneProtoData._buyAmt, + oneProtoData.feeCollector, + feePercent + ); + setUint(setId, leftBuyAmt); + + emitLogSellMulti(oneProtoData, getId, setId); + } +} + +contract OneProtoResolver is OneProtoResolverHelpers { + /** + * @dev Sell ETH/ERC20_Token using 1proto. + * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr selling token amount.(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 { + OneProtoData memory oneProtoData = OneProtoData({ + buyToken: TokenInterface(buyAddr), + sellToken: TokenInterface(sellAddr), + unitAmt: unitAmt, + distribution: new uint[](0), + feeCollector: address(0), + _sellAmt: sellAmt, + _buyAmt: 0, + disableDexes: 0, + feeAmount: 0 + }); + + _sell(oneProtoData, 0, getId, setId); + + } + + /** + * @dev Sell ETH/ERC20_Token using 1proto. + * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr selling token amount.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAmt selling token amount. + * @param unitAmt unit amount of buyAmt/sellAmt with slippage. + * @param feeCollector Fee amount to transfer. + * @param feePercent Fee percentage on buyAmt. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function sellFee( + address buyAddr, + address sellAddr, + uint sellAmt, + uint unitAmt, + address feeCollector, + uint feePercent, + uint getId, + uint setId + ) external payable { + require(feePercent > 0 && feePercent <= 2*10*16, "Fee more than 2%"); + require(feeCollector != address(0), "feeCollector is not vaild address"); + + OneProtoData memory oneProtoData = OneProtoData({ + buyToken: TokenInterface(buyAddr), + sellToken: TokenInterface(sellAddr), + unitAmt: unitAmt, + distribution: new uint[](0), + feeCollector: feeCollector, + _sellAmt: sellAmt, + _buyAmt: 0, + disableDexes: 0, + feeAmount: 0 + }); + + _sell(oneProtoData, feePercent, getId, setId); + } + + /** + * @dev Sell ETH/ERC20_Token using 1proto. + * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr selling token amount.(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 { + OneProtoData memory oneProtoData = OneProtoData({ + buyToken: TokenInterface(buyAddr), + sellToken: TokenInterface(sellAddr), + unitAmt: unitAmt, + distribution: distribution, + disableDexes: disableDexes, + _sellAmt: sellAmt, + feeCollector: address(0), + _buyAmt: 0, + feeAmount: 0 + }); + + _sellTwo(oneProtoData, 0, getId, setId); + } + + + /** + * @dev Sell ETH/ERC20_Token using 1proto. + * @param buyAddr buying token address.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr selling token amount.(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 feeCollector Fee amount to transfer. + * @param feePercent Fee percentage on buyAmt. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function sellFeeTwo( + address buyAddr, + address sellAddr, + uint sellAmt, + uint unitAmt, + uint[] calldata distribution, + uint disableDexes, + address feeCollector, + uint feePercent, + uint getId, + uint setId + ) external payable { + require(feePercent > 0 && feePercent <= 2*10*16, "Fee more than 2%"); + require(feeCollector != address(0), "feeCollector is not vaild address"); + OneProtoData memory oneProtoData = OneProtoData({ + buyToken: TokenInterface(buyAddr), + sellToken: TokenInterface(sellAddr), + unitAmt: unitAmt, + distribution: distribution, + disableDexes: disableDexes, + feeCollector: feeCollector, + _sellAmt: sellAmt, + _buyAmt: 0, + feeAmount: 0 + }); + + _sellTwo(oneProtoData, feePercent, getId, setId); + } + + /** + * @dev Sell ETH/ERC20_Token using 1proto using muliple token. + * @param tokens buying 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 sellMulti( + address[] calldata tokens, + uint sellAmt, + uint unitAmt, + uint[] calldata distribution, + uint[] calldata disableDexes, + uint getId, + uint setId + ) external payable { + OneProtoMultiData memory oneProtoData = OneProtoMultiData({ + tokens: tokens, + buyToken: TokenInterface(address(tokens[tokens.length - 1])), + sellToken: TokenInterface(address(tokens[0])), + unitAmt: unitAmt, + distribution: distribution, + disableDexes: disableDexes, + _sellAmt: sellAmt, + feeCollector: address(0), + _buyAmt: 0, + feeAmount: 0 + }); + + _sellMulti(oneProtoData, 0, getId, setId); + } + + /** + * @dev Sell ETH/ERC20_Token using 1proto using muliple token. + * @param tokens buying 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 feeCollector Fee amount to transfer. + * @param feePercent Fee percentage on buyAmt. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function sellFeeMulti( + address[] calldata tokens, + uint sellAmt, + uint unitAmt, + uint[] calldata distribution, + uint[] calldata disableDexes, + address feeCollector, + uint feePercent, + uint getId, + uint setId + ) external payable { + require(feePercent > 0 && feePercent <= 2*10*16, "Fee more than 2%"); + require(feeCollector != address(0), "feeCollector is not vaild address"); + TokenInterface buyToken = TokenInterface(address(tokens[tokens.length-1])); + OneProtoMultiData memory oneProtoData = OneProtoMultiData({ + tokens: tokens, + buyToken: buyToken, + sellToken: TokenInterface(address(tokens[0])), + unitAmt: unitAmt, + distribution: distribution, + feeCollector: feeCollector, + disableDexes: disableDexes, + _sellAmt: sellAmt, + _buyAmt: 0, + feeAmount: 0 + }); + + _sellMulti(oneProtoData, feePercent, getId, setId); + } +} + +contract ConnectOne is OneProtoResolver { + string public name = "1proto-v1"; +} \ No newline at end of file