Skip to content

Commit 3779c80

Browse files
authored
feat(ProductiveAssetExtensions): Add WrapExtension and ClaimExtension [SIM-270] (#35)
* add WrapExtension And ClaimExtension
1 parent 8ad1000 commit 3779c80

File tree

9 files changed

+4008
-8
lines changed

9 files changed

+4008
-8
lines changed

contracts/extensions/ClaimExtension.sol

Lines changed: 742 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
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+
}

contracts/interfaces/IDelegatedManager.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ interface IDelegatedManager {
3333
function updateOwnerFeeRecipient(address _newFeeRecipient) external;
3434

3535
function setMethodologist(address _newMethodologist) external;
36-
36+
3737
function transferOwnership(address _owner) external;
3838

3939
function setToken() external view returns(ISetToken);
4040
function owner() external view returns(address);
4141
function methodologist() external view returns(address);
4242
function operatorAllowlist(address _operator) external view returns(bool);
4343
function assetAllowlist(address _asset) external view returns(bool);
44+
function useAssetAllowlist() external view returns(bool);
4445
function isAllowedAsset(address _asset) external view returns(bool);
4546
function isPendingExtension(address _extension) external view returns(bool);
4647
function isInitializedExtension(address _extension) external view returns(bool);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
"web3": "^1.2.9"
9292
},
9393
"dependencies": {
94-
"@setprotocol/set-protocol-v2": "0.10.0-hhat.1",
94+
"@setprotocol/set-protocol-v2": "^0.10.3-hhat.1",
9595
"@uniswap/v3-sdk": "^3.5.1",
9696
"ethers": "5.5.2",
9797
"fs-extra": "^5.0.0",

0 commit comments

Comments
 (0)