From 4cfc1e3cb764f3b50d6f57ba8fdbb7162ddc3b41 Mon Sep 17 00:00:00 2001 From: Samyak Jain <34437877+KaymasJain@users.noreply.github.com> Date: Fri, 8 May 2020 19:11:46 +1000 Subject: [PATCH 01/11] 1inch connector --- contracts/connectors/1inch.sol | 316 +++++++++++++++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 contracts/connectors/1inch.sol diff --git a/contracts/connectors/1inch.sol b/contracts/connectors/1inch.sol new file mode 100644 index 0000000..3d12943 --- /dev/null +++ b/contracts/connectors/1inch.sol @@ -0,0 +1,316 @@ +pragma solidity ^0.6.0; + +interface OneInchInterace { + function swap( + TokenInterface fromToken, + TokenInterface toToken, + uint256 fromTokenAmount, + uint256 minReturnAmount, + uint256 guaranteedAmount, + address payable referrer, + address[] calldata callAddresses, + bytes calldata callDataConcat, + uint256[] calldata starts, + uint256[] calldata gasLimitsAndValues + ) + external + payable + returns (uint256 returnAmount); +} + +interface OneSplitInterface { + function swap( + TokenInterface fromToken, + TokenInterface toToken, + uint256 amount, + uint256 minReturn, + uint256[] calldata distribution, // [Uniswap, Kyber, Bancor, Oasis] + uint256 disableFlags // 16 - Compound, 32 - Fulcrum, 64 - Chai, 128 - Aave, 256 - SmartToken, 1024 - bDAI + ) external payable; + + function getExpectedReturn( + TokenInterface fromToken, + TokenInterface toToken, + uint256 amount, + uint256 parts, + uint256 disableFlags + ) + external + view + returns( + uint256 returnAmount, + uint256[] memory distribution + ); +} + + +interface TokenInterface { + function allowance(address, address) external view returns (uint); + function balanceOf(address) external view returns (uint); + function approve(address, uint) external; + function transfer(address, uint) external returns (bool); + function transferFrom(address, address, uint) external returns (bool); + function decimals() external view returns (uint); +} + +interface MemoryInterface { + function getUint(uint _id) external returns (uint _num); + function setUint(uint _id, uint _val) external; +} + +interface EventInterface { + function emitEvent(uint _connectorType, uint _connectorID, bytes32 _eventCode, bytes calldata _eventData) external; +} + +contract DSMath { + + function add(uint x, uint y) internal pure returns (uint z) { + require((z = x + y) >= x, "math-not-safe"); + } + + function mul(uint x, uint y) internal pure returns (uint z) { + require(y == 0 || (z = x * y) / y == x, "math-not-safe"); + } + + function sub(uint x, uint y) internal pure returns (uint z) { + require((z = x - y) <= x, "sub-overflow"); + } + + uint constant WAD = 10 ** 18; + + function wmul(uint x, uint y) internal pure returns (uint z) { + z = add(mul(x, y), WAD / 2) / WAD; + } + + function wdiv(uint x, uint y) internal pure returns (uint z) { + z = add(mul(x, WAD), y / 2) / y; + } + +} + + +contract Helpers is DSMath { + /** + * @dev Return ethereum address + */ + function getAddressETH() internal pure returns (address) { + return 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // ETH Address + } + + /** + * @dev Return Memory Variable Address + */ + function getMemoryAddr() internal pure returns (address) { + return 0x8a5419CfC711B2343c17a6ABf4B2bAFaBb06957F; // InstaMemory Address + } + + /** + * @dev Return InstaEvent Address. + */ + function getEventAddr() internal pure returns (address) { + return 0x2af7ea6Cb911035f3eb1ED895Cb6692C39ecbA97; // InstaEvent Address + } + + /** + * @dev Get Uint value from InstaMemory Contract. + */ + function getUint(uint getId, uint val) internal returns (uint returnVal) { + returnVal = getId == 0 ? val : MemoryInterface(getMemoryAddr()).getUint(getId); + } + + /** + * @dev Set Uint value in InstaMemory Contract. + */ + function setUint(uint setId, uint val) internal { + if (setId != 0) MemoryInterface(getMemoryAddr()).setUint(setId, val); + } + + /** + * @dev Connector Details + */ + function connectorID() public pure returns(uint _type, uint _id) { + (_type, _id) = (1, 0); + } +} + + +contract OneHelpers is Helpers { + /** + * @dev Return 1 Inch Address + */ + function getOneInchAddress() internal pure returns (address) { + return 0x11111254369792b2Ca5d084aB5eEA397cA8fa48B; + } + + /** + * @dev Return 1 Split Address + */ + function getOneSplitAddress() internal pure returns (address) { + return 0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E; + } + + 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) == getAddressETH() ? address(this).balance : token.balanceOf(address(this)); + } + + function convertDiv(uint xDec, uint yDec, uint x, uint y) internal pure returns(uint z) { + z = wdiv(convertTo18(xDec, x), convertTo18(yDec, y)); + } + + function getTokensDec(TokenInterface buyAddr, TokenInterface sellAddr) internal view returns(uint buyDec, uint sellDec) { + buyDec = address(buyAddr) == getAddressETH() ? 18 : buyAddr.decimals(); + sellDec = address(sellAddr) == getAddressETH() ? 18 : sellAddr.decimals(); + } + + function decodeData( + bytes memory data + ) + internal pure returns ( + address buyAddr, + address sellAddr, + uint256 fromTokenAmount + ) + { + bytes memory _data = data; + // solium-disable-next-line security/no-inline-assembly + assembly { + sellAddr := mload(add(_data, 36)) + buyAddr := mload(add(_data, 68)) + fromTokenAmount := mload(add(_data, 100)) + } + } +} + + +contract Resolver is OneHelpers { + function oneSplitSwap( + TokenInterface _sellAddr, + TokenInterface _buyAddr, + uint _sellAmt, + uint unitAmt + ) internal returns (uint buyAmt, uint[] memory distribution){ + (uint _buyDec, uint _sellDec) = getTokensDec(_buyAddr, _sellAddr); + uint _sellAmt18 = convertTo18(_sellDec, _sellAmt); + uint _slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18)); + + OneSplitInterface oneSplitContract = OneSplitInterface(getOneSplitAddress()); + + (buyAmt, distribution) = oneSplitContract.getExpectedReturn( + _sellAddr, + _buyAddr, + _sellAmt, + 3, // TODO - shall we hardcode? + 0 // TODO - do we need to disable anything? + ); + + require(_slippageAmt <= buyAmt, "Too much slippage"); + + uint ethAmt; + if (address(_sellAddr) == getAddressETH()) { + ethAmt = _sellAmt; + } else { + _sellAddr.approve(address(oneSplitContract), _sellAmt); + } + + oneSplitContract.swap.value(ethAmt)( + _sellAddr, + _buyAddr, + _sellAmt, + _slippageAmt, + distribution, + 0 + ); + } + + function oneInchSwap( + bytes memory _callData, + uint ethAmt + ) + internal returns (uint buyAmt) { + // solium-disable-next-line security/no-call-value + (bool success, bytes memory data) = address(getOneInchAddress()).call.value(ethAmt)(_callData); + if (!success) revert("1Inch-swap-failed"); + + buyAmt = abi.decode(data, (uint)); + } +} + +contract BasicResolver is Resolver { + event LogSellOneInch( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 setId + ); + + event LogSellOneSplit( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); + + function sell( + address buyAddr, + address sellAddr, + uint sellAmt, + uint unitAmt, + uint getId, + uint setId + ) external payable { + uint _sellAmt = sellAmt; + TokenInterface _buyAddr = TokenInterface(buyAddr); + TokenInterface _sellAddr = TokenInterface(sellAddr); + + uint initalBal = getTokenBal(_buyAddr); + _sellAmt = _sellAmt == uint(-1) ? getTokenBal(_sellAddr) : _sellAmt; + + oneSplitSwap( + _sellAddr, + _buyAddr, + _sellAmt, + unitAmt + ); + + uint finialBal = getTokenBal(_buyAddr); + uint _buyAmt = sub(finialBal, initalBal); + + setUint(setId, _buyAmt); + emit LogSellOneSplit(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); + + } + + function sell( + bytes calldata callData, + uint setId + ) external payable { + (address _buyAddr, address _sellAddr, uint sellAmt) = decodeData(callData); + + uint ethAmt; + if (address(_sellAddr) == getAddressETH()) { + ethAmt = sellAmt; + } else { + TokenInterface(_sellAddr).approve(getOneInchAddress(), sellAmt); + } + + uint _buyAmt = oneInchSwap(callData, ethAmt); + + setUint(setId, _buyAmt); + emit LogSellOneInch(address(_buyAddr), address(_sellAddr), _buyAmt, sellAmt, setId); + } +} + +contract ConnectOne is BasicResolver { + string public name = "1Inch-1Split-v1"; +} \ No newline at end of file From 93cf4e81dc4a2bac5fc124e7bedd14898ae23cae Mon Sep 17 00:00:00 2001 From: Samyak Jain <34437877+KaymasJain@users.noreply.github.com> Date: Fri, 8 May 2020 20:36:46 +1000 Subject: [PATCH 02/11] 1inch connector done --- contracts/connectors/1inch.sol | 124 ++++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 40 deletions(-) diff --git a/contracts/connectors/1inch.sol b/contracts/connectors/1inch.sol index 3d12943..555e47d 100644 --- a/contracts/connectors/1inch.sol +++ b/contracts/connectors/1inch.sol @@ -192,27 +192,18 @@ contract OneHelpers is Helpers { contract Resolver is OneHelpers { function oneSplitSwap( + OneSplitInterface oneSplitContract, TokenInterface _sellAddr, TokenInterface _buyAddr, uint _sellAmt, - uint unitAmt - ) internal returns (uint buyAmt, uint[] memory distribution){ + uint unitAmt, + uint[] memory distribution, + uint disableDexes + ) internal returns (uint buyAmt){ (uint _buyDec, uint _sellDec) = getTokensDec(_buyAddr, _sellAddr); uint _sellAmt18 = convertTo18(_sellDec, _sellAmt); uint _slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18)); - OneSplitInterface oneSplitContract = OneSplitInterface(getOneSplitAddress()); - - (buyAmt, distribution) = oneSplitContract.getExpectedReturn( - _sellAddr, - _buyAddr, - _sellAmt, - 3, // TODO - shall we hardcode? - 0 // TODO - do we need to disable anything? - ); - - require(_slippageAmt <= buyAmt, "Too much slippage"); - uint ethAmt; if (address(_sellAddr) == getAddressETH()) { ethAmt = _sellAmt; @@ -220,27 +211,23 @@ contract Resolver is OneHelpers { _sellAddr.approve(address(oneSplitContract), _sellAmt); } + uint initalBal = getTokenBal(_buyAddr); + oneSplitContract.swap.value(ethAmt)( _sellAddr, _buyAddr, _sellAmt, _slippageAmt, distribution, - 0 + disableDexes ); + + uint finalBal = getTokenBal(_buyAddr); + buyAmt = sub(finalBal, initalBal); + + require(_slippageAmt <= buyAmt, "Too much slippage"); } - function oneInchSwap( - bytes memory _callData, - uint ethAmt - ) - internal returns (uint buyAmt) { - // solium-disable-next-line security/no-call-value - (bool success, bytes memory data) = address(getOneInchAddress()).call.value(ethAmt)(_callData); - if (!success) revert("1Inch-swap-failed"); - - buyAmt = abi.decode(data, (uint)); - } } contract BasicResolver is Resolver { @@ -252,7 +239,7 @@ contract BasicResolver is Resolver { uint256 setId ); - event LogSellOneSplit( + event LogSell( address indexed buyToken, address indexed sellToken, uint256 buyAmt, @@ -268,34 +255,84 @@ contract BasicResolver is Resolver { uint unitAmt, uint getId, uint setId - ) external payable { - uint _sellAmt = sellAmt; + ) public payable { + uint _sellAmt = getUint(getId, sellAmt); + TokenInterface _buyAddr = TokenInterface(buyAddr); TokenInterface _sellAddr = TokenInterface(sellAddr); - uint initalBal = getTokenBal(_buyAddr); _sellAmt = _sellAmt == uint(-1) ? getTokenBal(_sellAddr) : _sellAmt; - oneSplitSwap( + OneSplitInterface oneSplitContract = OneSplitInterface(getOneSplitAddress()); + + (, uint[] memory distribution) = oneSplitContract.getExpectedReturn( + _sellAddr, + _buyAddr, + _sellAmt, + 3, // TODO - shall we hardcode? + 0 // TODO - do we need to disable anything? + ); + + uint _buyAmt = oneSplitSwap( + oneSplitContract, _sellAddr, _buyAddr, _sellAmt, - unitAmt + unitAmt, + distribution, + 0 ); - uint finialBal = getTokenBal(_buyAddr); - uint _buyAmt = sub(finialBal, initalBal); - setUint(setId, _buyAmt); - emit LogSellOneSplit(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); + emit LogSell(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); } function sell( + address buyAddr, + address sellAddr, + uint sellAmt, + uint unitAmt, + uint[] calldata distribution, + uint disableDexes, + uint getId, + uint setId + ) external payable { + uint _sellAmt = getUint(getId, sellAmt); + + TokenInterface _buyAddr = TokenInterface(buyAddr); + TokenInterface _sellAddr = TokenInterface(sellAddr); + + _sellAmt = _sellAmt == uint(-1) ? getTokenBal(_sellAddr) : _sellAmt; + + uint _buyAmt = oneSplitSwap( + OneSplitInterface(getOneSplitAddress()), + _sellAddr, + _buyAddr, + _sellAmt, + unitAmt, + distribution, + disableDexes + ); + + setUint(setId, _buyAmt); + emit LogSell(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); + } + + function sell( + address buyAddr, + address sellAddr, + uint sellAmt, + uint unitAmt, bytes calldata callData, uint setId ) external payable { - (address _buyAddr, address _sellAddr, uint sellAmt) = decodeData(callData); + TokenInterface _buyAddr = TokenInterface(buyAddr); + TokenInterface _sellAddr = TokenInterface(sellAddr); + + (uint _buyDec, uint _sellDec) = getTokensDec(_buyAddr, _sellAddr); + uint _sellAmt18 = convertTo18(_sellDec, sellAmt); + uint _slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18)); uint ethAmt; if (address(_sellAddr) == getAddressETH()) { @@ -304,10 +341,17 @@ contract BasicResolver is Resolver { TokenInterface(_sellAddr).approve(getOneInchAddress(), sellAmt); } - uint _buyAmt = oneInchSwap(callData, ethAmt); + uint initalBal = getTokenBal(_buyAddr); - setUint(setId, _buyAmt); - emit LogSellOneInch(address(_buyAddr), address(_sellAddr), _buyAmt, sellAmt, setId); + address(getOneInchAddress()).call.value(ethAmt)(callData); + + uint finalBal = getTokenBal(_buyAddr); + uint buyAmt = sub(finalBal, initalBal); + + require(_slippageAmt <= buyAmt, "Too much slippage"); + + setUint(setId, buyAmt); + emit LogSell(address(_buyAddr), address(_sellAddr), buyAmt, sellAmt, 0, setId); } } From 5181cffa041b9c5e822d6b61cfedb7a57cdb6fa2 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Sat, 9 May 2020 02:41:13 +0530 Subject: [PATCH 03/11] 1inch refactored --- contracts/connectors/1inch.sol | 142 +++------------------------------ 1 file changed, 13 insertions(+), 129 deletions(-) diff --git a/contracts/connectors/1inch.sol b/contracts/connectors/1inch.sol index 555e47d..8f91651 100644 --- a/contracts/connectors/1inch.sol +++ b/contracts/connectors/1inch.sol @@ -1,5 +1,10 @@ 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"; + interface OneInchInterace { function swap( TokenInterface fromToken, @@ -44,106 +49,16 @@ interface OneSplitInterface { } -interface TokenInterface { - function allowance(address, address) external view returns (uint); - function balanceOf(address) external view returns (uint); - function approve(address, uint) external; - function transfer(address, uint) external returns (bool); - function transferFrom(address, address, uint) external returns (bool); - function decimals() external view returns (uint); -} - -interface MemoryInterface { - function getUint(uint _id) external returns (uint _num); - function setUint(uint _id, uint _val) external; -} - -interface EventInterface { - function emitEvent(uint _connectorType, uint _connectorID, bytes32 _eventCode, bytes calldata _eventData) external; -} - -contract DSMath { - - function add(uint x, uint y) internal pure returns (uint z) { - require((z = x + y) >= x, "math-not-safe"); - } - - function mul(uint x, uint y) internal pure returns (uint z) { - require(y == 0 || (z = x * y) / y == x, "math-not-safe"); - } - - function sub(uint x, uint y) internal pure returns (uint z) { - require((z = x - y) <= x, "sub-overflow"); - } - - uint constant WAD = 10 ** 18; - - function wmul(uint x, uint y) internal pure returns (uint z) { - z = add(mul(x, y), WAD / 2) / WAD; - } - - function wdiv(uint x, uint y) internal pure returns (uint z) { - z = add(mul(x, WAD), y / 2) / y; - } - -} - - -contract Helpers is DSMath { +contract OneHelpers is Stores, DSMath { /** - * @dev Return ethereum address - */ - function getAddressETH() internal pure returns (address) { - return 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // ETH Address - } - - /** - * @dev Return Memory Variable Address - */ - function getMemoryAddr() internal pure returns (address) { - return 0x8a5419CfC711B2343c17a6ABf4B2bAFaBb06957F; // InstaMemory Address - } - - /** - * @dev Return InstaEvent Address. - */ - function getEventAddr() internal pure returns (address) { - return 0x2af7ea6Cb911035f3eb1ED895Cb6692C39ecbA97; // InstaEvent Address - } - - /** - * @dev Get Uint value from InstaMemory Contract. - */ - function getUint(uint getId, uint val) internal returns (uint returnVal) { - returnVal = getId == 0 ? val : MemoryInterface(getMemoryAddr()).getUint(getId); - } - - /** - * @dev Set Uint value in InstaMemory Contract. - */ - function setUint(uint setId, uint val) internal { - if (setId != 0) MemoryInterface(getMemoryAddr()).setUint(setId, val); - } - - /** - * @dev Connector Details - */ - function connectorID() public pure returns(uint _type, uint _id) { - (_type, _id) = (1, 0); - } -} - - -contract OneHelpers is Helpers { - /** - * @dev Return 1 Inch Address + * @dev Return 1Inch Address */ function getOneInchAddress() internal pure returns (address) { return 0x11111254369792b2Ca5d084aB5eEA397cA8fa48B; } /** - * @dev Return 1 Split Address + * @dev Return 1Split Address */ function getOneSplitAddress() internal pure returns (address) { return 0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E; @@ -158,34 +73,12 @@ contract OneHelpers is Helpers { } function getTokenBal(TokenInterface token) internal view returns(uint _amt) { - _amt = address(token) == getAddressETH() ? address(this).balance : token.balanceOf(address(this)); - } - - function convertDiv(uint xDec, uint yDec, uint x, uint y) internal pure returns(uint z) { - z = wdiv(convertTo18(xDec, x), convertTo18(yDec, y)); + _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) == getAddressETH() ? 18 : buyAddr.decimals(); - sellDec = address(sellAddr) == getAddressETH() ? 18 : sellAddr.decimals(); - } - - function decodeData( - bytes memory data - ) - internal pure returns ( - address buyAddr, - address sellAddr, - uint256 fromTokenAmount - ) - { - bytes memory _data = data; - // solium-disable-next-line security/no-inline-assembly - assembly { - sellAddr := mload(add(_data, 36)) - buyAddr := mload(add(_data, 68)) - fromTokenAmount := mload(add(_data, 100)) - } + buyDec = address(buyAddr) == getEthAddr() ? 18 : buyAddr.decimals(); + sellDec = address(sellAddr) == getEthAddr() ? 18 : sellAddr.decimals(); } } @@ -205,7 +98,7 @@ contract Resolver is OneHelpers { uint _slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18)); uint ethAmt; - if (address(_sellAddr) == getAddressETH()) { + if (address(_sellAddr) == getEthAddr()) { ethAmt = _sellAmt; } else { _sellAddr.approve(address(oneSplitContract), _sellAmt); @@ -227,18 +120,9 @@ contract Resolver is OneHelpers { require(_slippageAmt <= buyAmt, "Too much slippage"); } - } contract BasicResolver is Resolver { - event LogSellOneInch( - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - uint256 setId - ); - event LogSell( address indexed buyToken, address indexed sellToken, @@ -335,7 +219,7 @@ contract BasicResolver is Resolver { uint _slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18)); uint ethAmt; - if (address(_sellAddr) == getAddressETH()) { + if (address(_sellAddr) == getEthAddr()) { ethAmt = sellAmt; } else { TokenInterface(_sellAddr).approve(getOneInchAddress(), sellAmt); From 2c76a8ae27696dad8fc537f60d00796d4f5113ff Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Sat, 9 May 2020 02:41:47 +0530 Subject: [PATCH 04/11] Added events --- contracts/connectors/1inch.sol | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/contracts/connectors/1inch.sol b/contracts/connectors/1inch.sol index 8f91651..373c4f9 100644 --- a/contracts/connectors/1inch.sol +++ b/contracts/connectors/1inch.sol @@ -169,7 +169,9 @@ contract BasicResolver is Resolver { setUint(setId, _buyAmt); emit LogSell(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); - + bytes32 _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)"); + bytes memory _eventParam = abi.encode(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); + emitEvent(_eventCode, _eventParam); } function sell( @@ -201,6 +203,9 @@ contract BasicResolver is Resolver { setUint(setId, _buyAmt); emit LogSell(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); + bytes32 _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)"); + bytes memory _eventParam = abi.encode(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); + emitEvent(_eventCode, _eventParam); } function sell( @@ -236,6 +241,9 @@ contract BasicResolver is Resolver { setUint(setId, buyAmt); emit LogSell(address(_buyAddr), address(_sellAddr), buyAmt, sellAmt, 0, setId); + bytes32 _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)"); + bytes memory _eventParam = abi.encode(address(_buyAddr), address(_sellAddr), buyAmt, sellAmt, 0, setId); + emitEvent(_eventCode, _eventParam); } } From 466ce9b1e40c1c27c76c9e5e64a7b48e1f06b168 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Sat, 9 May 2020 02:41:56 +0530 Subject: [PATCH 05/11] fixed .call bug --- contracts/connectors/1inch.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/connectors/1inch.sol b/contracts/connectors/1inch.sol index 373c4f9..9cc64b5 100644 --- a/contracts/connectors/1inch.sol +++ b/contracts/connectors/1inch.sol @@ -232,7 +232,9 @@ contract BasicResolver is Resolver { uint initalBal = getTokenBal(_buyAddr); - address(getOneInchAddress()).call.value(ethAmt)(callData); + // solium-disable-next-line security/no-call-value + (bool success, ) = address(getOneInchAddress()).call.value(ethAmt)(callData); + if (!success) revert("1Inch-swap-failed"); uint finalBal = getTokenBal(_buyAddr); uint buyAmt = sub(finalBal, initalBal); From 72bbcfa8a3a95a7bfe623958c0554805f6ee3c53 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Sat, 9 May 2020 06:10:44 +0530 Subject: [PATCH 06/11] Fixed stack too deep Error --- contracts/connectors/1inch.sol | 40 +++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/contracts/connectors/1inch.sol b/contracts/connectors/1inch.sol index 9cc64b5..a9f61d6 100644 --- a/contracts/connectors/1inch.sol +++ b/contracts/connectors/1inch.sol @@ -120,6 +120,29 @@ contract Resolver is OneHelpers { require(_slippageAmt <= buyAmt, "Too much slippage"); } + + function oneInchSwap( + TokenInterface _buyAddr, + TokenInterface _sellAddr, + bytes memory callData, + uint sellAmt, + uint unitAmt, + 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); + + // solium-disable-next-line security/no-call-value + (bool success, ) = address(getOneInchAddress()).call.value(ethAmt)(callData); + if (!success) revert("1Inch-swap-failed"); + + uint finalBal = getTokenBal(_buyAddr); + buyAmt = sub(finalBal, initalBal); + + require(_slippageAmt <= buyAmt, "Too much slippage"); + } } contract BasicResolver is Resolver { @@ -219,10 +242,6 @@ contract BasicResolver is Resolver { TokenInterface _buyAddr = TokenInterface(buyAddr); TokenInterface _sellAddr = TokenInterface(sellAddr); - (uint _buyDec, uint _sellDec) = getTokensDec(_buyAddr, _sellAddr); - uint _sellAmt18 = convertTo18(_sellDec, sellAmt); - uint _slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18)); - uint ethAmt; if (address(_sellAddr) == getEthAddr()) { ethAmt = sellAmt; @@ -230,17 +249,8 @@ contract BasicResolver is Resolver { TokenInterface(_sellAddr).approve(getOneInchAddress(), sellAmt); } - uint initalBal = getTokenBal(_buyAddr); - - // solium-disable-next-line security/no-call-value - (bool success, ) = address(getOneInchAddress()).call.value(ethAmt)(callData); - if (!success) revert("1Inch-swap-failed"); - - uint finalBal = getTokenBal(_buyAddr); - uint buyAmt = sub(finalBal, initalBal); - - require(_slippageAmt <= buyAmt, "Too much slippage"); - + uint buyAmt = oneInchSwap(_buyAddr, _sellAddr, callData, sellAmt, unitAmt, sellAmt); + setUint(setId, buyAmt); emit LogSell(address(_buyAddr), address(_sellAddr), buyAmt, sellAmt, 0, setId); bytes32 _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)"); From aca6cad4d423722255589b02372f2a28728e56b0 Mon Sep 17 00:00:00 2001 From: Samyak Jain <34437877+KaymasJain@users.noreply.github.com> Date: Sat, 9 May 2020 17:26:03 +1000 Subject: [PATCH 07/11] 1inch connector method name edit --- contracts/connectors/1inch.sol | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/contracts/connectors/1inch.sol b/contracts/connectors/1inch.sol index a9f61d6..a3cb093 100644 --- a/contracts/connectors/1inch.sol +++ b/contracts/connectors/1inch.sol @@ -155,6 +155,24 @@ contract BasicResolver is Resolver { uint256 setId ); + event LogSellTwo( + 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 + ); + function sell( address buyAddr, address sellAddr, @@ -197,7 +215,7 @@ contract BasicResolver is Resolver { emitEvent(_eventCode, _eventParam); } - function sell( + function sellTwo( address buyAddr, address sellAddr, uint sellAmt, @@ -225,13 +243,13 @@ contract BasicResolver is Resolver { ); setUint(setId, _buyAmt); - emit LogSell(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); - bytes32 _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)"); + emit LogSellTwo(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); + bytes32 _eventCode = keccak256("LogSellTwo(address,address,uint256,uint256,uint256,uint256)"); bytes memory _eventParam = abi.encode(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); emitEvent(_eventCode, _eventParam); } - function sell( + function sellThree( address buyAddr, address sellAddr, uint sellAmt, @@ -250,10 +268,10 @@ contract BasicResolver is Resolver { } uint buyAmt = oneInchSwap(_buyAddr, _sellAddr, callData, sellAmt, unitAmt, sellAmt); - + setUint(setId, buyAmt); - emit LogSell(address(_buyAddr), address(_sellAddr), buyAmt, sellAmt, 0, setId); - bytes32 _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)"); + 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); } From 05eacbce94a903627edd78abe28a55e189af378e Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Sun, 10 May 2020 01:58:08 +0530 Subject: [PATCH 08/11] Added 1inch swap function sig check --- contracts/connectors/1inch.sol | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/contracts/connectors/1inch.sol b/contracts/connectors/1inch.sol index a3cb093..e07b19b 100644 --- a/contracts/connectors/1inch.sol +++ b/contracts/connectors/1inch.sol @@ -64,6 +64,13 @@ contract OneHelpers is Stores, DSMath { return 0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E; } + /** + * @dev Return 1Split swap function sig + */ + function getOneSplitSig() internal pure returns (bytes4) { + return 0xf88309d7; + } + function convert18ToDec(uint _dec, uint256 _amt) internal pure returns (uint256 amt) { amt = (_amt / 10 ** (18 - _dec)); } @@ -84,6 +91,16 @@ contract OneHelpers is Stores, DSMath { contract Resolver is OneHelpers { + function checkOneInchSig(bytes memory callData) internal pure returns(bool isOk) { + bytes memory _data = callData; + bytes4 sig; + // solium-disable-next-line security/no-inline-assembly + assembly { + sig := mload(add(_data, 32)) + } + isOk = sig == getOneSplitSig(); + } + function oneSplitSwap( OneSplitInterface oneSplitContract, TokenInterface _sellAddr, @@ -180,7 +197,7 @@ contract BasicResolver is Resolver { uint unitAmt, uint getId, uint setId - ) public payable { + ) external payable { uint _sellAmt = getUint(getId, sellAmt); TokenInterface _buyAddr = TokenInterface(buyAddr); @@ -195,7 +212,7 @@ contract BasicResolver is Resolver { _buyAddr, _sellAmt, 3, // TODO - shall we hardcode? - 0 // TODO - do we need to disable anything? + 0 ); uint _buyAmt = oneSplitSwap( @@ -209,6 +226,7 @@ contract BasicResolver is Resolver { ); setUint(setId, _buyAmt); + emit LogSell(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); bytes32 _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)"); bytes memory _eventParam = abi.encode(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); @@ -243,6 +261,7 @@ contract BasicResolver is Resolver { ); setUint(setId, _buyAmt); + emit LogSellTwo(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); bytes32 _eventCode = keccak256("LogSellTwo(address,address,uint256,uint256,uint256,uint256)"); bytes memory _eventParam = abi.encode(address(_buyAddr), address(_sellAddr), _buyAmt, _sellAmt, getId, setId); @@ -267,9 +286,12 @@ contract BasicResolver is Resolver { TokenInterface(_sellAddr).approve(getOneInchAddress(), sellAmt); } + require(checkOneInchSig(callData), "Not-swap-function"); + uint buyAmt = oneInchSwap(_buyAddr, _sellAddr, callData, sellAmt, unitAmt, sellAmt); 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); From cab6225016d0ee3fe15b4f38562d282726e474ae Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Mon, 11 May 2020 03:23:23 +0530 Subject: [PATCH 09/11] fixed a bug --- contracts/connectors/1inch.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/connectors/1inch.sol b/contracts/connectors/1inch.sol index e07b19b..54cb907 100644 --- a/contracts/connectors/1inch.sol +++ b/contracts/connectors/1inch.sol @@ -60,7 +60,7 @@ contract OneHelpers is Stores, DSMath { /** * @dev Return 1Split Address */ - function getOneSplitAddress() internal pure returns (address) { + function getOneSplitAddress() internal pure returns (address payable) { return 0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E; } @@ -288,7 +288,7 @@ contract BasicResolver is Resolver { require(checkOneInchSig(callData), "Not-swap-function"); - uint buyAmt = oneInchSwap(_buyAddr, _sellAddr, callData, sellAmt, unitAmt, sellAmt); + uint buyAmt = oneInchSwap(_buyAddr, _sellAddr, callData, sellAmt, unitAmt, ethAmt); setUint(setId, buyAmt); From dac5a7b1f5f1341c8d7ec28bcd8ad8c33ee63562 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Mon, 11 May 2020 03:23:56 +0530 Subject: [PATCH 10/11] Added token taker address --- contracts/connectors/1inch.sol | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/contracts/connectors/1inch.sol b/contracts/connectors/1inch.sol index 54cb907..afe030b 100644 --- a/contracts/connectors/1inch.sol +++ b/contracts/connectors/1inch.sol @@ -64,6 +64,13 @@ contract OneHelpers is Stores, DSMath { return 0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E; } + /** + * @dev Return 1Split Token Taker Address + */ + function getOneSplitTokenTaker() internal pure returns (address payable) { + return 0xE4C9194962532fEB467DCe8b3d42419641c6eD2E; + } + /** * @dev Return 1Split swap function sig */ @@ -283,7 +290,7 @@ contract BasicResolver is Resolver { if (address(_sellAddr) == getEthAddr()) { ethAmt = sellAmt; } else { - TokenInterface(_sellAddr).approve(getOneInchAddress(), sellAmt); + TokenInterface(_sellAddr).approve(getOneSplitTokenTaker(), sellAmt); } require(checkOneInchSig(callData), "Not-swap-function"); From f8b1c04388eafca8b980f24bf9751a2cf15bc093 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Mon, 11 May 2020 05:48:40 +0530 Subject: [PATCH 11/11] Added comments in 1inch --- contracts/connectors/1inch.sol | 35 +++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/contracts/connectors/1inch.sol b/contracts/connectors/1inch.sol index afe030b..ecb6142 100644 --- a/contracts/connectors/1inch.sol +++ b/contracts/connectors/1inch.sol @@ -29,8 +29,8 @@ interface OneSplitInterface { TokenInterface toToken, uint256 amount, uint256 minReturn, - uint256[] calldata distribution, // [Uniswap, Kyber, Bancor, Oasis] - uint256 disableFlags // 16 - Compound, 32 - Fulcrum, 64 - Chai, 128 - Aave, 256 - SmartToken, 1024 - bDAI + uint256[] calldata distribution, + uint256 disableFlags ) external payable; function getExpectedReturn( @@ -197,6 +197,15 @@ contract BasicResolver is Resolver { 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 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, @@ -218,7 +227,7 @@ contract BasicResolver is Resolver { _sellAddr, _buyAddr, _sellAmt, - 3, // TODO - shall we hardcode? + 5, 0 ); @@ -240,6 +249,17 @@ contract BasicResolver is Resolver { emitEvent(_eventCode, _eventParam); } + /** + * @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 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, @@ -275,6 +295,15 @@ contract BasicResolver is Resolver { emitEvent(_eventCode, _eventParam); } + /** + * @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,