@gearbox-protocol/periphery-v3 1.7.0-next.35 → 1.7.0-next.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/contracts/compressors/AdapterCompressor.sol +7 -8
  2. package/contracts/compressors/CreditAccountCompressor.sol +100 -202
  3. package/contracts/compressors/CreditSuiteCompressor.sol +91 -0
  4. package/contracts/compressors/MarketCompressor.sol +91 -68
  5. package/contracts/compressors/PoolCompressor.sol +25 -141
  6. package/contracts/compressors/PriceFeedCompressor.sol +7 -7
  7. package/contracts/data/Types.sol +1 -1
  8. package/contracts/data/ZapperRegister.sol +5 -8
  9. package/contracts/interfaces/IAdapterCompressor.sol +2 -2
  10. package/contracts/interfaces/ICreditAccountCompressor.sol +2 -1
  11. package/contracts/interfaces/IMarketCompressor.sol +4 -6
  12. package/contracts/libraries/BaseLib.sol +1 -1
  13. package/contracts/serializers/pool/{LinearInterestModelSerializer.sol → LinearInterestRateModelSerializer.sol} +2 -1
  14. package/contracts/test/ForkTest.sol +29 -8
  15. package/contracts/test/MultiPause.t.sol +2 -2
  16. package/contracts/types/CreditAccountState.sol +2 -24
  17. package/contracts/types/CreditFacadeState.sol +2 -5
  18. package/contracts/types/CreditManagerState.sol +11 -8
  19. package/contracts/types/CreditSuiteData.sol +20 -0
  20. package/contracts/types/Filters.sol +30 -0
  21. package/contracts/types/MarketData.sol +11 -34
  22. package/contracts/types/PoolState.sol +2 -5
  23. package/contracts/types/PriceOracleState.sol +1 -1
  24. package/contracts/types/TokenData.sol +0 -9
  25. package/package.json +1 -1
  26. package/contracts/interfaces/ITreasurySplitter.sol +0 -9
  27. package/contracts/interfaces/IVersion.sol +0 -13
  28. package/contracts/market/MarketManager.sol +0 -15
  29. package/contracts/types/ACLState.sol +0 -13
@@ -3,13 +3,13 @@
3
3
  // (c) Gearbox Holdings, 2024
4
4
  pragma solidity ^0.8.17;
5
5
 
6
+ import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";
6
7
  import {AdapterType} from "@gearbox-protocol/sdk-gov/contracts/AdapterType.sol";
7
- import {ContractAdapter} from "../types/MarketData.sol";
8
+ import {AdapterState} from "../types/CreditSuiteData.sol";
8
9
  import {IAdapterCompressor} from "../interfaces/IAdapterCompressor.sol";
