@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,212 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8.0;
|
4
|
+
|
5
|
+
/// CONTRACTS
|
6
|
+
import {ChainlinkedOracle} from './ChainlinkedOracle.sol';
|
7
|
+
import {UFarmCoreLink} from '../../shared/UFarmCoreLink.sol';
|
8
|
+
import {UFarmOwnableUUPS} from '../../shared/UFarmOwnableUUPS.sol';
|
9
|
+
|
10
|
+
/// INTERFACES
|
11
|
+
import {IPriceOracle} from './IPriceOracle.sol';
|
12
|
+
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
|
13
|
+
import {IERC721} from '@openzeppelin/contracts/token/ERC721/IERC721.sol';
|
14
|
+
import {IUFarmPool} from '../pool/IUFarmPool.sol';
|
15
|
+
import {IUFarmCore} from '../core/IUFarmCore.sol';
|
16
|
+
import {ICoreWhitelist} from '../core/CoreWhitelist.sol';
|
17
|
+
import {AggregatorV3Interface} from '@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol';
|
18
|
+
import {IController, IERC20CommonController, IERC20SynthController, IERC721Controller} from '../controllers/IController.sol';
|
19
|
+
import {AssetsStructs} from '../../shared/AssetController.sol';
|
20
|
+
import {UFarmErrors} from '../../shared/UFarmErrors.sol';
|
21
|
+
|
22
|
+
/// LIBRARIES
|
23
|
+
import {UFarmMathLib} from '../../shared/UFarmMathLib.sol';
|
24
|
+
|
25
|
+
/**
|
26
|
+
* @title PriceOracleCore contract
|
27
|
+
* @author https://ufarm.digital/
|
28
|
+
* @notice Connects to Chainlink price feeds and calculates the cost of assets
|
29
|
+
*/
|
30
|
+
abstract contract PriceOracleCore is
|
31
|
+
IPriceOracle,
|
32
|
+
UFarmCoreLink,
|
33
|
+
ChainlinkedOracle,
|
34
|
+
UFarmOwnableUUPS
|
35
|
+
{
|
36
|
+
error InvalidPath();
|
37
|
+
error InvalidMethod();
|
38
|
+
error InvalidRecipient();
|
39
|
+
error InvalidController();
|
40
|
+
|
41
|
+
/**
|
42
|
+
* @inheritdoc IPriceOracle
|
43
|
+
*/
|
44
|
+
function getCostERC20(
|
45
|
+
address tokenIn,
|
46
|
+
uint256 amountIn,
|
47
|
+
address tokenOut
|
48
|
+
) public view virtual returns (uint256 cost) {
|
49
|
+
(
|
50
|
+
ICoreWhitelist.AssetWithPriceFeed memory baseFeed,
|
51
|
+
ICoreWhitelist.AssetWithPriceFeed memory quoteFeed
|
52
|
+
) = (
|
53
|
+
ICoreWhitelist(ufarmCore()).tokenInfo(tokenIn),
|
54
|
+
ICoreWhitelist(ufarmCore()).tokenInfo(tokenOut)
|
55
|
+
);
|
56
|
+
|
57
|
+
if (baseFeed.priceFeed.feedAddr == address(0)) revert ChainlinkOracleNotSet(baseFeed.assetAddr);
|
58
|
+
if (quoteFeed.priceFeed.feedAddr == address(0))
|
59
|
+
revert ChainlinkOracleNotSet(quoteFeed.assetAddr);
|
60
|
+
|
61
|
+
(int256 basePrice, int256 quotePrice) = getNormalizedPrice(
|
62
|
+
baseFeed.priceFeed.feedAddr,
|
63
|
+
baseFeed.priceFeed.feedDec,
|
64
|
+
quoteFeed.priceFeed.feedAddr,
|
65
|
+
quoteFeed.priceFeed.feedDec
|
66
|
+
);
|
67
|
+
|
68
|
+
cost = uint256((int256(amountIn) * basePrice) / quotePrice);
|
69
|
+
cost = uint256(
|
70
|
+
UFarmMathLib.convertDecimals(int256(cost), baseFeed.assetDec, quoteFeed.assetDec)
|
71
|
+
);
|
72
|
+
}
|
73
|
+
|
74
|
+
/**
|
75
|
+
* @notice Returns the normalized price of the base and quote tokens
|
76
|
+
* @param _baseOracle - address of the base token's oracle
|
77
|
+
* @param _baseOracleDecimals - decimals of the base oracle
|
78
|
+
* @param _quoteOracle - address of the quote oracle
|
79
|
+
* @param _quoteOracleDecimals - decimals of the quote token's oracle
|
80
|
+
* @return basePrice - price of the base token
|
81
|
+
* @return quotePrice - price of the quote token
|
82
|
+
*/
|
83
|
+
function getNormalizedPrice(
|
84
|
+
address _baseOracle,
|
85
|
+
uint8 _baseOracleDecimals,
|
86
|
+
address _quoteOracle,
|
87
|
+
uint8 _quoteOracleDecimals
|
88
|
+
) public view returns (int256 basePrice, int256 quotePrice) {
|
89
|
+
uint8 biggerDecimals = _baseOracleDecimals > _quoteOracleDecimals
|
90
|
+
? _baseOracleDecimals
|
91
|
+
: _quoteOracleDecimals;
|
92
|
+
|
93
|
+
basePrice = _chainlinkLatestAnswer(_baseOracle);
|
94
|
+
basePrice = UFarmMathLib.convertDecimals(basePrice, _baseOracleDecimals, biggerDecimals);
|
95
|
+
|
96
|
+
quotePrice = _chainlinkLatestAnswer(_quoteOracle);
|
97
|
+
quotePrice = UFarmMathLib.convertDecimals(quotePrice, _quoteOracleDecimals, biggerDecimals);
|
98
|
+
|
99
|
+
return (basePrice, quotePrice);
|
100
|
+
}
|
101
|
+
|
102
|
+
/**
|
103
|
+
* @inheritdoc IPriceOracle
|
104
|
+
*/
|
105
|
+
function getCostControlledERC20(
|
106
|
+
address tokenIn,
|
107
|
+
uint256 amountIn,
|
108
|
+
address tokenOut,
|
109
|
+
address controller
|
110
|
+
) public view returns (uint256 cost) {
|
111
|
+
try IERC20SynthController(controller).getCostControlledERC20(tokenIn, amountIn, tokenOut) returns (uint256 cost20) {
|
112
|
+
cost = cost20;
|
113
|
+
} catch {
|
114
|
+
cost = 0;
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
/**
|
119
|
+
* @inheritdoc IPriceOracle
|
120
|
+
*/
|
121
|
+
function getCostERC721(
|
122
|
+
address tokenIn,
|
123
|
+
uint256[] memory ids,
|
124
|
+
address tokenOut,
|
125
|
+
address controller
|
126
|
+
) public view returns (uint256 cost) {
|
127
|
+
try IERC721Controller(controller).getCostControlledERC721(tokenIn, ids, tokenOut) returns (uint256 cost721) {
|
128
|
+
cost = cost721;
|
129
|
+
} catch {
|
130
|
+
cost = 0;
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
/**
|
135
|
+
* @notice Returns total cost of the pool in value token
|
136
|
+
* @dev Doesn't check if pool is pool.
|
137
|
+
* @param _ufarmPool - address of the pool
|
138
|
+
* @param _valueToken - address of the value token
|
139
|
+
*/
|
140
|
+
function getTotalCostOfPool(
|
141
|
+
address _ufarmPool,
|
142
|
+
address _valueToken
|
143
|
+
) external view returns (uint256 totalCost) {
|
144
|
+
IUFarmPool pool = IUFarmPool(_ufarmPool);
|
145
|
+
IUFarmCore core = IUFarmCore(pool.ufarmCore());
|
146
|
+
|
147
|
+
// gas saving
|
148
|
+
uint256 length;
|
149
|
+
address thisAsset;
|
150
|
+
address controllerAddr;
|
151
|
+
|
152
|
+
// common erc20 block
|
153
|
+
{
|
154
|
+
address[] memory nonZeroAssets = pool.erc20CommonAssets();
|
155
|
+
length = nonZeroAssets.length;
|
156
|
+
uint256 balanceOfAsset;
|
157
|
+
for (uint256 i; i < length; ++i) {
|
158
|
+
thisAsset = nonZeroAssets[i];
|
159
|
+
balanceOfAsset = IERC20(thisAsset).balanceOf(_ufarmPool);
|
160
|
+
totalCost += thisAsset == _valueToken
|
161
|
+
? balanceOfAsset
|
162
|
+
: getCostERC20(thisAsset, balanceOfAsset, _valueToken);
|
163
|
+
}
|
164
|
+
}
|
165
|
+
|
166
|
+
// controlled erc20 block
|
167
|
+
{
|
168
|
+
AssetsStructs.ControlledERC20[] memory controlledAssets20 = pool.erc20ControlledAssets();
|
169
|
+
length = controlledAssets20.length;
|
170
|
+
|
171
|
+
for (uint256 i; i < length; ++i) {
|
172
|
+
thisAsset = controlledAssets20[i].addr;
|
173
|
+
controllerAddr = core.controllers(controlledAssets20[i].controller);
|
174
|
+
if (controllerAddr == address(0)) revert InvalidController();
|
175
|
+
totalCost += getCostControlledERC20(
|
176
|
+
thisAsset,
|
177
|
+
IERC20(thisAsset).balanceOf(_ufarmPool),
|
178
|
+
_valueToken,
|
179
|
+
controllerAddr
|
180
|
+
);
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
// controlled erc721 block
|
185
|
+
{
|
186
|
+
AssetsStructs.ControlledERC721[] memory controlledAssets721 = pool.erc721ControlledAssets();
|
187
|
+
length = controlledAssets721.length;
|
188
|
+
|
189
|
+
AssetsStructs.ControlledERC721 memory controlledAsset721;
|
190
|
+
|
191
|
+
for (uint256 i; i < length; ++i) {
|
192
|
+
controlledAsset721 = controlledAssets721[i];
|
193
|
+
controllerAddr = core.controllers(controlledAsset721.controller);
|
194
|
+
if (controllerAddr == address(0)) revert InvalidController();
|
195
|
+
totalCost += getCostERC721(
|
196
|
+
controlledAsset721.addr,
|
197
|
+
controlledAsset721.ids,
|
198
|
+
_valueToken,
|
199
|
+
controllerAddr
|
200
|
+
);
|
201
|
+
}
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
function __init__PriceOracleCore(address ufarmCoreLink) internal onlyInitializing {
|
206
|
+
__init__UFarmOwnableUUPS();
|
207
|
+
__init__UFarmCoreLink(ufarmCoreLink);
|
208
|
+
__init__ChainlinkedOracle(HOUR * 25); // 25 hours
|
209
|
+
}
|
210
|
+
|
211
|
+
uint256[50] private __gap;
|
212
|
+
}
|
@@ -0,0 +1,64 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8.0;
|
4
|
+
|
5
|
+
import {ChainlinkedOracle} from './ChainlinkedOracle.sol';
|
6
|
+
import {IChainlinkAggregator} from './IChainlinkAggregator.sol';
|
7
|
+
|
8
|
+
/**
|
9
|
+
* @title WstETHOracle contract
|
10
|
+
* @author https://ufarm.digital/
|
11
|
+
* @notice Wraps the stETH/USD and wstETH/stETH Chainlink price feeds to query the wstETH/USD price
|
12
|
+
*/
|
13
|
+
contract WstETHOracle is IChainlinkAggregator, ChainlinkedOracle {
|
14
|
+
uint8 public immutable decimals;
|
15
|
+
|
16
|
+
address public immutable stETHUSDOracle;
|
17
|
+
address public immutable wstETHstETHOracle;
|
18
|
+
address public immutable wstETH;
|
19
|
+
|
20
|
+
constructor(address _wstETH, address _stETHUSDOracle, address _wstETHstETHOracle) initializer {
|
21
|
+
__init__ChainlinkedOracle(HOUR * 25);
|
22
|
+
stETHUSDOracle = _stETHUSDOracle;
|
23
|
+
wstETHstETHOracle = _wstETHstETHOracle;
|
24
|
+
wstETH = _wstETH;
|
25
|
+
decimals = IChainlinkAggregator(_stETHUSDOracle).decimals();
|
26
|
+
}
|
27
|
+
|
28
|
+
function latestAnswer() external view override returns (int256 answer) {
|
29
|
+
answer = _stETHtoWstETH(_chainlinkLatestAnswer(stETHUSDOracle));
|
30
|
+
}
|
31
|
+
|
32
|
+
function latestRoundData()
|
33
|
+
external
|
34
|
+
view
|
35
|
+
override
|
36
|
+
returns (
|
37
|
+
uint80 roundId,
|
38
|
+
int256 answer,
|
39
|
+
uint256 startedAt,
|
40
|
+
uint256 updatedAt,
|
41
|
+
uint80 answeredInRound
|
42
|
+
)
|
43
|
+
{
|
44
|
+
ChainlinkAnswer memory stETHRoundData = _chainlinkLatestRoundData(stETHUSDOracle);
|
45
|
+
answer = _stETHtoWstETH(stETHRoundData.answer);
|
46
|
+
return (
|
47
|
+
stETHRoundData.roundId,
|
48
|
+
answer,
|
49
|
+
stETHRoundData.startedAt,
|
50
|
+
stETHRoundData.updatedAt,
|
51
|
+
stETHRoundData.answeredInRound
|
52
|
+
);
|
53
|
+
}
|
54
|
+
|
55
|
+
function description() external pure returns (string memory) {
|
56
|
+
return 'UFarm WstETH/USD Oracle';
|
57
|
+
}
|
58
|
+
|
59
|
+
function _stETHtoWstETH(int256 _stETHUSDPrice) internal view returns (int256 wstETHUSDPrice) {
|
60
|
+
wstETHUSDPrice = _chainlinkLatestAnswer(wstETHstETHOracle);
|
61
|
+
|
62
|
+
return (wstETHUSDPrice * _stETHUSDPrice) / 10 ** 18;
|
63
|
+
}
|
64
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8.0;
|
4
|
+
|
5
|
+
interface Permissions {
|
6
|
+
enum Fund {
|
7
|
+
Member,
|
8
|
+
Owner,
|
9
|
+
UpdateFund,
|
10
|
+
InviteFundMember,
|
11
|
+
BlockFundMember,
|
12
|
+
UpdateFundPermissions,
|
13
|
+
CreatePool,
|
14
|
+
UpdatePoolDescription,
|
15
|
+
UpdatePoolPermissions,
|
16
|
+
PoolStatusControl,
|
17
|
+
UpdatePoolFees,
|
18
|
+
UpdatePoolTopUpAmount,
|
19
|
+
UpdateLockupPeriods,
|
20
|
+
ManageFund,
|
21
|
+
ApprovePoolTopup,
|
22
|
+
ApprovePoolWithdrawals,
|
23
|
+
ManagePoolFunds
|
24
|
+
}
|
25
|
+
|
26
|
+
enum Pool {
|
27
|
+
Member,
|
28
|
+
UpdatePoolDescription,
|
29
|
+
UpdatePoolPermissions,
|
30
|
+
PoolStatusControl,
|
31
|
+
UpdatePoolFees,
|
32
|
+
UpdatePoolTopUpAmount,
|
33
|
+
UpdateLockupPeriods,
|
34
|
+
ApprovePoolTopup,
|
35
|
+
ApprovePoolWithdrawals,
|
36
|
+
ManagePoolFunds
|
37
|
+
}
|
38
|
+
|
39
|
+
enum UFarm {
|
40
|
+
Member,
|
41
|
+
Owner,
|
42
|
+
UpdatePermissions,
|
43
|
+
UpdateUFarmMember,
|
44
|
+
DeleteUFarmMember,
|
45
|
+
ApproveFundCreation,
|
46
|
+
BlockFund,
|
47
|
+
BlockInvestor,
|
48
|
+
ManageFees,
|
49
|
+
ManageFundDeposit,
|
50
|
+
ManageWhitelist,
|
51
|
+
ManageAssets,
|
52
|
+
TurnPauseOn
|
53
|
+
}
|
54
|
+
}
|
@@ -0,0 +1,136 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8.0;
|
4
|
+
|
5
|
+
import {UFarmErrors} from '../../shared/UFarmErrors.sol';
|
6
|
+
|
7
|
+
/**
|
8
|
+
* @title UFarmPermissionsModel contract
|
9
|
+
* @author https://ufarm.digital/
|
10
|
+
* @notice Contract that implements permissions model for UFarm contracts
|
11
|
+
*/
|
12
|
+
abstract contract UFarmPermissionsModel {
|
13
|
+
uint256 internal constant _FULL_PERMISSIONS_MASK = type(uint256).max;
|
14
|
+
mapping(address => uint256) internal _accountMask;
|
15
|
+
|
16
|
+
// EVENTS
|
17
|
+
event PermissionsUpdated(address account, uint256 newPermissions);
|
18
|
+
|
19
|
+
// ERRORS
|
20
|
+
error PermissionAlreadyGranted(address account, uint256 permissions);
|
21
|
+
|
22
|
+
// MODIFIERS
|
23
|
+
/**
|
24
|
+
* @notice Reverts if account has no required permissions
|
25
|
+
* @param account - address to check permissions
|
26
|
+
* @param permission1 - first permission to check
|
27
|
+
* @param permission2 - second permission to check
|
28
|
+
*/
|
29
|
+
modifier shouldHaveTwoPermissions(
|
30
|
+
address account,
|
31
|
+
uint8 permission1,
|
32
|
+
uint8 permission2
|
33
|
+
) {
|
34
|
+
_checkForPermissions(account, _twoPermissionsToMask(permission1, permission2));
|
35
|
+
_;
|
36
|
+
}
|
37
|
+
|
38
|
+
// PUBLIC
|
39
|
+
|
40
|
+
/**
|
41
|
+
* @notice Returns 'true' if account has required permission, 'false' otherwise
|
42
|
+
* @param account - address to check permissions
|
43
|
+
* @param permissionToCheck - permission to check
|
44
|
+
*/
|
45
|
+
function hasPermission(
|
46
|
+
address account,
|
47
|
+
uint8 permissionToCheck
|
48
|
+
) external view virtual returns (bool) {
|
49
|
+
return _hasPermission(account, permissionToCheck);
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* @notice Returns 'true' if account has required permissions mask, 'false' otherwise
|
54
|
+
* @param account - address to check permissions
|
55
|
+
* @param permissionsToCheck - permissions mask to compare with
|
56
|
+
*/
|
57
|
+
function hasPermissionsMask(
|
58
|
+
address account,
|
59
|
+
uint256 permissionsToCheck
|
60
|
+
) external view virtual returns (bool) {
|
61
|
+
return __hasPermissions(_accountMask[account], permissionsToCheck);
|
62
|
+
}
|
63
|
+
|
64
|
+
/**
|
65
|
+
* @notice Reverts if account has no required permissions mask
|
66
|
+
* @param account - address to check permissions
|
67
|
+
* @param permissionsToCheck - permissions mask to compare with
|
68
|
+
*/
|
69
|
+
function checkForPermissionsMask(
|
70
|
+
address account,
|
71
|
+
uint256 permissionsToCheck
|
72
|
+
) external view virtual {
|
73
|
+
_checkForPermissions(account, permissionsToCheck);
|
74
|
+
}
|
75
|
+
|
76
|
+
// INTERNAL SETTERS
|
77
|
+
|
78
|
+
function _updatePermissions(address account, uint256 newPermissions) internal {
|
79
|
+
if (_accountMask[account] != newPermissions) {
|
80
|
+
_accountMask[account] = newPermissions;
|
81
|
+
emit PermissionsUpdated(account, newPermissions);
|
82
|
+
} else {
|
83
|
+
revert PermissionAlreadyGranted(account, newPermissions);
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
// INTERNAL CHECKS
|
88
|
+
|
89
|
+
function _checkForPermissions(address account, uint256 permissions) internal view {
|
90
|
+
if (!__hasPermissions(_accountMask[account], permissions)) {
|
91
|
+
revert UFarmErrors.NonAuthorized();
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
// INTERNAL GETTERS
|
96
|
+
|
97
|
+
function _hasPermission(address account, uint8 permissionToCheck) internal view returns (bool) {
|
98
|
+
return (_accountMask[account] & (1 << permissionToCheck)) != 0;
|
99
|
+
}
|
100
|
+
|
101
|
+
function _maskHasPermission(uint256 mask, uint8 permissionToCheck) internal pure returns (bool) {
|
102
|
+
return (mask & (1 << permissionToCheck)) != 0;
|
103
|
+
}
|
104
|
+
|
105
|
+
function _hasPermissionMask(
|
106
|
+
address account,
|
107
|
+
uint256 permissionToCheck
|
108
|
+
) internal view returns (bool) {
|
109
|
+
return (_accountMask[account] & permissionToCheck) == permissionToCheck;
|
110
|
+
}
|
111
|
+
|
112
|
+
function _isPermissionDiff(
|
113
|
+
uint8 permission,
|
114
|
+
uint256 mask1,
|
115
|
+
uint256 mask2
|
116
|
+
) internal pure returns (bool) {
|
117
|
+
return ((mask1 & (1 << permission)) != (mask2 & (1 << permission)));
|
118
|
+
}
|
119
|
+
|
120
|
+
function _permissionToMask(uint8 permission) internal pure returns (uint256 mask) {
|
121
|
+
return (1 << permission);
|
122
|
+
}
|
123
|
+
|
124
|
+
function _twoPermissionsToMask(
|
125
|
+
uint8 permission1,
|
126
|
+
uint8 permission2
|
127
|
+
) internal pure returns (uint256 mask) {
|
128
|
+
return (1 << permission1) | (1 << permission2);
|
129
|
+
}
|
130
|
+
|
131
|
+
function __hasPermissions(uint256 accountPermissions, uint256 mask) private pure returns (bool) {
|
132
|
+
return (accountPermissions & mask) == mask;
|
133
|
+
}
|
134
|
+
|
135
|
+
uint256[50] private __gap;
|
136
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
import {IUFarmPool} from './IUFarmPool.sol';
|
4
|
+
import {Permissions} from '../permissions/Permissions.sol';
|
5
|
+
|
6
|
+
pragma solidity ^0.8.0;
|
7
|
+
|
8
|
+
interface IPoolAdmin {
|
9
|
+
struct PoolConfig {
|
10
|
+
uint256 managementCommission;
|
11
|
+
uint256 packedPerformanceFee;
|
12
|
+
uint256 minInvestment;
|
13
|
+
uint256 maxInvestment;
|
14
|
+
uint128 withdrawalLockupPeriod;
|
15
|
+
}
|
16
|
+
|
17
|
+
/**
|
18
|
+
* @notice Initializes the pool admin contract during the pool creation
|
19
|
+
* @param _settings - Pool parameters
|
20
|
+
* @param _poolAddr - Address of the pool
|
21
|
+
*/
|
22
|
+
function __init_PoolAdmin(
|
23
|
+
IUFarmPool.CreationSettingsWithLinks memory _settings,
|
24
|
+
address _poolAddr
|
25
|
+
) external;
|
26
|
+
|
27
|
+
/**
|
28
|
+
* @notice Returns pool configuration
|
29
|
+
* @return config - PoolConfig struct
|
30
|
+
*/
|
31
|
+
function getConfig() external view returns (PoolConfig memory config);
|
32
|
+
|
33
|
+
/**
|
34
|
+
* @notice Returns `true` if the caller has enough permissions to manage the pool funds
|
35
|
+
* @param manager - Address of the fund manager
|
36
|
+
* @return isAble - `true` if the caller has enough permissions to manage the pool funds
|
37
|
+
*/
|
38
|
+
function isAbleToManageFunds(address manager) external view returns (bool isAble);
|
39
|
+
|
40
|
+
/**
|
41
|
+
* @notice Changes pool status on the connected UFarmPool contract
|
42
|
+
* @param _newStatus - New pool status
|
43
|
+
*/
|
44
|
+
function changePoolStatus(IUFarmPool.PoolStatus _newStatus) external;
|
45
|
+
|
46
|
+
/**
|
47
|
+
* @notice Reverts if the caller doesn't have pool permission or fund permission
|
48
|
+
* @param _account - address of the account to check permissions
|
49
|
+
* @param _poolPermission - permission in the pool
|
50
|
+
* @param _fundPermission - permission in the fund
|
51
|
+
*/
|
52
|
+
function checkPoolOrFundPermission(
|
53
|
+
address _account,
|
54
|
+
Permissions.Pool _poolPermission,
|
55
|
+
Permissions.Fund _fundPermission
|
56
|
+
) external view;
|
57
|
+
}
|