1
+ /*
2
+ Copyright 2021 Set Labs Inc.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+
16
+ SPDX-License-Identifier: Apache License, Version 2.0
17
+ */
18
+
19
+ pragma solidity 0.6.10 ;
20
+ pragma experimental "ABIEncoderV2 " ;
21
+
22
+ import { BytesLib } from "external/contracts/uniswap/v3/lib/BytesLib.sol " ;
23
+ import { IDMMFactory } from "../../../interfaces/external/IDMMFactory.sol " ;
24
+ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol " ;
25
+ import { IIndexExchangeAdapter } from "../../../interfaces/IIndexExchangeAdapter.sol " ;
26
+
27
+ /**
28
+ * @title KyberV3IndexExchangeAdapter
29
+ * @author Set Protocol
30
+ *
31
+ * A Kyber V3 DMM exchange adapter that returns calldata for trading with GeneralIndexModule, allows encoding a trade with a fixed input quantity or
32
+ * a fixed output quantity.
33
+ */
34
+ contract KyberV3IndexExchangeAdapter is IIndexExchangeAdapter {
35
+
36
+ using BytesLib for bytes ;
37
+
38
+ /* ============ Constants ============ */
39
+
40
+ // DMMRouter function string for swapping exact tokens for a minimum of receive tokens
41
+ string internal constant SWAP_EXACT_TOKENS_FOR_TOKENS = "swapExactTokensForTokens(uint256,uint256,address[],address[],address,uint256) " ;
42
+ // DMMRouter function string for swapping tokens for an exact amount of receive tokens
43
+ string internal constant SWAP_TOKENS_FOR_EXACT_TOKENS = "swapTokensForExactTokens(uint256,uint256,address[],address[],address,uint256) " ;
44
+
45
+ /* ============ State Variables ============ */
46
+
47
+ address public immutable dmmRouter;
48
+ IDMMFactory public immutable dmmFactory;
49
+
50
+ /* ============ Constructor ============ */
51
+
52
+ /**
53
+ * Set state variables
54
+ *
55
+ * @param _dmmRouter Address of Kyber V3 DMM Router
56
+ * @param _dmmFactory Address of Kyber V3 DMM Factory
57
+ */
58
+ constructor (address _dmmRouter , IDMMFactory _dmmFactory ) public {
59
+ dmmRouter = _dmmRouter;
60
+ dmmFactory = _dmmFactory;
61
+ }
62
+
63
+ /* ============ External Getter Functions ============ */
64
+
65
+ /**
66
+ * Return calldata for trading with Kyber V3 DMM Router. Trade paths are created from _sourceToken and
67
+ * _destinationToken. On Kyber DMM exchange, for each token pair, there can be possibly many multiple pools with
68
+ * different configurations for the pricing curve. Hence the address of the pool to be used for trading must be passed
69
+ * in the _data parameter.
70
+ *
71
+ * ---------------------------------------------------------------------------------------------------------------
72
+ * _isSendTokenFixed | Parameter | Amount |
73
+ * ---------------------------------------------------------------------------------------------------------------
74
+ * True | _sourceQuantity | Fixed amount of _sourceToken to trade |
75
+ * | _destinationQuantity | Minimum amount of _destinationToken willing to receive |
76
+ * ---------------------------------------------------------------------------------------------------------------
77
+ * False | _sourceQuantity | Maximum amount of _sourceToken to trade |
78
+ * | _destinationQuantity | Fixed amount of _destinationToken want to receive |
79
+ * ---------------------------------------------------------------------------------------------------------------
80
+ *
81
+ * @param _sourceToken Address of source token to be sold
82
+ * @param _destinationToken Address of destination token to buy
83
+ * @param _destinationAddress Address that assets should be transferred to
84
+ * @param _isSendTokenFixed Boolean indicating if the send quantity is fixed, used to determine correct trade interface
85
+ * @param _sourceQuantity Fixed/Max amount of source token to sell
86
+ * @param _destinationQuantity Min/Fixed amount of destination token to buy
87
+ * @param _data Arbitray bytes containing the pool address to be used for trading. Can use
88
+ * `getPoolWithBestLiquidity()` to get the most liquid pool for a given pair of tokens
89
+ * on the Kyber DMM exchange.
90
+ *
91
+ * @return address Target contract address
92
+ * @return uint256 Call value
93
+ * @return bytes Trade calldata
94
+ */
95
+ function getTradeCalldata (
96
+ address _sourceToken ,
97
+ address _destinationToken ,
98
+ address _destinationAddress ,
99
+ bool _isSendTokenFixed ,
100
+ uint256 _sourceQuantity ,
101
+ uint256 _destinationQuantity ,
102
+ bytes memory _data
103
+ )
104
+ external
105
+ view
106
+ override
107
+ returns (address , uint256 , bytes memory )
108
+ {
109
+
110
+ address [] memory path = new address [](2 );
111
+ path[0 ] = _sourceToken;
112
+ path[1 ] = _destinationToken;
113
+
114
+ address [] memory poolsPath = new address [](1 );
115
+ poolsPath[0 ] = _data.toAddress (0 );
116
+
117
+ require (dmmFactory.isPool (IERC20 (_sourceToken), IERC20 (_destinationToken), poolsPath[0 ]), "Invalid pool address " );
118
+
119
+ bytes memory callData = abi.encodeWithSignature (
120
+ _isSendTokenFixed ? SWAP_EXACT_TOKENS_FOR_TOKENS : SWAP_TOKENS_FOR_EXACT_TOKENS,
121
+ _isSendTokenFixed ? _sourceQuantity : _destinationQuantity,
122
+ _isSendTokenFixed ? _destinationQuantity : _sourceQuantity,
123
+ poolsPath,
124
+ path,
125
+ _destinationAddress,
126
+ block .timestamp
127
+ );
128
+ return (dmmRouter, 0 , callData);
129
+ }
130
+
131
+ /**
132
+ * Returns the address to approve source tokens to for trading. This is the Kyber DMM Router.
133
+ *
134
+ * @return address Address of the contract to approve tokens to
135
+ */
136
+ function getSpender () external view override returns (address ) {
137
+ return dmmRouter;
138
+ }
139
+ }
0 commit comments