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