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