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 { ISwapRouter } from "contracts/interfaces/external/ISwapRouter.sol " ;
23+ import { BytesLib } from "external/contracts/uniswap/v3/lib/BytesLib.sol " ;
24+
25+ import { IIndexExchangeAdapter } from "../../../interfaces/IIndexExchangeAdapter.sol " ;
26+
27+ /**
28+ * @title UniswapV3IndexExchangeAdapter
29+ * @author Set Protocol
30+ *
31+ * A Uniswap V3 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 UniswapV3IndexExchangeAdapter is IIndexExchangeAdapter {
35+
36+ using BytesLib for bytes ;
37+
38+ /* ============ Constants ============ */
39+
40+ // Uniswap router function string for swapping exact amount of input tokens for a minimum of output tokens
41+ string internal constant SWAP_EXACT_INPUT = "exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160)) " ;
42+ // Uniswap router function string for swapping max amoutn of input tokens for an exact amount of output tokens
43+ string internal constant SWAP_EXACT_OUTPUT = "exactOutputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160)) " ;
44+
45+ /* ============ State Variables ============ */
46+
47+ // Address of Uniswap V3 SwapRouter contract
48+ address public immutable router;
49+
50+ /* ============ Constructor ============ */
51+
52+ /**
53+ * Set state variables
54+ *
55+ * @param _router Address of Uniswap V3 SwapRouter contract
56+ */
57+ constructor (address _router ) public {
58+ router = _router;
59+ }
60+
61+ /* ============ External Getter Functions ============ */
62+
63+ /**
64+ * Return calldata for trading with Uniswap V3 SwapRouter. Trade paths are created from _sourceToken,
65+ * _destinationToken and pool fees (which is encoded in _data).
66+ *
67+ * ---------------------------------------------------------------------------------------------------------------
68+ * _isSendTokenFixed | Parameter | Amount |
69+ * ---------------------------------------------------------------------------------------------------------------
70+ * True | _sourceQuantity | Fixed amount of _sourceToken to trade |
71+ * | _destinationQuantity | Minimum amount of _destinationToken willing to receive |
72+ * ---------------------------------------------------------------------------------------------------------------
73+ * False | _sourceQuantity | Maximum amount of _sourceToken to trade |
74+ * | _destinationQuantity | Fixed amount of _destinationToken want to receive |
75+ * ---------------------------------------------------------------------------------------------------------------
76+ *
77+ * @param _sourceToken Address of source token to be sold
78+ * @param _destinationToken Address of destination token to buy
79+ * @param _destinationAddress Address that assets should be transferred to
80+ * @param _isSendTokenFixed Boolean indicating if the send quantity is fixed, used to determine correct trade interface
81+ * @param _sourceQuantity Fixed/Max amount of source token to sell
82+ * @param _destinationQuantity Min/Fixed amount of destination token to buy
83+ * @param _data Arbitrary bytes containing fees value, expressed in hundredths of a bip,
84+ * used to determine the pool to trade among similar asset pools on Uniswap V3.
85+ * Note: SetToken manager must set the appropriate pool fees via `setExchangeData` in GeneralIndexModule
86+ * for each component that needs to be traded on UniswapV3. This is different from UniswapV3ExchangeAdapter,
87+ * where `_data` represents UniswapV3 trade path vs just the pool fees percentage.
88+ *
89+ * @return address Target contract address
90+ * @return uint256 Call value
91+ * @return bytes Trade calldata
92+ */
93+ function getTradeCalldata (
94+ address _sourceToken ,
95+ address _destinationToken ,
96+ address _destinationAddress ,
97+ bool _isSendTokenFixed ,
98+ uint256 _sourceQuantity ,
99+ uint256 _destinationQuantity ,
100+ bytes memory _data
101+ )
102+ external
103+ view
104+ override
105+ returns (address , uint256 , bytes memory )
106+ {
107+ uint24 fee = _data.toUint24 (0 );
108+
109+ bytes memory callData = _isSendTokenFixed
110+ ? abi.encodeWithSignature (
111+ SWAP_EXACT_INPUT,
112+ ISwapRouter.ExactInputSingleParams (
113+ _sourceToken,
114+ _destinationToken,
115+ fee,
116+ _destinationAddress,
117+ block .timestamp ,
118+ _sourceQuantity,
119+ _destinationQuantity,
120+ 0
121+ )
122+ ) : abi.encodeWithSignature (
123+ SWAP_EXACT_OUTPUT,
124+ ISwapRouter.ExactOutputSingleParams (
125+ _sourceToken,
126+ _destinationToken,
127+ fee,
128+ _destinationAddress,
129+ block .timestamp ,
130+ _destinationQuantity,
131+ _sourceQuantity,
132+ 0
133+ )
134+ );
135+
136+ return (router, 0 , callData);
137+ }
138+
139+ /**
140+ * Returns the address to approve source tokens to for trading. This is the Uniswap V3 router address.
141+ *
142+ * @return address Address of the contract to approve tokens to
143+ */
144+ function getSpender () external view override returns (address ) {
145+ return router;
146+ }
147+
148+ /**
149+ * Helper that returns encoded fee value.
150+ *
151+ * @param fee UniswapV3 pool fee percentage, expressed in hundredths of a bip
152+ *
153+ * @return bytes Encoded fee value
154+ */
155+ function getEncodedFeeData (uint24 fee ) external view returns (bytes memory ) {
156+ return abi.encodePacked (fee);
157+ }
158+ }
0 commit comments