@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,332 @@
1
+ // SPDX-License-Identifier: GPL-2.0-or-later
2
+
3
+ pragma solidity ^0.8.0;
4
+
5
+ /// CONTRACTS
6
+ import {UFarmErrors} from '../../shared/UFarmErrors.sol';
7
+ import {NZGuard} from '../../shared/NZGuard.sol';
8
+ import {Controller, IController} from './Controller.sol';
9
+ import {SafeOPS} from '../../shared/SafeOPS.sol';
10
+ import {ReentrancyGuard} from '@openzeppelin/contracts/utils/ReentrancyGuard.sol';
11
+
12
+ /// INTERFACES
13
+ import {IUFarmPool} from '../pool/IUFarmPool.sol';
14
+ import {IUFarmCore} from '../core/IUFarmCore.sol';
15
+ import {ICoreWhitelist} from '../core/ICoreWhitelist.sol';
16
+ import {IPoolWhitelist} from '../pool/PoolWhitelist.sol';
17
+ import {IUniswapV2Pair} from '../../../test/Uniswap/contracts/v2-core/contracts/interfaces/IUniswapV2Pair.sol';
18
+
19
+ /// LIBRARIES
20
+ import {BytesLib} from '../../../test/UniswapV3/@uniswap/v3-periphery/contracts/libraries/BytesLib.sol';
21
+
22
+ interface IAggregationExecutor {
23
+ /// @notice propagates information about original msg.sender and executes arbitrary data
24
+ function execute(address msgSender) external payable; // 0x4b64e492
25
+ }
26
+
27
+ interface IAggregationRouterV5 {
28
+ struct SwapDescription {
29
+ address srcToken;
30
+ address dstToken;
31
+ address payable srcReceiver;
32
+ address payable dstReceiver;
33
+ uint256 amount;
34
+ uint256 minReturnAmount;
35
+ uint256 flags;
36
+ }
37
+
38
+ function swap(
39
+ IAggregationExecutor executor,
40
+ SwapDescription calldata desc,
41
+ bytes calldata permit,
42
+ bytes calldata data
43
+ ) external payable returns (uint256 returnAmount, uint256 spentAmount);
44
+
45
+ function unoswap(
46
+ address srcToken,
47
+ uint256 amount,
48
+ uint256 minReturn,
49
+ uint256[] calldata pools
50
+ ) external payable returns (uint256 returnAmount);
51
+
52
+ function unoswapTo(
53
+ address payable recipient,
54
+ address srcToken,
55
+ uint256 amount,
56
+ uint256 minReturn,
57
+ uint256[] calldata pools
58
+ ) external payable returns (uint256 returnAmount);
59
+
60
+ function uniswapV3Swap(
61
+ uint256 amount,
62
+ uint256 minReturn,
63
+ uint256[] calldata pools
64
+ ) external payable returns (uint256 returnAmount);
65
+
66
+ function uniswapV3SwapTo(
67
+ address payable recipient,
68
+ uint256 amount,
69
+ uint256 minReturn,
70
+ uint256[] calldata pools
71
+ ) external payable returns (uint256 returnAmount);
72
+ }
73
+
74
+ interface IUniswapV3Pool {
75
+ function token0() external view returns (address);
76
+
77
+ function token1() external view returns (address);
78
+ }
79
+
80
+ /**
81
+ * @title 1Inch V5 Controller contract
82
+ * @author https://ufarm.digital/
83
+ * @notice Controller contract for 1Inch V5 aggregation router
84
+ */
85
+ contract OneInchV5Controller is Controller, NZGuard, UFarmErrors, ReentrancyGuard {
86
+ using BytesLib for bytes;
87
+
88
+ bytes32 internal constant _PROTOCOL = keccak256(abi.encodePacked('OneInchV5'));
89
+
90
+ /// @notice 1inch V5 aggregation router address
91
+ address public immutable aggregationRouterV5;
92
+
93
+ constructor(address _aggregationRouterV5) {
94
+ aggregationRouterV5 = _aggregationRouterV5;
95
+ }
96
+
97
+ /**
98
+ * @notice Delegates swap to 1inch V5 aggregation router
99
+ * @param tokenIn - token to swap from
100
+ * @param tokenOut - token to swap to
101
+ * @param amountIn - amount of tokenIn to swap
102
+ * @param amountOut - minimum amount of tokenOut to receive
103
+ * @param protocol - protocol hashed name
104
+ */
105
+ event SwapOneInchV5(
106
+ address indexed tokenIn,
107
+ address indexed tokenOut,
108
+ uint256 amountIn,
109
+ uint256 amountOut,
110
+ bytes32 indexed protocol
111
+ );
112
+
113
+ error EmptySwapPath();
114
+ error InvalidPath();
115
+ error InvalidMethod();
116
+ error InvalidRecipient();
117
+ error OneInchSwapFailed();
118
+
119
+ /**
120
+ * @inheritdoc IController
121
+ */
122
+ function PROTOCOL() public pure override returns (bytes32) {
123
+ return _PROTOCOL;
124
+ }
125
+
126
+ /**
127
+ * @notice Executes multiple swaps one by one using 1inch V5 aggregation router
128
+ * @param _multiData - array of bytes data for multiple swaps
129
+ */
130
+ function delegated1InchMultiSwap(
131
+ bytes[] calldata _multiData
132
+ ) external checkDelegateCall nonReentrant {
133
+ uint256 swapsCount = _multiData.length;
134
+ if (swapsCount == 0) revert EmptySwapPath();
135
+
136
+ (address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut) = _run1InchSwap(
137
+ _multiData[0]
138
+ );
139
+
140
+ for (uint256 i = 1; i < swapsCount; ++i) {
141
+ (, tokenOut, , amountOut) = _run1InchSwap(_multiData[i]);
142
+ }
143
+
144
+ _afterSwapExecuted(tokenIn, tokenOut, amountIn, amountOut);
145
+ }
146
+
147
+ /**
148
+ * @notice Executes swap using 1inch V5 aggregation router
149
+ * @param _data - swap transaction data
150
+ */
151
+ function delegated1InchSwap(bytes calldata _data) public checkDelegateCall nonReentrant {
152
+ (address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut) = _run1InchSwap(_data);
153
+ _afterSwapExecuted(tokenIn, tokenOut, amountIn, amountOut);
154
+ }
155
+
156
+ function _run1InchSwap(
157
+ bytes memory _data
158
+ ) internal returns (address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut) {
159
+ bytes4 method;
160
+ assembly {
161
+ method := mload(add(_data, 32)) // load first 4 bytes of data
162
+ }
163
+
164
+ uint256[] memory pools;
165
+
166
+ if (method == IAggregationRouterV5.unoswapTo.selector) {
167
+ address payable recipient;
168
+ address localTokenIn;
169
+ (recipient, localTokenIn, amountIn, amountOut, pools) = abi.decode(
170
+ _data.slice(4, _data.length - 4),
171
+ (address, address, uint256, uint256, uint256[])
172
+ );
173
+
174
+ if (recipient != address(this)) revert InvalidRecipient();
175
+
176
+ tokenIn = localTokenIn;
177
+
178
+ _onlyIfTokenAllowed(localTokenIn);
179
+
180
+ address v2Pool;
181
+ for (uint256 i; i < pools.length; ++i) {
182
+ v2Pool = address(uint160(pools[i]));
183
+
184
+ (address token0, address token1) = (
185
+ IUniswapV2Pair(v2Pool).token0(),
186
+ IUniswapV2Pair(v2Pool).token1()
187
+ );
188
+
189
+ if (token0 == localTokenIn) {
190
+ localTokenIn = token1;
191
+ } else if (token1 == localTokenIn) {
192
+ localTokenIn = token0;
193
+ } else revert InvalidPath();
194
+ _onlyIfTokenAllowed(localTokenIn);
195
+ }
196
+ tokenOut = localTokenIn;
197
+ } else if (method == IAggregationRouterV5.unoswap.selector) {
198
+ address localTokenIn;
199
+ (localTokenIn, amountIn, amountOut, pools) = abi.decode(
200
+ _data.slice(4, _data.length - 4),
201
+ (address, uint256, uint256, uint256[])
202
+ );
203
+
204
+ tokenIn = localTokenIn;
205
+
206
+ _onlyIfTokenAllowed(localTokenIn);
207
+
208
+ address v2Pool;
209
+ for (uint256 i; i < pools.length; ++i) {
210
+ v2Pool = address(uint160(pools[i]));
211
+
212
+ (address token0, address token1) = (
213
+ IUniswapV2Pair(v2Pool).token0(),
214
+ IUniswapV2Pair(v2Pool).token1()
215
+ );
216
+
217
+ if (token0 == localTokenIn) {
218
+ localTokenIn = token1;
219
+ } else if (token1 == localTokenIn) {
220
+ localTokenIn = token0;
221
+ } else revert InvalidPath();
222
+ _onlyIfTokenAllowed(localTokenIn);
223
+ }
224
+ tokenOut = localTokenIn;
225
+ } else if (method == IAggregationRouterV5.uniswapV3SwapTo.selector) {
226
+ address payable recipient;
227
+ (recipient, amountIn, amountOut, pools) = abi.decode(
228
+ _data.slice(4, _data.length - 4),
229
+ (address, uint256, uint256, uint256[])
230
+ );
231
+
232
+ if (recipient != address(this)) revert InvalidRecipient();
233
+
234
+ uint256 length = pools.length;
235
+ for (uint256 i; i < length; ++i) {
236
+ address v2Pool = address(uint160(pools[i]));
237
+
238
+ bool zeroForOne = pools[i] & (1 << 255) == 0;
239
+
240
+ (address token0, address token1) = (
241
+ IUniswapV3Pool(v2Pool).token0(),
242
+ IUniswapV3Pool(v2Pool).token1()
243
+ );
244
+ if (i > 0) {
245
+ // get dst token
246
+ tokenOut = zeroForOne ? token1 : token0;
247
+ } else {
248
+ (tokenIn, tokenOut) = zeroForOne ? (token0, token1) : (token1, token0);
249
+ // check src token if it's first pool
250
+ _onlyIfTokenAllowed(tokenIn);
251
+ }
252
+ // check dst token
253
+ _onlyIfTokenAllowed(tokenOut);
254
+ }
255
+ } else if (method == IAggregationRouterV5.uniswapV3Swap.selector) {
256
+ (amountIn, amountOut, pools) = abi.decode(
257
+ _data.slice(4, _data.length - 4),
258
+ (uint256, uint256, uint256[])
259
+ );
260
+
261
+ uint256 length = pools.length;
262
+ for (uint256 i; i < length; ++i) {
263
+ address v2Pool = address(uint160(pools[i]));
264
+
265
+ bool zeroForOne = pools[i] & (1 << 255) == 0;
266
+
267
+ (address token0, address token1) = (
268
+ IUniswapV3Pool(v2Pool).token0(),
269
+ IUniswapV3Pool(v2Pool).token1()
270
+ );
271
+ if (i > 0) {
272
+ // get dst token
273
+ tokenOut = zeroForOne ? token1 : token0;
274
+ } else {
275
+ (tokenIn, tokenOut) = zeroForOne ? (token0, token1) : (token1, token0);
276
+ // check src token if it's first pool
277
+ _onlyIfTokenAllowed(tokenIn);
278
+ }
279
+ // check dst token
280
+ _onlyIfTokenAllowed(tokenOut);
281
+ }
282
+ } else if (method == IAggregationRouterV5.swap.selector) {
283
+ IAggregationRouterV5.SwapDescription memory swapDescription;
284
+ (, swapDescription) = abi.decode(
285
+ _data.slice(4, _data.length - 4),
286
+ (address, IAggregationRouterV5.SwapDescription)
287
+ );
288
+
289
+ tokenIn = swapDescription.srcToken;
290
+ tokenOut = swapDescription.dstToken;
291
+ amountIn = swapDescription.amount;
292
+ amountOut = swapDescription.minReturnAmount;
293
+
294
+ if (swapDescription.dstReceiver != address(this)) revert InvalidRecipient();
295
+ _onlyIfTokenAllowed(tokenOut);
296
+ } else revert InvalidMethod();
297
+
298
+ if (amountIn == 0 || amountOut == 0) revert OneInchSwapFailed();
299
+
300
+ SafeOPS._forceApprove(tokenIn, aggregationRouterV5, amountIn);
301
+
302
+ (, bytes memory result) = SafeOPS._safeCall(aggregationRouterV5, _data);
303
+
304
+ uint256 amountOutResult;
305
+ assembly {
306
+ // return amount should be in 0x20 offset from any result
307
+ amountOutResult := mload(add(result, 0x20))
308
+ }
309
+
310
+ if (amountOutResult < amountOut) revert OneInchSwapFailed();
311
+ amountOut = amountOutResult;
312
+ }
313
+
314
+ function _afterSwapExecuted(
315
+ address tokenIn,
316
+ address tokenOut,
317
+ uint256 amountIn,
318
+ uint256 amountOut
319
+ ) internal {
320
+ IUFarmPool(address(this)).removeERC20(tokenIn);
321
+ IUFarmPool(address(this)).addERC20(tokenOut, bytes32(0));
322
+ emit SwapOneInchV5(tokenIn, tokenOut, amountIn, amountOut, PROTOCOL());
323
+ }
324
+
325
+ function _onlyIfTokenAllowed(address token) internal view {
326
+ if (IPoolWhitelist(address(this)).isTokenAllowed(token) == false &&
327
+ token != 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
328
+ ) {
329
+ revert IPoolWhitelist.TokenIsNotAllowed(token);
330
+ }
331
+ }
332
+ }