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
+ pragma solidity 0.6.10 ;
19
+ pragma experimental "ABIEncoderV2 " ;
20
+
21
+ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol " ;
22
+
23
+ import { ISetToken } from "./ISetToken.sol " ;
24
+ import { IDebtIssuanceModule } from "./IDebtIssuanceModule.sol " ;
25
+ import { IAccountBalance } from "./external/perp-v2/IAccountBalance.sol " ;
26
+ import { IClearingHouse } from "./external/perp-v2/IClearingHouse.sol " ;
27
+ import { IExchange } from "./external/perp-v2/IExchange.sol " ;
28
+ import { IVault } from "./external/perp-v2/IVault.sol " ;
29
+ import { IQuoter } from "./external/perp-v2/IQuoter.sol " ;
30
+ import { IMarketRegistry } from "./external/perp-v2/IMarketRegistry.sol " ;
31
+
32
+
33
+ /**
34
+ * @title IPerpV2LeverageModule
35
+ * @author Set Protocol
36
+ *
37
+ * Interface for the PerpV2LeverageModule. Only specifies Manager permissioned functions, events
38
+ * and getters. PerpV2LeverageModule also inherits from ModuleBase and SetTokenAccessible which support
39
+ * additional methods.
40
+ */
41
+ interface IPerpV2LeverageModule {
42
+
43
+ /* ============ Structs ============ */
44
+
45
+ struct PositionNotionalInfo {
46
+ address baseToken; // Virtual token minted by the Perp protocol
47
+ int256 baseBalance; // Base position notional quantity in 10**18 decimals. When negative, position is short
48
+ int256 quoteBalance; // vUSDC "debt" notional quantity minted to open position. When positive, position is short
49
+ }
50
+
51
+ struct PositionUnitInfo {
52
+ address baseToken; // Virtual token minted by the Perp protocol
53
+ int256 baseUnit; // Base position unit. When negative, position is short
54
+ int256 quoteUnit; // vUSDC "debt" position unit. When positive, position is short
55
+ }
56
+
57
+ // Note: when `pendingFundingPayments` is positive it will be credited to account on settlement,
58
+ // when negative it's a debt owed that will be repaid on settlement. (PerpProtocol.Exchange returns the value
59
+ // with the opposite meaning, e.g positively signed payments are owed by account to system).
60
+ struct AccountInfo {
61
+ int256 collateralBalance; // Quantity of collateral deposited in Perp vault in 10**18 decimals
62
+ int256 owedRealizedPnl; // USDC quantity of profit and loss in 10**18 decimals not yet settled to vault
63
+ int256 pendingFundingPayments; // USDC quantity of pending funding payments in 10**18 decimals
64
+ int256 netQuoteBalance; // USDC quantity of net quote balance for all open positions in Perp account
65
+ }
66
+
67
+ /* ============ Events ============ */
68
+
69
+ /**
70
+ * @dev Emitted on trade
71
+ * @param _setToken Instance of SetToken
72
+ * @param _baseToken Virtual token minted by the Perp protocol
73
+ * @param _deltaBase Change in baseToken position size resulting from trade
74
+ * @param _deltaQuote Change in vUSDC position size resulting from trade
75
+ * @param _protocolFee Quantity in collateral decimals sent to fee recipient during lever trade
76
+ * @param _isBuy True when baseToken is being bought, false when being sold
77
+ */
78
+ event PerpTraded (
79
+ ISetToken indexed _setToken ,
80
+ address indexed _baseToken ,
81
+ uint256 _deltaBase ,
82
+ uint256 _deltaQuote ,
83
+ uint256 _protocolFee ,
84
+ bool _isBuy
85
+ );
86
+
87
+ /**
88
+ * @dev Emitted on deposit (not issue or redeem)
89
+ * @param _setToken Instance of SetToken
90
+ * @param _collateralToken Token being deposited as collateral (USDC)
91
+ * @param _amountDeposited Amount of collateral being deposited into Perp
92
+ */
93
+ event CollateralDeposited (
94
+ ISetToken indexed _setToken ,
95
+ IERC20 _collateralToken ,
96
+ uint256 _amountDeposited
97
+ );
98
+
99
+ /**
100
+ * @dev Emitted on withdraw (not issue or redeem)
101
+ * @param _setToken Instance of SetToken
102
+ * @param _collateralToken Token being withdrawn as collateral (USDC)
103
+ * @param _amountWithdrawn Amount of collateral being withdrawn from Perp
104
+ */
105
+ event CollateralWithdrawn (
106
+ ISetToken indexed _setToken ,
107
+ IERC20 _collateralToken ,
108
+ uint256 _amountWithdrawn
109
+ );
110
+
111
+ /* ============ State Variable Getters ============ */
112
+
113
+ // PerpV2 contract which provides getters for base, quote, and owedRealizedPnl balances
114
+ function perpAccountBalance () external view returns (IAccountBalance);
115
+
116
+ // PerpV2 contract which provides a trading API
117
+ function perpClearingHouse () external view returns (IClearingHouse);
118
+
119
+ // PerpV2 contract which manages trading logic. Provides getters for UniswapV3 pools and pending funding balances
120
+ function perpExchange () external view returns (IExchange);
121
+
122
+ // PerpV2 contract which handles deposits and withdrawals. Provides getter for collateral balances
123
+ function perpVault () external view returns (IVault);
124
+
125
+ // PerpV2 contract which makes it possible to simulate a trade before it occurs
126
+ function perpQuoter () external view returns (IQuoter);
127
+
128
+ // PerpV2 contract which provides a getter for baseToken UniswapV3 pools
129
+ function perpMarketRegistry () external view returns (IMarketRegistry);
130
+
131
+ // Token (USDC) used as a vault deposit, Perp currently only supports USDC as it's settlement and collateral token
132
+ function collateralToken () external view returns (IERC20 );
133
+
134
+ // Decimals of collateral token. We set this in the constructor for later reading
135
+ function collateralDecimals () external view returns (uint8 );
136
+
137
+ /* ============ External Functions ============ */
138
+
139
+ /**
140
+ * @dev MANAGER ONLY: Initializes this module to the SetToken. Either the SetToken needs to be on the
141
+ * allowed list or anySetAllowed needs to be true.
142
+ *
143
+ * @param _setToken Instance of the SetToken to initialize
144
+ */
145
+ function initialize (ISetToken _setToken ) external ;
146
+
147
+ /**
148
+ * @dev MANAGER ONLY: Allows manager to buy or sell perps to change exposure to the underlying baseToken.
149
+ * Providing a positive value for `_baseQuantityUnits` buys vToken on UniswapV3 via Perp's ClearingHouse,
150
+ * Providing a negative value sells the token. `_quoteBoundQuantityUnits` defines a min-receive-like slippage
151
+ * bound for the amount of vUSDC quote asset the trade will either pay or receive as a result of the action.
152
+ *
153
+ * NOTE: This method doesn't update the externalPositionUnit because it is a function of UniswapV3 virtual
154
+ * token market prices and needs to be generated on the fly to be meaningful.
155
+ *
156
+ * As a user when levering, e.g increasing the magnitude of your position, you'd trade as below
157
+ * | ----------------------------------------------------------------------------------------------- |
158
+ * | Type | Action | Goal | `quoteBoundQuantity` | `baseQuantityUnits` |
159
+ * | ----- |-------- | ------------------------- | --------------------------- | ------------------- |
160
+ * | Long | Buy | pay least amt. of vQuote | upper bound of input quote | positive |
161
+ * | Short | Sell | get most amt. of vQuote | lower bound of output quote | negative |
162
+ * | ----------------------------------------------------------------------------------------------- |
163
+ *
164
+ * As a user when delevering, e.g decreasing the magnitude of your position, you'd trade as below
165
+ * | ----------------------------------------------------------------------------------------------- |
166
+ * | Type | Action | Goal | `quoteBoundQuantity` | `baseQuantityUnits` |
167
+ * | ----- |-------- | ------------------------- | --------------------------- | ------------------- |
168
+ * | Long | Sell | get most amt. of vQuote | upper bound of input quote | negative |
169
+ * | Short | Buy | pay least amt. of vQuote | lower bound of output quote | positive |
170
+ * | ----------------------------------------------------------------------------------------------- |
171
+ *
172
+ * @param _setToken Instance of the SetToken
173
+ * @param _baseToken Address virtual token being traded
174
+ * @param _baseQuantityUnits Quantity of virtual token to trade in position units
175
+ * @param _quoteBoundQuantityUnits Max/min of vQuote asset to pay/receive when buying or selling
176
+ */
177
+ function trade (
178
+ ISetToken _setToken ,
179
+ address _baseToken ,
180
+ int256 _baseQuantityUnits ,
181
+ uint256 _quoteBoundQuantityUnits
182
+ )
183
+ external ;
184
+
185
+ /**
186
+ * @dev MANAGER ONLY: Deposits default position collateral token into the PerpV2 Vault, increasing
187
+ * the size of the Perp account external position. This method is useful for establishing initial
188
+ * collateralization ratios, e.g the flow when setting up a 2X external position would be to deposit
189
+ * 100 units of USDC and execute a lever trade for ~200 vUSDC worth of vToken with the difference
190
+ * between these made up as automatically "issued" margin debt in the PerpV2 system.
191
+ *
192
+ * @param _setToken Instance of the SetToken
193
+ * @param _collateralQuantityUnits Quantity of collateral to deposit in position units
194
+ */
195
+ function deposit (ISetToken _setToken , uint256 _collateralQuantityUnits ) external ;
196
+
197
+
198
+ /**
199
+ * @dev MANAGER ONLY: Withdraws collateral token from the PerpV2 Vault to a default position on
200
+ * the SetToken. This method is useful when adjusting the overall composition of a Set which has
201
+ * a Perp account external position as one of several components.
202
+ *
203
+ * NOTE: Within PerpV2, `withdraw` settles `owedRealizedPnl` and any pending funding payments
204
+ * to the Perp vault prior to transfer.
205
+ *
206
+ * @param _setToken Instance of the SetToken
207
+ * @param _collateralQuantityUnits Quantity of collateral to withdraw in position units
208
+ */
209
+ function withdraw (ISetToken _setToken , uint256 _collateralQuantityUnits ) external ;
210
+
211
+
212
+ /* ============ External Getter Functions ============ */
213
+
214
+ /**
215
+ * @dev Gets the positive equity collateral externalPositionUnit that would be calculated for
216
+ * issuing a quantity of SetToken, representing the amount of collateral that would need to
217
+ * be transferred in per SetToken. Values in the returned arrays map to the same index in the
218
+ * SetToken's components array
219
+ *
220
+ * @param _setToken Instance of SetToken
221
+ * @param _setTokenQuantity Number of sets to issue
222
+ *
223
+ * @return equityAdjustments array containing a single element and an empty debtAdjustments array
224
+ */
225
+ function getIssuanceAdjustments (ISetToken _setToken , uint256 _setTokenQuantity )
226
+ external
227
+ returns (int256 [] memory , int256 [] memory );
228
+
229
+
230
+ /**
231
+ * @dev Gets the positive equity collateral externalPositionUnit that would be calculated for
232
+ * redeeming a quantity of SetToken representing the amount of collateral returned per SetToken.
233
+ * Values in the returned arrays map to the same index in the SetToken's components array.
234
+ *
235
+ * @param _setToken Instance of SetToken
236
+ * @param _setTokenQuantity Number of sets to issue
237
+ *
238
+ * @return equityAdjustments array containing a single element and an empty debtAdjustments array
239
+ */
240
+ function getRedemptionAdjustments (ISetToken _setToken , uint256 _setTokenQuantity )
241
+ external
242
+ returns (int256 [] memory , int256 [] memory );
243
+
244
+ /**
245
+ * @dev Returns a PositionUnitNotionalInfo array representing all positions open for the SetToken.
246
+ *
247
+ * @param _setToken Instance of SetToken
248
+ *
249
+ * @return PositionUnitInfo array, in which each element has properties:
250
+ *
251
+ * + baseToken: address,
252
+ * + baseBalance: baseToken balance as notional quantity (10**18)
253
+ * + quoteBalance: USDC quote asset balance as notional quantity (10**18)
254
+ */
255
+ function getPositionNotionalInfo (ISetToken _setToken ) external view returns (PositionNotionalInfo[] memory );
256
+
257
+ /**
258
+ * @dev Returns a PositionUnitInfo array representing all positions open for the SetToken.
259
+ *
260
+ * @param _setToken Instance of SetToken
261
+ *
262
+ * @return PositionUnitInfo array, in which each element has properties:
263
+ *
264
+ * + baseToken: address,
265
+ * + baseUnit: baseToken balance as position unit (10**18)
266
+ * + quoteUnit: USDC quote asset balance as position unit (10**18)
267
+ */
268
+ function getPositionUnitInfo (ISetToken _setToken ) external view returns (PositionUnitInfo[] memory );
269
+
270
+ /**
271
+ * @dev Gets Perp account info for SetToken. Returns an AccountInfo struct containing account wide
272
+ * (rather than position specific) balance info
273
+ *
274
+ * @param _setToken Instance of the SetToken
275
+ *
276
+ * @return accountInfo struct with properties for:
277
+ *
278
+ * + collateral balance (10**18, regardless of underlying collateral decimals)
279
+ * + owed realized Pnl` (10**18)
280
+ * + pending funding payments (10**18)
281
+ * + net quote balance (10**18)
282
+ */
283
+ function getAccountInfo (ISetToken _setToken ) external view returns (AccountInfo memory accountInfo );
284
+
285
+ /**
286
+ * @dev Gets the mid-point price of a virtual asset from UniswapV3 markets maintained by Perp Protocol
287
+ *
288
+ * @param _baseToken) Address of virtual token to price
289
+ * @return price Mid-point price of virtual token in UniswapV3 AMM market
290
+ */
291
+ function getAMMSpotPrice (address _baseToken ) external view returns (uint256 price );
292
+ }
0 commit comments