@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.
- package/contracts/compressors/AdapterCompressor.sol +7 -8
- package/contracts/compressors/CreditAccountCompressor.sol +100 -202
- package/contracts/compressors/CreditSuiteCompressor.sol +91 -0
- package/contracts/compressors/MarketCompressor.sol +91 -68
- package/contracts/compressors/PoolCompressor.sol +25 -141
- package/contracts/compressors/PriceFeedCompressor.sol +7 -7
- package/contracts/data/Types.sol +1 -1
- package/contracts/data/ZapperRegister.sol +5 -8
- package/contracts/interfaces/IAdapterCompressor.sol +2 -2
- package/contracts/interfaces/ICreditAccountCompressor.sol +2 -1
- package/contracts/interfaces/IMarketCompressor.sol +4 -6
- package/contracts/libraries/BaseLib.sol +1 -1
- package/contracts/serializers/pool/{LinearInterestModelSerializer.sol → LinearInterestRateModelSerializer.sol} +2 -1
- package/contracts/test/ForkTest.sol +29 -8
- package/contracts/test/MultiPause.t.sol +2 -2
- package/contracts/types/CreditAccountState.sol +2 -24
- package/contracts/types/CreditFacadeState.sol +2 -5
- package/contracts/types/CreditManagerState.sol +11 -8
- package/contracts/types/CreditSuiteData.sol +20 -0
- package/contracts/types/Filters.sol +30 -0
- package/contracts/types/MarketData.sol +11 -34
- package/contracts/types/PoolState.sol +2 -5
- package/contracts/types/PriceOracleState.sol +1 -1
- package/contracts/types/TokenData.sol +0 -9
- package/package.json +1 -1
- package/contracts/interfaces/ITreasurySplitter.sol +0 -9
- package/contracts/interfaces/IVersion.sol +0 -13
- package/contracts/market/MarketManager.sol +0 -15
- 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 {
|
|
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
|
|
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
|
|
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
|
|
78
|
-
adapters[i].baseParams.contractType =
|
|
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 {
|
|
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 {
|
|
19
|
-
import {
|
|
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,
|
|
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
|
|
49
|
+
address public immutable addressProvider;
|
|
38
50
|
|
|
39
|
-
|
|
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
|
|
44
|
-
constructor(address
|
|
45
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
-
|
|
315
|
-
);
|
|
272
|
+
data.owner = ICreditManagerV3(creditManager).getBorrowerOrRevert(creditAccount);
|
|
273
|
+
data.expirationDate = ICreditFacadeV3(creditManager).expirationDate();
|
|
316
274
|
|
|
317
|
-
CollateralDebtData memory cdd =
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
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
|
|
412
|
-
.creditAccountInfo(creditAccount);
|
|
351
|
+
(uint256 debt,,,,,,,) = ICreditManagerV3(creditManager).creditAccountInfo(creditAccount);
|
|
413
352
|
if (debt == 0) return false;
|
|
414
353
|
}
|
|
415
354
|
|
|
416
|
-
if (
|
|
417
|
-
|
|
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
|
-
|
|
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
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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 =
|
|
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
|
-
|
|
471
|
-
|
|
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
|
-
|
|
484
|
-
|
|
485
|
-
if (
|
|
486
|
-
|
|
487
|
-
|
|
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++] =
|
|
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
|
+
}
|