@@ -118,7 +118,7 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
118
118
event PerpTraded (
119
119
ISetToken indexed _setToken ,
120
120
address indexed _baseToken ,
121
- uint256 _deltaBase ,
121
+ uint256 indexed _deltaBase ,
122
122
uint256 _deltaQuote ,
123
123
uint256 _protocolFee ,
124
124
bool _isBuy
@@ -132,8 +132,8 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
132
132
*/
133
133
event CollateralDeposited (
134
134
ISetToken indexed _setToken ,
135
- IERC20 _collateralToken ,
136
- uint256 _amountDeposited
135
+ IERC20 indexed _collateralToken ,
136
+ uint256 indexed _amountDeposited
137
137
);
138
138
139
139
/**
@@ -144,8 +144,8 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
144
144
*/
145
145
event CollateralWithdrawn (
146
146
ISetToken indexed _setToken ,
147
- IERC20 _collateralToken ,
148
- uint256 _amountWithdrawn
147
+ IERC20 indexed _collateralToken ,
148
+ uint256 indexed _amountWithdrawn
149
149
);
150
150
151
151
/* ============ Constants ============ */
@@ -166,25 +166,25 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
166
166
uint8 internal immutable collateralDecimals;
167
167
168
168
// PerpV2 contract which provides getters for base, quote, and owedRealizedPnl balances
169
- IAccountBalance internal immutable perpAccountBalance;
169
+ IAccountBalance public immutable perpAccountBalance;
170
170
171
171
// PerpV2 contract which provides a trading API
172
- IClearingHouse internal immutable perpClearingHouse;
172
+ IClearingHouse public immutable perpClearingHouse;
173
173
174
174
// PerpV2 contract which manages trading logic. Provides getters for UniswapV3 pools and pending funding balances
175
- IExchange internal immutable perpExchange;
175
+ IExchange public immutable perpExchange;
176
176
177
177
// PerpV2 contract which handles deposits and withdrawals. Provides getter for collateral balances
178
- IVault internal immutable perpVault;
178
+ IVault public immutable perpVault;
179
179
180
180
// PerpV2 contract which makes it possible to simulate a trade before it occurs
181
- IQuoter internal immutable perpQuoter;
181
+ IQuoter public immutable perpQuoter;
182
182
183
183
// PerpV2 contract which provides a getter for baseToken UniswapV3 pools
184
- IMarketRegistry internal immutable perpMarketRegistry;
184
+ IMarketRegistry public immutable perpMarketRegistry;
185
185
186
186
// Mapping of SetTokens to an array of virtual token addresses the Set has open positions for.
187
- // Array is automatically updated when new positions are opened or old positions are zeroed out.
187
+ // Array is updated when new positions are opened or old positions are zeroed out.
188
188
mapping (ISetToken => address []) internal positions;
189
189
190
190
/* ============ Constructor ============ */
@@ -249,7 +249,13 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
249
249
// Try if register exists on any of the modules including the debt issuance module
250
250
address [] memory modules = _setToken.getModules ();
251
251
for (uint256 i = 0 ; i < modules.length ; i++ ) {
252
- try IDebtIssuanceModule (modules[i]).registerToIssuanceModule (_setToken) {} catch {}
252
+ try IDebtIssuanceModule (modules[i]).registerToIssuanceModule (_setToken) {
253
+ // This module registered itself on `modules[i]` issuance module.
254
+ } catch {
255
+ // Try will fail if `modules[i]` is not an instance of IDebtIssuanceModule and does not
256
+ // implement the `registerToIssuanceModule` function, or if the `registerToIssuanceModule`
257
+ // function call reverted. Irrespective of the reason for failure, continue to the next module.
258
+ }
253
259
}
254
260
}
255
261
@@ -384,7 +390,10 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
384
390
"Account balance exists "
385
391
);
386
392
387
- delete positions[setToken]; // Should already be empty
393
+ // `positions[setToken]` mapping stores an array of addresses. The base token addresses are removed from the array when the
394
+ // corresponding base token positions are zeroed out. Since no positions exist when removing the module, the stored array should
395
+ // already be empty, and the mapping can be deleted directly.
396
+ delete positions[setToken];
388
397
389
398
// Try if unregister exists on any of the modules
390
399
address [] memory modules = setToken.getModules ();
@@ -599,10 +608,12 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
599
608
* + quoteBalance: USDC quote asset balance as notional quantity (10**18)
600
609
*/
601
610
function getPositionNotionalInfo (ISetToken _setToken ) public view returns (PositionNotionalInfo[] memory ) {
602
- PositionNotionalInfo[] memory positionInfo = new PositionNotionalInfo [](positions[_setToken].length );
611
+ address [] memory positionList = positions[_setToken];
612
+ uint256 positionLength = positionList.length ;
613
+ PositionNotionalInfo[] memory positionInfo = new PositionNotionalInfo [](positionLength);
603
614
604
- for (uint i = 0 ; i < positions[_setToken]. length ; i++ ){
605
- address baseToken = positions[_setToken] [i];
615
+ for (uint i = 0 ; i < positionLength ; i++ ){
616
+ address baseToken = positionList [i];
606
617
positionInfo[i] = PositionNotionalInfo ({
607
618
baseToken: baseToken,
608
619
baseBalance: perpAccountBalance.getBase (
@@ -630,26 +641,22 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
630
641
* + baseUnit: baseToken balance as position unit (10**18)
631
642
* + quoteUnit: USDC quote asset balance as position unit (10**18)
632
643
*/
633
- function getPositionUnitInfo (ISetToken _setToken ) public view returns (PositionUnitInfo[] memory ) {
644
+ function getPositionUnitInfo (ISetToken _setToken ) external view returns (PositionUnitInfo[] memory ) {
634
645
int256 totalSupply = _setToken.totalSupply ().toInt256 ();
635
- PositionUnitInfo[] memory positionInfo = new PositionUnitInfo [](positions[_setToken].length );
636
-
637
- for (uint i = 0 ; i < positions[_setToken].length ; i++ ){
638
- address baseToken = positions[_setToken][i];
639
- positionInfo[i] = PositionUnitInfo ({
640
- baseToken: baseToken,
641
- baseUnit: perpAccountBalance.getBase (
642
- address (_setToken),
643
- baseToken
644
- ).preciseDiv (totalSupply),
645
- quoteUnit: perpAccountBalance.getQuote (
646
- address (_setToken),
647
- baseToken
648
- ).preciseDiv (totalSupply)
646
+ PositionNotionalInfo[] memory positionNotionalInfo = getPositionNotionalInfo (_setToken);
647
+ uint256 positionLength = positionNotionalInfo.length ;
648
+ PositionUnitInfo[] memory positionUnitInfo = new PositionUnitInfo [](positionLength);
649
+
650
+ for (uint i = 0 ; i < positionLength; i++ ){
651
+ PositionNotionalInfo memory currentPosition = positionNotionalInfo[i];
652
+ positionUnitInfo[i] = PositionUnitInfo ({
653
+ baseToken: currentPosition.baseToken,
654
+ baseUnit: currentPosition.baseBalance.preciseDiv (totalSupply),
655
+ quoteUnit: currentPosition.quoteBalance.preciseDiv (totalSupply)
649
656
});
650
657
}
651
658
652
- return positionInfo ;
659
+ return positionUnitInfo ;
653
660
}
654
661
655
662
@@ -675,29 +682,11 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
675
682
accountInfo = AccountInfo ({
676
683
collateralBalance: _getCollateralBalance (_setToken),
677
684
owedRealizedPnl: owedRealizedPnl,
678
- pendingFundingPayments: perpExchange.getAllPendingFundingPayment (address (_setToken)).mul ( - 1 ),
685
+ pendingFundingPayments: perpExchange.getAllPendingFundingPayment (address (_setToken)).neg ( ),
679
686
netQuoteBalance: _getNetQuoteBalance (_setToken)
680
687
});
681
688
}
682
689
683
- /**
684
- * @dev Returns important Perpetual Protocol addresses such as ClearingHouse, Vault, AccountBalance, etc. in an array.
685
- * Array is used in order to save bytecode vs a struct. Returned addresses are in the following order:
686
- * [AccountBalance, ClearingHouse, Exchange, Vault, Quoter, MarketRegistry]
687
- *
688
- * @return Array containing important Perpetual Protocol addresses
689
- */
690
- function getPerpContracts () external view returns (address [6 ] memory ) {
691
- return [
692
- address (perpAccountBalance),
693
- address (perpClearingHouse),
694
- address (perpExchange),
695
- address (perpVault),
696
- address (perpQuoter),
697
- address (perpMarketRegistry)
698
- ];
699
- }
700
-
701
690
/* ============ Internal Functions ============ */
702
691
703
692
/**
@@ -749,17 +738,19 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
749
738
// and variable may refer to the value which will be redeemed.
750
739
int256 accountValueIssued = _calculatePartialAccountValuePositionUnit (_setToken).preciseMul (setTokenQuantityInt);
751
740
752
- PositionUnitInfo[] memory positionInfo = getPositionUnitInfo (_setToken);
741
+ PositionNotionalInfo[] memory positionInfo = getPositionNotionalInfo (_setToken);
742
+ uint256 positionLength = positionInfo.length ;
743
+ int256 totalSupply = _setToken.totalSupply ().toInt256 ();
753
744
754
- for (uint i = 0 ; i < positionInfo. length ; i++ ) {
755
- int256 baseTradeNotionalQuantity = positionInfo[i].baseUnit .preciseMul (setTokenQuantityInt);
745
+ for (uint i = 0 ; i < positionLength ; i++ ) {
746
+ int256 baseTradeNotionalQuantity = positionInfo[i].baseBalance. preciseDiv (totalSupply) .preciseMul (setTokenQuantityInt);
756
747
757
748
// When redeeming, we flip the sign of baseTradeNotionalQuantity because we are reducing the size of the position,
758
749
// e.g selling base when long, buying base when short
759
750
ActionInfo memory actionInfo = _createActionInfoNotional (
760
751
_setToken,
761
752
positionInfo[i].baseToken,
762
- _isIssue ? baseTradeNotionalQuantity : baseTradeNotionalQuantity.mul ( - 1 ),
753
+ _isIssue ? baseTradeNotionalQuantity : baseTradeNotionalQuantity.neg ( ),
763
754
0
764
755
);
765
756
@@ -1082,9 +1073,11 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
1082
1073
address [] memory positionList = positions[_setToken];
1083
1074
bool hasBaseToken = positionList.contains (_baseToken);
1084
1075
1085
- if (hasBaseToken && ! _hasBaseBalance (_setToken, _baseToken)) {
1086
- positions[_setToken].removeStorage (_baseToken);
1087
- } else if (! hasBaseToken) {
1076
+ if (hasBaseToken) {
1077
+ if (! _hasBaseBalance (_setToken, _baseToken)) {
1078
+ positions[_setToken].removeStorage (_baseToken);
1079
+ }
1080
+ } else {
1088
1081
positions[_setToken].push (_baseToken);
1089
1082
}
1090
1083
}
@@ -1098,10 +1091,12 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
1098
1091
*/
1099
1092
function _syncPositionList (ISetToken _setToken ) internal {
1100
1093
address [] memory positionList = positions[_setToken];
1101
-
1102
- for (uint256 i = 0 ; i < positionList.length ; i++ ) {
1103
- if (! _hasBaseBalance (_setToken, positionList[i])) {
1104
- positions[_setToken].removeStorage (positionList[i]);
1094
+ uint256 positionLength = positionList.length ;
1095
+
1096
+ for (uint256 i = 0 ; i < positionLength; i++ ) {
1097
+ address currPosition = positionList[i];
1098
+ if (! _hasBaseBalance (_setToken, currPosition)) {
1099
+ positions[_setToken].removeStorage (currPosition);
1105
1100
}
1106
1101
}
1107
1102
}
@@ -1144,9 +1139,10 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
1144
1139
*/
1145
1140
function _calculateExternalPositionUnit (ISetToken _setToken ) internal view returns (int256 ) {
1146
1141
PositionNotionalInfo[] memory positionInfo = getPositionNotionalInfo (_setToken);
1142
+ uint256 positionLength = positionInfo.length ;
1147
1143
int256 totalPositionValue = 0 ;
1148
1144
1149
- for (uint i = 0 ; i < positionInfo. length ; i++ ) {
1145
+ for (uint i = 0 ; i < positionLength ; i++ ) {
1150
1146
int256 spotPrice = _calculateAMMSpotPrice (positionInfo[i].baseToken).toInt256 ();
1151
1147
totalPositionValue = totalPositionValue.add (
1152
1148
positionInfo[i].baseBalance.preciseMul (spotPrice)
@@ -1159,22 +1155,29 @@ contract PerpV2LeverageModule is ModuleBase, ReentrancyGuard, Ownable, SetTokenA
1159
1155
return externalPositionUnitInPreciseUnits.fromPreciseUnitToDecimals (collateralDecimals);
1160
1156
}
1161
1157
1162
- // @dev Retrieves collateral balance as an 18 decimal vUSDC quote value
1163
- //
1164
- // @param _setToken Instance of SetToken
1165
- // @return int256 Collateral balance as an 18 decimal vUSDC quote value
1158
+ /**
1159
+ * @dev Retrieves collateral balance as an 18 decimal vUSDC quote value
1160
+ *
1161
+ * @param _setToken Instance of SetToken
1162
+ * @return int256 Collateral balance as an 18 decimal vUSDC quote value
1163
+ */
1166
1164
function _getCollateralBalance (ISetToken _setToken ) internal view returns (int256 ) {
1167
1165
return perpVault.getBalance (address (_setToken)).toPreciseUnitsFromDecimals (collateralDecimals);
1168
1166
}
1169
1167
1170
- // @dev Retrieves net quote balance of all open positions
1171
- //
1172
- // @param _setToken Instance of SetToken
1173
- // @return int256 Net quote balance of all open positions
1168
+ /**
1169
+ * @dev Retrieves net quote balance of all open positions
1170
+ *
1171
+ * @param _setToken Instance of SetToken
1172
+ * @return netQuoteBalance Net quote balance of all open positions
1173
+ */
1174
1174
function _getNetQuoteBalance (ISetToken _setToken ) internal view returns (int256 netQuoteBalance ) {
1175
- for (uint256 i = 0 ; i < positions[_setToken].length ; i++ ) {
1175
+ address [] memory positionList = positions[_setToken];
1176
+ uint256 positionLength = positionList.length ;
1177
+
1178
+ for (uint256 i = 0 ; i < positionLength; i++ ) {
1176
1179
netQuoteBalance = netQuoteBalance.add (
1177
- perpAccountBalance.getQuote (address (_setToken), positions[_setToken] [i])
1180
+ perpAccountBalance.getQuote (address (_setToken), positionList [i])
1178
1181
);
1179
1182
}
1180
1183
}
0 commit comments