@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.
Files changed (127) hide show
  1. package/.docker/Dockerfile +17 -0
  2. package/.dockerignore +7 -0
  3. package/.env.sample +24 -0
  4. package/.gitlab-ci.yml +51 -0
  5. package/.gitmodules +15 -0
  6. package/.prettierrc +10 -0
  7. package/.solcover.js +4 -0
  8. package/.vscode/settings.json +23 -0
  9. package/LICENSE.MD +51 -0
  10. package/README.md +135 -0
  11. package/contracts/arbitrum/contracts/controllers/UniswapV2ControllerArbitrum.sol +37 -0
  12. package/contracts/arbitrum/contracts/controllers/UniswapV3ControllerArbitrum.sol +46 -0
  13. package/contracts/arbitrum/contracts/oracle/PriceOracleArbitrum.sol +51 -0
  14. package/contracts/main/contracts/controllers/Controller.sol +61 -0
  15. package/contracts/main/contracts/controllers/IController.sol +81 -0
  16. package/contracts/main/contracts/controllers/OneInchV5Controller.sol +332 -0
  17. package/contracts/main/contracts/controllers/UnoswapV2Controller.sol +789 -0
  18. package/contracts/main/contracts/controllers/UnoswapV3Controller.sol +1018 -0
  19. package/contracts/main/contracts/core/CoreWhitelist.sol +192 -0
  20. package/contracts/main/contracts/core/ICoreWhitelist.sol +92 -0
  21. package/contracts/main/contracts/core/IUFarmCore.sol +95 -0
  22. package/contracts/main/contracts/core/UFarmCore.sol +402 -0
  23. package/contracts/main/contracts/fund/FundFactory.sol +59 -0
  24. package/contracts/main/contracts/fund/IUFarmFund.sol +68 -0
  25. package/contracts/main/contracts/fund/UFarmFund.sol +504 -0
  26. package/contracts/main/contracts/oracle/ChainlinkedOracle.sol +71 -0
  27. package/contracts/main/contracts/oracle/IChainlinkAggregator.sol +18 -0
  28. package/contracts/main/contracts/oracle/IPriceOracle.sol +55 -0
  29. package/contracts/main/contracts/oracle/PriceOracle.sol +20 -0
  30. package/contracts/main/contracts/oracle/PriceOracleCore.sol +212 -0
  31. package/contracts/main/contracts/oracle/WstETHOracle.sol +64 -0
  32. package/contracts/main/contracts/permissions/Permissions.sol +54 -0
  33. package/contracts/main/contracts/permissions/UFarmPermissionsModel.sol +136 -0
  34. package/contracts/main/contracts/pool/IPoolAdmin.sol +57 -0
  35. package/contracts/main/contracts/pool/IUFarmPool.sol +304 -0
  36. package/contracts/main/contracts/pool/PerformanceFeeLib.sol +81 -0
  37. package/contracts/main/contracts/pool/PoolAdmin.sol +437 -0
  38. package/contracts/main/contracts/pool/PoolFactory.sol +74 -0
  39. package/contracts/main/contracts/pool/PoolWhitelist.sol +70 -0
  40. package/contracts/main/contracts/pool/UFarmPool.sol +959 -0
  41. package/contracts/main/shared/AssetController.sol +194 -0
  42. package/contracts/main/shared/ECDSARecover.sol +91 -0
  43. package/contracts/main/shared/NZGuard.sol +99 -0
  44. package/contracts/main/shared/SafeOPS.sol +128 -0
  45. package/contracts/main/shared/UFarmCoreLink.sol +83 -0
  46. package/contracts/main/shared/UFarmErrors.sol +16 -0
  47. package/contracts/main/shared/UFarmMathLib.sol +80 -0
  48. package/contracts/main/shared/UFarmOwnableUUPS.sol +59 -0
  49. package/contracts/main/shared/UFarmOwnableUUPSBeacon.sol +34 -0
  50. package/contracts/test/Block.sol +15 -0
  51. package/contracts/test/InchSwapTestProxy.sol +292 -0
  52. package/contracts/test/MockPoolAdmin.sol +8 -0
  53. package/contracts/test/MockUFarmPool.sol +8 -0
  54. package/contracts/test/MockV3wstETHstETHAgg.sol +128 -0
  55. package/contracts/test/MockedWETH9.sol +72 -0
  56. package/contracts/test/OneInchToUFarmTestEnv.sol +466 -0
  57. package/contracts/test/StableCoin.sol +25 -0
  58. package/contracts/test/UFarmMockSequencerUptimeFeed.sol +44 -0
  59. package/contracts/test/UFarmMockV3Aggregator.sol +145 -0
  60. package/contracts/test/UUPSBlock.sol +19 -0
  61. package/contracts/test/ufarmLocal/MulticallV3.sol +220 -0
  62. package/contracts/test/ufarmLocal/controllers/UniswapV2ControllerUFarm.sol +27 -0
  63. package/contracts/test/ufarmLocal/controllers/UniswapV3ControllerUFarm.sol +43 -0
  64. package/deploy/100_test_env_setup.ts +483 -0
  65. package/deploy/20_deploy_uniV2.ts +48 -0
  66. package/deploy/21_create_pairs_uniV2.ts +149 -0
  67. package/deploy/22_deploy_mocked_aggregators.ts +123 -0
  68. package/deploy/22_deploy_wsteth_oracle.ts +65 -0
  69. package/deploy/23_deploy_uniV3.ts +80 -0
  70. package/deploy/24_create_pairs_uniV3.ts +140 -0
  71. package/deploy/25_deploy_oneInch.ts +38 -0
  72. package/deploy/2_deploy_multicall.ts +34 -0
  73. package/deploy/30_deploy_price_oracle.ts +33 -0
  74. package/deploy/3_deploy_lido.ts +114 -0
  75. package/deploy/40_deploy_pool_beacon.ts +19 -0
  76. package/deploy/41_deploy_poolAdmin_beacon.ts +19 -0
  77. package/deploy/42_deploy_ufarmcore.ts +29 -0
  78. package/deploy/43_deploy_fund_beacon.ts +19 -0
  79. package/deploy/4_deploy_tokens.ts +76 -0
  80. package/deploy/50_deploy_poolFactory.ts +35 -0
  81. package/deploy/51_deploy_fundFactory.ts +29 -0
  82. package/deploy/60_init_contracts.ts +101 -0
  83. package/deploy/61_whitelist_tokens.ts +18 -0
  84. package/deploy/70_deploy_uniV2Controller.ts +70 -0
  85. package/deploy/71_deploy_uniV3Controller.ts +67 -0
  86. package/deploy/72_deploy_oneInchController.ts +25 -0
  87. package/deploy/79_whitelist_controllers.ts +125 -0
  88. package/deploy/ufarm/arbitrum/1_prepare_env.ts +82 -0
  89. package/deploy/ufarm/arbitrum/2_deploy_ufarm.ts +178 -0
  90. package/deploy/ufarm/arbitrum-sepolia/1000_prepare_arb_sepolia_env.ts +308 -0
  91. package/deploy-config.json +112 -0
  92. package/deploy-data/oracles.csv +32 -0
  93. package/deploy-data/protocols.csv +10 -0
  94. package/deploy-data/tokens.csv +32 -0
  95. package/docker-compose.yml +67 -0
  96. package/hardhat.config.ts +449 -0
  97. package/index.js +93 -0
  98. package/package.json +82 -0
  99. package/scripts/_deploy_helpers.ts +992 -0
  100. package/scripts/_deploy_network_options.ts +49 -0
  101. package/scripts/activatePool.ts +51 -0
  102. package/scripts/createPool.ts +62 -0
  103. package/scripts/deploy_1inch_proxy.ts +98 -0
  104. package/scripts/pool-data.ts +420 -0
  105. package/scripts/post-deploy.sh +24 -0
  106. package/scripts/setUniV2Rate.ts +252 -0
  107. package/scripts/swapOneInchV5.ts +94 -0
  108. package/scripts/swapUniswapV2.ts +65 -0
  109. package/scripts/swapUniswapV3.ts +71 -0
  110. package/scripts/test.ts +61 -0
  111. package/scripts/typings-copy-artifacts.ts +83 -0
  112. package/tasks/boostPool.ts +39 -0
  113. package/tasks/createFund.ts +44 -0
  114. package/tasks/deboostPool.ts +48 -0
  115. package/tasks/grantUFarmPermissions.ts +57 -0
  116. package/tasks/index.ts +7 -0
  117. package/tasks/mintUSDT.ts +62 -0
  118. package/test/Periphery.test.ts +640 -0
  119. package/test/PriceOracle.test.ts +82 -0
  120. package/test/TestCases.MD +109 -0
  121. package/test/UFarmCore.test.ts +331 -0
  122. package/test/UFarmFund.test.ts +406 -0
  123. package/test/UFarmPool.test.ts +4736 -0
  124. package/test/_fixtures.ts +783 -0
  125. package/test/_helpers.ts +2195 -0
  126. package/test/_oneInchTestData.ts +632 -0
  127. 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
+ }