1
+ /*
2
+ Copyright 2022 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 { ISetToken } from "@setprotocol/set-protocol-v2/contracts/interfaces/ISetToken.sol " ;
23
+ import { IWETH } from "@setprotocol/set-protocol-v2/contracts/interfaces/external/IWETH.sol " ;
24
+ import { IWrapModuleV2 } from "@setprotocol/set-protocol-v2/contracts/interfaces/IWrapModuleV2.sol " ;
25
+
26
+ import { BaseGlobalExtension } from "../lib/BaseGlobalExtension.sol " ;
27
+ import { IDelegatedManager } from "../interfaces/IDelegatedManager.sol " ;
28
+ import { IManagerCore } from "../interfaces/IManagerCore.sol " ;
29
+
30
+ /**
31
+ * @title WrapExtension
32
+ * @author Set Protocol
33
+ *
34
+ * Smart contract global extension which provides DelegatedManager operator(s) the ability to wrap ERC20 and Ether positions
35
+ * via third party protocols.
36
+ *
37
+ * Some examples of wrap actions include wrapping, DAI to cDAI (Compound) or Dai to aDai (AAVE).
38
+ */
39
+ contract WrapExtension is BaseGlobalExtension {
40
+
41
+ /* ============ Events ============ */
42
+
43
+ event WrapExtensionInitialized (
44
+ address indexed _setToken ,
45
+ address indexed _delegatedManager
46
+ );
47
+
48
+ /* ============ State Variables ============ */
49
+
50
+ // Instance of WrapModuleV2
51
+ IWrapModuleV2 public immutable wrapModule;
52
+
53
+ /* ============ Constructor ============ */
54
+
55
+ /**
56
+ * Instantiate with ManagerCore address and WrapModuleV2 address.
57
+ *
58
+ * @param _managerCore Address of ManagerCore contract
59
+ * @param _wrapModule Address of WrapModuleV2 contract
60
+ */
61
+ constructor (
62
+ IManagerCore _managerCore ,
63
+ IWrapModuleV2 _wrapModule
64
+ )
65
+ public
66
+ BaseGlobalExtension (_managerCore)
67
+ {
68
+ wrapModule = _wrapModule;
69
+ }
70
+
71
+ /* ============ External Functions ============ */
72
+
73
+ /**
74
+ * ONLY OWNER: Initializes WrapModuleV2 on the SetToken associated with the DelegatedManager.
75
+ *
76
+ * @param _delegatedManager Instance of the DelegatedManager to initialize the WrapModuleV2 for
77
+ */
78
+ function initializeModule (IDelegatedManager _delegatedManager ) external onlyOwnerAndValidManager (_delegatedManager) {
79
+ _initializeModule (_delegatedManager.setToken (), _delegatedManager);
80
+ }
81
+
82
+ /**
83
+ * ONLY OWNER: Initializes WrapExtension to the DelegatedManager.
84
+ *
85
+ * @param _delegatedManager Instance of the DelegatedManager to initialize
86
+ */
87
+ function initializeExtension (IDelegatedManager _delegatedManager ) external onlyOwnerAndValidManager (_delegatedManager) {
88
+ ISetToken setToken = _delegatedManager.setToken ();
89
+
90
+ _initializeExtension (setToken, _delegatedManager);
91
+
92
+ emit WrapExtensionInitialized (address (setToken), address (_delegatedManager));
93
+ }
94
+
95
+ /**
96
+ * ONLY OWNER: Initializes WrapExtension to the DelegatedManager and TradeModule to the SetToken
97
+ *
98
+ * @param _delegatedManager Instance of the DelegatedManager to initialize
99
+ */
100
+ function initializeModuleAndExtension (IDelegatedManager _delegatedManager ) external onlyOwnerAndValidManager (_delegatedManager){
101
+ ISetToken setToken = _delegatedManager.setToken ();
102
+
103
+ _initializeExtension (setToken, _delegatedManager);
104
+ _initializeModule (setToken, _delegatedManager);
105
+
106
+ emit WrapExtensionInitialized (address (setToken), address (_delegatedManager));
107
+ }
108
+
109
+ /**
110
+ * ONLY MANAGER: Remove an existing SetToken and DelegatedManager tracked by the WrapExtension
111
+ */
112
+ function removeExtension () external override {
113
+ IDelegatedManager delegatedManager = IDelegatedManager (msg .sender );
114
+ ISetToken setToken = delegatedManager.setToken ();
115
+
116
+ _removeExtension (setToken, delegatedManager);
117
+ }
118
+
119
+ /**
120
+ * ONLY OPERATOR: Instructs the SetToken to wrap an underlying asset into a wrappedToken via a specified adapter.
121
+ *
122
+ * @param _setToken Instance of the SetToken
123
+ * @param _underlyingToken Address of the component to be wrapped
124
+ * @param _wrappedToken Address of the desired wrapped token
125
+ * @param _underlyingUnits Quantity of underlying units in Position units
126
+ * @param _integrationName Name of wrap module integration (mapping on integration registry)
127
+ * @param _wrapData Arbitrary bytes to pass into the WrapV2Adapter
128
+ */
129
+ function wrap (
130
+ ISetToken _setToken ,
131
+ address _underlyingToken ,
132
+ address _wrappedToken ,
133
+ uint256 _underlyingUnits ,
134
+ string calldata _integrationName ,
135
+ bytes memory _wrapData
136
+ )
137
+ external
138
+ onlyOperator (_setToken)
139
+ onlyAllowedAsset (_setToken, _wrappedToken)
140
+ {
141
+ bytes memory callData = abi.encodeWithSelector (
142
+ IWrapModuleV2.wrap.selector ,
143
+ _setToken,
144
+ _underlyingToken,
145
+ _wrappedToken,
146
+ _underlyingUnits,
147
+ _integrationName,
148
+ _wrapData
149
+ );
150
+ _invokeManager (_manager (_setToken), address (wrapModule), callData);
151
+ }
152
+
153
+ /**
154
+ * ONLY OPERATOR: Instructs the SetToken to wrap Ether into a wrappedToken via a specified adapter. Since SetTokens
155
+ * only hold WETH, in order to support protocols that collateralize with Ether the SetToken's WETH must be unwrapped
156
+ * first before sending to the external protocol.
157
+ *
158
+ * @param _setToken Instance of the SetToken
159
+ * @param _wrappedToken Address of the desired wrapped token
160
+ * @param _underlyingUnits Quantity of underlying units in Position units
161
+ * @param _integrationName Name of wrap module integration (mapping on integration registry)
162
+ * @param _wrapData Arbitrary bytes to pass into the WrapV2Adapter
163
+ */
164
+ function wrapWithEther (
165
+ ISetToken _setToken ,
166
+ address _wrappedToken ,
167
+ uint256 _underlyingUnits ,
168
+ string calldata _integrationName ,
169
+ bytes memory _wrapData
170
+ )
171
+ external
172
+ onlyOperator (_setToken)
173
+ onlyAllowedAsset (_setToken, _wrappedToken)
174
+ {
175
+ bytes memory callData = abi.encodeWithSelector (
176
+ IWrapModuleV2.wrapWithEther.selector ,
177
+ _setToken,
178
+ _wrappedToken,
179
+ _underlyingUnits,
180
+ _integrationName,
181
+ _wrapData
182
+ );
183
+ _invokeManager (_manager (_setToken), address (wrapModule), callData);
184
+ }
185
+
186
+ /**
187
+ * ONLY OPERATOR: Instructs the SetToken to unwrap a wrapped asset into its underlying via a specified adapter.
188
+ *
189
+ * @param _setToken Instance of the SetToken
190
+ * @param _underlyingToken Address of the underlying asset
191
+ * @param _wrappedToken Address of the component to be unwrapped
192
+ * @param _wrappedUnits Quantity of wrapped tokens in Position units
193
+ * @param _integrationName ID of wrap module integration (mapping on integration registry)
194
+ * @param _unwrapData Arbitrary bytes to pass into the WrapV2Adapter
195
+ */
196
+ function unwrap (
197
+ ISetToken _setToken ,
198
+ address _underlyingToken ,
199
+ address _wrappedToken ,
200
+ uint256 _wrappedUnits ,
201
+ string calldata _integrationName ,
202
+ bytes memory _unwrapData
203
+ )
204
+ external
205
+ onlyOperator (_setToken)
206
+ onlyAllowedAsset (_setToken, _underlyingToken)
207
+ {
208
+ bytes memory callData = abi.encodeWithSelector (
209
+ IWrapModuleV2.unwrap.selector ,
210
+ _setToken,
211
+ _underlyingToken,
212
+ _wrappedToken,
213
+ _wrappedUnits,
214
+ _integrationName,
215
+ _unwrapData
216
+ );
217
+ _invokeManager (_manager (_setToken), address (wrapModule), callData);
218
+ }
219
+
220
+ /**
221
+ * ONLY OPERATOR: Instructs the SetToken to unwrap a wrapped asset collateralized by Ether into Wrapped Ether. Since
222
+ * external protocol will send back Ether that Ether must be Wrapped into WETH in order to be accounted for by SetToken.
223
+ *
224
+ * @param _setToken Instance of the SetToken
225
+ * @param _wrappedToken Address of the component to be unwrapped
226
+ * @param _wrappedUnits Quantity of wrapped tokens in Position units
227
+ * @param _integrationName ID of wrap module integration (mapping on integration registry)
228
+ * @param _unwrapData Arbitrary bytes to pass into the WrapV2Adapter
229
+ */
230
+ function unwrapWithEther (
231
+ ISetToken _setToken ,
232
+ address _wrappedToken ,
233
+ uint256 _wrappedUnits ,
234
+ string calldata _integrationName ,
235
+ bytes memory _unwrapData
236
+ )
237
+ external
238
+ onlyOperator (_setToken)
239
+ onlyAllowedAsset (_setToken, address (wrapModule.weth ()))
240
+ {
241
+ bytes memory callData = abi.encodeWithSelector (
242
+ IWrapModuleV2.unwrapWithEther.selector ,
243
+ _setToken,
244
+ _wrappedToken,
245
+ _wrappedUnits,
246
+ _integrationName,
247
+ _unwrapData
248
+ );
249
+ _invokeManager (_manager (_setToken), address (wrapModule), callData);
250
+ }
251
+
252
+ /* ============ Internal Functions ============ */
253
+
254
+ /**
255
+ * Internal function to initialize WrapModuleV2 on the SetToken associated with the DelegatedManager.
256
+ *
257
+ * @param _setToken Instance of the SetToken corresponding to the DelegatedManager
258
+ * @param _delegatedManager Instance of the DelegatedManager to initialize the WrapModuleV2 for
259
+ */
260
+ function _initializeModule (ISetToken _setToken , IDelegatedManager _delegatedManager ) internal {
261
+ bytes memory callData = abi.encodeWithSelector (IWrapModuleV2.initialize.selector , _setToken);
262
+ _invokeManager (_delegatedManager, address (wrapModule), callData);
263
+ }
264
+ }
0 commit comments