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