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 );
@@ -98,12 +104,12 @@ contract EulerSwapFactory is IEulerSwapFactory, EVCUtil, ProtocolFee {
98
104
99
105
/// @inheritdoc IEulerSwapFactory
100
106
function poolByEulerAccount (address eulerAccount ) external view returns (address ) {
101
- return eulerAccountState [eulerAccount].pool ;
107
+ return installedPools [eulerAccount];
102
108
}
103
109
104
110
/// @inheritdoc IEulerSwapFactory
105
111
function poolsLength () external view returns (uint256 ) {
106
- return allPools.length ;
112
+ return allPools.length () ;
107
113
}
108
114
109
115
/// @inheritdoc IEulerSwapFactory
@@ -113,12 +119,12 @@ contract EulerSwapFactory is IEulerSwapFactory, EVCUtil, ProtocolFee {
113
119
114
120
/// @inheritdoc IEulerSwapFactory
115
121
function pools () external view returns (address [] memory ) {
116
- return _getSlice ( allPools, 0 , type ( uint256 ).max );
122
+ return allPools. values ( );
117
123
}
118
124
119
125
/// @inheritdoc IEulerSwapFactory
120
126
function poolsByPairLength (address asset0 , address asset1 ) external view returns (uint256 ) {
121
- return poolMap[asset0][asset1].length ;
127
+ return poolMap[asset0][asset1].length () ;
122
128
}
123
129
124
130
/// @inheritdoc IEulerSwapFactory
@@ -132,7 +138,7 @@ contract EulerSwapFactory is IEulerSwapFactory, EVCUtil, ProtocolFee {
132
138
133
139
/// @inheritdoc IEulerSwapFactory
134
140
function poolsByPair (address asset0 , address asset1 ) external view returns (address [] memory ) {
135
- return _getSlice ( poolMap[asset0][asset1], 0 , type ( uint256 ).max );
141
+ return poolMap[asset0][asset1]. values ( );
136
142
}
137
143
138
144
/// @notice Validates operator authorization for euler account and update the relevant EulerAccountState.
@@ -143,16 +149,10 @@ contract EulerSwapFactory is IEulerSwapFactory, EVCUtil, ProtocolFee {
143
149
144
150
(address asset0 , address asset1 ) = _getAssets (newOperator);
145
151
146
- address [] storage poolMapArray = poolMap[asset0][asset1] ;
152
+ installedPools[eulerAccount] = newOperator ;
147
153
148
- eulerAccountState[eulerAccount] = EulerAccountState ({
149
- pool: newOperator,
150
- allPoolsIndex: uint48 (allPools.length ),
151
- poolMapIndex: uint48 (poolMapArray.length )
152
- });
153
-
154
- allPools.push (newOperator);
155
- poolMapArray.push (newOperator);
154
+ allPools.add (newOperator);
155
+ poolMap[asset0][asset1].add (newOperator);
156
156
}
157
157
158
158
/// @notice Uninstalls the pool associated with the given Euler account
@@ -161,32 +161,22 @@ contract EulerSwapFactory is IEulerSwapFactory, EVCUtil, ProtocolFee {
161
161
/// @dev If no pool exists for the account, the function returns without any action
162
162
/// @param eulerAccount The address of the Euler account whose pool should be uninstalled
163
163
function uninstall (address eulerAccount ) internal {
164
- address pool = eulerAccountState [eulerAccount].pool ;
164
+ address pool = installedPools [eulerAccount];
165
165
166
166
if (pool == address (0 )) return ;
167
167
168
168
require (! evc.isAccountOperatorAuthorized (eulerAccount, pool), OldOperatorStillInstalled ());
169
169
170
170
(address asset0 , address asset1 ) = _getAssets (pool);
171
171
172
- address [] storage poolMapArr = poolMap[asset0][asset1];
173
-
174
- swapAndPop (allPools, eulerAccountState[eulerAccount].allPoolsIndex);
175
- swapAndPop (poolMapArr, eulerAccountState[eulerAccount].poolMapIndex);
172
+ allPools.remove (pool);
173
+ poolMap[asset0][asset1].remove (pool);
176
174
177
- delete eulerAccountState [eulerAccount];
175
+ delete installedPools [eulerAccount];
178
176
179
177
emit PoolUninstalled (asset0, asset1, eulerAccount, pool);
180
178
}
181
179
182
- /// @notice Swaps the element at the given index with the last element and removes the last element
183
- /// @param arr The storage array to modify
184
- /// @param index The index of the element to remove
185
- function swapAndPop (address [] storage arr , uint256 index ) internal {
186
- arr[index] = arr[arr.length - 1 ];
187
- arr.pop ();
188
- }
189
-
190
180
/// @notice Retrieves the asset addresses for a given pool
191
181
/// @dev Calls the pool contract to get its asset0 and asset1 addresses
192
182
/// @param pool The address of the pool to query
@@ -202,14 +192,18 @@ contract EulerSwapFactory is IEulerSwapFactory, EVCUtil, ProtocolFee {
202
192
/// @param start The starting index of the slice (inclusive)
203
193
/// @param end The ending index of the slice (exclusive)
204
194
/// @return A new memory array containing the requested slice of addresses
205
- function _getSlice (address [] storage arr , uint256 start , uint256 end ) internal view returns (address [] memory ) {
206
- uint256 length = arr.length ;
195
+ function _getSlice (EnumerableSet.AddressSet storage arr , uint256 start , uint256 end )
196
+ internal
197
+ view
198
+ returns (address [] memory )
199
+ {
200
+ uint256 length = arr.length ();
207
201
if (end == type (uint256 ).max) end = length;
208
202
if (end < start || end > length) revert SliceOutOfBounds ();
209
203
210
204
address [] memory slice = new address [](end - start);
211
205
for (uint256 i; i < end - start; ++ i) {
212
- slice[i] = arr[ start + i] ;
206
+ slice[i] = arr. at ( start + i) ;
213
207
}
214
208
215
209
return slice;
0 commit comments