@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,483 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+
3
+ import { ABI, DeployFunction } from 'hardhat-deploy/types'
4
+ import { HardhatRuntimeEnvironment } from 'hardhat/types'
5
+ import {
6
+ isTestnet,
7
+ getDeployerSigner,
8
+ getInstanceFromDeployment,
9
+ customSetTimeout,
10
+ retryOperation,
11
+ getOrDeployPoolInstance,
12
+ deployOrGetFund,
13
+ activatePool,
14
+ checkMinFundDep,
15
+ updateFundPermissionsIfNotYet,
16
+ _deployTags,
17
+ } from '../scripts/_deploy_helpers'
18
+ import {
19
+ PoolCreationStruct,
20
+ bigNumberToBits,
21
+ bitsToBigNumber,
22
+ constants,
23
+ getFieldsByValue,
24
+ mintAndDeposit,
25
+ packPerformanceCommission,
26
+ prepareWithdrawRequest,
27
+ } from '../test/_helpers'
28
+ import {
29
+ StableCoin,
30
+ UFarmCore,
31
+ UnoswapV2Controller,
32
+ WETH9,
33
+ } from '../typechain-types'
34
+ import { ethers } from 'hardhat'
35
+ import { BigNumberish, BigNumber } from '@ethersproject/bignumber'
36
+ import { _poolSwapUniV2 } from '../test/_fixtures'
37
+
38
+ const testEnvSetup: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
39
+ if (hre.network.tags['public'] || !isTestnet(hre.network)) {
40
+ return
41
+ }
42
+
43
+ const deployerSigner = await getDeployerSigner(hre)
44
+ const usdt_deployment = await hre.deployments.get('USDT')
45
+ const ufarmCore_deployment = await hre.deployments.get('UFarmCore')
46
+
47
+ const ufarmCore_instance = await getInstanceFromDeployment<UFarmCore>(
48
+ hre,
49
+ ufarmCore_deployment,
50
+ deployerSigner,
51
+ )
52
+ const usdt_instance = await getInstanceFromDeployment<StableCoin>(
53
+ hre,
54
+ usdt_deployment,
55
+ deployerSigner,
56
+ )
57
+
58
+ const namedSigners = await hre.getNamedAccounts()
59
+
60
+ const fund_instance = (
61
+ await deployOrGetFund('TestFund', deployerSigner.address, ufarmCore_instance, hre)
62
+ ).connect(deployerSigner)
63
+
64
+ const fundStatus = await fund_instance.status()
65
+ if (fundStatus !== constants.Fund.State.Active) {
66
+ await (await fund_instance.changeStatus(constants.Fund.State.Active)).wait()
67
+ console.log(`Fund status changed to active`)
68
+ } else {
69
+ console.log(`Fund status is already active`)
70
+ }
71
+
72
+ const emptyPoolArgs: PoolCreationStruct = {
73
+ minInvestment: 0,
74
+ maxInvestment: hre.ethers.constants.MaxUint256,
75
+ managementCommission: 0,
76
+ packedPerformanceCommission: packPerformanceCommission([
77
+ { step: 0, commission: constants.Pool.Commission.MAX_PERFORMANCE_COMMISION / 10 },
78
+ ]),
79
+ withdrawalLockupPeriod: 0,
80
+ valueToken: usdt_deployment.address,
81
+ staff: [],
82
+ name: 'Initialized Pool',
83
+ symbol: 'IP-1',
84
+ }
85
+
86
+ async function updateUFarmPermissions(
87
+ coreWithSigner: UFarmCore,
88
+ address: string,
89
+ permissions: BigNumberish,
90
+ ) {
91
+ ;(await coreWithSigner.updatePermissions(address, permissions)).wait()
92
+
93
+ const permissionsString = getFieldsByValue(
94
+ constants.UFarm.Permissions,
95
+ bigNumberToBits(BigNumber.from(permissions)),
96
+ ).join(', ')
97
+
98
+ console.log(
99
+ `` + `Addr: [${address}]\n UFarmCore Permissions: [${permissionsString}]\n-----------------`,
100
+ )
101
+ }
102
+
103
+ const carolInStaff = [
104
+ {
105
+ addr: namedSigners.carol,
106
+ permissionsMask: bitsToBigNumber([
107
+ constants.Pool.Permissions.Member,
108
+ constants.Pool.Permissions.ApprovePoolTopup,
109
+ constants.Pool.Permissions.PoolStatusControl,
110
+ constants.Pool.Permissions.ManagePoolFunds,
111
+ constants.Pool.Permissions.UpdatePoolDescription,
112
+ constants.Pool.Permissions.UpdatePoolFees,
113
+ constants.Pool.Permissions.UpdatePoolTopUpAmount,
114
+ constants.Pool.Permissions.UpdatePoolPermissions,
115
+ ]),
116
+ },
117
+ ]
118
+
119
+ const pool_instance_1 = await getOrDeployPoolInstance(
120
+ 'TestPool',
121
+ {
122
+ ...emptyPoolArgs,
123
+ staff: [...carolInStaff],
124
+ },
125
+ fund_instance,
126
+ hre,
127
+ )
128
+
129
+ await checkMinFundDep(ufarmCore_instance.connect(deployerSigner), BigNumber.from(0))
130
+
131
+ await activatePool(pool_instance_1, usdt_instance, deployerSigner, hre)
132
+
133
+ const sharesRequired = constants.ONE_BUCKS.mul(1337)
134
+ const deployerShares = await pool_instance_1.pool.balanceOf(deployerSigner.address)
135
+ if (deployerShares.lt(sharesRequired)) {
136
+ const sharesToMint = sharesRequired.sub(deployerShares)
137
+ console.log(
138
+ `Minting ${ethers.utils.formatUnits(
139
+ sharesRequired.sub(deployerShares),
140
+ 6,
141
+ )} shares to deployer`,
142
+ )
143
+ // Deposit to the pool
144
+ await mintAndDeposit(pool_instance_1.pool, usdt_instance, deployerSigner, sharesToMint)
145
+ }
146
+
147
+ {
148
+ await customSetTimeout(1)
149
+
150
+ console.log(`\nSetting up permissions for pool 1:`)
151
+ console.log(`\nOwner [${deployerSigner.address}] permissions: \n - All`)
152
+
153
+ const aliceMask = bitsToBigNumber(
154
+ constants.Fund.Roles.MemberRole.concat(Object.values(constants.Fund.Roles.FundEditorRole)),
155
+ )
156
+ await updateFundPermissionsIfNotYet(fund_instance, namedSigners.alice, aliceMask)
157
+
158
+ const bobMask = bitsToBigNumber(
159
+ constants.Fund.Roles.MemberRole.concat(
160
+ Object.values(constants.Fund.Roles.PoolCreatorAndEditorRole),
161
+ ),
162
+ )
163
+ await updateFundPermissionsIfNotYet(fund_instance, namedSigners.bob, bobMask)
164
+
165
+ const carolMask = ethers.constants.MaxUint256
166
+ await updateFundPermissionsIfNotYet(fund_instance, namedSigners.carol, carolMask)
167
+
168
+ const creatorFinanceManagerMask = bitsToBigNumber(
169
+ constants.Fund.Roles.MemberRole.concat(
170
+ Object.values(constants.Fund.Roles.PoolCreatorAndEditorRole),
171
+ Object.values(constants.Fund.Roles.AllPoolsFinanceManagerRole),
172
+ ),
173
+ )
174
+ await updateFundPermissionsIfNotYet(
175
+ fund_instance,
176
+ namedSigners.david,
177
+ creatorFinanceManagerMask,
178
+ )
179
+ await updateFundPermissionsIfNotYet(fund_instance, namedSigners.emma, creatorFinanceManagerMask)
180
+
181
+ const frankMask = bitsToBigNumber(
182
+ constants.Fund.Roles.MemberRole.concat(
183
+ Object.values(constants.Fund.Roles.PoolCreatorAndEditorRole),
184
+ ),
185
+ )
186
+ await updateFundPermissionsIfNotYet(fund_instance, namedSigners.frank, frankMask)
187
+
188
+ await updateFundPermissionsIfNotYet(
189
+ fund_instance,
190
+ namedSigners.grace,
191
+ bitsToBigNumber(constants.Fund.Roles.MemberRole),
192
+ )
193
+
194
+ const henryMask = bitsToBigNumber(
195
+ constants.Fund.Roles.MemberRole.concat(
196
+ Object.values(constants.Fund.Roles.FundEditorRole),
197
+ Object.values(constants.Fund.Roles.FundFinanceManagerRole),
198
+ ),
199
+ )
200
+
201
+ await updateFundPermissionsIfNotYet(fund_instance, namedSigners.henry, henryMask)
202
+ }
203
+ // Swap UNIv2
204
+ {
205
+ const uniswapV2Controller_deployment = await hre.deployments.get('UniV2Controller')
206
+ const uniswapV2Controller_instance = await getInstanceFromDeployment<UnoswapV2Controller>(
207
+ hre,
208
+ uniswapV2Controller_deployment,
209
+ )
210
+
211
+ const weth_instance = await getInstanceFromDeployment<WETH9>(
212
+ hre,
213
+ await hre.deployments.get('WETH'),
214
+ )
215
+
216
+ const usdtPoolBalance = await usdt_instance.balanceOf(pool_instance_1.pool.address)
217
+ const wethPoolBalance = await weth_instance.balanceOf(pool_instance_1.pool.address)
218
+
219
+ if (usdtPoolBalance.gt(constants.ONE_HUNDRED_BUCKS) && wethPoolBalance.isZero()) {
220
+ await retryOperation(async () => {
221
+ const swap1usdt = await _poolSwapUniV2(
222
+ pool_instance_1.pool,
223
+ uniswapV2Controller_instance,
224
+ constants.ONE_BUCKS,
225
+ [usdt_instance.address, weth_instance.address],
226
+ )
227
+ await (await swap1usdt.tx).wait()
228
+ }, 3)
229
+ }
230
+
231
+ console.log(
232
+ `Weth balance in pool 1: ${await weth_instance.balanceOf(pool_instance_1.pool.address)}`,
233
+ )
234
+ }
235
+
236
+ const anotherPool_instance = await getOrDeployPoolInstance(
237
+ 'TestPool2',
238
+ {
239
+ ...emptyPoolArgs,
240
+ minInvestment: constants.ONE_HUNDRED_BUCKS.mul(5),
241
+ maxInvestment: constants.ONE_HUNDRED_BUCKS.mul(100),
242
+ },
243
+ fund_instance,
244
+ hre,
245
+ )
246
+
247
+ const simplePool_staff = [
248
+ {
249
+ addr: namedSigners.carol,
250
+ permissionsMask: bitsToBigNumber([
251
+ constants.Pool.Permissions.Member,
252
+ constants.Pool.Permissions.ApprovePoolTopup,
253
+ constants.Pool.Permissions.PoolStatusControl,
254
+ constants.Pool.Permissions.ManagePoolFunds,
255
+ constants.Pool.Permissions.UpdatePoolDescription,
256
+ constants.Pool.Permissions.UpdatePoolFees,
257
+ constants.Pool.Permissions.UpdatePoolTopUpAmount,
258
+ constants.Pool.Permissions.UpdatePoolPermissions,
259
+ ]),
260
+ },
261
+ {
262
+ addr: namedSigners.henry,
263
+ permissionsMask: bitsToBigNumber([
264
+ constants.Pool.Permissions.Member,
265
+ constants.Pool.Permissions.UpdatePoolDescription,
266
+ constants.Pool.Permissions.UpdatePoolFees,
267
+ constants.Pool.Permissions.UpdatePoolTopUpAmount,
268
+ constants.Pool.Permissions.UpdatePoolPermissions,
269
+ ]),
270
+ },
271
+ ]
272
+
273
+ const poolTest3_instance = await getOrDeployPoolInstance(
274
+ 'TestPool3',
275
+ {
276
+ ...emptyPoolArgs,
277
+ name: 'Simple Pool',
278
+ symbol: 'SP',
279
+ staff: simplePool_staff,
280
+ },
281
+ fund_instance,
282
+ hre,
283
+ )
284
+
285
+ await activatePool(poolTest3_instance, usdt_instance, deployerSigner, hre)
286
+
287
+ {
288
+ // mint random USDT amount to every named signer
289
+ const first8signers = Object.entries(namedSigners).slice(0, 8)
290
+ for (const [name, address] of first8signers) {
291
+ const usdtToMint = constants.ONE_HUNDRED_BUCKS.mul(10).mul(
292
+ BigNumber.from(
293
+ // random:
294
+ Math.floor(Math.random() * 100) + 1,
295
+ ),
296
+ )
297
+
298
+ const signer = await hre.ethers.getSigner(address)
299
+ const signerShares = await poolTest3_instance.pool.balanceOf(address)
300
+ if (signerShares.isZero()) {
301
+ const usdToDeposit = usdtToMint.div(3)
302
+
303
+ await (
304
+ await mintAndDeposit(poolTest3_instance.pool, usdt_instance, signer, usdToDeposit)
305
+ ).wait()
306
+
307
+ console.log(
308
+ `Minted:${ethers.utils.formatUnits(
309
+ usdtToMint,
310
+ 6,
311
+ )} to ${name} and deposited ${ethers.utils.formatUnits(usdToDeposit, 6)} to pool 3`,
312
+ )
313
+ } else {
314
+ console.log(`Skipping ${name} as they already have shares in pool 3`)
315
+ continue
316
+ }
317
+
318
+ // Withdraw
319
+
320
+ const withdrawAmount = (await poolTest3_instance.pool.balanceOf(signer.address)).div(2)
321
+
322
+ await retryOperation(async () => {
323
+ const withdrawalRequest = await prepareWithdrawRequest(
324
+ signer,
325
+ poolTest3_instance.pool,
326
+ withdrawAmount,
327
+ )
328
+
329
+ // await (await poolTest3_instance.pool.connect(signer).withdraw(withdrawalRequest)).wait()
330
+ await hre.deployments.execute(
331
+ 'TestPool3',
332
+ { from: signer.address, estimateGasExtra: 1000000 },
333
+ 'withdraw',
334
+ withdrawalRequest,
335
+ )
336
+
337
+ console.log(
338
+ `Withdrew ${ethers.utils.formatUnits(withdrawAmount, 6)} from pool 3 to ${name}`,
339
+ )
340
+
341
+ await customSetTimeout(1)
342
+ }, 3)
343
+ }
344
+
345
+ // mint to fund
346
+
347
+ await (
348
+ await usdt_instance.mint(fund_instance.address, constants.ONE_HUNDRED_BUCKS.mul(77777))
349
+ ).wait()
350
+ }
351
+ // ;(await ufarmCore_instance.setMinimumFundDeposit(constants.ONE_HUNDRED_BUCKS.mul(10))).wait()
352
+
353
+ await checkMinFundDep(ufarmCore_instance.connect(deployerSigner), constants.ONE_BUCKS.mul(10))
354
+ {
355
+ // Give UFarmCore permissions
356
+ console.log('\n\n UFarmCore permissions: \n')
357
+ const updateCorePermissionsIfNotYet = async (
358
+ core: UFarmCore,
359
+ coreMember: string,
360
+ permissions: BigNumberish,
361
+ ) => {
362
+ const hasPermissions = await core.hasPermissionsMask(coreMember, permissions)
363
+ if (!hasPermissions) {
364
+ await retryOperation(async () => {
365
+ await updateUFarmPermissions(core, coreMember, permissions)
366
+ }, 3)
367
+ console.log(`\n${coreMember} permissions updated`)
368
+ } else {
369
+ console.log(`\n${coreMember} already has permissions in UFarmCore`)
370
+ }
371
+ }
372
+
373
+ const permissionsUpdaterMask = bitsToBigNumber([
374
+ constants.UFarm.Permissions.Member,
375
+ constants.UFarm.Permissions.UpdatePermissions,
376
+ constants.UFarm.Permissions.UpdateUFarmMember,
377
+ constants.UFarm.Permissions.DeleteUFarmMember,
378
+ ])
379
+
380
+ await updateCorePermissionsIfNotYet(
381
+ ufarmCore_instance,
382
+ namedSigners.alice,
383
+ permissionsUpdaterMask,
384
+ )
385
+
386
+ const whitelistAndFundApproverMask = bitsToBigNumber([
387
+ constants.UFarm.Permissions.Member,
388
+ constants.UFarm.Permissions.ManageWhitelist,
389
+ constants.UFarm.Permissions.ApproveFundCreation,
390
+ constants.UFarm.Permissions.BlockFund,
391
+ ])
392
+
393
+ await updateCorePermissionsIfNotYet(
394
+ ufarmCore_instance,
395
+ namedSigners.bob,
396
+ whitelistAndFundApproverMask,
397
+ )
398
+ await updateCorePermissionsIfNotYet(
399
+ ufarmCore_instance,
400
+ namedSigners.carol,
401
+ whitelistAndFundApproverMask,
402
+ )
403
+
404
+ const moderatorRoleMask = bitsToBigNumber(
405
+ constants.UFarm.Roles.MemberRole.concat(Object.values(constants.UFarm.Roles.ModeratorRole)),
406
+ )
407
+
408
+ await updateCorePermissionsIfNotYet(ufarmCore_instance, namedSigners.david, moderatorRoleMask)
409
+ await updateCorePermissionsIfNotYet(ufarmCore_instance, namedSigners.emma, moderatorRoleMask)
410
+
411
+ const teamAndCrisisManagerMask = bitsToBigNumber(
412
+ constants.UFarm.Roles.MemberRole.concat(
413
+ Object.values(constants.UFarm.Roles.TeamManagerRole),
414
+ Object.values(constants.UFarm.Roles.CrisisManagerRole),
415
+ ),
416
+ )
417
+
418
+ await updateCorePermissionsIfNotYet(
419
+ ufarmCore_instance,
420
+ namedSigners.frank,
421
+ teamAndCrisisManagerMask,
422
+ )
423
+ }
424
+
425
+ {
426
+ console.log('Topup demo balances')
427
+
428
+ const demoAddresses = [
429
+ '0x5B16aBc8268f0fa6B111F45e20003f227389967C',
430
+ '0x2cD031Cb7e075Ad30aCB2f7B8acc2A7d372EaFd5',
431
+ namedSigners.carol,
432
+ ]
433
+
434
+ for (const addr of demoAddresses) {
435
+ const addrUSDTBalance = await usdt_instance.balanceOf(addr)
436
+ const addrETHBalance = await hre.ethers.provider.getBalance(addr)
437
+
438
+ const desiredUsdtBalance = constants.ONE.mul(88888888888)
439
+ const desiredEthBalance = constants.ONE.mul(100)
440
+
441
+ if (addrUSDTBalance.lt(desiredUsdtBalance)) {
442
+ await (await usdt_instance.mint(addr, desiredUsdtBalance.sub(addrUSDTBalance))).wait()
443
+ console.log(`Sent some USDT to ${addr}`)
444
+ }
445
+ if (addrETHBalance.lt(desiredEthBalance)) {
446
+ await deployerSigner.sendTransaction({
447
+ to: addr,
448
+ value: desiredEthBalance.sub(addrETHBalance),
449
+ })
450
+ console.log(`Sent some ETH to ${addr}`)
451
+ }
452
+ }
453
+ }
454
+
455
+ // set protocol fee
456
+ const currentProtocolCommission = await ufarmCore_instance.protocolCommission()
457
+ if (!currentProtocolCommission.eq(constants.ZERO_POINT_3_PERCENTS)) {
458
+ console.log(`Current protocol commission is ${currentProtocolCommission}, setting to 0.3%`)
459
+ await retryOperation(async () => {
460
+ await hre.deployments.execute(
461
+ 'UFarmCore',
462
+ { from: deployerSigner.address },
463
+ 'setProtocolCommission',
464
+ constants.ZERO_POINT_3_PERCENTS,
465
+ )
466
+ }, 3)
467
+ } else {
468
+ console.log(`Protocol commission set to 0.3%`)
469
+ }
470
+
471
+ console.log(`\n\nDone!`)
472
+ }
473
+
474
+ export default testEnvSetup
475
+ testEnvSetup.dependencies = _deployTags([
476
+ 'Multicall3',
477
+ 'UniV2Pairs',
478
+ 'UniV3Pairs',
479
+ 'InitializeUFarm',
480
+ 'WhitelistControllers',
481
+ 'WhiteListTokens',
482
+ ])
483
+ testEnvSetup.tags = _deployTags(['TestEnv'])
@@ -0,0 +1,48 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+
3
+ import { DeployFunction } from 'hardhat-deploy/types'
4
+ import { HardhatRuntimeEnvironment } from 'hardhat/types'
5
+ import {
6
+ deployContract,isTestnet,
7
+ getTokenDeployments,
8
+ getDeployerSigner,
9
+ _deployTags,
10
+ } from '../scripts/_deploy_helpers'
11
+
12
+ const deployUniV2: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
13
+ if (!isTestnet(hre.network)){
14
+ console.log(`Skipping Uniswap V2 deployment`)
15
+ return
16
+ }
17
+
18
+ const tokenDeployments = await getTokenDeployments(hre)
19
+ const weth_deployment = tokenDeployments.WETH
20
+
21
+ console.log('\nDeploying Uniswap V2...')
22
+
23
+ const deployerSigner = await getDeployerSigner(hre)
24
+
25
+ const uniswapV2Factory_deployment = await deployContract(hre, {
26
+ deploymentName: 'UniswapV2Factory',
27
+ from: deployerSigner.address,
28
+ args: [deployerSigner.address],
29
+ log: true,
30
+ skipIfAlreadyDeployed: true,
31
+ contract: 'UniswapV2Factory',
32
+ })
33
+
34
+ const uniswapV2Router_deployment = await deployContract(hre, {
35
+ deploymentName: 'UniswapV2Router02',
36
+ from: deployerSigner.address,
37
+ args: [uniswapV2Factory_deployment.address, weth_deployment.address],
38
+ log: true,
39
+ skipIfAlreadyDeployed: true,
40
+ contract: 'UniswapV2Router02',
41
+ })
42
+
43
+ console.log('\nUniswap V2 deployed!')
44
+ }
45
+
46
+ export default deployUniV2
47
+ deployUniV2.dependencies = _deployTags(['Tokens'])
48
+ deployUniV2.tags = _deployTags(['UniV2'])
@@ -0,0 +1,149 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+
3
+ import { DeployFunction } from 'hardhat-deploy/types'
4
+ import { HardhatRuntimeEnvironment } from 'hardhat/types'
5
+ import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'
6
+ import {
7
+ getTokenDeployments,
8
+ retryOperation,
9
+ getInstanceFromDeployment,
10
+ getDeployerSigner,
11
+ _deployTags,
12
+ isMainnet,
13
+ } from '../scripts/_deploy_helpers'
14
+ import { BigNumberish } from 'ethers'
15
+ import {
16
+ UniswapV2Factory,
17
+ UniswapV2Router02,
18
+ } from '../typechain-types'
19
+ import {
20
+ mintAndCreatePairUniV2,
21
+ MintableToken,
22
+ } from '../test/_helpers'
23
+
24
+ const createUniV2Pairs: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
25
+ async function isUniswapV2PairExist(
26
+ factoryContract: UniswapV2Factory,
27
+ token0Address: string,
28
+ token1Address: string,
29
+ ): Promise<boolean> {
30
+ try {
31
+ const pairAddress = await factoryContract.getPair(token0Address, token1Address)
32
+ const hasCode = (await hre.ethers.provider.getCode(pairAddress)) !== '0x'
33
+
34
+ if (!hasCode) {
35
+ return false
36
+ }
37
+
38
+ const tokenInstance0 = await hre.ethers.getContractAt('StableCoin', token0Address)
39
+ const pairBalance0 = await tokenInstance0.balanceOf(pairAddress)
40
+ const tokenInstance1 = await hre.ethers.getContractAt('StableCoin', token1Address)
41
+ const pairBalance1 = await tokenInstance1.balanceOf(pairAddress)
42
+ return pairBalance0.gt(0) && pairBalance1.gt(0)
43
+ } catch (error) {
44
+ console.error('Error checking pair existence:', error)
45
+ return false
46
+ }
47
+ }
48
+
49
+ async function checkAndCreateUniV2Pair(
50
+ factoryContract: UniswapV2Factory,
51
+ token0Contract: MintableToken,
52
+ token1Contract: MintableToken,
53
+ amount0: BigNumberish,
54
+ amount1: BigNumberish,
55
+ signer: SignerWithAddress,
56
+ routerContract: UniswapV2Router02,
57
+ maxRetries: number,
58
+ ): Promise<void> {
59
+ const token0Address = token0Contract.address
60
+ const token1Address = token1Contract.address
61
+
62
+ const [token0Symbol, token1Symbol] = await Promise.all([
63
+ token0Contract.symbol(),
64
+ token1Contract.symbol(),
65
+ ])
66
+
67
+ const pairName = `${token0Symbol}/${token1Symbol}`
68
+
69
+ if (await isUniswapV2PairExist(factoryContract, token0Address, token1Address)) {
70
+ console.log(`${pairName} pair already exists!`)
71
+ } else {
72
+ console.log(`Creating ${pairName} pair...`)
73
+ await retryOperation(async () => {
74
+ await mintAndCreatePairUniV2(
75
+ token0Contract,
76
+ token1Contract,
77
+ amount0,
78
+ amount1,
79
+ signer,
80
+ routerContract,
81
+ )
82
+ }, maxRetries)
83
+
84
+ console.log(`${pairName} pair created!`)
85
+ }
86
+ }
87
+
88
+ async function createV2PairForTokens(rate: (typeof allPairs)[0]) {
89
+ const [token0Name, token1Name] = [rate.rawName0, rate.rawName1]
90
+ const [token0_instance, token1_instance] = await Promise.all([
91
+ getInstanceFromDeployment<MintableToken>(hre, tokenDeployments[token0Name]),
92
+ getInstanceFromDeployment<MintableToken>(hre, tokenDeployments[token1Name]),
93
+ ])
94
+
95
+ const [decimals0, decimals1] = await Promise.all([
96
+ token0_instance.decimals(),
97
+ token1_instance.decimals(),
98
+ ])
99
+
100
+ console.log(`decimals0: ${decimals0}, decimals1: ${decimals1}`)
101
+
102
+ await checkAndCreateUniV2Pair(
103
+ uniV2Factory_instance,
104
+ token0_instance,
105
+ token1_instance,
106
+ rate.amount0,
107
+ rate.amount1,
108
+ deployerSigner,
109
+ uniV2Router_instance,
110
+ 3,
111
+ )
112
+ }
113
+
114
+ if (isMainnet(hre.network)){
115
+ console.log(`Skipping Uniswap V2 pairs creation`)
116
+ return
117
+ }
118
+
119
+ const tokenDeployments = await getTokenDeployments(hre)
120
+ const deployerSigner = await getDeployerSigner(hre)
121
+
122
+ const uniV2Router_deployment = await hre.deployments.get('UniswapV2Router02')
123
+ const uniV2Factory_deployment = await hre.deployments.get('UniswapV2Factory')
124
+
125
+ const uniV2Router_instance = new hre.ethers.Contract(
126
+ uniV2Router_deployment.address,
127
+ uniV2Router_deployment.abi,
128
+ hre.ethers.provider,
129
+ ) as UniswapV2Router02
130
+ const uniV2Factory_instance = new hre.ethers.Contract(
131
+ uniV2Factory_deployment.address,
132
+ uniV2Factory_deployment.abi,
133
+ hre.ethers.provider,
134
+ ) as UniswapV2Factory
135
+
136
+ console.log('\nCreating Uniswap V2 pairs...')
137
+
138
+ const allPairs = hre.testnetDeployConfig.initialRates
139
+
140
+ for (const rate of allPairs) {
141
+ await createV2PairForTokens(rate)
142
+ }
143
+
144
+ console.log('Uniswap V2 pairs created!')
145
+ }
146
+
147
+ export default createUniV2Pairs
148
+ createUniV2Pairs.dependencies = _deployTags(['UniV2'])
149
+ createUniV2Pairs.tags = _deployTags(['UniV2Pairs'])