9
10
  import {ICreditConfiguratorV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditConfiguratorV3.sol";
10
11
  import {ICreditManagerV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditManagerV3.sol";
11
12
  import {IStateSerializer} from "../interfaces/IStateSerializer.sol";
12
- import {IVersion} from "../interfaces/IVersion.sol";
13
13
 
14
14
  interface ILegacyAdapter {
15
15
  function _gearboxAdapterVersion() external view returns (uint16);
@@ -58,24 +58,23 @@ contract AdapterCompressor is IAdapterCompressor {
58
58
  contractTypes[uint8(AdapterType.DAI_USDS_EXCHANGE)] = "AD_DAI_USDS_EXCHANGE";
59
59
  contractTypes[uint8(AdapterType.MELLOW_ERC4626_VAULT)] = "AD_MELLOW_ERC4626_VAULT";
60
60
  contractTypes[uint8(AdapterType.STAKING_REWARDS)] = "AD_STAKING_REWARDS";
61
+ // TODO: should add equalizer as well
61
62
  }
62
63
 
63
- function getContractAdapters(address creditManager) external view returns (ContractAdapter[] memory adapters) {
64
+ function getAdapters(address creditManager) external view returns (AdapterState[] memory adapters) {
64
65
  ICreditConfiguratorV3 creditConfigurator =
65
66
  ICreditConfiguratorV3(ICreditManagerV3(creditManager).creditConfigurator());
66
67
 
67
68
  address[] memory allowedAdapters = creditConfigurator.allowedAdapters();
68
69
  uint256 len = allowedAdapters.length;
69
70
 
70
- adapters = new ContractAdapter[](len);
71
- bytes memory stateSerialised;
72
-
71
+ adapters = new AdapterState[](len);
73
72
  unchecked {
74
73
  for (uint256 i = 0; i < len; ++i) {
75
74
  address adapter = allowedAdapters[i];
76
75
  adapters[i].baseParams.addr = adapter;
77
- try IVersion(adapter).contractType() returns (bytes32 adapterType) {
78
- adapters[i].baseParams.contractType = adapterType;
76
+ try IVersion(adapter).contractType() returns (bytes32 contractType_) {
77
+ adapters[i].baseParams.contractType = contractType_;
79
78
  } catch {
80
79
  try ILegacyAdapter(adapter)._gearboxAdapterType() returns (uint8 adapterType) {
81
80
  adapters[i].baseParams.contractType = contractTypes[adapterType];
@@ -3,22 +3,34 @@
3
3
  // (c) Gearbox Foundation, 2024.
4
4
  pragma solidity ^0.8.17;
5
5
 
6
+ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
6
7
  import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7
8
  import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
8
9
 
9
- import {IContractsRegister} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IContractsRegister.sol";
10
10
  import {ICreditAccountV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditAccountV3.sol";
11
- import {CollateralCalcTask, CollateralDebtData, ICreditManagerV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditManagerV3.sol";
11
+ import {ICreditFacadeV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditFacadeV3.sol";
12
+ import {
13
+ CollateralCalcTask,
14
+ CollateralDebtData,
15
+ ICreditManagerV3
16
+ } from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditManagerV3.sol";
12
17
  import {IPoolQuotaKeeperV3} from "@gearbox-protocol/core-v3/contracts/interfaces/IPoolQuotaKeeperV3.sol";
13
- import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";
14
18
  import {PERCENTAGE_FACTOR} from "@gearbox-protocol/core-v3/contracts/libraries/Constants.sol";
15
19
  import {SanityCheckTrait} from "@gearbox-protocol/core-v3/contracts/traits/SanityCheckTrait.sol";
16
20
  import {ICreditAccountCompressor} from "../interfaces/ICreditAccountCompressor.sol";
17
21
 
18
- import {IAddressProviderV3_1} from "@gearbox-protocol/governance/contracts/interfaces/IAddressProviderV3_1.sol";
19
- import {IMarketConfiguratorV3} from "@gearbox-protocol/governance/contracts/interfaces/IMarketConfiguratorV3.sol";
22
+ import {IContractsRegister} from "@gearbox-protocol/governance/contracts/interfaces/extensions/IContractsRegister.sol";
23
+ import {IAddressProvider} from "@gearbox-protocol/governance/contracts/interfaces/IAddressProvider.sol";
24
+ import {IMarketConfigurator} from "@gearbox-protocol/governance/contracts/interfaces/IMarketConfigurator.sol";
25
+ import {IMarketConfiguratorFactory} from
26
+ "@gearbox-protocol/governance/contracts/interfaces/IMarketConfiguratorFactory.sol";
27
+ import {
28
+ AP_MARKET_CONFIGURATOR_FACTORY,
29
+ NO_VERSION_CONTROL
30
+ } from "@gearbox-protocol/governance/contracts/libraries/ContractLiterals.sol";
20
31
 
21
- import {CreditAccountData, CreditAccountFilter, MarketFilter, TokenInfo} from "../types/CreditAccountState.sol";
32
+ import {CreditAccountData, TokenInfo} from "../types/CreditAccountState.sol";
33
+ import {CreditAccountFilter, MarketFilter} from "../types/Filters.sol";
22
34
 
23
35
  import {Contains} from "../libraries/Contains.sol";
24
36
 
@@ -34,22 +46,23 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
34
46
  bytes32 public constant override contractType = "CREDIT_ACCOUNT_COMPRESSOR";
35
47
 
36
48
  /// @notice Address provider contract address
37
- address public immutable ADDRESS_PROVIDER;
49
+ address public immutable addressProvider;
38
50
 
39
- /// @notice Thrown when address provider is not a contract or does not implement `marketConfigurators()`
51
+ address public immutable marketConfiguratorFactory;
52
+
53
+ /// @notice Thrown when address provider is not a contract
40
54
  error InvalidAddressProviderException();
41
55
 
42
56
  /// @notice Constructor
43
- /// @param addressProvider Address provider contract address
44
- constructor(address addressProvider) nonZeroAddress(addressProvider) {
45
- if (addressProvider.code.length == 0)
46
- revert InvalidAddressProviderException();
47
- try
48
- IAddressProviderV3_1(addressProvider).marketConfigurators()
49
- {} catch {
57
+ /// @param addressProvider_ Address provider contract address
58
+ constructor(address addressProvider_) nonZeroAddress(addressProvider) {
59
+ if (addressProvider_.code.length == 0) {
50
60
  revert InvalidAddressProviderException();
51
61
  }
52
- ADDRESS_PROVIDER = addressProvider;
62
+
63
+ addressProvider = addressProvider_;
64
+ marketConfiguratorFactory =
65
+ IAddressProvider(addressProvider_).getAddressOrRevert(AP_MARKET_CONFIGURATOR_FACTORY, NO_VERSION_CONTROL);
53
66
  }
54
67
 
55
68
  // -------- //
@@ -57,9 +70,7 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
57
70
  // -------- //
58
71
 
59
72
  /// @notice Returns data for a particular `creditAccount`
60
- function getCreditAccountData(
61
- address creditAccount
62
- ) external view returns (CreditAccountData memory) {
73
+ function getCreditAccountData(address creditAccount) external view returns (CreditAccountData memory) {
63
74
  address creditManager = ICreditAccountV3(creditAccount).creditManager();
64
75
  return _getCreditAccountData(creditAccount, creditManager);
65
76
  }
@@ -67,23 +78,13 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
67
78
  /// @notice Returns data for credit accounts that match `caFilter` in credit managers matching `marketFilter`
68
79
  /// @dev The non-zero value of `nextOffset` return variable indicates that gas supplied with a call was
69
80
  /// insufficient to process all the accounts and next iteration starting from this value is needed
70
- function getCreditAccounts(
71
- MarketFilter memory marketFilter,
72
- CreditAccountFilter memory caFilter,
73
- uint256 offset
74
- )
81
+ function getCreditAccounts(MarketFilter memory marketFilter, CreditAccountFilter memory caFilter, uint256 offset)
75
82
  external
76
83
  view
77
84
  returns (CreditAccountData[] memory data, uint256 nextOffset)
78
85
  {
79
86
  address[] memory creditManagers = _getCreditManagers(marketFilter);
80
- return
81
- _getCreditAccounts(
82
- creditManagers,
83
- caFilter,
84
- offset,
85
- type(uint256).max
86
- );
87
+ return _getCreditAccounts(creditManagers, caFilter, offset, type(uint256).max);
87
88
  }
88
89
 
89
90
  /// @dev Same as above but with `limit` parameter that specifies the number of accounts to process
@@ -92,11 +93,7 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
92
93
  CreditAccountFilter memory caFilter,
93
94
  uint256 offset,
94
95
  uint256 limit
95
- )
96
- public
97
- view
98
- returns (CreditAccountData[] memory data, uint256 nextOffset)
99
- {
96
+ ) public view returns (CreditAccountData[] memory data, uint256 nextOffset) {
100
97
  address[] memory creditManagers = _getCreditManagers(marketFilter);
101
98
  return _getCreditAccounts(creditManagers, caFilter, offset, limit);
102
99
  }
@@ -104,24 +101,14 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
104
101
  /// @notice Returns data for credit accounts that match `caFilter` in a given `creditManager`
105
102
  /// @dev The non-zero value of `nextOffset` return variable indicates that gas supplied with a call was
106
103
  /// insufficient to process all the accounts and next iteration starting from this value is needed
107
- function getCreditAccounts(
108
- address creditManager,
109
- CreditAccountFilter memory caFilter,
110
- uint256 offset
111
- )
104
+ function getCreditAccounts(address creditManager, CreditAccountFilter memory caFilter, uint256 offset)
112
105
  external
113
106
  view
114
107
  returns (CreditAccountData[] memory data, uint256 nextOffset)
115
108
  {
116
109
  address[] memory creditManagers = new address[](1);
117
110
  creditManagers[0] = creditManager;
118
- return
119
- _getCreditAccounts(
120
- creditManagers,
121
- caFilter,
122
- offset,
123
- type(uint256).max
124
- );
111
+ return _getCreditAccounts(creditManagers, caFilter, offset, type(uint256).max);
125
112
  }
126
113
 
127
114
  /// @dev Same as above but with `limit` parameter that specifies the number of accounts to process
@@ -130,11 +117,7 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
130
117
  CreditAccountFilter memory caFilter,
131
118
  uint256 offset,
132
119
  uint256 limit
133
- )
134
- external
135
- view
136
- returns (CreditAccountData[] memory data, uint256 nextOffset)
137
- {
120
+ ) external view returns (CreditAccountData[] memory data, uint256 nextOffset) {
138
121
  address[] memory creditManagers = new address[](1);
139
122
  creditManagers[0] = creditManager;
140
123
  return _getCreditAccounts(creditManagers, caFilter, offset, limit);
@@ -145,34 +128,24 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
145
128
  // -------- //
146
129
 
147
130
  /// @notice Counts credit accounts that match `caFilter` in credit managers matching `marketFilter`
148
- function countCreditAccounts(
149
- MarketFilter memory marketFilter,
150
- CreditAccountFilter memory caFilter
151
- ) external view returns (uint256) {
131
+ function countCreditAccounts(MarketFilter memory marketFilter, CreditAccountFilter memory caFilter)
132
+ external
133
+ view
134
+ returns (uint256)
135
+ {
152
136
  address[] memory creditManagers = _getCreditManagers(marketFilter);
153
- return
154
- _countCreditAccounts(
155
- creditManagers,
156
- caFilter,
157
- 0,
158
- type(uint256).max
159
- );
137
+ return _countCreditAccounts(creditManagers, caFilter, 0, type(uint256).max);
160
138
  }
161
139
 
162
140
  /// @notice Counts credit accounts that match `caFilter` in a given `creditManager`
163
- function countCreditAccounts(
164
- address creditManager,
165
- CreditAccountFilter memory caFilter
166
- ) external view returns (uint256) {
141
+ function countCreditAccounts(address creditManager, CreditAccountFilter memory caFilter)
142
+ external
143
+ view
144
+ returns (uint256)
145
+ {
167
146
  address[] memory creditManagers = new address[](1);
168
147
  creditManagers[0] = creditManager;
169
- return
170
- _countCreditAccounts(
171
- creditManagers,
172
- caFilter,
173
- 0,
174
- type(uint256).max
175
- );
148
+ return _countCreditAccounts(creditManagers, caFilter, 0, type(uint256).max);
176
149
  }
177
150
 
178
151
  // --------- //
@@ -185,17 +158,8 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
185
158
  CreditAccountFilter memory filter,
186
159
  uint256 offset,
187
160
  uint256 limit
188
- )
189
- internal
190
- view
191
- returns (CreditAccountData[] memory data, uint256 nextOffset)
192
- {
193
- uint256 num = _countCreditAccounts(
194
- creditManagers,
195
- filter,
196
- offset,
197
- limit
198
- );
161
+ ) internal view returns (CreditAccountData[] memory data, uint256 nextOffset) {
162
+ uint256 num = _countCreditAccounts(creditManagers, filter, offset, limit);
199
163
  if (num == 0) return (data, 0);
200
164
 
201
165
  // allocating the `CreditAccountData` array might consume most of the gas leaving no room for computations,
@@ -220,8 +184,7 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
220
184
  }
221
185
 
222
186
  uint256 count = Math.min(len - offset, limit);
223
- address[] memory creditAccounts = ICreditManagerV3(creditManager)
224
- .creditAccounts(offset, count);
187
+ address[] memory creditAccounts = ICreditManagerV3(creditManager).creditAccounts(offset, count);
225
188
 
226
189
  // circumvent the "Stack too deep." error
227
190
  CreditAccountFilter memory filter_ = filter;
@@ -231,10 +194,7 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
231
194
  if (_checkFilterMatch(creditAccount, creditManager, filter_)) {
232
195
  uint256 gasBefore = gasleft();
233
196
 
234
- CreditAccountData memory d = _getCreditAccountData(
235
- creditAccount,
236
- creditManager
237
- );
197
+ CreditAccountData memory d = _getCreditAccountData(creditAccount, creditManager);
238
198
  ++dataOffset;
239
199
  assembly {
240
200
  // save the pointer to created struct
@@ -285,12 +245,10 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
285
245
  continue;
286
246
  }
287
247
 
288
- address[] memory creditAccounts = ICreditManagerV3(creditManager)
289
- .creditAccounts(offset, Math.min(len - offset, limit));
248
+ address[] memory creditAccounts =
249
+ ICreditManagerV3(creditManager).creditAccounts(offset, Math.min(len - offset, limit));
290
250
  for (uint256 j; j < creditAccounts.length; ++j) {
291
- if (
292
- _checkFilterMatch(creditAccounts[j], creditManager, filter)
293
- ) {
251
+ if (_checkFilterMatch(creditAccounts[j], creditManager, filter)) {
294
252
  ++num;
295
253
  }
296
254
  }
@@ -302,46 +260,40 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
302
260
  }
303
261
 
304
262
  /// @dev Data loading implementation
305
- function _getCreditAccountData(
306
- address creditAccount,
307
- address creditManager
308
- ) internal view returns (CreditAccountData memory data) {
263
+ function _getCreditAccountData(address creditAccount, address creditManager)
264
+ internal
265
+ view
266
+ returns (CreditAccountData memory data)
267
+ {
309
268
  data.creditAccount = creditAccount;
310
269
  data.creditManager = creditManager;
311
270
  data.creditFacade = ICreditManagerV3(creditManager).creditFacade();
312
271
  data.underlying = ICreditManagerV3(creditManager).underlying();
313
- data.owner = ICreditManagerV3(creditManager).getBorrowerOrRevert(
314
- creditAccount
315
- );
272
+ data.owner = ICreditManagerV3(creditManager).getBorrowerOrRevert(creditAccount);
273
+ data.expirationDate = ICreditFacadeV3(creditManager).expirationDate();
316
274
 
317
- CollateralDebtData memory cdd = ICreditManagerV3(creditManager)
318
- .calcDebtAndCollateral(creditAccount, CollateralCalcTask.DEBT_ONLY);
275
+ CollateralDebtData memory cdd =
276
+ ICreditManagerV3(creditManager).calcDebtAndCollateral(creditAccount, CollateralCalcTask.DEBT_ONLY);
319
277
  data.enabledTokensMask = cdd.enabledTokensMask;
320
278
  data.debt = cdd.debt;
321
279
  data.accruedInterest = cdd.accruedInterest;
322
280
  data.accruedFees = cdd.accruedFees;
323
281
 
324
282
  // collateral is computed separately since it might revert on `balanceOf` and `latestRoundData` calls
325
- try
326
- ICreditManagerV3(creditManager).calcDebtAndCollateral(
327
- creditAccount,
328
- CollateralCalcTask.DEBT_COLLATERAL
329
- )
283
+ try ICreditManagerV3(creditManager).calcDebtAndCollateral(creditAccount, CollateralCalcTask.DEBT_COLLATERAL)
330
284
  returns (CollateralDebtData memory cdd_) {
331
285
  data.totalDebtUSD = cdd_.totalDebtUSD;
332
286
  data.totalValueUSD = cdd_.totalValueUSD;
333
287
  data.twvUSD = cdd_.twvUSD;
334
288
  data.totalValue = cdd_.totalValue;
335
289
 
336
- data.healthFactor = cdd_.twvUSD * PERCENTAGE_FACTOR >=
337
- type(uint16).max * cdd_.totalDebtUSD
290
+ data.healthFactor = cdd_.twvUSD * PERCENTAGE_FACTOR >= type(uint16).max * cdd_.totalDebtUSD
338
291
  ? type(uint16).max
339
292
  : uint16((cdd_.twvUSD * PERCENTAGE_FACTOR) / cdd_.totalDebtUSD);
340
293
  data.success = true;
341
294
  } catch {}
342
295
 
343
- uint256 maxTokens = ICreditManagerV3(creditManager)
344
- .collateralTokensCount();
296
+ uint256 maxTokens = ICreditManagerV3(creditManager).collateralTokensCount();
345
297
 
346
298
  // the function is called for every account, so allocating an array of size `maxTokens` and trimming it
347
299
  // might cause issues with memory expansion and we must count the precise number of tokens in advance
@@ -350,12 +302,8 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
350
302
  for (uint256 k; k < maxTokens; ++k) {
351
303
  uint256 mask = 1 << k;
352
304
  if (cdd.enabledTokensMask & mask == 0) {
353
- address token = ICreditManagerV3(creditManager).getTokenByMask(
354
- mask
355
- );
356
- try IERC20(token).balanceOf(creditAccount) returns (
357
- uint256 balance
358
- ) {
305
+ address token = ICreditManagerV3(creditManager).getTokenByMask(mask);
306
+ try IERC20(token).balanceOf(creditAccount) returns (uint256 balance) {
359
307
  if (balance <= 1) continue;
360
308
  } catch {
361
309
  continue;
@@ -368,25 +316,19 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
368
316
  data.tokens = new TokenInfo[](numTokens);
369
317
  uint256 i;
370
318
  while (returnedTokensMask != 0) {
371
- uint256 mask = returnedTokensMask &
372
- uint256(-int256(returnedTokensMask));
373
- address token = ICreditManagerV3(creditManager).getTokenByMask(
374
- mask
375
- );
319
+ uint256 mask = returnedTokensMask & uint256(-int256(returnedTokensMask));
320
+ address token = ICreditManagerV3(creditManager).getTokenByMask(mask);
376
321
  data.tokens[i].token = token;
377
322
  data.tokens[i].mask = mask;
378
323
 
379
- try IERC20(token).balanceOf(creditAccount) returns (
380
- uint256 balance
381
- ) {
324
+ try IERC20(token).balanceOf(creditAccount) returns (uint256 balance) {
382
325
  data.tokens[i].balance = balance;
383
326
  data.tokens[i].success = true;
384
327
  } catch {}
385
328
 
386
329
  if (IPoolQuotaKeeperV3(cdd._poolQuotaKeeper).isQuotedToken(token)) {
387
- (data.tokens[i].quota, ) = IPoolQuotaKeeperV3(
388
- cdd._poolQuotaKeeper
389
- ).getQuotaAndOutstandingInterest(creditAccount, token);
330
+ (data.tokens[i].quota,) =
331
+ IPoolQuotaKeeperV3(cdd._poolQuotaKeeper).getQuotaAndOutstandingInterest(creditAccount, token);
390
332
  }
391
333
 
392
334
  returnedTokensMask ^= mask;
@@ -395,50 +337,30 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
395
337
  }
396
338
 
397
339
  /// @dev Credit account filtering implementation
398
- function _checkFilterMatch(
399
- address creditAccount,
400
- address creditManager,
401
- CreditAccountFilter memory filter
402
- ) internal view returns (bool) {
340
+ function _checkFilterMatch(address creditAccount, address creditManager, CreditAccountFilter memory filter)
341
+ internal
342
+ view
343
+ returns (bool)
344
+ {
403
345
  if (filter.owner != address(0)) {
404
- address owner = ICreditManagerV3(creditManager).getBorrowerOrRevert(
405
- creditAccount
406
- );
346
+ address owner = ICreditManagerV3(creditManager).getBorrowerOrRevert(creditAccount);
407
347
  if (owner != filter.owner) return false;
408
348
  }
409
349
 
410
350
  if (!filter.includeZeroDebt) {
411
- (uint256 debt, , , , , , , ) = ICreditManagerV3(creditManager)
412
- .creditAccountInfo(creditAccount);
351
+ (uint256 debt,,,,,,,) = ICreditManagerV3(creditManager).creditAccountInfo(creditAccount);
413
352
  if (debt == 0) return false;
414
353
  }
415
354
 
416
- if (
417
- filter.minHealthFactor != 0 ||
418
- filter.maxHealthFactor != 0 ||
419
- filter.reverting
420
- ) {
421
- try
422
- ICreditManagerV3(creditManager).calcDebtAndCollateral(
423
- creditAccount,
424
- CollateralCalcTask.DEBT_COLLATERAL
425
- )
355
+ if (filter.minHealthFactor != 0 || filter.maxHealthFactor != 0 || filter.reverting) {
356
+ try ICreditManagerV3(creditManager).calcDebtAndCollateral(creditAccount, CollateralCalcTask.DEBT_COLLATERAL)
426
357
  returns (CollateralDebtData memory cdd) {
427
358
  if (filter.reverting) return false;
428
- uint16 healthFactor = cdd.twvUSD * PERCENTAGE_FACTOR >=
429
- type(uint16).max * cdd.totalDebtUSD
359
+ uint16 healthFactor = cdd.twvUSD * PERCENTAGE_FACTOR >= type(uint16).max * cdd.totalDebtUSD
430
360
  ? type(uint16).max
431
- : uint16(
432
- (cdd.twvUSD * PERCENTAGE_FACTOR) / cdd.totalDebtUSD
433
- );
434
- if (
435
- filter.minHealthFactor != 0 &&
436
- healthFactor < filter.minHealthFactor
437
- ) return false;
438
- if (
439
- filter.maxHealthFactor != 0 &&
440
- healthFactor > filter.maxHealthFactor
441
- ) return false;
361
+ : uint16((cdd.twvUSD * PERCENTAGE_FACTOR) / cdd.totalDebtUSD);
362
+ if (filter.minHealthFactor != 0 && healthFactor < filter.minHealthFactor) return false;
363
+ if (filter.maxHealthFactor != 0 && healthFactor > filter.maxHealthFactor) return false;
442
364
  } catch {
443
365
  if (!filter.reverting) return false;
444
366
  }
@@ -448,17 +370,15 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
448
370
  }
449
371
 
450
372
  /// @dev Credit managers discovery
451
- function _getCreditManagers(
452
- MarketFilter memory filter
453
- ) internal view returns (address[] memory creditManagers) {
454
- address[] memory configurators = IAddressProviderV3_1(ADDRESS_PROVIDER)
455
- .marketConfigurators();
373
+ function _getCreditManagers(MarketFilter memory filter) internal view returns (address[] memory creditManagers) {
374
+ address[] memory configurators = filter.configurators.length != 0
375
+ ? filter.configurators
376
+ : IMarketConfiguratorFactory(marketConfiguratorFactory).getMarketConfigurators();
456
377
 
457
378
  // rough estimate of maximum number of credit managers
458
379
  uint256 max;
459
380
  for (uint256 i; i < configurators.length; ++i) {
460
- address cr = IMarketConfiguratorV3(configurators[i])
461
- .contractsRegister();
381
+ address cr = IMarketConfigurator(configurators[i]).contractsRegister();
462
382
  max += IContractsRegister(cr).getCreditManagers().length;
463
383
  }
464
384
 
@@ -467,39 +387,17 @@ contract CreditAccountCompressor is ICreditAccountCompressor, SanityCheckTrait {
467
387
  creditManagers = new address[](max);
468
388
  uint256 num;
469
389
  for (uint256 i; i < configurators.length; ++i) {
470
- if (filter.curators.length != 0) {
471
- if (
472
- !filter.curators.contains(
473
- IMarketConfiguratorV3(configurators[i]).owner()
474
- )
475
- ) continue;
476
- }
477
-
478
- address cr = IMarketConfiguratorV3(configurators[i])
479
- .contractsRegister();
480
- address[] memory managers = IContractsRegister(cr)
481
- .getCreditManagers();
390
+ address cr = IMarketConfigurator(configurators[i]).contractsRegister();
391
+ address[] memory managers = IContractsRegister(cr).getCreditManagers();
482
392
  for (uint256 j; j < managers.length; ++j) {
483
- // we're only concerned with v3 contracts
484
- uint256 ver = IVersion(managers[j]).version();
485
- if (ver < 3_00 || ver > 3_99) continue;
486
-
487
- if (filter.pools.length != 0) {
488
- if (
489
- !filter.pools.contains(
490
- ICreditManagerV3(managers[j]).pool()
491
- )
492
- ) continue;
493
- }
494
-
495
- if (filter.underlying != address(0)) {
496
- if (
497
- ICreditManagerV3(managers[j]).underlying() !=
498
- filter.underlying
499
- ) continue;
393
+ address manager = managers[j];
394
+ // FIXME: there's room for optimization that allows to avoid scanning over all configurators
395
+ if (filter.pools.length != 0 && !filter.pools.contains(ICreditManagerV3(manager).pool())) continue;
396
+ if (filter.underlying != address(0) && ICreditManagerV3(manager).underlying() != filter.underlying) {
397
+ continue;
500
398
  }
501
399
 
502
- creditManagers[num++] = managers[j];
400
+ creditManagers[num++] = manager;
503
401
  }
504
402
  }
505
403
 
@@ -0,0 +1,91 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Gearbox Protocol. Generalized leverage for DeFi protocols
3
+ // (c) Gearbox Foundation, 2024.
4
+ pragma solidity ^0.8.23;
5
+
6
+ import {ICreditConfiguratorV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditConfiguratorV3.sol";
7
+ import {CreditFacadeV3} from "@gearbox-protocol/core-v3/contracts/credit/CreditFacadeV3.sol";
8
+ import {ICreditManagerV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditManagerV3.sol";
9
+
10
+ import {BaseLib} from "../libraries/BaseLib.sol";
11
+
12
+ import {BaseParams, BaseState} from "../types/BaseState.sol";
13
+ import {CreditFacadeState} from "../types/CreditFacadeState.sol";
14
+ import {CollateralToken, CreditManagerState} from "../types/CreditManagerState.sol";
15
+ import {CreditSuiteData} from "../types/CreditSuiteData.sol";
16
+
17
+ import {AdapterCompressor} from "./AdapterCompressor.sol";
18
+
19
+ contract CreditSuiteCompressor {
20
+ AdapterCompressor adapterCompressor;
21
+
22
+ constructor() {
23
+ adapterCompressor = new AdapterCompressor();
24
+ }
25
+
26
+ function getCreditSuiteData(address creditManager) public view returns (CreditSuiteData memory result) {
27
+ result.creditManager = getCreditManagerState(creditManager);
28
+ result.creditFacade = getCreditFacadeState(ICreditManagerV3(creditManager).creditFacade());
29
+ result.creditConfigurator = BaseLib.getBaseState(
30
+ ICreditManagerV3(creditManager).creditConfigurator(), "CREDIT_CONFIGURATOR", address(0)
31
+ );
32
+
33
+ result.adapters = adapterCompressor.getAdapters(creditManager);
34
+ }
35
+
36
+ /// @dev Returns CreditManagerData for a particular _cm
37
+ /// @param _cm CreditManager address
38
+ function getCreditManagerState(address _cm) public view returns (CreditManagerState memory result) {
39
+ ICreditManagerV3 creditManager = ICreditManagerV3(_cm);
40
+ ICreditConfiguratorV3 creditConfigurator = ICreditConfiguratorV3(creditManager.creditConfigurator());
41
+ CreditFacadeV3 creditFacade = CreditFacadeV3(creditManager.creditFacade());
42
+
43
+ result.baseParams = BaseLib.getBaseParams(_cm, "CREDIT_MANAGER", address(0));
44
+ // string name;
45
+ result.name = ICreditManagerV3(_cm).name();
46
+
47
+ // address accountFactory;
48
+ result.accountFactory = creditManager.accountFactory();
49
+ // address underlying;
50
+ result.underlying = creditManager.underlying();
51
+ // address pool;
52
+ result.pool = creditManager.pool();
53
+ // address creditFacade;
54
+ result.creditFacade = address(creditFacade);
55
+ // address creditConfigurator;
56
+ result.creditConfigurator = address(creditConfigurator);
57
+ // uint8 maxEnabledTokens;
58
+ result.maxEnabledTokens = creditManager.maxEnabledTokens();
59
+
60
+ uint256 collateralTokensCount = creditManager.collateralTokensCount();
61
+ result.collateralTokens = new CollateralToken[](collateralTokensCount);
62
+ for (uint256 i; i < collateralTokensCount; ++i) {
63
+ (address token, uint16 lt) = creditManager.collateralTokenByMask(1 << i);
64
+ result.collateralTokens[i] = CollateralToken(token, lt);
65
+ }
66
+
67
+ (
68
+ result.feeInterest,
69
+ result.feeLiquidation,
70
+ result.liquidationDiscount,
71
+ result.feeLiquidationExpired,
72
+ result.liquidationDiscountExpired
73
+ ) = creditManager.fees();
74
+ }
75
+
76
+ /// @dev Returns CreditManagerData for a particular _cm
77
+ /// @param _cf CreditFacade address
78
+ function getCreditFacadeState(address _cf) public view returns (CreditFacadeState memory result) {
79
+ CreditFacadeV3 creditFacade = CreditFacadeV3(_cf);
80
+
81
+ result.baseParams = BaseLib.getBaseParams(_cf, "CREDIT_FACADE", address(0));
82
+ result.expirable = creditFacade.expirable();
83
+ result.degenNFT = creditFacade.degenNFT();
84
+ result.expirationDate = creditFacade.expirationDate();
85
+ result.maxDebtPerBlockMultiplier = creditFacade.maxDebtPerBlockMultiplier();
86
+ result.botList = creditFacade.botList();
87
+ (result.minDebt, result.maxDebt) = creditFacade.debtLimits();
88
+ result.forbiddenTokenMask = creditFacade.forbiddenTokenMask();
89
+ result.isPaused = creditFacade.paused();
90
+ }
91
+ }