@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,402 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8.0;
|
4
|
+
|
5
|
+
/// INTERFACES
|
6
|
+
import {IUFarmCore} from './IUFarmCore.sol';
|
7
|
+
import {IUFarmFund} from '../fund/IUFarmFund.sol';
|
8
|
+
import {IFundFactory} from '../fund/FundFactory.sol';
|
9
|
+
import {IPoolFactory} from '../pool/PoolFactory.sol';
|
10
|
+
import {IUFarmCoreLink} from '../../shared/UFarmCoreLink.sol';
|
11
|
+
import {Permissions} from '../permissions/Permissions.sol';
|
12
|
+
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
|
13
|
+
|
14
|
+
/// CONTRACTS
|
15
|
+
import {CoreWhitelist, ICoreWhitelist} from './CoreWhitelist.sol';
|
16
|
+
import {UFarmPermissionsModel} from '../permissions/UFarmPermissionsModel.sol';
|
17
|
+
import {ReentrancyGuardUpgradeable as ReentrancyGuard} from '@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol';
|
18
|
+
import {UFarmOwnableUUPS} from '../../shared/UFarmOwnableUUPS.sol';
|
19
|
+
|
20
|
+
/// LIBRARIES
|
21
|
+
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
|
22
|
+
import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol';
|
23
|
+
|
24
|
+
/**
|
25
|
+
* @title UFarmCore
|
26
|
+
* @author https://ufarm.digital/
|
27
|
+
* @notice UFarmCore is the core contract of the UFarm protocol.
|
28
|
+
* Keeps track of all funds, assets, UFarm permissions, and fees.
|
29
|
+
*/
|
30
|
+
contract UFarmCore is
|
31
|
+
IUFarmCore,
|
32
|
+
CoreWhitelist,
|
33
|
+
UFarmPermissionsModel,
|
34
|
+
ReentrancyGuard,
|
35
|
+
UFarmOwnableUUPS
|
36
|
+
{
|
37
|
+
using SafeERC20 for IERC20;
|
38
|
+
using EnumerableSet for EnumerableSet.AddressSet;
|
39
|
+
|
40
|
+
/**
|
41
|
+
* @inheritdoc IUFarmCore
|
42
|
+
*/
|
43
|
+
uint256 public protocolCommission;
|
44
|
+
|
45
|
+
/**
|
46
|
+
* @inheritdoc IUFarmCore
|
47
|
+
*/
|
48
|
+
uint256 public minimumFundDeposit;
|
49
|
+
|
50
|
+
/**
|
51
|
+
* @inheritdoc IUFarmCore
|
52
|
+
*/
|
53
|
+
IFundFactory public fundFactory;
|
54
|
+
|
55
|
+
/**
|
56
|
+
* @inheritdoc IUFarmCore
|
57
|
+
*/
|
58
|
+
IPoolFactory public poolFactory;
|
59
|
+
|
60
|
+
/**
|
61
|
+
* @inheritdoc IUFarmCore
|
62
|
+
*/
|
63
|
+
address public priceOracle;
|
64
|
+
|
65
|
+
/**
|
66
|
+
* @inheritdoc IUFarmCore
|
67
|
+
*/
|
68
|
+
bool public isPaused;
|
69
|
+
|
70
|
+
EnumerableSet.AddressSet private _funds;
|
71
|
+
|
72
|
+
/// EVENTS
|
73
|
+
/**
|
74
|
+
* @notice Emitted when new fund is created
|
75
|
+
* @param applicationId - internal DB application id
|
76
|
+
* @param fundId - fund id
|
77
|
+
* @param fund - fund address
|
78
|
+
*/
|
79
|
+
event FundCreated(bytes32 indexed applicationId, uint256 fundId, address fund);
|
80
|
+
/**
|
81
|
+
* @notice Emitted when minimum fund deposit is changed
|
82
|
+
* @param minimumFundDeposit - new minimum fund deposit
|
83
|
+
*/
|
84
|
+
event MinimumFundDepositChanged(uint256 minimumFundDeposit);
|
85
|
+
/**
|
86
|
+
* @notice Emitted when protocol commission is changed
|
87
|
+
* @param protocolCommission - new protocol commission
|
88
|
+
*/
|
89
|
+
event ProtocolCommissionChanged(uint256 protocolCommission);
|
90
|
+
/**
|
91
|
+
* @notice Emitted when pause action is performed
|
92
|
+
* @param isPaused - new pause status: `true` if paused, `false` if unpaused
|
93
|
+
*/
|
94
|
+
event PauseAction(bool isPaused);
|
95
|
+
|
96
|
+
/// MODIFIERS
|
97
|
+
/**
|
98
|
+
* @notice Reverts if the caller doesn't have two permissions or is not the owner
|
99
|
+
* @param permission1 - first permission (often membership)
|
100
|
+
* @param permission2 - second permission (often some kind of editor)
|
101
|
+
*/
|
102
|
+
modifier ownerOrHaveTwoPermissions(uint8 permission1, uint8 permission2) {
|
103
|
+
if (!_hasPermission(msg.sender, uint8(Permissions.UFarm.Owner))) {
|
104
|
+
_checkForPermissions(msg.sender, _twoPermissionsToMask(permission1, permission2));
|
105
|
+
}
|
106
|
+
_;
|
107
|
+
}
|
108
|
+
|
109
|
+
function __init__UFarmCore(
|
110
|
+
address _admin,
|
111
|
+
address _fundFactory,
|
112
|
+
address _poolFactory,
|
113
|
+
address _priceOracle
|
114
|
+
)
|
115
|
+
external
|
116
|
+
onlyDeployer
|
117
|
+
nonZeroAddress(_admin)
|
118
|
+
nonZeroAddress(_fundFactory)
|
119
|
+
nonZeroAddress(_poolFactory)
|
120
|
+
nonZeroAddress(_priceOracle)
|
121
|
+
initializer
|
122
|
+
{
|
123
|
+
__init__UFarmOwnableUUPS();
|
124
|
+
__init__UFarmCore_unchained(_admin, _fundFactory, _poolFactory, _priceOracle);
|
125
|
+
}
|
126
|
+
|
127
|
+
function __init__UFarmCore_unchained(
|
128
|
+
address _admin,
|
129
|
+
address _fundFactory,
|
130
|
+
address _poolFactory,
|
131
|
+
address _priceOracle
|
132
|
+
) internal onlyInitializing {
|
133
|
+
priceOracle = _priceOracle;
|
134
|
+
IUFarmCoreLink(_priceOracle).coreCallback();
|
135
|
+
|
136
|
+
fundFactory = IFundFactory(_fundFactory);
|
137
|
+
IUFarmCoreLink(_fundFactory).coreCallback();
|
138
|
+
|
139
|
+
poolFactory = IPoolFactory(_poolFactory);
|
140
|
+
IUFarmCoreLink(_poolFactory).coreCallback();
|
141
|
+
|
142
|
+
_updatePermissions(_admin, _FULL_PERMISSIONS_MASK);
|
143
|
+
}
|
144
|
+
|
145
|
+
/**
|
146
|
+
* @inheritdoc IUFarmCore
|
147
|
+
*/
|
148
|
+
function getFund(uint256 fundId) external view returns (address) {
|
149
|
+
return _funds.at(fundId);
|
150
|
+
}
|
151
|
+
|
152
|
+
/**
|
153
|
+
* @inheritdoc IUFarmCore
|
154
|
+
*/
|
155
|
+
function fundsCount() external view returns (uint256) {
|
156
|
+
return _funds.length();
|
157
|
+
}
|
158
|
+
|
159
|
+
/**
|
160
|
+
* @inheritdoc IUFarmCore
|
161
|
+
*/
|
162
|
+
function isFund(address _fund) external view returns (bool) {
|
163
|
+
return _funds.contains(_fund);
|
164
|
+
}
|
165
|
+
|
166
|
+
/**
|
167
|
+
* @inheritdoc IUFarmCore
|
168
|
+
*/
|
169
|
+
function createFund(
|
170
|
+
address _fundManager,
|
171
|
+
bytes32 _applicationId
|
172
|
+
)
|
173
|
+
external
|
174
|
+
override
|
175
|
+
ownerOrHaveTwoPermissions(
|
176
|
+
uint8(Permissions.UFarm.Member),
|
177
|
+
uint8(Permissions.UFarm.ApproveFundCreation)
|
178
|
+
)
|
179
|
+
nonReentrant
|
180
|
+
returns (address fund)
|
181
|
+
{
|
182
|
+
uint256 nextFundId = _funds.length();
|
183
|
+
|
184
|
+
fund = fundFactory.createFund(_fundManager, _applicationId);
|
185
|
+
|
186
|
+
_funds.add(fund);
|
187
|
+
|
188
|
+
emit FundCreated(_applicationId, nextFundId, fund);
|
189
|
+
}
|
190
|
+
|
191
|
+
/**
|
192
|
+
* @notice Allows managers to use this tokens
|
193
|
+
* @param _tokens - array of tokens with PriceFeeds to whitelist
|
194
|
+
*/
|
195
|
+
function whitelistTokens(
|
196
|
+
AssetWithPriceFeed[] calldata _tokens
|
197
|
+
)
|
198
|
+
external
|
199
|
+
override
|
200
|
+
nonReentrant
|
201
|
+
ownerOrHaveTwoPermissions(
|
202
|
+
uint8(Permissions.UFarm.Member),
|
203
|
+
uint8(Permissions.UFarm.ManageWhitelist)
|
204
|
+
)
|
205
|
+
{
|
206
|
+
_whitelistTokens(_tokens);
|
207
|
+
}
|
208
|
+
|
209
|
+
/**
|
210
|
+
* @notice Disallows managers to use this tokens
|
211
|
+
* @param _tokens - array of token addresses to blacklist
|
212
|
+
*/
|
213
|
+
function blacklistTokens(
|
214
|
+
address[] calldata _tokens
|
215
|
+
)
|
216
|
+
external
|
217
|
+
override
|
218
|
+
nonReentrant
|
219
|
+
ownerOrHaveTwoPermissions(
|
220
|
+
uint8(Permissions.UFarm.Member),
|
221
|
+
uint8(Permissions.UFarm.ManageWhitelist)
|
222
|
+
)
|
223
|
+
{
|
224
|
+
_blacklistTokens(_tokens);
|
225
|
+
}
|
226
|
+
|
227
|
+
/**
|
228
|
+
* @inheritdoc IUFarmCore
|
229
|
+
*/
|
230
|
+
function setMinimumFundDeposit(
|
231
|
+
uint256 _minimumFundDeposit
|
232
|
+
)
|
233
|
+
external
|
234
|
+
override
|
235
|
+
nonSameValue(_minimumFundDeposit, minimumFundDeposit)
|
236
|
+
ownerOrHaveTwoPermissions(
|
237
|
+
uint8(Permissions.UFarm.Member),
|
238
|
+
uint8(Permissions.UFarm.ManageFundDeposit)
|
239
|
+
)
|
240
|
+
{
|
241
|
+
if (minimumFundDeposit != _minimumFundDeposit) {
|
242
|
+
minimumFundDeposit = _minimumFundDeposit;
|
243
|
+
emit MinimumFundDepositChanged(_minimumFundDeposit);
|
244
|
+
} else revert ActionAlreadyDone();
|
245
|
+
}
|
246
|
+
|
247
|
+
/**
|
248
|
+
* @inheritdoc IUFarmCore
|
249
|
+
*/
|
250
|
+
function setProtocolCommission(
|
251
|
+
uint256 _protocolCommission
|
252
|
+
)
|
253
|
+
external
|
254
|
+
override
|
255
|
+
valueInRange(_protocolCommission, 0, 1e17)
|
256
|
+
ownerOrHaveTwoPermissions(uint8(Permissions.UFarm.Member), uint8(Permissions.UFarm.ManageFees))
|
257
|
+
{
|
258
|
+
if (protocolCommission != _protocolCommission) {
|
259
|
+
protocolCommission = _protocolCommission;
|
260
|
+
emit ProtocolCommissionChanged(_protocolCommission);
|
261
|
+
} else revert ActionAlreadyDone();
|
262
|
+
}
|
263
|
+
|
264
|
+
/**
|
265
|
+
* @notice Allows managers to use this protocols
|
266
|
+
* @param _protocolNames - array of protocols to whitelist [keccak256(protocolName)]
|
267
|
+
* @param _protocolControllers - array of controllers for protocols [controllerAddress]
|
268
|
+
*/
|
269
|
+
function whitelistProtocolsWithControllers(
|
270
|
+
bytes32[] memory _protocolNames,
|
271
|
+
address[] memory _protocolControllers
|
272
|
+
)
|
273
|
+
public
|
274
|
+
override(CoreWhitelist, ICoreWhitelist)
|
275
|
+
nonReentrant
|
276
|
+
ownerOrHaveTwoPermissions(
|
277
|
+
uint8(Permissions.UFarm.Member),
|
278
|
+
uint8(Permissions.UFarm.ManageWhitelist)
|
279
|
+
)
|
280
|
+
{
|
281
|
+
super.whitelistProtocolsWithControllers(_protocolNames, _protocolControllers);
|
282
|
+
}
|
283
|
+
|
284
|
+
/**
|
285
|
+
* @inheritdoc ICoreWhitelist
|
286
|
+
*/
|
287
|
+
function updateProtocolsControllers(
|
288
|
+
bytes32[] memory _protocolNames,
|
289
|
+
address[] memory _protocolControllers
|
290
|
+
)
|
291
|
+
public
|
292
|
+
override(CoreWhitelist, ICoreWhitelist)
|
293
|
+
nonReentrant
|
294
|
+
ownerOrHaveTwoPermissions(
|
295
|
+
uint8(Permissions.UFarm.Member),
|
296
|
+
uint8(Permissions.UFarm.ManageWhitelist)
|
297
|
+
)
|
298
|
+
{
|
299
|
+
super.updateProtocolsControllers(_protocolNames, _protocolControllers);
|
300
|
+
}
|
301
|
+
|
302
|
+
/**
|
303
|
+
* @inheritdoc ICoreWhitelist
|
304
|
+
*/
|
305
|
+
function blacklistProtocols(
|
306
|
+
bytes32[] memory _protocols
|
307
|
+
)
|
308
|
+
public
|
309
|
+
override(CoreWhitelist, ICoreWhitelist)
|
310
|
+
nonReentrant
|
311
|
+
ownerOrHaveTwoPermissions(
|
312
|
+
uint8(Permissions.UFarm.Member),
|
313
|
+
uint8(Permissions.UFarm.ManageWhitelist)
|
314
|
+
)
|
315
|
+
{
|
316
|
+
super.blacklistProtocols(_protocols);
|
317
|
+
}
|
318
|
+
|
319
|
+
/**
|
320
|
+
* @inheritdoc IUFarmCore
|
321
|
+
*/
|
322
|
+
function updatePermissions(address _user, uint256 _newPermissionsMask) external override {
|
323
|
+
uint256 currentMask = _accountMask[_user];
|
324
|
+
|
325
|
+
// if update owner permissions
|
326
|
+
if (_isPermissionDiff(uint8(Permissions.UFarm.Owner), currentMask, _newPermissionsMask)) {
|
327
|
+
// only owner can grant or revoke owner permissions
|
328
|
+
_checkForPermissions(msg.sender, _permissionToMask(uint8(Permissions.UFarm.Owner))); // reverts if caller is not owner
|
329
|
+
// owner cant update his own permissions
|
330
|
+
if (msg.sender == _user) revert NonAuthorized();
|
331
|
+
}
|
332
|
+
// skip if msg.sender is owner
|
333
|
+
else if (!_hasPermission(msg.sender, uint8(Permissions.UFarm.Owner))) {
|
334
|
+
bool isMember = _maskHasPermission(_newPermissionsMask, uint8(Permissions.UFarm.Member));
|
335
|
+
|
336
|
+
// if membership status changes
|
337
|
+
if (_isPermissionDiff(uint8(Permissions.UFarm.Member), currentMask, _newPermissionsMask)) {
|
338
|
+
_checkForPermissions(
|
339
|
+
msg.sender,
|
340
|
+
_twoPermissionsToMask(
|
341
|
+
uint8(Permissions.UFarm.Member),
|
342
|
+
isMember
|
343
|
+
? uint8(Permissions.UFarm.DeleteUFarmMember) // if was member
|
344
|
+
: uint8(Permissions.UFarm.UpdateUFarmMember) // else will be member
|
345
|
+
)
|
346
|
+
);
|
347
|
+
}
|
348
|
+
|
349
|
+
// shift left new bitmask for 2 bits, leaving only permissions (not Owner and Member roles)
|
350
|
+
if ((_newPermissionsMask << 2) > 0) {
|
351
|
+
_checkForPermissions(
|
352
|
+
msg.sender,
|
353
|
+
_twoPermissionsToMask(
|
354
|
+
uint8(Permissions.UFarm.Member),
|
355
|
+
uint8(Permissions.UFarm.UpdatePermissions)
|
356
|
+
)
|
357
|
+
);
|
358
|
+
}
|
359
|
+
}
|
360
|
+
|
361
|
+
// checks for `already done` action
|
362
|
+
_updatePermissions(_user, _newPermissionsMask);
|
363
|
+
}
|
364
|
+
|
365
|
+
/**
|
366
|
+
* @inheritdoc IUFarmCore
|
367
|
+
*/
|
368
|
+
function withdrawAssets(
|
369
|
+
address[] calldata _tokens,
|
370
|
+
uint256[] calldata _amounts
|
371
|
+
)
|
372
|
+
external
|
373
|
+
ownerOrHaveTwoPermissions(
|
374
|
+
uint8(Permissions.UFarm.Member),
|
375
|
+
uint8(Permissions.UFarm.ManageAssets)
|
376
|
+
)
|
377
|
+
nonReentrant
|
378
|
+
{
|
379
|
+
uint256 tokensLength = _tokens.length;
|
380
|
+
if (tokensLength != _amounts.length) revert ArraysLengthMismatch();
|
381
|
+
for (uint256 i; i < tokensLength; ++i) {
|
382
|
+
IERC20(_tokens[i]).safeTransfer(msg.sender, _amounts[i]);
|
383
|
+
}
|
384
|
+
}
|
385
|
+
|
386
|
+
/**
|
387
|
+
* @inheritdoc IUFarmCore
|
388
|
+
*/
|
389
|
+
function switchPause() external override {
|
390
|
+
if (!_hasPermission(msg.sender, uint8(Permissions.UFarm.Owner))) {
|
391
|
+
// if user becomes member caller should have special permission
|
392
|
+
_checkForPermissions(
|
393
|
+
msg.sender,
|
394
|
+
_twoPermissionsToMask(uint8(Permissions.UFarm.Member), uint8(Permissions.UFarm.TurnPauseOn))
|
395
|
+
);
|
396
|
+
}
|
397
|
+
isPaused = !isPaused;
|
398
|
+
emit PauseAction(isPaused);
|
399
|
+
}
|
400
|
+
|
401
|
+
uint256[50] private __gap;
|
402
|
+
}
|
@@ -0,0 +1,59 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8.0;
|
4
|
+
|
5
|
+
/// INTERFACES
|
6
|
+
import {IUFarmCore} from '../core/IUFarmCore.sol';
|
7
|
+
import {IUFarmFund} from './IUFarmFund.sol';
|
8
|
+
|
9
|
+
/// CONTRACTS
|
10
|
+
import {UFarmCoreLink} from '../../shared/UFarmCoreLink.sol';
|
11
|
+
|
12
|
+
/// LIBRARIES
|
13
|
+
import {SafeOPS} from '../../shared/SafeOPS.sol';
|
14
|
+
|
15
|
+
/**
|
16
|
+
* @title IFundFactory interface
|
17
|
+
* @author https://ufarm.digital/
|
18
|
+
* @notice Interface for the FundFactory contract
|
19
|
+
*/
|
20
|
+
interface IFundFactory {
|
21
|
+
/**
|
22
|
+
* @notice Creates a new fund
|
23
|
+
* @param _manager The manager of the fund
|
24
|
+
* @param _salt The salt for the fund
|
25
|
+
* @return fund The address of the new fund
|
26
|
+
*/
|
27
|
+
function createFund(address _manager, bytes32 _salt) external returns (address fund);
|
28
|
+
}
|
29
|
+
|
30
|
+
/**
|
31
|
+
* @title FundFactory contract
|
32
|
+
* @author https://ufarm.digital/
|
33
|
+
* @notice Deployer of new funds
|
34
|
+
* @dev Needs to be initialized with UFarmCore address
|
35
|
+
*/
|
36
|
+
contract FundFactory is IFundFactory, UFarmCoreLink {
|
37
|
+
// Beacon is UUPS upgradeable proxy address, implementation can be upgraded if needed
|
38
|
+
address public immutable fundImplBeacon;
|
39
|
+
|
40
|
+
constructor(address _ufarmCore, address _fundImplBeacon) {
|
41
|
+
__init__UFarmCoreLink(_ufarmCore);
|
42
|
+
fundImplBeacon = _fundImplBeacon;
|
43
|
+
}
|
44
|
+
|
45
|
+
/**
|
46
|
+
* @inheritdoc IFundFactory
|
47
|
+
*/
|
48
|
+
function createFund(address _manager, bytes32 _salt) external onlyLinked returns (address fund) {
|
49
|
+
return SafeOPS._safeBeaconCreate2Deploy(fundImplBeacon, _salt, _getInitFundCall(_manager));
|
50
|
+
}
|
51
|
+
|
52
|
+
function getFundBySalt(address _manager, bytes32 _salt) public view returns (address fund) {
|
53
|
+
return SafeOPS.computeBeaconProxyAddress(fundImplBeacon, _salt, _getInitFundCall(_manager));
|
54
|
+
}
|
55
|
+
|
56
|
+
function _getInitFundCall(address _manager) internal view returns (bytes memory) {
|
57
|
+
return abi.encodeCall(IUFarmFund.__init_UFarmFund, (_manager, ufarmCore()));
|
58
|
+
}
|
59
|
+
}
|
@@ -0,0 +1,68 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8.0;
|
4
|
+
|
5
|
+
/**
|
6
|
+
* @title IUFarmFund interface
|
7
|
+
* @author https://ufarm.digital/
|
8
|
+
* @notice Fund interface for the UFarm protocol
|
9
|
+
*/
|
10
|
+
interface IUFarmFund {
|
11
|
+
/**
|
12
|
+
* Possible statuses of the fund
|
13
|
+
*/
|
14
|
+
enum FundStatus {
|
15
|
+
Approved,
|
16
|
+
Active,
|
17
|
+
Terminated,
|
18
|
+
Blocked
|
19
|
+
}
|
20
|
+
|
21
|
+
/**
|
22
|
+
* @notice Struct for storing the fund member invitation
|
23
|
+
* @param invitee - address of the invitee
|
24
|
+
* @param permissionsMask - masked permissions of the invitee
|
25
|
+
* @param deadline - deadline for the invitee to accept the invitation
|
26
|
+
*/
|
27
|
+
struct FundMemberInvitation {
|
28
|
+
address invitee;
|
29
|
+
uint256 permissionsMask;
|
30
|
+
uint256 deadline;
|
31
|
+
}
|
32
|
+
|
33
|
+
/**
|
34
|
+
* @notice Reverts if the fund is not in the required status
|
35
|
+
* @param requiredStatus - required status of the fund
|
36
|
+
* @param currentStatus - current status of the fund
|
37
|
+
*/
|
38
|
+
error WrongFundStatus(FundStatus requiredStatus, FundStatus currentStatus);
|
39
|
+
|
40
|
+
/**
|
41
|
+
* @notice Returns the current status of the fund
|
42
|
+
*/
|
43
|
+
function status() external view returns (FundStatus);
|
44
|
+
|
45
|
+
/**
|
46
|
+
* @notice Returns the address of the UFarmCore contract
|
47
|
+
*/
|
48
|
+
function ufarmCore() external view returns (address);
|
49
|
+
|
50
|
+
/**
|
51
|
+
* @notice Changes the status of the fund
|
52
|
+
* @param newStatus New status of the fund
|
53
|
+
*/
|
54
|
+
function changeStatus(FundStatus newStatus) external;
|
55
|
+
|
56
|
+
/**
|
57
|
+
* @notice Returns `true` if the pool is been managed by the fund
|
58
|
+
* @param _pool - address of the pool to be checked
|
59
|
+
*/
|
60
|
+
function isPool(address _pool) external view returns (bool);
|
61
|
+
|
62
|
+
/**
|
63
|
+
* @notice Initializes the fund, gives full permissions to the owner
|
64
|
+
* @param _owner - fund owner
|
65
|
+
* @param _ufarmCore - address of the UFarmCore contract
|
66
|
+
*/
|
67
|
+
function __init_UFarmFund(address _owner, address _ufarmCore) external;
|
68
|
+
}
|