@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,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'])
|