1
1
// SPDX-License-Identifier: UNLICENSED
2
2
pragma solidity ^ 0.8.27 ;
3
3
4
+ import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol " ;
5
+
4
6
import {IEulerSwapFactory, IEulerSwap} from "./interfaces/IEulerSwapFactory.sol " ;
5
7
import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol " ;
6
8
import {GenericFactory} from "evk/GenericFactory/GenericFactory.sol " ;
@@ -13,15 +15,19 @@ import {MetaProxyDeployer} from "./utils/MetaProxyDeployer.sol";
13
15
/// @custom:security-contact [email protected]
14
16
/// @author Euler Labs (https://www.eulerlabs.com/)
15
17
contract EulerSwapFactory is IEulerSwapFactory , EVCUtil , ProtocolFee {
16
- /// @dev An array to store all pools addresses.
17
- address [] private allPools;
18
+ using EnumerableSet for EnumerableSet.AddressSet;
19
+
18
20
/// @dev Vaults must be deployed by this factory
19
21
address public immutable evkFactory;
20
22
/// @dev The EulerSwap code instance that will be proxied to
21
23
address public immutable eulerSwapImpl;
22
- /// @dev Mapping between euler account and EulerAccountState
23
- mapping (address eulerAccount = > EulerAccountState state ) private eulerAccountState;
24
- mapping (address asset0 = > mapping (address asset1 = > address [])) private poolMap;
24
+
25
+ /// @dev Mapping from euler account to pool, if installed
26
+ mapping (address eulerAccount = > address ) internal installedPools;
27
+ /// @dev Set of all pool addresses
28
+ EnumerableSet.AddressSet internal allPools;
29
+ /// @dev Mapping from sorted pair of underlyings to set of pools
30
+ mapping (address asset0 = > mapping (address asset1 = > EnumerableSet.AddressSet)) internal poolMap;
25
31
26
32
event PoolDeployed (address indexed asset0 , address indexed asset1 , address indexed eulerAccount , address pool );
27
33
event PoolConfig (address indexed pool , IEulerSwap.Params params , IEulerSwap.InitialState initialState );
@@ -102,12 +108,12 @@ contract EulerSwapFactory is IEulerSwapFactory, EVCUtil, ProtocolFee {
102
108
103
109
/// @inheritdoc IEulerSwapFactory
104
110
function poolByEulerAccount (address eulerAccount ) external view returns (address ) {
105
- return eulerAccountState [eulerAccount].pool ;
111
+ return installedPools [eulerAccount];
106
112
}
107
113
108
114
/// @inheritdoc IEulerSwapFactory
109
115
function poolsLength () external view returns (uint256 ) {
110
- return allPools.length ;
116
+ return allPools.length () ;
111
117
}
112
118
113
119
/// @inheritdoc IEulerSwapFactory
@@ -122,7 +128,7 @@ contract EulerSwapFactory is IEulerSwapFactory, EVCUtil, ProtocolFee {
122
128
123
129
/// @inheritdoc IEulerSwapFactory
124
130
function poolsByPairLength (address asset0 , address asset1 ) external view returns (uint256 ) {
125
- return poolMap[asset0][asset1].length ;
131
+ return poolMap[asset0][asset1].length () ;
126
132
}
127
133
128
134
/// @inheritdoc IEulerSwapFactory
@@ -147,16 +153,10 @@ contract EulerSwapFactory is IEulerSwapFactory, EVCUtil, ProtocolFee {
147
153
148
154
(address asset0 , address asset1 ) = _getAssets (newOperator);
149
155
150
- address [] storage poolMapArray = poolMap[asset0][asset1] ;
156
+ installedPools[eulerAccount] = newOperator ;
151
157
152
- eulerAccountState[eulerAccount] = EulerAccountState ({
153
- pool: newOperator,
154
- allPoolsIndex: uint48 (allPools.length ),
155
- poolMapIndex: uint48 (poolMapArray.length )
156
- });
157
-
158
- allPools.push (newOperator);
159
- poolMapArray.push (newOperator);
158
+ allPools.add (newOperator);
159
+ poolMap[asset0][asset1].add (newOperator);
160
160
}
161
161
162
162
/// @notice Uninstalls the pool associated with the given Euler account
@@ -165,32 +165,22 @@ contract EulerSwapFactory is IEulerSwapFactory, EVCUtil, ProtocolFee {
165
165
/// @dev If no pool exists for the account, the function returns without any action
166
166
/// @param eulerAccount The address of the Euler account whose pool should be uninstalled
167
167
function uninstall (address eulerAccount ) internal {
168
- address pool = eulerAccountState [eulerAccount].pool ;
168
+ address pool = installedPools [eulerAccount];
169
169
170
170
if (pool == address (0 )) return ;
171
171
172
172
require (! evc.isAccountOperatorAuthorized (eulerAccount, pool), OldOperatorStillInstalled ());
173
173
174
174
(address asset0 , address asset1 ) = _getAssets (pool);
175
175
176
- address [] storage poolMapArr = poolMap[asset0][asset1];
177
-
178
- swapAndPop (allPools, eulerAccountState[eulerAccount].allPoolsIndex);
179
- swapAndPop (poolMapArr, eulerAccountState[eulerAccount].poolMapIndex);
176
+ allPools.remove (pool);
177
+ poolMap[asset0][asset1].remove (pool);
180
178
181
- delete eulerAccountState [eulerAccount];
179
+ delete installedPools [eulerAccount];
182
180
183
181
emit PoolUninstalled (asset0, asset1, eulerAccount, pool);
184
182
}
185
183
186
- /// @notice Swaps the element at the given index with the last element and removes the last element
187
- /// @param arr The storage array to modify
188
- /// @param index The index of the element to remove
189
- function swapAndPop (address [] storage arr , uint256 index ) internal {
190
- arr[index] = arr[arr.length - 1 ];
191
- arr.pop ();
192
- }
193
-
194
184
/// @notice Retrieves the asset addresses for a given pool
195
185
/// @dev Calls the pool contract to get its asset0 and asset1 addresses
196
186
/// @param pool The address of the pool to query
@@ -206,14 +196,18 @@ contract EulerSwapFactory is IEulerSwapFactory, EVCUtil, ProtocolFee {
206
196
/// @param start The starting index of the slice (inclusive)
207
197
/// @param end The ending index of the slice (exclusive)
208
198
/// @return A new memory array containing the requested slice of addresses
209
- function _getSlice (address [] storage arr , uint256 start , uint256 end ) internal view returns (address [] memory ) {
210
- uint256 length = arr.length ;
199
+ function _getSlice (EnumerableSet.AddressSet storage arr , uint256 start , uint256 end )
200
+ internal
201
+ view
202
+ returns (address [] memory )
203
+ {
204
+ uint256 length = arr.length ();
211
205
if (end == type (uint256 ).max) end = length;
212
206
if (end < start || end > length) revert SliceOutOfBounds ();
213
207
214
208
address [] memory slice = new address [](end - start);
215
209
for (uint256 i; i < end - start; ++ i) {
216
- slice[i] = arr[ start + i] ;
210
+ slice[i] = arr. at ( start + i) ;
217
211
}
218
212
219
213
return slice;
0 commit comments