diff --git a/contracts/mainnet/connectors/automated_defi_limit_order/events.sol b/contracts/mainnet/connectors/automated_defi_limit_order/events.sol new file mode 100644 index 00000000..8c77f2c4 --- /dev/null +++ b/contracts/mainnet/connectors/automated_defi_limit_order/events.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogCreate(address _tokenFrom, address _tokenTo, uint256 _price, uint32 _route, bytes8 _pos); + event LogCancel(address _tokenFrom, address _tokenTo, bytes8 _orderId); + event LogCancelPublic(address _tokenFrom, address _tokenTo, bytes8 _orderId); + event LogSell( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); +} diff --git a/contracts/mainnet/connectors/automated_defi_limit_order/helpers.sol b/contracts/mainnet/connectors/automated_defi_limit_order/helpers.sol new file mode 100644 index 00000000..a56abc76 --- /dev/null +++ b/contracts/mainnet/connectors/automated_defi_limit_order/helpers.sol @@ -0,0 +1,14 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +import { DSMath } from "../../common/math.sol"; +import { Basic } from "../../common/basic.sol"; +import { ComptrollerInterface, COMPInterface, CompoundMappingInterface } from "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + /** + * @dev Compound Comptroller + */ + LimitOrderInterface internal constant limitOrderContract = LimitOrderInterface(address(0)); // TODO: add Limit Order contract's address + +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/automated_defi_limit_order/interface.sol b/contracts/mainnet/connectors/automated_defi_limit_order/interface.sol new file mode 100644 index 00000000..e2f3011e --- /dev/null +++ b/contracts/mainnet/connectors/automated_defi_limit_order/interface.sol @@ -0,0 +1,19 @@ +pragma solidity ^0.7.0; + + +interface LimitOrderInterface { + function create(address _tokenFrom, address _tokenTo, uint128 _price, uint32 _route, bytes8 _pos) external; + function create(address _tokenFrom, address _tokenTo, uint128 _price, uint32 _route) external; + function sell(address _tokenFrom, address _tokenTo, uint _amountFrom, bytes8 _orderId, address _to) external returns (uint _amountTo); + function sell( + address _tokenFrom, + address _tokenTo, + uint _amountFrom, + bytes8[] memory _orderIds, + uint[] memory _distributions, + uint _units, + address _to + ) external returns (uint _amountTo); + function cancel(address _tokenFrom, address _tokenTo, bytes8 _orderId) external; + function cancelPublic(address _tokenFrom, address _tokenTo, bytes8 _orderId) external; +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/automated_defi_limit_order/main.sol b/contracts/mainnet/connectors/automated_defi_limit_order/main.sol new file mode 100644 index 00000000..320e2e68 --- /dev/null +++ b/contracts/mainnet/connectors/automated_defi_limit_order/main.sol @@ -0,0 +1,137 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +/** + * @title COMP. + * @dev Claim COMP. + */ +import { TokenInterface } from "../../common/interfaces.sol"; +import { Stores } from "../../common/stores.sol"; +import { Helpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract CompResolver is Events, Helpers { + + function create( + address _tokenFrom, + address _tokenTo, + uint128 _price, + uint32 _route, + bytes8 _pos + ) external payable returns ( + string memory _eventName, + bytes memory _eventParam + ) { + if (_pos == bytes8(0)) { + limitOrderContract.create(_tokenFrom, _tokenTo, _price, _route); + } else { + limitOrderContract.create(_tokenFrom, _tokenTo, _price, _route, _pos); + } + + _eventName = "LogCreate(address,address,uint256,uint32,bytes8)"; + _eventParam = abi.encode(_tokenFrom, _tokenTo, _price, _route, _pos); + } + + function cancel( + address _tokenFrom, + address _tokenTo, + bytes8 _orderId + ) external payable returns ( + string memory _eventName, + bytes memory _eventParam + ) { + limitOrderContract.cancel(_tokenFrom, _tokenTo, _orderId); + + _eventName = "LogCancel(address,address,bytes8)"; + _eventParam = abi.encode(_tokenFrom, _tokenTo, _orderId); + } + + function cancelPublic( + address _tokenFrom, + address _tokenTo, + bytes8 _orderId + ) external payable returns ( + string memory _eventName, + bytes memory _eventParam + ) { + limitOrderContract.cancelPublic(_tokenFrom, _tokenTo, _orderId); + + _eventName = "LogCancelPublic(address,address,bytes8)"; + _eventParam = abi.encode(_tokenFrom, _tokenTo, _orderId); + } + + function _sellSlippageCheck( + TokenInterface buyToken, + TokenInterface sellToken, + uint sellAmt, + uint buyAmt, + uint unitAmt + ) internal { + TokenInterface buyToken = TokenInterface(buyAddr); + TokenInterface sellToken = TokenInterface(sellAddr); + (uint _buyDec, uint _sellDec) = getTokensDec(buyToken, sellToken); + uint _sellAmt18 = convertTo18(_sellDec, sellAmt); + uint _slippageAmt = convert18ToDec(_buyDec, wmul(unitAmt, _sellAmt18)); + + require(_slippageAmt <= buyAmt, "Too much slippage"); + } + + function sell( + address buyAddr, + address sellAddr, + uint sellAmt, + uint unitAmt, + bytes8 _orderId, + uint getId, + uint setId + ) external payable returns ( + string memory _eventName, + bytes memory _eventParam + ) { + uint buyAmt = limitOrderContract.sell(sellAddr, buyAddr, sellAmt, _orderId, address(this)); + + _sellSlippageCheck(TokenInterface(buyAddr), TokenInterface(sellAddr), sellAmt, buyAmt, unitAmt); + + _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(buyAddr, sellAddr, buyAmt, sellAmt, 0, setId); + } + + function sell( + address buyAddr, + address sellAddr, + uint sellAmt, + bytes8[] memory orderIds, + uint[] memory distributions, + uint units, + uint getId, + uint setId + ) external payable returns ( + string memory _eventName, + bytes memory _eventParam + ) { + uint buyAmt = limitOrderContract.sell(sellAddr, buyAddr, sellAmt, orderIds, distributions, units, address(this)); + + _sellSlippageCheck(TokenInterface(buyAddr), TokenInterface(sellAddr), sellAmt, buyAmt, unitAmt); + + _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(buyAddr, sellAddr, buyAmt, sellAmt, 0, setId); + } + + /** + * @dev Delegate votes. + * @notice Delegate votes. + * @param delegatee The address to delegate the votes to. + */ + function delegate(address delegatee) external payable returns (string memory _eventName, bytes memory _eventParam) { + require(compToken.delegates(address(this)) != delegatee, "Already delegated to same delegatee."); + + compToken.delegate(delegatee); + + _eventName = "LogDelegate(address)"; + _eventParam = abi.encode(delegatee); + } +} + +contract ConnectV2DefiLimitOrders is CompResolver { + string public constant name = "DeFi-Limit-Order-v1"; +}