@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,194 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8.0;
|
4
|
+
|
5
|
+
import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol';
|
6
|
+
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
|
7
|
+
import {IERC721} from '@openzeppelin/contracts/token/ERC721/IERC721.sol';
|
8
|
+
|
9
|
+
interface AssetsStructs {
|
10
|
+
struct ControlledERC20 {
|
11
|
+
address addr;
|
12
|
+
bytes32 controller;
|
13
|
+
}
|
14
|
+
|
15
|
+
struct ControlledERC721 {
|
16
|
+
address addr;
|
17
|
+
bytes32 controller;
|
18
|
+
uint256[] ids;
|
19
|
+
}
|
20
|
+
|
21
|
+
struct Assets {
|
22
|
+
uint256 totalWeight;
|
23
|
+
ERC20CommonAssets erc20;
|
24
|
+
ERC20ControlledAssets erc20Controlled;
|
25
|
+
ERC721ControlledAssets erc721Controlled;
|
26
|
+
}
|
27
|
+
struct ERC20CommonAssets {
|
28
|
+
EnumerableSet.AddressSet assets;
|
29
|
+
}
|
30
|
+
struct ERC20ControlledAssets {
|
31
|
+
EnumerableSet.AddressSet assets;
|
32
|
+
mapping(address => bytes32) controllers;
|
33
|
+
}
|
34
|
+
struct ERC721ControlledAssets {
|
35
|
+
EnumerableSet.AddressSet assets;
|
36
|
+
mapping(address => EnumerableSet.UintSet) idsOfAsset;
|
37
|
+
mapping(address => bytes32) controllers;
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
library AssetLib {
|
42
|
+
using EnumerableSet for EnumerableSet.AddressSet;
|
43
|
+
using EnumerableSet for EnumerableSet.UintSet;
|
44
|
+
|
45
|
+
uint256 internal constant COMMON_ERC20_WEIGHT = 1;
|
46
|
+
uint256 internal constant CONTROLLED_ERC20_WEIGHT = 2;
|
47
|
+
uint256 internal constant CONTROLLED_ERC721_WEIGHT = 5;
|
48
|
+
|
49
|
+
/**
|
50
|
+
* @notice Returns the list of all ERC20 assets
|
51
|
+
* @param _self - Assets struct
|
52
|
+
*/
|
53
|
+
function erc20CommonAssets(
|
54
|
+
AssetsStructs.Assets storage _self
|
55
|
+
) internal view returns (address[] memory tokenAssets) {
|
56
|
+
return _self.erc20.assets.values();
|
57
|
+
}
|
58
|
+
|
59
|
+
function erc20ControlledAssets(
|
60
|
+
AssetsStructs.Assets storage _self
|
61
|
+
) internal view returns (AssetsStructs.ControlledERC20[] memory liquidityAssetsERC20) {
|
62
|
+
AssetsStructs.ERC20ControlledAssets storage controlledERC20 = _self.erc20Controlled;
|
63
|
+
uint256 assetsLength = controlledERC20.assets.length();
|
64
|
+
liquidityAssetsERC20 = new AssetsStructs.ControlledERC20[](assetsLength);
|
65
|
+
address asset;
|
66
|
+
for (uint256 i; i < assetsLength; ++i) {
|
67
|
+
asset = controlledERC20.assets.at(i);
|
68
|
+
liquidityAssetsERC20[i] = AssetsStructs.ControlledERC20({
|
69
|
+
addr: asset,
|
70
|
+
controller: controlledERC20.controllers[asset]
|
71
|
+
});
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
function erc721ControlledAssets(
|
76
|
+
AssetsStructs.Assets storage _self
|
77
|
+
) internal view returns (AssetsStructs.ControlledERC721[] memory liquidityAssetsERC721) {
|
78
|
+
AssetsStructs.ERC721ControlledAssets storage controlledERC721 = _self.erc721Controlled;
|
79
|
+
uint256 assetsLength = controlledERC721.assets.length();
|
80
|
+
liquidityAssetsERC721 = new AssetsStructs.ControlledERC721[](assetsLength);
|
81
|
+
address asset;
|
82
|
+
for (uint256 i; i < assetsLength; ++i) {
|
83
|
+
asset = controlledERC721.assets.at(i);
|
84
|
+
liquidityAssetsERC721[i] = AssetsStructs.ControlledERC721({
|
85
|
+
addr: asset,
|
86
|
+
controller: controlledERC721.controllers[asset],
|
87
|
+
ids: controlledERC721.idsOfAsset[asset].values()
|
88
|
+
});
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
function addERC20(
|
93
|
+
AssetsStructs.Assets storage _self,
|
94
|
+
address _asset,
|
95
|
+
bytes32 _controller
|
96
|
+
) internal {
|
97
|
+
if (_controller > bytes32(0)) {
|
98
|
+
// return if asset already added to controlled list
|
99
|
+
if (_self.erc20.assets.contains(_asset)) return;
|
100
|
+
|
101
|
+
// add if balance > 0 and not added yet
|
102
|
+
if (
|
103
|
+
!_self.erc20Controlled.assets.contains(_asset) &&
|
104
|
+
IERC20(_asset).balanceOf(address(this)) > 0
|
105
|
+
) {
|
106
|
+
_self.erc20Controlled.assets.add(_asset);
|
107
|
+
_self.erc20Controlled.controllers[_asset] = _controller;
|
108
|
+
_self.totalWeight += CONTROLLED_ERC20_WEIGHT;
|
109
|
+
}
|
110
|
+
} else {
|
111
|
+
// return if asset already added to controlled assets list
|
112
|
+
if (_self.erc20Controlled.assets.contains(_asset)) return;
|
113
|
+
|
114
|
+
// add if balance > 0 and not added yet
|
115
|
+
if (!_self.erc20.assets.contains(_asset) && IERC20(_asset).balanceOf(address(this)) > 0) {
|
116
|
+
_self.erc20.assets.add(_asset);
|
117
|
+
_self.totalWeight += COMMON_ERC20_WEIGHT;
|
118
|
+
}
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
function removeERC20(AssetsStructs.Assets storage _self, address _asset) internal {
|
123
|
+
if (IERC20(_asset).balanceOf(address(this)) == 0) {
|
124
|
+
// removes asset if balance is 0
|
125
|
+
if (_self.erc20.assets.remove(_asset)) {
|
126
|
+
_self.totalWeight -= COMMON_ERC20_WEIGHT;
|
127
|
+
} else if (_self.erc20Controlled.assets.remove(_asset)) {
|
128
|
+
delete _self.erc20Controlled.controllers[_asset];
|
129
|
+
_self.totalWeight -= CONTROLLED_ERC20_WEIGHT;
|
130
|
+
}
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
function addERC721WithController(
|
135
|
+
AssetsStructs.Assets storage _self,
|
136
|
+
address _asset,
|
137
|
+
uint256[] memory _ids,
|
138
|
+
bytes32 _controller
|
139
|
+
) internal {
|
140
|
+
uint256 idsLength = _ids.length;
|
141
|
+
if (idsLength == 0 || IERC721(_asset).balanceOf(address(this)) == 0) return;
|
142
|
+
|
143
|
+
AssetsStructs.ERC721ControlledAssets storage erc721Controlled = _self.erc721Controlled;
|
144
|
+
|
145
|
+
bool atLeastOneAdded; // false by default
|
146
|
+
for (uint256 i; i < idsLength; ++i) {
|
147
|
+
if (
|
148
|
+
_checkERC721Ownership(_asset, _ids[i]) && erc721Controlled.idsOfAsset[_asset].add(_ids[i])
|
149
|
+
) {
|
150
|
+
_self.totalWeight += CONTROLLED_ERC721_WEIGHT;
|
151
|
+
if (!atLeastOneAdded) {
|
152
|
+
atLeastOneAdded = true;
|
153
|
+
}
|
154
|
+
} else continue;
|
155
|
+
}
|
156
|
+
|
157
|
+
if (atLeastOneAdded && !erc721Controlled.assets.contains(_asset)) {
|
158
|
+
erc721Controlled.assets.add(_asset);
|
159
|
+
erc721Controlled.controllers[_asset] = _controller;
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
function removeERC721WithController(
|
164
|
+
AssetsStructs.Assets storage _self,
|
165
|
+
address _asset,
|
166
|
+
uint256[] memory _ids
|
167
|
+
) internal {
|
168
|
+
uint256 toRemove;
|
169
|
+
AssetsStructs.ERC721ControlledAssets storage erc721Controlled = _self.erc721Controlled;
|
170
|
+
for (uint256 i; i < _ids.length; ++i) {
|
171
|
+
// skip if pool still owns this token
|
172
|
+
if (_checkERC721Ownership(_asset, _ids[i])) continue;
|
173
|
+
erc721Controlled.idsOfAsset[_asset].remove(_ids[i]);
|
174
|
+
toRemove++;
|
175
|
+
}
|
176
|
+
if (IERC721(_asset).balanceOf(address(this)) == 0) {
|
177
|
+
erc721Controlled.assets.remove(_asset);
|
178
|
+
delete erc721Controlled.controllers[_asset];
|
179
|
+
toRemove += erc721Controlled.idsOfAsset[_asset].length();
|
180
|
+
delete erc721Controlled.idsOfAsset[_asset];
|
181
|
+
}
|
182
|
+
_self.totalWeight -= toRemove * CONTROLLED_ERC721_WEIGHT;
|
183
|
+
}
|
184
|
+
|
185
|
+
/// solhint-disable-next-line no-unassigned-vars
|
186
|
+
function _checkERC721Ownership(address _asset, uint256 _id) private view returns (bool) {
|
187
|
+
// doesn't crash when token isn't exists
|
188
|
+
try IERC721(_asset).ownerOf(_id) returns (address owner) {
|
189
|
+
return owner == address(this);
|
190
|
+
} catch {
|
191
|
+
return false;
|
192
|
+
}
|
193
|
+
}
|
194
|
+
}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8;
|
4
|
+
import {ECDSA} from '@openzeppelin/contracts/utils/cryptography/ECDSA.sol';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* @title ECDSARecover
|
8
|
+
* @author https://ufarm.digital/
|
9
|
+
* @notice Contract that provides ECDSA signature recovery based on EIP712 standard
|
10
|
+
*/
|
11
|
+
abstract contract ECDSARecover {
|
12
|
+
struct EIP712Domain {
|
13
|
+
string name;
|
14
|
+
string version;
|
15
|
+
uint256 chainId;
|
16
|
+
address verifyingContract;
|
17
|
+
}
|
18
|
+
|
19
|
+
// Safe to use, because it is constant
|
20
|
+
/// @custom:oz-upgrades-unsafe-allow state-variable-assignment state-variable-immutable
|
21
|
+
bytes32 private immutable DOMAIN_STRUCTURE_HASH =
|
22
|
+
keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)');
|
23
|
+
|
24
|
+
/**
|
25
|
+
* @notice EIP712 Domain Separator
|
26
|
+
*/
|
27
|
+
function DOMAIN_SEPARATOR() public view returns (bytes32) {
|
28
|
+
return
|
29
|
+
hashDomain(
|
30
|
+
EIP712Domain({
|
31
|
+
name: name(),
|
32
|
+
version: version(),
|
33
|
+
chainId: block.chainid,
|
34
|
+
verifyingContract: address(this)
|
35
|
+
})
|
36
|
+
);
|
37
|
+
}
|
38
|
+
|
39
|
+
/**
|
40
|
+
* @notice Reverts if the provided signature was incorrectly formatted.
|
41
|
+
*/
|
42
|
+
error WrongSignature();
|
43
|
+
|
44
|
+
/**
|
45
|
+
* @notice Returns the current version of the contract
|
46
|
+
*/
|
47
|
+
function version() public pure virtual returns (string memory);
|
48
|
+
|
49
|
+
/**
|
50
|
+
* @notice Returns the name of the contract
|
51
|
+
*/
|
52
|
+
function name() public view virtual returns (string memory);
|
53
|
+
|
54
|
+
/**
|
55
|
+
* @notice Computes EIP712 DOMAIN_SEPARATOR hash
|
56
|
+
* @param domain - EIP712 domain struct
|
57
|
+
*/
|
58
|
+
function hashDomain(ECDSARecover.EIP712Domain memory domain) internal view returns (bytes32) {
|
59
|
+
return
|
60
|
+
keccak256(
|
61
|
+
abi.encode(
|
62
|
+
DOMAIN_STRUCTURE_HASH,
|
63
|
+
keccak256(bytes(domain.name)),
|
64
|
+
keccak256(bytes(domain.version)),
|
65
|
+
domain.chainId,
|
66
|
+
domain.verifyingContract
|
67
|
+
)
|
68
|
+
);
|
69
|
+
}
|
70
|
+
|
71
|
+
/**
|
72
|
+
* @notice Recovers signer address from a message by using their signature
|
73
|
+
* @param domainHash - hash of the EIP712 domain
|
74
|
+
* @param msgHash - hash of the message
|
75
|
+
*/
|
76
|
+
function toEIP712MessageHash(
|
77
|
+
bytes32 domainHash,
|
78
|
+
bytes32 msgHash
|
79
|
+
) internal pure returns (bytes32) {
|
80
|
+
return keccak256(abi.encodePacked('\x19\x01', domainHash, msgHash));
|
81
|
+
}
|
82
|
+
|
83
|
+
/**
|
84
|
+
* @notice Recovers signer address from a message by using their signature
|
85
|
+
* @param digest - hash of the message
|
86
|
+
* @param signature - signature of the hash
|
87
|
+
*/
|
88
|
+
function recoverAddress(bytes32 digest, bytes memory signature) internal pure returns (address) {
|
89
|
+
return ECDSA.recover(digest, signature);
|
90
|
+
}
|
91
|
+
}
|
@@ -0,0 +1,99 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8.0;
|
4
|
+
|
5
|
+
/// @title NZGuard contract contains modifiers to check inputs for non-zero address, non-zero value, non-same address, non-same value, and non-more-than-one
|
6
|
+
abstract contract NZGuard {
|
7
|
+
error ZeroAddress();
|
8
|
+
error ZeroValue();
|
9
|
+
error EmptyArray();
|
10
|
+
error SameAddress();
|
11
|
+
error SameValue();
|
12
|
+
error MoreThanOne();
|
13
|
+
error ValueNotInRange(uint256 _value, uint256 _min, uint256 _max);
|
14
|
+
|
15
|
+
modifier nonZeroAddress(address _address) {
|
16
|
+
_nonZeroAddress(_address);
|
17
|
+
_;
|
18
|
+
}
|
19
|
+
modifier nonZeroValue(uint256 _value) {
|
20
|
+
_nonZeroValue(_value);
|
21
|
+
_;
|
22
|
+
}
|
23
|
+
modifier nonSameValue(uint256 _value1, uint256 _value2) {
|
24
|
+
_nonSameValue(_value1, _value2);
|
25
|
+
_;
|
26
|
+
}
|
27
|
+
modifier nonZeroBytes32(bytes32 _value) {
|
28
|
+
_nonZeroBytes32(_value);
|
29
|
+
_;
|
30
|
+
}
|
31
|
+
modifier nonSameAddress(address _address1, address _address2) {
|
32
|
+
_nonSameAddress(_address1, _address2);
|
33
|
+
_;
|
34
|
+
}
|
35
|
+
modifier nonMoreThenOne(uint256 _value) {
|
36
|
+
_nonMoreThenOne(_value);
|
37
|
+
_;
|
38
|
+
}
|
39
|
+
modifier nonEmptyArray(uint256 arrLength) {
|
40
|
+
_nonEmptyArray(arrLength);
|
41
|
+
_;
|
42
|
+
}
|
43
|
+
modifier valueInRange(
|
44
|
+
uint256 _value,
|
45
|
+
uint256 _min,
|
46
|
+
uint256 _max
|
47
|
+
) {
|
48
|
+
_valueInRange(_value, _min, _max);
|
49
|
+
_;
|
50
|
+
}
|
51
|
+
|
52
|
+
function _nonZeroAddress(address _address) internal pure {
|
53
|
+
if (_address == address(0)) {
|
54
|
+
revert ZeroAddress();
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
function _nonZeroValue(uint256 _value) internal pure {
|
59
|
+
if (_value == 0) {
|
60
|
+
revert ZeroValue();
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
function _nonZeroBytes32(bytes32 _value) internal pure {
|
65
|
+
if (_value == bytes32(0)) {
|
66
|
+
revert ZeroValue();
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
function _nonSameAddress(address _address1, address _address2) internal pure {
|
71
|
+
if (_address1 == _address2) {
|
72
|
+
revert SameAddress();
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
function _nonSameValue(uint256 _value1, uint256 _value2) internal pure {
|
77
|
+
if (_value1 == _value2) {
|
78
|
+
revert SameValue();
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
function _nonMoreThenOne(uint256 _value) internal pure {
|
83
|
+
if (_value > 1e18) {
|
84
|
+
revert MoreThanOne();
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
function _nonEmptyArray(uint256 arrLength) internal pure {
|
89
|
+
if (arrLength == 0) {
|
90
|
+
revert EmptyArray();
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
function _valueInRange(uint256 _value, uint256 _min, uint256 _max) internal pure {
|
95
|
+
if (_value < _min || _value > _max) {
|
96
|
+
revert ValueNotInRange(_value, _min, _max);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
@@ -0,0 +1,128 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8.0;
|
4
|
+
|
5
|
+
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
|
6
|
+
import {BeaconProxy} from '@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol';
|
7
|
+
|
8
|
+
/**
|
9
|
+
* @title SafeOPS
|
10
|
+
* @author https://ufarm.digital/
|
11
|
+
* @notice Contract module which provides a safe wrappers for some external calls
|
12
|
+
*/
|
13
|
+
library SafeOPS {
|
14
|
+
error DelegateCallFailed(address to);
|
15
|
+
error StaticCallFailed(address to);
|
16
|
+
error CallFailed(address to);
|
17
|
+
error ETHTransferFailed();
|
18
|
+
error BeaconProxyDeployFailed();
|
19
|
+
|
20
|
+
function _forceApprove(address token, address spender, uint256 value) internal {
|
21
|
+
bytes memory approvalCall = abi.encodeCall(IERC20.approve, (spender, value));
|
22
|
+
|
23
|
+
(bool success, ) = _safeCall(token, approvalCall);
|
24
|
+
if (!success) {
|
25
|
+
_safeCall(token, abi.encodeCall(IERC20.approve, (spender, 0)));
|
26
|
+
_safeCall(token, approvalCall);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
function _safeCall(
|
31
|
+
address _to,
|
32
|
+
bytes memory _data
|
33
|
+
) internal returns (bool success, bytes memory result) {
|
34
|
+
(success, result) = _to.call(_data);
|
35
|
+
if (!success) {
|
36
|
+
if (result.length > 0) {
|
37
|
+
// solhint-disable-next-line no-inline-assembly
|
38
|
+
assembly {
|
39
|
+
let data_size := mload(result)
|
40
|
+
revert(add(32, result), data_size)
|
41
|
+
}
|
42
|
+
} else revert CallFailed(_to);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
function _safeStaticCall(
|
47
|
+
address _to,
|
48
|
+
bytes calldata _data
|
49
|
+
) internal view returns (bool success, bytes memory result) {
|
50
|
+
(success, result) = _to.staticcall(_data);
|
51
|
+
if (!success) {
|
52
|
+
if (result.length > 0) {
|
53
|
+
// solhint-disable-next-line no-inline-assembly
|
54
|
+
assembly {
|
55
|
+
let data_size := mload(result)
|
56
|
+
revert(add(32, result), data_size)
|
57
|
+
}
|
58
|
+
} else revert StaticCallFailed(_to);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
function _safeDelegateCall(
|
63
|
+
bool _ignoreRevert,
|
64
|
+
address _to,
|
65
|
+
bytes memory _data
|
66
|
+
) internal returns (bool success, bytes memory result) {
|
67
|
+
/// @custom:oz-upgrades-unsafe-allow delegatecall
|
68
|
+
(success, result) = _to.delegatecall(_data);
|
69
|
+
if (!success && !_ignoreRevert) {
|
70
|
+
if (result.length > 0) {
|
71
|
+
// solhint-disable-next-line no-inline-assembly
|
72
|
+
assembly {
|
73
|
+
let data_size := mload(result)
|
74
|
+
revert(add(32, result), data_size)
|
75
|
+
}
|
76
|
+
} else revert DelegateCallFailed(_to);
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
function _safeTransferETH(address _to, uint256 _amount) internal {
|
81
|
+
/// @solidity memory-safe-assembly
|
82
|
+
assembly {
|
83
|
+
if iszero(call(gas(), _to, _amount, gas(), 0x00, gas(), 0x00)) {
|
84
|
+
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
|
85
|
+
revert(0x1c, 0x04)
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
function _safeBeaconCreate2Deploy(
|
91
|
+
address _beacon,
|
92
|
+
bytes32 _salt,
|
93
|
+
bytes memory _initCall
|
94
|
+
) internal returns (address addr) {
|
95
|
+
try new BeaconProxy{salt: _salt}(_beacon, _initCall) returns (BeaconProxy beaconProxy) {
|
96
|
+
return address(beaconProxy);
|
97
|
+
} catch {
|
98
|
+
revert BeaconProxyDeployFailed();
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
function computeBeaconProxyAddress(
|
103
|
+
address _implBeacon,
|
104
|
+
bytes32 _salt,
|
105
|
+
bytes memory _initCall
|
106
|
+
) internal view returns (address addr) {
|
107
|
+
return
|
108
|
+
address(
|
109
|
+
uint160(
|
110
|
+
uint(
|
111
|
+
keccak256(
|
112
|
+
abi.encodePacked(
|
113
|
+
bytes1(0xff),
|
114
|
+
address(this),
|
115
|
+
_salt,
|
116
|
+
keccak256(
|
117
|
+
abi.encodePacked(
|
118
|
+
type(BeaconProxy).creationCode,
|
119
|
+
abi.encode(_implBeacon, _initCall)
|
120
|
+
)
|
121
|
+
)
|
122
|
+
)
|
123
|
+
)
|
124
|
+
)
|
125
|
+
)
|
126
|
+
);
|
127
|
+
}
|
128
|
+
}
|
@@ -0,0 +1,83 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8.0;
|
4
|
+
|
5
|
+
/**
|
6
|
+
* @title UFarmCoreLink interface
|
7
|
+
* @author https://ufarm.digital/
|
8
|
+
* @notice Interface for the UFarmCoreLink contract
|
9
|
+
*/
|
10
|
+
interface IUFarmCoreLink {
|
11
|
+
function coreCallback() external;
|
12
|
+
}
|
13
|
+
|
14
|
+
/**
|
15
|
+
* @title UFarmCoreLink contract
|
16
|
+
* @author https://ufarm.digital/
|
17
|
+
* @notice Sets ufarmCore link for contracts that deployed before than UFarmCore
|
18
|
+
*/
|
19
|
+
abstract contract UFarmCoreLink is IUFarmCoreLink {
|
20
|
+
/**
|
21
|
+
* @notice Address of the UFarmCore contract
|
22
|
+
*/
|
23
|
+
function ufarmCore() public view returns (address) {
|
24
|
+
return _ufarmCore;
|
25
|
+
}
|
26
|
+
|
27
|
+
address private _ufarmCore;
|
28
|
+
/// @dev Keeps track of UFarmCore link approval
|
29
|
+
bool private linkApproved;
|
30
|
+
|
31
|
+
/**
|
32
|
+
* @notice Emitted when UFarmCore address is set
|
33
|
+
* @param ufarmCore Address of the UFarmCore contract
|
34
|
+
*/
|
35
|
+
event UFarmCoreLinkSet(address ufarmCore);
|
36
|
+
|
37
|
+
/**
|
38
|
+
* @notice Reverts if UFarmCore address is not set
|
39
|
+
*/
|
40
|
+
error UFarmCoreLinkNotSet();
|
41
|
+
/**
|
42
|
+
* @notice Reverts if UFarmCore address is not approved
|
43
|
+
*/
|
44
|
+
error UFarmCoreLinkNotApproved();
|
45
|
+
|
46
|
+
/**
|
47
|
+
* @notice Reverts if UFarmCore address is not set
|
48
|
+
*/
|
49
|
+
modifier onlyLinked() {
|
50
|
+
if (!linkApproved) revert UFarmCoreLinkNotApproved();
|
51
|
+
_;
|
52
|
+
}
|
53
|
+
|
54
|
+
function __init__UFarmCoreLink(address ufarmCoreLink) internal {
|
55
|
+
_setLink(ufarmCoreLink);
|
56
|
+
}
|
57
|
+
|
58
|
+
/**
|
59
|
+
* @notice Callback function for UFarmCore contract
|
60
|
+
* @dev UFarmCore contract calls this function during initialization to approve UFarmCore link
|
61
|
+
*/
|
62
|
+
function coreCallback() external override(IUFarmCoreLink) {
|
63
|
+
if (!linkApproved && msg.sender == _ufarmCore) {
|
64
|
+
linkApproved = true;
|
65
|
+
_coreCallbackHook();
|
66
|
+
} else revert UFarmCoreLinkNotApproved();
|
67
|
+
}
|
68
|
+
|
69
|
+
/// @dev override this function to add custom logic on UFarmCore callback
|
70
|
+
function _coreCallbackHook() internal virtual {}
|
71
|
+
|
72
|
+
/**
|
73
|
+
* @notice Initializes UFarmCore link
|
74
|
+
* @param ufarmCoreLink Address of the UFarmCore contract
|
75
|
+
*/
|
76
|
+
function _setLink(address ufarmCoreLink) internal {
|
77
|
+
_ufarmCore = ufarmCoreLink;
|
78
|
+
|
79
|
+
emit UFarmCoreLinkSet(ufarmCoreLink);
|
80
|
+
}
|
81
|
+
|
82
|
+
uint256[50] private __gap;
|
83
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8.0;
|
4
|
+
|
5
|
+
/**
|
6
|
+
* @title UFarmErrors contract
|
7
|
+
* @author https://ufarm.digital/
|
8
|
+
* @notice Stores shared errors for some UFarm contracts
|
9
|
+
*/
|
10
|
+
abstract contract UFarmErrors {
|
11
|
+
error ActionAlreadyDone();
|
12
|
+
error FETCHING_CONTROLLER_FAILED();
|
13
|
+
error ArraysLengthMismatch();
|
14
|
+
error UFarmIsPaused();
|
15
|
+
error NonAuthorized();
|
16
|
+
}
|
@@ -0,0 +1,80 @@
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
2
|
+
|
3
|
+
pragma solidity ^0.8.15;
|
4
|
+
|
5
|
+
/**
|
6
|
+
* @title UFarmMathLib
|
7
|
+
* @dev Library for mathematical calculations used in UFarm contracts.
|
8
|
+
*/
|
9
|
+
library UFarmMathLib {
|
10
|
+
/**
|
11
|
+
* @notice Converts an amount from one decimal format to another.
|
12
|
+
* @param amount The amount to be converted.
|
13
|
+
* @param fromDecimals The current decimal representation of the amount.
|
14
|
+
* @param toDecimals The target decimal representation.
|
15
|
+
* @return The amount converted to the target decimal format.
|
16
|
+
*/
|
17
|
+
function convertDecimals(
|
18
|
+
int256 amount,
|
19
|
+
uint8 fromDecimals,
|
20
|
+
uint8 toDecimals
|
21
|
+
) internal pure returns (int256) {
|
22
|
+
if (fromDecimals > toDecimals) {
|
23
|
+
return amount / int256(10 ** (fromDecimals - toDecimals));
|
24
|
+
} else if (fromDecimals < toDecimals) {
|
25
|
+
return amount * int256(10 ** (toDecimals - fromDecimals));
|
26
|
+
}
|
27
|
+
return amount;
|
28
|
+
}
|
29
|
+
|
30
|
+
/**
|
31
|
+
* @notice Calculates the square root of a given number.
|
32
|
+
* implementation from https://github.com/Uniswap/uniswap-lib/commit/99f3f28770640ba1bb1ff460ac7c5292fb8291a0
|
33
|
+
* original implementation: https://github.com/abdk-consulting/abdk-libraries-solidity/blob/master/ABDKMath64x64.sol#L687
|
34
|
+
* @param x - uint256
|
35
|
+
*/
|
36
|
+
function sqrt(uint256 x) internal pure returns (uint256) {
|
37
|
+
if (x == 0) return 0;
|
38
|
+
uint256 xx = x;
|
39
|
+
uint256 r = 1;
|
40
|
+
|
41
|
+
if (xx >= 0x100000000000000000000000000000000) {
|
42
|
+
xx >>= 128;
|
43
|
+
r <<= 64;
|
44
|
+
}
|
45
|
+
|
46
|
+
if (xx >= 0x10000000000000000) {
|
47
|
+
xx >>= 64;
|
48
|
+
r <<= 32;
|
49
|
+
}
|
50
|
+
if (xx >= 0x100000000) {
|
51
|
+
xx >>= 32;
|
52
|
+
r <<= 16;
|
53
|
+
}
|
54
|
+
if (xx >= 0x10000) {
|
55
|
+
xx >>= 16;
|
56
|
+
r <<= 8;
|
57
|
+
}
|
58
|
+
if (xx >= 0x100) {
|
59
|
+
xx >>= 8;
|
60
|
+
r <<= 4;
|
61
|
+
}
|
62
|
+
if (xx >= 0x10) {
|
63
|
+
xx >>= 4;
|
64
|
+
r <<= 2;
|
65
|
+
}
|
66
|
+
if (xx >= 0x8) {
|
67
|
+
r <<= 1;
|
68
|
+
}
|
69
|
+
|
70
|
+
r = (r + x / r) >> 1;
|
71
|
+
r = (r + x / r) >> 1;
|
72
|
+
r = (r + x / r) >> 1;
|
73
|
+
r = (r + x / r) >> 1;
|
74
|
+
r = (r + x / r) >> 1;
|
75
|
+
r = (r + x / r) >> 1;
|
76
|
+
r = (r + x / r) >> 1; // Seven iterations should be enough
|
77
|
+
uint256 r1 = x / r;
|
78
|
+
return (r < r1 ? r : r1);
|
79
|
+
}
|
80
|
+
}
|