@oldzeppelin/contract 1.1.1
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/.docker/Dockerfile +17 -0
- package/.dockerignore +7 -0
- package/.env.sample +24 -0
- package/.gitlab-ci.yml +51 -0
- package/.gitmodules +15 -0
- package/.prettierrc +10 -0
- package/.solcover.js +4 -0
- package/.vscode/settings.json +23 -0
- package/LICENSE.MD +51 -0
- package/README.md +135 -0
- package/contracts/arbitrum/contracts/controllers/UniswapV2ControllerArbitrum.sol +37 -0
- package/contracts/arbitrum/contracts/controllers/UniswapV3ControllerArbitrum.sol +46 -0
- package/contracts/arbitrum/contracts/oracle/PriceOracleArbitrum.sol +51 -0
- package/contracts/main/contracts/controllers/Controller.sol +61 -0
- package/contracts/main/contracts/controllers/IController.sol +81 -0
- package/contracts/main/contracts/controllers/OneInchV5Controller.sol +332 -0
- package/contracts/main/contracts/controllers/UnoswapV2Controller.sol +789 -0
- package/contracts/main/contracts/controllers/UnoswapV3Controller.sol +1018 -0
- package/contracts/main/contracts/core/CoreWhitelist.sol +192 -0
- package/contracts/main/contracts/core/ICoreWhitelist.sol +92 -0
- package/contracts/main/contracts/core/IUFarmCore.sol +95 -0
- package/contracts/main/contracts/core/UFarmCore.sol +402 -0
- package/contracts/main/contracts/fund/FundFactory.sol +59 -0
- package/contracts/main/contracts/fund/IUFarmFund.sol +68 -0
- package/contracts/main/contracts/fund/UFarmFund.sol +504 -0
- package/contracts/main/contracts/oracle/ChainlinkedOracle.sol +71 -0
- package/contracts/main/contracts/oracle/IChainlinkAggregator.sol +18 -0
- package/contracts/main/contracts/oracle/IPriceOracle.sol +55 -0
- package/contracts/main/contracts/oracle/PriceOracle.sol +20 -0
- package/contracts/main/contracts/oracle/PriceOracleCore.sol +212 -0
- package/contracts/main/contracts/oracle/WstETHOracle.sol +64 -0
- package/contracts/main/contracts/permissions/Permissions.sol +54 -0
- package/contracts/main/contracts/permissions/UFarmPermissionsModel.sol +136 -0
- package/contracts/main/contracts/pool/IPoolAdmin.sol +57 -0
- package/contracts/main/contracts/pool/IUFarmPool.sol +304 -0
- package/contracts/main/contracts/pool/PerformanceFeeLib.sol +81 -0
- package/contracts/main/contracts/pool/PoolAdmin.sol +437 -0
- package/contracts/main/contracts/pool/PoolFactory.sol +74 -0
- package/contracts/main/contracts/pool/PoolWhitelist.sol +70 -0
- package/contracts/main/contracts/pool/UFarmPool.sol +959 -0
- package/contracts/main/shared/AssetController.sol +194 -0
- package/contracts/main/shared/ECDSARecover.sol +91 -0
- package/contracts/main/shared/NZGuard.sol +99 -0
- package/contracts/main/shared/SafeOPS.sol +128 -0
- package/contracts/main/shared/UFarmCoreLink.sol +83 -0
- package/contracts/main/shared/UFarmErrors.sol +16 -0
- package/contracts/main/shared/UFarmMathLib.sol +80 -0
- package/contracts/main/shared/UFarmOwnableUUPS.sol +59 -0
- package/contracts/main/shared/UFarmOwnableUUPSBeacon.sol +34 -0
- package/contracts/test/Block.sol +15 -0
- package/contracts/test/InchSwapTestProxy.sol +292 -0
- package/contracts/test/MockPoolAdmin.sol +8 -0
- package/contracts/test/MockUFarmPool.sol +8 -0
- package/contracts/test/MockV3wstETHstETHAgg.sol +128 -0
- package/contracts/test/MockedWETH9.sol +72 -0
- package/contracts/test/OneInchToUFarmTestEnv.sol +466 -0
- package/contracts/test/StableCoin.sol +25 -0
- package/contracts/test/UFarmMockSequencerUptimeFeed.sol +44 -0
- package/contracts/test/UFarmMockV3Aggregator.sol +145 -0
- package/contracts/test/UUPSBlock.sol +19 -0
- package/contracts/test/ufarmLocal/MulticallV3.sol +220 -0
- package/contracts/test/ufarmLocal/controllers/UniswapV2ControllerUFarm.sol +27 -0
- package/contracts/test/ufarmLocal/controllers/UniswapV3ControllerUFarm.sol +43 -0
- package/deploy/100_test_env_setup.ts +483 -0
- package/deploy/20_deploy_uniV2.ts +48 -0
- package/deploy/21_create_pairs_uniV2.ts +149 -0
- package/deploy/22_deploy_mocked_aggregators.ts +123 -0
- package/deploy/22_deploy_wsteth_oracle.ts +65 -0
- package/deploy/23_deploy_uniV3.ts +80 -0
- package/deploy/24_create_pairs_uniV3.ts +140 -0
- package/deploy/25_deploy_oneInch.ts +38 -0
- package/deploy/2_deploy_multicall.ts +34 -0
- package/deploy/30_deploy_price_oracle.ts +33 -0
- package/deploy/3_deploy_lido.ts +114 -0
- package/deploy/40_deploy_pool_beacon.ts +19 -0
- package/deploy/41_deploy_poolAdmin_beacon.ts +19 -0
- package/deploy/42_deploy_ufarmcore.ts +29 -0
- package/deploy/43_deploy_fund_beacon.ts +19 -0
- package/deploy/4_deploy_tokens.ts +76 -0
- package/deploy/50_deploy_poolFactory.ts +35 -0
- package/deploy/51_deploy_fundFactory.ts +29 -0
- package/deploy/60_init_contracts.ts +101 -0
- package/deploy/61_whitelist_tokens.ts +18 -0
- package/deploy/70_deploy_uniV2Controller.ts +70 -0
- package/deploy/71_deploy_uniV3Controller.ts +67 -0
- package/deploy/72_deploy_oneInchController.ts +25 -0
- package/deploy/79_whitelist_controllers.ts +125 -0
- package/deploy/ufarm/arbitrum/1_prepare_env.ts +82 -0
- package/deploy/ufarm/arbitrum/2_deploy_ufarm.ts +178 -0
- package/deploy/ufarm/arbitrum-sepolia/1000_prepare_arb_sepolia_env.ts +308 -0
- package/deploy-config.json +112 -0
- package/deploy-data/oracles.csv +32 -0
- package/deploy-data/protocols.csv +10 -0
- package/deploy-data/tokens.csv +32 -0
- package/docker-compose.yml +67 -0
- package/hardhat.config.ts +449 -0
- package/index.js +93 -0
- package/package.json +82 -0
- package/scripts/_deploy_helpers.ts +992 -0
- package/scripts/_deploy_network_options.ts +49 -0
- package/scripts/activatePool.ts +51 -0
- package/scripts/createPool.ts +62 -0
- package/scripts/deploy_1inch_proxy.ts +98 -0
- package/scripts/pool-data.ts +420 -0
- package/scripts/post-deploy.sh +24 -0
- package/scripts/setUniV2Rate.ts +252 -0
- package/scripts/swapOneInchV5.ts +94 -0
- package/scripts/swapUniswapV2.ts +65 -0
- package/scripts/swapUniswapV3.ts +71 -0
- package/scripts/test.ts +61 -0
- package/scripts/typings-copy-artifacts.ts +83 -0
- package/tasks/boostPool.ts +39 -0
- package/tasks/createFund.ts +44 -0
- package/tasks/deboostPool.ts +48 -0
- package/tasks/grantUFarmPermissions.ts +57 -0
- package/tasks/index.ts +7 -0
- package/tasks/mintUSDT.ts +62 -0
- package/test/Periphery.test.ts +640 -0
- package/test/PriceOracle.test.ts +82 -0
- package/test/TestCases.MD +109 -0
- package/test/UFarmCore.test.ts +331 -0
- package/test/UFarmFund.test.ts +406 -0
- package/test/UFarmPool.test.ts +4736 -0
- package/test/_fixtures.ts +783 -0
- package/test/_helpers.ts +2195 -0
- package/test/_oneInchTestData.ts +632 -0
- package/tsconfig.json +12 -0
@@ -0,0 +1,332 @@
|
|
1
|
+
// SPDX-License-Identifier: GPL-2.0-or-later
|
2
|
+
|
3
|
+
pragma solidity ^0.8.0;
|
4
|
+
|
5
|
+
/// CONTRACTS
|
6
|
+
import {UFarmErrors} from '../../shared/UFarmErrors.sol';
|
7
|
+
import {NZGuard} from '../../shared/NZGuard.sol';
|
8
|
+
import {Controller, IController} from './Controller.sol';
|
9
|
+
import {SafeOPS} from '../../shared/SafeOPS.sol';
|
10
|
+
import {ReentrancyGuard} from '@openzeppelin/contracts/utils/ReentrancyGuard.sol';
|
11
|
+
|
12
|
+
/// INTERFACES
|
13
|
+
import {IUFarmPool} from '../pool/IUFarmPool.sol';
|
14
|
+
import {IUFarmCore} from '../core/IUFarmCore.sol';
|
15
|
+
import {ICoreWhitelist} from '../core/ICoreWhitelist.sol';
|
16
|
+
import {IPoolWhitelist} from '../pool/PoolWhitelist.sol';
|
17
|
+
import {IUniswapV2Pair} from '../../../test/Uniswap/contracts/v2-core/contracts/interfaces/IUniswapV2Pair.sol';
|
18
|
+
|
19
|
+
/// LIBRARIES
|
20
|
+
import {BytesLib} from '../../../test/UniswapV3/@uniswap/v3-periphery/contracts/libraries/BytesLib.sol';
|
21
|
+
|
22
|
+
interface IAggregationExecutor {
|
23
|
+
/// @notice propagates information about original msg.sender and executes arbitrary data
|
24
|
+
function execute(address msgSender) external payable; // 0x4b64e492
|
25
|
+
}
|
26
|
+
|
27
|
+
interface IAggregationRouterV5 {
|
28
|
+
struct SwapDescription {
|
29
|
+
address srcToken;
|
30
|
+
address dstToken;
|
31
|
+
address payable srcReceiver;
|
32
|
+
address payable dstReceiver;
|
33
|
+
uint256 amount;
|
34
|
+
uint256 minReturnAmount;
|
35
|
+
uint256 flags;
|
36
|
+
}
|
37
|
+
|
38
|
+
function swap(
|
39
|
+
IAggregationExecutor executor,
|
40
|
+
SwapDescription calldata desc,
|
41
|
+
bytes calldata permit,
|
42
|
+
bytes calldata data
|
43
|
+
) external payable returns (uint256 returnAmount, uint256 spentAmount);
|
44
|
+
|
45
|
+
function unoswap(
|
46
|
+
address srcToken,
|
47
|
+
uint256 amount,
|
48
|
+
uint256 minReturn,
|
49
|
+
uint256[] calldata pools
|
50
|
+
) external payable returns (uint256 returnAmount);
|
51
|
+
|
52
|
+
function unoswapTo(
|
53
|
+
address payable recipient,
|
54
|
+
address srcToken,
|
55
|
+
uint256 amount,
|
56
|
+
uint256 minReturn,
|
57
|
+
uint256[] calldata pools
|
58
|
+
) external payable returns (uint256 returnAmount);
|
59
|
+
|
60
|
+
function uniswapV3Swap(
|
61
|
+
uint256 amount,
|
62
|
+
uint256 minReturn,
|
63
|
+
uint256[] calldata pools
|
64
|
+
) external payable returns (uint256 returnAmount);
|
65
|
+
|
66
|
+
function uniswapV3SwapTo(
|
67
|
+
address payable recipient,
|
68
|
+
uint256 amount,
|
69
|
+
uint256 minReturn,
|
70
|
+
uint256[] calldata pools
|
71
|
+
) external payable returns (uint256 returnAmount);
|
72
|
+
}
|
73
|
+
|
74
|
+
interface IUniswapV3Pool {
|
75
|
+
function token0() external view returns (address);
|
76
|
+
|
77
|
+
function token1() external view returns (address);
|
78
|
+
}
|
79
|
+
|
80
|
+
/**
|
81
|
+
* @title 1Inch V5 Controller contract
|
82
|
+
* @author https://ufarm.digital/
|
83
|
+
* @notice Controller contract for 1Inch V5 aggregation router
|
84
|
+
*/
|
85
|
+
contract OneInchV5Controller is Controller, NZGuard, UFarmErrors, ReentrancyGuard {
|
86
|
+
using BytesLib for bytes;
|
87
|
+
|
88
|
+
bytes32 internal constant _PROTOCOL = keccak256(abi.encodePacked('OneInchV5'));
|
89
|
+
|
90
|
+
/// @notice 1inch V5 aggregation router address
|
91
|
+
address public immutable aggregationRouterV5;
|
92
|
+
|
93
|
+
constructor(address _aggregationRouterV5) {
|
94
|
+
aggregationRouterV5 = _aggregationRouterV5;
|
95
|
+
}
|
96
|
+
|
97
|
+
/**
|
98
|
+
* @notice Delegates swap to 1inch V5 aggregation router
|
99
|
+
* @param tokenIn - token to swap from
|
100
|
+
* @param tokenOut - token to swap to
|
101
|
+
* @param amountIn - amount of tokenIn to swap
|
102
|
+
* @param amountOut - minimum amount of tokenOut to receive
|
103
|
+
* @param protocol - protocol hashed name
|
104
|
+
*/
|
105
|
+
event SwapOneInchV5(
|
106
|
+
address indexed tokenIn,
|
107
|
+
address indexed tokenOut,
|
108
|
+
uint256 amountIn,
|
109
|
+
uint256 amountOut,
|
110
|
+
bytes32 indexed protocol
|
111
|
+
);
|
112
|
+
|
113
|
+
error EmptySwapPath();
|
114
|
+
error InvalidPath();
|
115
|
+
error InvalidMethod();
|
116
|
+
error InvalidRecipient();
|
117
|
+
error OneInchSwapFailed();
|
118
|
+
|
119
|
+
/**
|
120
|
+
* @inheritdoc IController
|
121
|
+
*/
|
122
|
+
function PROTOCOL() public pure override returns (bytes32) {
|
123
|
+
return _PROTOCOL;
|
124
|
+
}
|
125
|
+
|
126
|
+
/**
|
127
|
+
* @notice Executes multiple swaps one by one using 1inch V5 aggregation router
|
128
|
+
* @param _multiData - array of bytes data for multiple swaps
|
129
|
+
*/
|
130
|
+
function delegated1InchMultiSwap(
|
131
|
+
bytes[] calldata _multiData
|
132
|
+
) external checkDelegateCall nonReentrant {
|
133
|
+
uint256 swapsCount = _multiData.length;
|
134
|
+
if (swapsCount == 0) revert EmptySwapPath();
|
135
|
+
|
136
|
+
(address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut) = _run1InchSwap(
|
137
|
+
_multiData[0]
|
138
|
+
);
|
139
|
+
|
140
|
+
for (uint256 i = 1; i < swapsCount; ++i) {
|
141
|
+
(, tokenOut, , amountOut) = _run1InchSwap(_multiData[i]);
|
142
|
+
}
|
143
|
+
|
144
|
+
_afterSwapExecuted(tokenIn, tokenOut, amountIn, amountOut);
|
145
|
+
}
|
146
|
+
|
147
|
+
/**
|
148
|
+
* @notice Executes swap using 1inch V5 aggregation router
|
149
|
+
* @param _data - swap transaction data
|
150
|
+
*/
|
151
|
+
function delegated1InchSwap(bytes calldata _data) public checkDelegateCall nonReentrant {
|
152
|
+
(address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut) = _run1InchSwap(_data);
|
153
|
+
_afterSwapExecuted(tokenIn, tokenOut, amountIn, amountOut);
|
154
|
+
}
|
155
|
+
|
156
|
+
function _run1InchSwap(
|
157
|
+
bytes memory _data
|
158
|
+
) internal returns (address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut) {
|
159
|
+
bytes4 method;
|
160
|
+
assembly {
|
161
|
+
method := mload(add(_data, 32)) // load first 4 bytes of data
|
162
|
+
}
|
163
|
+
|
164
|
+
uint256[] memory pools;
|
165
|
+
|
166
|
+
if (method == IAggregationRouterV5.unoswapTo.selector) {
|
167
|
+
address payable recipient;
|
168
|
+
address localTokenIn;
|
169
|
+
(recipient, localTokenIn, amountIn, amountOut, pools) = abi.decode(
|
170
|
+
_data.slice(4, _data.length - 4),
|
171
|
+
(address, address, uint256, uint256, uint256[])
|
172
|
+
);
|
173
|
+
|
174
|
+
if (recipient != address(this)) revert InvalidRecipient();
|
175
|
+
|
176
|
+
tokenIn = localTokenIn;
|
177
|
+
|
178
|
+
_onlyIfTokenAllowed(localTokenIn);
|
179
|
+
|
180
|
+
address v2Pool;
|
181
|
+
for (uint256 i; i < pools.length; ++i) {
|
182
|
+
v2Pool = address(uint160(pools[i]));
|
183
|
+
|
184
|
+
(address token0, address token1) = (
|
185
|
+
IUniswapV2Pair(v2Pool).token0(),
|
186
|
+
IUniswapV2Pair(v2Pool).token1()
|
187
|
+
);
|
188
|
+
|
189
|
+
if (token0 == localTokenIn) {
|
190
|
+
localTokenIn = token1;
|
191
|
+
} else if (token1 == localTokenIn) {
|
192
|
+
localTokenIn = token0;
|
193
|
+
} else revert InvalidPath();
|
194
|
+
_onlyIfTokenAllowed(localTokenIn);
|
195
|
+
}
|
196
|
+
tokenOut = localTokenIn;
|
197
|
+
} else if (method == IAggregationRouterV5.unoswap.selector) {
|
198
|
+
address localTokenIn;
|
199
|
+
(localTokenIn, amountIn, amountOut, pools) = abi.decode(
|
200
|
+
_data.slice(4, _data.length - 4),
|
201
|
+
(address, uint256, uint256, uint256[])
|
202
|
+
);
|
203
|
+
|
204
|
+
tokenIn = localTokenIn;
|
205
|
+
|
206
|
+
_onlyIfTokenAllowed(localTokenIn);
|
207
|
+
|
208
|
+
address v2Pool;
|
209
|
+
for (uint256 i; i < pools.length; ++i) {
|
210
|
+
v2Pool = address(uint160(pools[i]));
|
211
|
+
|
212
|
+
(address token0, address token1) = (
|
213
|
+
IUniswapV2Pair(v2Pool).token0(),
|
214
|
+
IUniswapV2Pair(v2Pool).token1()
|
215
|
+
);
|
216
|
+
|
217
|
+
if (token0 == localTokenIn) {
|
218
|
+
localTokenIn = token1;
|
219
|
+
} else if (token1 == localTokenIn) {
|
220
|
+
localTokenIn = token0;
|
221
|
+
} else revert InvalidPath();
|
222
|
+
_onlyIfTokenAllowed(localTokenIn);
|
223
|
+
}
|
224
|
+
tokenOut = localTokenIn;
|
225
|
+
} else if (method == IAggregationRouterV5.uniswapV3SwapTo.selector) {
|
226
|
+
address payable recipient;
|
227
|
+
(recipient, amountIn, amountOut, pools) = abi.decode(
|
228
|
+
_data.slice(4, _data.length - 4),
|
229
|
+
(address, uint256, uint256, uint256[])
|
230
|
+
);
|
231
|
+
|
232
|
+
if (recipient != address(this)) revert InvalidRecipient();
|
233
|
+
|
234
|
+
uint256 length = pools.length;
|
235
|
+
for (uint256 i; i < length; ++i) {
|
236
|
+
address v2Pool = address(uint160(pools[i]));
|
237
|
+
|
238
|
+
bool zeroForOne = pools[i] & (1 << 255) == 0;
|
239
|
+
|
240
|
+
(address token0, address token1) = (
|
241
|
+
IUniswapV3Pool(v2Pool).token0(),
|
242
|
+
IUniswapV3Pool(v2Pool).token1()
|
243
|
+
);
|
244
|
+
if (i > 0) {
|
245
|
+
// get dst token
|
246
|
+
tokenOut = zeroForOne ? token1 : token0;
|
247
|
+
} else {
|
248
|
+
(tokenIn, tokenOut) = zeroForOne ? (token0, token1) : (token1, token0);
|
249
|
+
// check src token if it's first pool
|
250
|
+
_onlyIfTokenAllowed(tokenIn);
|
251
|
+
}
|
252
|
+
// check dst token
|
253
|
+
_onlyIfTokenAllowed(tokenOut);
|
254
|
+
}
|
255
|
+
} else if (method == IAggregationRouterV5.uniswapV3Swap.selector) {
|
256
|
+
(amountIn, amountOut, pools) = abi.decode(
|
257
|
+
_data.slice(4, _data.length - 4),
|
258
|
+
(uint256, uint256, uint256[])
|
259
|
+
);
|
260
|
+
|
261
|
+
uint256 length = pools.length;
|
262
|
+
for (uint256 i; i < length; ++i) {
|
263
|
+
address v2Pool = address(uint160(pools[i]));
|
264
|
+
|
265
|
+
bool zeroForOne = pools[i] & (1 << 255) == 0;
|
266
|
+
|
267
|
+
(address token0, address token1) = (
|
268
|
+
IUniswapV3Pool(v2Pool).token0(),
|
269
|
+
IUniswapV3Pool(v2Pool).token1()
|
270
|
+
);
|
271
|
+
if (i > 0) {
|
272
|
+
// get dst token
|
273
|
+
tokenOut = zeroForOne ? token1 : token0;
|
274
|
+
} else {
|
275
|
+
(tokenIn, tokenOut) = zeroForOne ? (token0, token1) : (token1, token0);
|
276
|
+
// check src token if it's first pool
|
277
|
+
_onlyIfTokenAllowed(tokenIn);
|
278
|
+
}
|
279
|
+
// check dst token
|
280
|
+
_onlyIfTokenAllowed(tokenOut);
|
281
|
+
}
|
282
|
+
} else if (method == IAggregationRouterV5.swap.selector) {
|
283
|
+
IAggregationRouterV5.SwapDescription memory swapDescription;
|
284
|
+
(, swapDescription) = abi.decode(
|
285
|
+
_data.slice(4, _data.length - 4),
|
286
|
+
(address, IAggregationRouterV5.SwapDescription)
|
287
|
+
);
|
288
|
+
|
289
|
+
tokenIn = swapDescription.srcToken;
|
290
|
+
tokenOut = swapDescription.dstToken;
|
291
|
+
amountIn = swapDescription.amount;
|
292
|
+
amountOut = swapDescription.minReturnAmount;
|
293
|
+
|
294
|
+
if (swapDescription.dstReceiver != address(this)) revert InvalidRecipient();
|
295
|
+
_onlyIfTokenAllowed(tokenOut);
|
296
|
+
} else revert InvalidMethod();
|
297
|
+
|
298
|
+
if (amountIn == 0 || amountOut == 0) revert OneInchSwapFailed();
|
299
|
+
|
300
|
+
SafeOPS._forceApprove(tokenIn, aggregationRouterV5, amountIn);
|
301
|
+
|
302
|
+
(, bytes memory result) = SafeOPS._safeCall(aggregationRouterV5, _data);
|
303
|
+
|
304
|
+
uint256 amountOutResult;
|
305
|
+
assembly {
|
306
|
+
// return amount should be in 0x20 offset from any result
|
307
|
+
amountOutResult := mload(add(result, 0x20))
|
308
|
+
}
|
309
|
+
|
310
|
+
if (amountOutResult < amountOut) revert OneInchSwapFailed();
|
311
|
+
amountOut = amountOutResult;
|
312
|
+
}
|
313
|
+
|
314
|
+
function _afterSwapExecuted(
|
315
|
+
address tokenIn,
|
316
|
+
address tokenOut,
|
317
|
+
uint256 amountIn,
|
318
|
+
uint256 amountOut
|
319
|
+
) internal {
|
320
|
+
IUFarmPool(address(this)).removeERC20(tokenIn);
|
321
|
+
IUFarmPool(address(this)).addERC20(tokenOut, bytes32(0));
|
322
|
+
emit SwapOneInchV5(tokenIn, tokenOut, amountIn, amountOut, PROTOCOL());
|
323
|
+
}
|
324
|
+
|
325
|
+
function _onlyIfTokenAllowed(address token) internal view {
|
326
|
+
if (IPoolWhitelist(address(this)).isTokenAllowed(token) == false &&
|
327
|
+
token != 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
|
328
|
+
) {
|
329
|
+
revert IPoolWhitelist.TokenIsNotAllowed(token);
|
330
|
+
}
|
331
|
+
}
|
332
|
+
}
|