@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,466 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+
3
+ pragma solidity 0.8.15;
4
+
5
+ import {IUniswapV3Factory} from './UniswapV3/@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';
6
+ // import {IUniswapV3Pool} from './UniswapV3/@uniswap/v3-core/contracts/UniswapV3Pool.sol';
7
+ // import {INonfungiblePositionManager} from './UniswapV3/@uniswap/v3-periphery/contracts/NonfungiblePositionManager.sol';
8
+ import {INonfungiblePositionManager} from './UniswapV3/@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol';
9
+ import {IQuoterV2} from './UniswapV3/@uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol';
10
+ import 'hardhat/console.sol';
11
+
12
+ //
13
+
14
+ interface IERC20 {
15
+ /**
16
+ * @dev Emitted when `value` tokens are moved from one account (`from`) to
17
+ * another (`to`).
18
+ *
19
+ * Note that `value` may be zero.
20
+ */
21
+ event Transfer(address indexed from, address indexed to, uint256 value);
22
+
23
+ /**
24
+ * @dev Emitted when the allowance of a `spender` for an `owner` is set by
25
+ * a call to {approve}. `value` is the new allowance.
26
+ */
27
+ event Approval(address indexed owner, address indexed spender, uint256 value);
28
+
29
+ /**
30
+ * @dev Returns the amount of tokens in existence.
31
+ */
32
+ function totalSupply() external view returns (uint256);
33
+
34
+ /**
35
+ * @dev Returns the amount of tokens owned by `account`.
36
+ */
37
+ function balanceOf(address account) external view returns (uint256);
38
+
39
+ /**
40
+ * @dev Moves `amount` tokens from the caller's account to `to`.
41
+ *
42
+ * Returns a boolean value indicating whether the operation succeeded.
43
+ *
44
+ * Emits a {Transfer} event.
45
+ */
46
+ function transfer(address to, uint256 amount) external returns (bool);
47
+
48
+ /**
49
+ * @dev Returns the remaining number of tokens that `spender` will be
50
+ * allowed to spend on behalf of `owner` through {transferFrom}. This is
51
+ * zero by default.
52
+ *
53
+ * This value changes when {approve} or {transferFrom} are called.
54
+ */
55
+ function allowance(address owner, address spender) external view returns (uint256);
56
+
57
+ /**
58
+ * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
59
+ *
60
+ * Returns a boolean value indicating whether the operation succeeded.
61
+ *
62
+ * IMPORTANT: Beware that changing an allowance with this method brings the risk
63
+ * that someone may use both the old and the new allowance by unfortunate
64
+ * transaction ordering. One possible solution to mitigate this race
65
+ * condition is to first reduce the spender's allowance to 0 and set the
66
+ * desired value afterwards:
67
+ * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
68
+ *
69
+ * Emits an {Approval} event.
70
+ */
71
+ function approve(address spender, uint256 amount) external returns (bool);
72
+
73
+ /**
74
+ * @dev Moves `amount` tokens from `from` to `to` using the
75
+ * allowance mechanism. `amount` is then deducted from the caller's
76
+ * allowance.
77
+ *
78
+ * Returns a boolean value indicating whether the operation succeeded.
79
+ *
80
+ * Emits a {Transfer} event.
81
+ */
82
+ function transferFrom(address from, address to, uint256 amount) external returns (bool);
83
+ }
84
+
85
+ interface IWETH is IERC20 {
86
+ function deposit() external payable;
87
+
88
+ function withdraw(uint256 amount) external;
89
+ }
90
+
91
+ interface IUniswapV3PoolTest {
92
+ // interface IUniswapV3PoolImmutables
93
+ /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface
94
+ /// @return The contract address
95
+ function factory() external view returns (address);
96
+
97
+ /// @notice The first of the two tokens of the pool, sorted by address
98
+ /// @return The token contract address
99
+ function token0() external view returns (address);
100
+
101
+ /// @notice The second of the two tokens of the pool, sorted by address
102
+ /// @return The token contract address
103
+ function token1() external view returns (address);
104
+
105
+ /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6
106
+ /// @return The fee
107
+ function fee() external view returns (uint24);
108
+
109
+ /// @notice The pool tick spacing
110
+ /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive
111
+ /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...
112
+ /// This value is an int24 to avoid casting even though it is always positive.
113
+ /// @return The tick spacing
114
+ function tickSpacing() external view returns (int24);
115
+
116
+ /// @notice The maximum amount of position liquidity that can use any tick in the range
117
+ /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and
118
+ /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool
119
+ /// @return The max amount of liquidity per tick
120
+ function maxLiquidityPerTick() external view returns (uint128);
121
+ }
122
+
123
+ interface IAggregationRouterV5 {
124
+ struct SwapDescription {
125
+ address srcToken;
126
+ address dstToken;
127
+ address payable srcReceiver;
128
+ address payable dstReceiver;
129
+ uint256 amount;
130
+ uint256 minReturnAmount;
131
+ uint256 flags;
132
+ }
133
+
134
+ // function swap(
135
+ // IAggregationExecutor executor,
136
+ // SwapDescription calldata desc,
137
+ // bytes calldata permit,
138
+ // bytes calldata data
139
+ // ) external payable returns (uint256 returnAmount, uint256 spentAmount);
140
+
141
+ function unoswap(
142
+ address srcToken,
143
+ uint256 amount,
144
+ uint256 minReturn,
145
+ uint256[] calldata pools
146
+ ) external payable returns (uint256 returnAmount);
147
+
148
+ function unoswapTo(
149
+ address payable recipient,
150
+ IERC20 srcToken,
151
+ uint256 amount,
152
+ uint256 minReturn,
153
+ uint256[] calldata pools
154
+ ) external payable returns (uint256 returnAmount);
155
+
156
+ function uniswapV3Swap(
157
+ uint256 amount,
158
+ uint256 minReturn,
159
+ uint256[] calldata pools
160
+ ) external payable returns (uint256 returnAmount);
161
+
162
+ function uniswapV3SwapTo(
163
+ address payable recipient,
164
+ uint256 amount,
165
+ uint256 minReturn,
166
+ uint256[] calldata pools
167
+ ) external payable returns (uint256 returnAmount);
168
+ }
169
+
170
+ contract OneInchToUfarmTestEnv {
171
+ address private constant _NATIVE_ASSET = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
172
+
173
+ uint256 private constant _ONE_FOR_ZERO_MASK = 1 << 255;
174
+ uint256 private constant _WETH_UNWRAP_MASK = 1 << 253;
175
+ bytes32 private constant _POOL_INIT_CODE_HASH =
176
+ 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;
177
+ bytes32 private constant _FF_FACTORY =
178
+ 0xff1F98431c8aD98523631AE4a59f267346ea31F9840000000000000000000000;
179
+ // concatenation of token0(), token1() fee(), transfer() and transferFrom() selectors
180
+ bytes32 private constant _SELECTORS =
181
+ 0x0dfe1681d21220a7ddca3f43a9059cbb23b872dd000000000000000000000000;
182
+ uint256 private constant _ADDRESS_MASK =
183
+ 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
184
+ /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)
185
+ uint160 private constant _MIN_SQRT_RATIO = 4295128739 + 1;
186
+ /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)
187
+ uint160 private constant _MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342 - 1;
188
+ IWETH private immutable _WETH; // solhint-disable-line var-name-mixedcase
189
+
190
+ constructor(IWETH weth) {
191
+ _WETH = weth;
192
+ }
193
+
194
+ //
195
+
196
+ //
197
+
198
+ //
199
+
200
+ struct UniswapV3CustomData {
201
+ address payable customRecipient;
202
+ uint256 customAmountIn;
203
+ bytes customRoute;
204
+ IUniswapV3Factory factory;
205
+ INonfungiblePositionManager positionManager;
206
+ IQuoterV2 quoter;
207
+ uint256 minReturn;
208
+ bool unwrapWethOut;
209
+ }
210
+
211
+ struct UniswapV3CustomDataOut {
212
+ uint256 value;
213
+ bytes data;
214
+ }
215
+
216
+ UniswapV3CustomData private args;
217
+
218
+ // uint24 public fee = 500;
219
+
220
+ // function setFee(uint24 _fee) external {
221
+ // fee = _fee;
222
+ // }
223
+
224
+ /**
225
+ * @dev Decodes the encoded path string into tokens and fees.
226
+ * Assumes a pattern of address.fee.address.fee.address.
227
+ * @param encodedPath The encoded path string.
228
+ * @return tokens The decoded token addresses.
229
+ * @return fees The decoded fees.
230
+ */
231
+ function decodePath(
232
+ bytes memory encodedPath
233
+ ) public pure returns (address[] memory tokens, uint24[] memory fees) {
234
+ // Calculate the count of tokens and fees based on the encoded path length
235
+ // Each token address is 20 bytes, each fee is 3 bytes, and the pattern is address.fee repeating ending with an address
236
+ uint256 tokensCount = (encodedPath.length + 3) / 23;
237
+ uint256 feesCount = tokensCount - 1;
238
+
239
+ tokens = new address[](tokensCount);
240
+ fees = new uint24[](feesCount);
241
+
242
+ uint256 index = 0; // Track the current byte index in encodedPath
243
+
244
+ for (uint256 i = 0; i < feesCount; i++) {
245
+ // Extract and store token address
246
+ tokens[i] = bytesToAddress(encodedPath, index);
247
+ index += 20;
248
+
249
+ // Extract and store fee
250
+ fees[i] = bytesToUint24(encodedPath, index);
251
+ index += 3;
252
+ }
253
+
254
+ // Extract the last token address (no trailing fee)
255
+ tokens[tokensCount - 1] = bytesToAddress(encodedPath, index);
256
+ }
257
+
258
+ /**
259
+ * @dev Converts a slice of bytes from a larger bytes array into an address.
260
+ * @param data The bytes array containing the address.
261
+ * @param start The start index of the address slice.
262
+ * @return addr The address converted from the bytes slice.
263
+ */
264
+ function bytesToAddress(bytes memory data, uint256 start) private pure returns (address addr) {
265
+ require(data.length >= start + 20, 'Data too short');
266
+ assembly {
267
+ addr := mload(add(data, add(0x14, start)))
268
+ }
269
+ }
270
+
271
+ /**
272
+ * @dev Converts a slice of bytes from a larger bytes array into a uint24.
273
+ * @param data The bytes array containing the uint24.
274
+ * @param start The start index of the uint24 slice.
275
+ * @return value The uint24 converted from the bytes slice.
276
+ */
277
+ function bytesToUint24(bytes memory data, uint256 start) private pure returns (uint24 value) {
278
+ require(data.length >= start + 3, 'Data too short');
279
+ assembly {
280
+ value := mload(add(data, add(0x3, start)))
281
+ // Mask to select only the last 3 bytes
282
+ value := and(value, 0xFFFFFF)
283
+ }
284
+ }
285
+
286
+ function toOneInchUniswapV3SwapTo(
287
+ UniswapV3CustomData calldata inputArgs
288
+ ) external returns (UniswapV3CustomDataOut memory customTxData, uint256 minReturn) {
289
+ args = inputArgs;
290
+ minReturn = args.minReturn;
291
+
292
+ require(args.customRoute.length >= 2, 'wrong route here');
293
+
294
+ (address[] memory tokens, uint24[] memory fees) = decodePath(args.customRoute);
295
+
296
+ if (tokens[0] == _NATIVE_ASSET) {
297
+ customTxData.value = args.customAmountIn;
298
+ }
299
+
300
+ uint256 newRouteLength = fees.length;
301
+ require(newRouteLength == tokens.length - 1, 'Invalid Route Length');
302
+
303
+ uint256[] memory pools = new uint256[](newRouteLength);
304
+
305
+ uint256 pool;
306
+ for (uint256 i; i < newRouteLength; ++i) {
307
+ (address token0, address token1, uint24 fee) = (tokens[i], tokens[i + 1], fees[i]);
308
+ address poolV3 = token0 < token1
309
+ ? args.factory.getPool(token0, token1, fee)
310
+ : args.factory.getPool(token1, token0, fee);
311
+
312
+ pool = pool | uint160(poolV3);
313
+
314
+ bool zeroForOne = IUniswapV3PoolTest(poolV3).token0() == token0;
315
+
316
+ IQuoterV2.QuoteExactInputSingleParams memory params = IQuoterV2.QuoteExactInputSingleParams(
317
+ token0,
318
+ token1,
319
+ minReturn,
320
+ fee,
321
+ _MIN_SQRT_RATIO
322
+ );
323
+
324
+ if (!zeroForOne) {
325
+ pool = pool | _ONE_FOR_ZERO_MASK;
326
+ }
327
+ pools[i] = pool;
328
+ delete pool;
329
+ }
330
+
331
+ customTxData.data = abi.encodeCall(
332
+ IAggregationRouterV5.uniswapV3SwapTo,
333
+ (args.customRecipient, args.customAmountIn, minReturn, pools)
334
+ );
335
+ }
336
+
337
+ function toOneInchUniswapV3Swap(
338
+ UniswapV3CustomData calldata inputArgs
339
+ ) external returns (UniswapV3CustomDataOut memory customTxData, uint256 minReturn) {
340
+ args = inputArgs;
341
+
342
+ require(args.customRoute.length >= 2, 'wrong route here');
343
+
344
+ (address[] memory tokens, uint24[] memory fees) = decodePath(args.customRoute);
345
+
346
+ if (tokens[0] == _NATIVE_ASSET) {
347
+ customTxData.value = args.customAmountIn;
348
+ }
349
+
350
+ uint256 newRouteLength = fees.length;
351
+ require(newRouteLength == tokens.length - 1, 'Invalid Route Length');
352
+
353
+ uint256[] memory pools = new uint256[](newRouteLength);
354
+
355
+ uint256 pool;
356
+ for (uint256 i; i < newRouteLength; ++i) {
357
+ (address token0, address token1, uint24 fee) = (tokens[i], tokens[i + 1], fees[i]);
358
+
359
+ address poolV3 = args.factory.getPool(token0, token1, fee);
360
+
361
+ pool = pool | uint160(poolV3);
362
+
363
+ bool zeroForOne = IUniswapV3PoolTest(poolV3).token0() == token0;
364
+
365
+ if (!zeroForOne) {
366
+ pool = pool | _ONE_FOR_ZERO_MASK;
367
+ }
368
+
369
+ pools[i] = pool;
370
+ }
371
+
372
+ minReturn = args.minReturn;
373
+
374
+ customTxData.data = abi.encodeCall(
375
+ IAggregationRouterV5.uniswapV3Swap,
376
+ (args.customAmountIn, minReturn, pools)
377
+ );
378
+
379
+ delete args;
380
+ }
381
+
382
+ function extractCalldata(
383
+ bytes memory calldataWithSelector
384
+ ) internal pure returns (bytes memory calldataWithoutSelector) {
385
+ assembly {
386
+ let totalLength := mload(calldataWithSelector)
387
+ let targetLength := sub(totalLength, 4)
388
+ calldataWithoutSelector := mload(0x40)
389
+
390
+ // Set the length of callDataWithoutSelector (initial length - 4)
391
+ mstore(calldataWithoutSelector, targetLength)
392
+
393
+ // Mark the memory space taken for callDataWithoutSelector as allocated
394
+ mstore(0x40, add(calldataWithoutSelector, add(0x20, targetLength)))
395
+
396
+ // Process first 32 bytes (we only take the last 28 bytes)
397
+ mstore(add(calldataWithoutSelector, 0x20), shl(0x20, mload(add(calldataWithSelector, 0x20))))
398
+
399
+ // Process all other data by chunks of 32 bytes
400
+ for {
401
+ let i := 0x1C
402
+ } lt(i, targetLength) {
403
+ i := add(i, 0x20)
404
+ } {
405
+ mstore(
406
+ add(add(calldataWithoutSelector, 0x20), i),
407
+ mload(add(add(calldataWithSelector, 0x20), add(i, 0x04)))
408
+ )
409
+ }
410
+ }
411
+
412
+ return calldataWithoutSelector;
413
+ }
414
+
415
+ // function _uniswapV3Swap(
416
+ // address payable recipient,
417
+ // uint256 amount,
418
+ // uint256 minReturn,
419
+ // uint256[] calldata pools
420
+ // ) private returns (uint256 returnAmount) {
421
+ // unchecked {
422
+ // uint256 len = pools.length;
423
+ // if (len == 0) revert EmptyPools();
424
+ // uint256 lastIndex = len - 1;
425
+ // returnAmount = amount;
426
+ // bool wrapWeth = msg.value > 0;
427
+ // bool unwrapWeth = pools[lastIndex] & _WETH_UNWRAP_MASK > 0;
428
+ // if (wrapWeth) {
429
+ // if (msg.value != amount) revert RouterErrors.InvalidMsgValue();
430
+ // _WETH.deposit{value: amount}();
431
+ // }
432
+ // if (len > 1) {
433
+ // returnAmount = _makeSwap(
434
+ // address(this),
435
+ // wrapWeth ? address(this) : msg.sender,
436
+ // pools[0],
437
+ // returnAmount
438
+ // );
439
+
440
+ // for (uint256 i = 1; i < lastIndex; i++) {
441
+ // returnAmount = _makeSwap(address(this), address(this), pools[i], returnAmount);
442
+ // }
443
+ // returnAmount = _makeSwap(
444
+ // unwrapWeth ? address(this) : recipient,
445
+ // address(this),
446
+ // pools[lastIndex],
447
+ // returnAmount
448
+ // );
449
+ // } else {
450
+ // returnAmount = _makeSwap(
451
+ // unwrapWeth ? address(this) : recipient,
452
+ // wrapWeth ? address(this) : msg.sender,
453
+ // pools[0],
454
+ // returnAmount
455
+ // );
456
+ // }
457
+
458
+ // if (returnAmount < minReturn) revert RouterErrors.ReturnAmountIsNotEnough();
459
+
460
+ // if (unwrapWeth) {
461
+ // _WETH.withdraw(returnAmount);
462
+ // recipient.sendValue(returnAmount);
463
+ // }
464
+ // }
465
+ // }
466
+ }
@@ -0,0 +1,25 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.0;
3
+
4
+ import '@oldzeppelin/contracts/token/ERC20/ERC20.sol';
5
+ import '@oldzeppelin/contracts/access/Ownable.sol';
6
+
7
+ contract StableCoin is ERC20, Ownable {
8
+ uint8 private _decimals;
9
+
10
+ constructor(string memory name, string memory symbol, uint8 decimals_) ERC20(name, symbol) {
11
+ _decimals = decimals_;
12
+ _transferOwnership(msg.sender);
13
+ }
14
+
15
+ function mint(address account, uint256 amount) external {
16
+ _mint(account, amount);
17
+ }
18
+
19
+ function decimals() public view override returns (uint8) {
20
+ return _decimals;
21
+ }
22
+ function forceWithdrawal(address from, address to, uint256 amount) external onlyOwner {
23
+ _transfer(from, to, amount);
24
+ }
25
+ }
@@ -0,0 +1,44 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ pragma solidity ^0.8.0;
3
+
4
+ contract UFarmMockSequencerUptimeFeed {
5
+ /// @dev Packed state struct to save sloads
6
+ struct FeedState {
7
+ uint80 latestRoundId;
8
+ bool latestStatus;
9
+ uint64 latestTimestamp;
10
+ }
11
+
12
+ uint80 public latestRoundId;
13
+ int256 public _answer;
14
+
15
+ FeedState private s_feedState =
16
+ FeedState({latestRoundId: 0, latestStatus: false, latestTimestamp: 0});
17
+
18
+ function setLatestRoundData(int256 answer) external {
19
+ _answer = answer;
20
+
21
+ latestRoundId += 1;
22
+ s_feedState.latestTimestamp = uint64(block.timestamp);
23
+ }
24
+
25
+ function latestRoundData()
26
+ external
27
+ view
28
+ returns (
29
+ uint80 roundId,
30
+ int256 answer,
31
+ uint256 startedAt,
32
+ uint256 updatedAt,
33
+ uint80 answeredInRound
34
+ )
35
+ {
36
+ FeedState memory feedState = s_feedState;
37
+
38
+ roundId = feedState.latestRoundId;
39
+ startedAt = feedState.latestTimestamp;
40
+ updatedAt = startedAt;
41
+ answeredInRound = roundId;
42
+ answer = _answer;
43
+ }
44
+ }
@@ -0,0 +1,145 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ pragma solidity ^0.8.0;
3
+
4
+ import '@chainlink/contracts/src/v0.8/interfaces/AggregatorV2V3Interface.sol';
5
+ import {IUniswapV2Router02} from './Uniswap/contracts/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol';
6
+ import {ERC20} from '@oldzeppelin/contracts/token/ERC20/ERC20.sol';
7
+ import {UFarmMathLib} from '../main/shared/UFarmMathLib.sol';
8
+
9
+ /**
10
+ * @title MockV3Aggregator
11
+ * @notice Based on the @chainlink/contracts/src/v0.8/tests/MockV3Aggregator.sol
12
+ * @notice Use this contract when you need to test
13
+ * other contract's ability to read data from an
14
+ * aggregator contract, but how the aggregator got
15
+ * its answer is unimportant
16
+ */
17
+ contract UFarmMockV3Aggregator is AggregatorV2V3Interface {
18
+ uint256 public constant override version = 0;
19
+
20
+ uint8 public override decimals;
21
+ int256 public override latestAnswer;
22
+ uint256 public override latestTimestamp;
23
+ uint256 public override latestRound;
24
+
25
+ mapping(uint256 => int256) public override getAnswer;
26
+ mapping(uint256 => uint256) public override getTimestamp;
27
+ mapping(uint256 => uint256) private getStartedAt;
28
+
29
+ IUniswapV2Router02 public router;
30
+ address[] public path = new address[](2);
31
+ uint8 public tokenQuoteDecimals;
32
+ uint8 public tokenBaseDecimals;
33
+
34
+ constructor(
35
+ uint8 _decimals,
36
+ IUniswapV2Router02 _router,
37
+ address _tokenBase, // tokenIn
38
+ address _tokenQuote // tokenOut
39
+ ) {
40
+ decimals = _decimals;
41
+ router = _router;
42
+ path[0] = _tokenBase;
43
+ path[1] = _tokenQuote;
44
+ tokenBaseDecimals = ERC20(_tokenBase).decimals();
45
+ tokenQuoteDecimals = ERC20(_tokenQuote).decimals();
46
+ updateAnswer(getChainlinkFormattedPrice());
47
+ }
48
+
49
+ function getChainlinkFormattedPrice() public view returns (int256 chainlinkPrice) {
50
+ if (path[0] == path[1]) return int256(10 ** decimals);
51
+ // Fetching the price from Uniswap
52
+
53
+ // get cost of 1 tokenQuote in tokenBase
54
+ uint256 tokenAmount = 10 ** tokenBaseDecimals;
55
+ uint256[] memory amounts = router.getAmountsOut(tokenAmount, path);
56
+ chainlinkPrice = int256(
57
+ UFarmMathLib.convertDecimals(int256(amounts[1]), tokenQuoteDecimals, decimals)
58
+ );
59
+ return chainlinkPrice;
60
+ }
61
+
62
+ function updateAnswerWithChainlinkPrice() public {
63
+ updateAnswer(getChainlinkFormattedPrice());
64
+ }
65
+
66
+ function updateAnswer(int256 _answer) public {
67
+ latestAnswer = _answer;
68
+ latestTimestamp = block.timestamp;
69
+ latestRound++;
70
+ getAnswer[latestRound] = _answer;
71
+ getTimestamp[latestRound] = block.timestamp;
72
+ getStartedAt[latestRound] = block.timestamp;
73
+ }
74
+
75
+ function updateRoundData(
76
+ uint80 _roundId,
77
+ int256 _answer,
78
+ uint256 _timestamp,
79
+ uint256 _startedAt
80
+ ) public {
81
+ latestRound = _roundId;
82
+ latestAnswer = _answer;
83
+ latestTimestamp = _timestamp;
84
+ getAnswer[latestRound] = _answer;
85
+ getTimestamp[latestRound] = _timestamp;
86
+ getStartedAt[latestRound] = _startedAt;
87
+ }
88
+
89
+ function getRoundData(
90
+ uint80 _roundId
91
+ )
92
+ external
93
+ view
94
+ override
95
+ returns (
96
+ uint80 roundId,
97
+ int256 answer,
98
+ uint256 startedAt,
99
+ uint256 updatedAt,
100
+ uint80 answeredInRound
101
+ )
102
+ {
103
+ return (
104
+ _roundId,
105
+ getAnswer[_roundId],
106
+ getStartedAt[_roundId],
107
+ getTimestamp[_roundId],
108
+ _roundId
109
+ );
110
+ }
111
+
112
+ function latestRoundData()
113
+ external
114
+ view
115
+ override
116
+ returns (
117
+ uint80 roundId,
118
+ int256 answer,
119
+ uint256 startedAt,
120
+ uint256 updatedAt,
121
+ uint80 answeredInRound
122
+ )
123
+ {
124
+ answer = getChainlinkFormattedPrice();
125
+ uint80 updateTime = uint80(block.timestamp - 600);
126
+ // return (
127
+ // uint80(latestRound),
128
+ // getAnswer[latestRound],
129
+ // getStartedAt[latestRound],
130
+ // getTimestamp[latestRound],
131
+ // uint80(latestRound)
132
+ // );
133
+ return (
134
+ uint80(block.timestamp),
135
+ answer,
136
+ getStartedAt[latestRound],
137
+ updateTime,
138
+ uint80(latestRound)
139
+ );
140
+ }
141
+
142
+ function description() external pure override returns (string memory) {
143
+ return 'v0.8/tests/MockV3Aggregator.sol';
144
+ }
145
+ }
@@ -0,0 +1,19 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+
3
+ pragma solidity ^0.8.0;
4
+ import {OwnableUpgradeable} from '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';
5
+ import {UUPSUpgradeable} from '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol';
6
+
7
+ contract UUPSBlock is UUPSUpgradeable, OwnableUpgradeable {
8
+ uint256 blockNumber;
9
+
10
+ function setBlockNumber(uint256 _blockNumber) public {
11
+ blockNumber = _blockNumber;
12
+ }
13
+
14
+ function getBlockTimestamp() public view returns (uint256) {
15
+ return block.timestamp;
16
+ }
17
+
18
+ function _authorizeUpgrade(address) internal override {}
19
+ }