@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,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
+ }