@ensuro/core 2.6.2 → 2.8.0-beta1

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 (79) hide show
  1. package/README.md +11 -5
  2. package/contracts/AccessManager.sol +3 -13
  3. package/contracts/EToken.sol +29 -95
  4. package/contracts/LPManualWhitelist.sol +11 -26
  5. package/contracts/LiquidityThresholdAssetManager.sol +10 -21
  6. package/contracts/Policy.sol +6 -17
  7. package/contracts/PolicyPool.sol +39 -91
  8. package/contracts/PolicyPoolComponent.sol +9 -32
  9. package/contracts/PremiumsAccount.sol +16 -47
  10. package/contracts/Reserve.sol +10 -16
  11. package/contracts/RiskModule.sol +22 -80
  12. package/contracts/SignedBucketRiskModule.sol +18 -80
  13. package/contracts/SignedQuoteRiskModule.sol +13 -44
  14. package/contracts/TieredSignedQuoteRiskModule.sol +7 -13
  15. package/contracts/TimeScaled.sol +8 -39
  16. package/contracts/TrustfulRiskModule.sol +13 -48
  17. package/contracts/interfaces/IAccessManager.sol +2 -11
  18. package/contracts/interfaces/IEToken.sol +1 -5
  19. package/contracts/interfaces/ILPWhitelist.sol +2 -10
  20. package/contracts/interfaces/IPolicyHolder.sol +2 -11
  21. package/contracts/interfaces/IPremiumsAccount.sol +1 -5
  22. package/contracts/migration/LPManualWhitelistV20.sol +3 -15
  23. package/contracts/migration/LPManualWhitelistV20Upgraded.sol +1 -5
  24. package/contracts/mocks/FixedRateVault.sol +1 -6
  25. package/contracts/mocks/PolicyHolderMock.sol +73 -29
  26. package/contracts/mocks/PolicyPoolComponentMock.sol +1 -3
  27. package/contracts/mocks/PolicyPoolMock.sol +8 -28
  28. package/contracts/mocks/RiskModuleMock.sol +3 -16
  29. package/contracts/mocks/TestNFT.sol +1 -1
  30. package/js/constants.js +8 -2
  31. package/js/deploy.js +65 -62
  32. package/js/enums.js +26 -8
  33. package/js/test-utils.js +105 -23
  34. package/js/utils.js +78 -28
  35. package/package.json +1 -1
  36. package/scripts/utils.sh +23 -12
  37. package/build/contracts/AccessManager.sol/AccessManager.json +0 -618
  38. package/build/contracts/ERC4626AssetManager.sol/ERC4626AssetManager.json +0 -238
  39. package/build/contracts/EToken.sol/EToken.json +0 -1277
  40. package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +0 -647
  41. package/build/contracts/LiquidityThresholdAssetManager.sol/LiquidityThresholdAssetManager.json +0 -222
  42. package/build/contracts/Policy.sol/Policy.json +0 -10
  43. package/build/contracts/PolicyPool.sol/PolicyPool.json +0 -1416
  44. package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +0 -332
  45. package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +0 -970
  46. package/build/contracts/Reserve.sol/Reserve.json +0 -403
  47. package/build/contracts/RiskModule.sol/RiskModule.json +0 -559
  48. package/build/contracts/SignedBucketRiskModule.sol/SignedBucketRiskModule.json +0 -1262
  49. package/build/contracts/SignedQuoteRiskModule.sol/SignedQuoteRiskModule.json +0 -1110
  50. package/build/contracts/TieredSignedQuoteRiskModule.sol/TieredSignedQuoteRiskModule.json +0 -1316
  51. package/build/contracts/TimeScaled.sol/TimeScaled.json +0 -10
  52. package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +0 -984
  53. package/build/contracts/dependencies/ERC1967Proxy.sol/ERC1967Proxy.json +0 -64
  54. package/build/contracts/dependencies/IERC20Metadata.sol/IERC20Metadata.json +0 -233
  55. package/build/contracts/dependencies/WadRayMath.sol/WadRayMath.json +0 -10
  56. package/build/contracts/interfaces/IAccessManager.sol/IAccessManager.json +0 -343
  57. package/build/contracts/interfaces/IAssetManager.sol/IAssetManager.json +0 -128
  58. package/build/contracts/interfaces/IEToken.sol/IEToken.json +0 -460
  59. package/build/contracts/interfaces/ILPWhitelist.sol/ILPWhitelist.json +0 -103
  60. package/build/contracts/interfaces/IPolicyHolder.sol/IPolicyHolder.json +0 -108
  61. package/build/contracts/interfaces/IPolicyPool.sol/IPolicyPool.json +0 -501
  62. package/build/contracts/interfaces/IPolicyPoolComponent.sol/IPolicyPoolComponent.json +0 -43
  63. package/build/contracts/interfaces/IPremiumsAccount.sol/IPremiumsAccount.json +0 -315
  64. package/build/contracts/interfaces/IRiskModule.sol/IRiskModule.json +0 -165
  65. package/build/contracts/migration/LPManualWhitelistV20.sol/LPManualWhitelistV20.json +0 -481
  66. package/build/contracts/migration/LPManualWhitelistV20Upgraded.sol/LPManualWhitelistV20Upgraded.json +0 -492
  67. package/build/contracts/mocks/FixedRateVault.sol/FixedRateVault.json +0 -736
  68. package/build/contracts/mocks/ForwardProxy.sol/ForwardProxy.json +0 -43
  69. package/build/contracts/mocks/IMintableERC20.sol/IMintableERC20.json +0 -47
  70. package/build/contracts/mocks/InterfaceIdCalculator.sol/InterfaceIdCalculator.json +0 -180
  71. package/build/contracts/mocks/PolicyHolderMock.sol/PolicyHolderMock.json +0 -228
  72. package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +0 -54
  73. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +0 -721
  74. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +0 -92
  75. package/build/contracts/mocks/RiskModuleMock.sol/RiskModuleMock.json +0 -783
  76. package/build/contracts/mocks/TestCurrency.sol/TestCurrency.json +0 -343
  77. package/build/contracts/mocks/TestNFT.sol/TestNFT.json +0 -388
  78. package/contracts/dependencies/ERC1967Proxy.sol +0 -19
  79. package/contracts/dependencies/IERC20Metadata.sol +0 -19
package/js/deploy.js CHANGED
@@ -1,7 +1,6 @@
1
1
  const upgrades_core = require("@openzeppelin/upgrades-core");
2
2
  const helpers = require("@nomicfoundation/hardhat-network-helpers");
3
3
  const fs = require("fs");
4
- const { request } = require("undici");
5
4
  const ethers = require("ethers");
6
5
  const { task, types } = require("hardhat/config");
7
6
  const { WhitelistStatus } = require("../js/enums");
@@ -78,53 +77,50 @@ async function logContractCreated(hre, contractName, address) {
78
77
  async function verifyContract(hre, contract, isProxy, constructorArguments) {
79
78
  if (isProxy === undefined) isProxy = false;
80
79
  if (constructorArguments === undefined) constructorArguments = [];
81
- let address = contract.address;
82
- if (isProxy) address = await upgrades_core.getImplementationAddress(hre.network.provider, address);
80
+ const contractAddr = await ethers.resolveAddress(contract);
81
+ const address = isProxy
82
+ ? await upgrades_core.getImplementationAddress(hre.network.provider, contractAddr)
83
+ : contractAddr;
83
84
  try {
84
85
  await hre.run("verify:verify", {
85
86
  address: address,
86
87
  constructorArguments: constructorArguments,
87
88
  });
89
+ } catch (error) {
90
+ console.log("Error verifying contract implementation: ", error);
91
+ console.log("You can retry with:");
92
+ console.log(
93
+ ` npx hardhat verify --network '${hre.network.name}' '${address}' ${constructorArguments
94
+ .map((a) => `'${a.toString()}'`)
95
+ .join(" ")}`
96
+ );
97
+ }
98
+ try {
88
99
  if (isProxy) {
89
- // the following should work but it fails with the current @openzeppelin/hardhat-upgrades version (1.20.0)
90
- // await hre.run("verify:verify", {
91
- // address: contract.address,
92
- // });
93
-
94
- // so we use the following workaround
95
- const endpoints = await hre.run("verify:get-etherscan-endpoint");
96
- const params = new URLSearchParams({
97
- module: "contract",
98
- action: "verifyproxycontract",
99
- apiKey: hre.config.etherscan.apiKey,
100
- address: contract.address,
101
- });
102
- const response = await request(endpoints.urls.apiURL, {
103
- method: "POST",
104
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
105
- body: params.toString(),
100
+ await hre.run("verify:verify", {
101
+ address: contractAddr,
102
+ constructorArguments: constructorArguments,
106
103
  });
107
- if (response.statusCode != 200)
108
- throw new Error(`Etherscan replied with ${response.statusCode}: ${await response.body.text()}`);
109
- const body = await response.body.json();
110
- if (body.status != 1) throw new Error(`Etherscan replied with ${body}`);
111
104
  }
112
105
  } catch (error) {
113
- console.log("Error verifying contract", error);
106
+ console.log("Error verifying contract proxy: ", error);
107
+ const endpoints = await hre.run("verify:get-etherscan-endpoint");
108
+ console.log(`You should do it manually at ${endpoints.urls.browserURL}/proxyContractChecker?a=${contractAddr}`);
114
109
  }
115
110
  }
116
111
 
117
112
  async function deployContract({ saveAddr, verify, contractClass, constructorArgs }, hre) {
118
113
  const ContractFactory = await hre.ethers.getContractFactory(contractClass);
119
114
  const contract = await ContractFactory.deploy(...constructorArgs, txOverrides());
115
+ const contractAddr = await ethers.resolveAddress(contract);
120
116
  if (verify) {
121
117
  // From https://ethereum.stackexchange.com/a/119622/79726
122
118
  await contract.deployTransaction.wait(6);
123
119
  } else {
124
- await contract.deployed();
120
+ await contract.waitForDeployment();
125
121
  }
126
- await logContractCreated(hre, contractClass, contract.address);
127
- saveAddress(saveAddr, contract.address);
122
+ await logContractCreated(hre, contractClass, contractAddr);
123
+ saveAddress(saveAddr, contractAddr);
128
124
  if (verify) await verifyContract(hre, contract, false, constructorArgs);
129
125
  return { ContractFactory, contract };
130
126
  }
@@ -140,14 +136,15 @@ async function deployProxyContract(
140
136
  initializer: initializer,
141
137
  ...deployProxyArgs,
142
138
  });
139
+ const contractAddr = await ethers.resolveAddress(contract);
143
140
  if (verify) {
144
141
  // From https://ethereum.stackexchange.com/a/119622/79726
145
142
  await contract.deployTransaction.wait(6);
146
143
  } else {
147
- await contract.deployed();
144
+ await contract.waitForDeployment();
148
145
  }
149
- await logContractCreated(hre, contractClass, contract.address);
150
- saveAddress(saveAddr, contract.address);
146
+ await logContractCreated(hre, contractClass, contractAddr);
147
+ saveAddress(saveAddr, contractAddr);
151
148
  if (verify) await verifyContract(hre, contract, true, constructorArgs);
152
149
  return { ContractFactory, contract };
153
150
  }
@@ -161,7 +158,7 @@ async function grantRoleTask({ contractAddress, role, account, component, impers
161
158
  }
162
159
  contract = contract.connect(signer);
163
160
  }
164
- if (component === ethers.constants.AddressZero) {
161
+ if (component === ethers.ZeroAddress) {
165
162
  await grantRole(hre, contract, role, account, txOverrides(), console.log);
166
163
  } else {
167
164
  await grantComponentRole(hre, contract, component, role, account, txOverrides(), console.log);
@@ -178,11 +175,11 @@ async function deployTestCurrency({ currName, currSymbol, initialSupply, ...opts
178
175
  },
179
176
  hre
180
177
  )
181
- ).contract.address;
178
+ ).contract;
182
179
  }
183
180
 
184
181
  async function deployAccessManager(opts, hre) {
185
- return (await deployProxyContract({ contractClass: "AccessManager", ...opts }, hre)).contract.address;
182
+ return (await deployProxyContract({ contractClass: "AccessManager", ...opts }, hre)).contract;
186
183
  }
187
184
 
188
185
  async function deployPolicyPool({ accessAddress, currencyAddress, nftName, nftSymbol, treasuryAddress, ...opts }, hre) {
@@ -196,7 +193,7 @@ async function deployPolicyPool({ accessAddress, currencyAddress, nftName, nftSy
196
193
  },
197
194
  hre
198
195
  )
199
- ).contract.address;
196
+ ).contract;
200
197
  }
201
198
 
202
199
  async function deployEToken(
@@ -216,9 +213,9 @@ async function deployEToken(
216
213
  if (opts.addComponent) {
217
214
  let policyPool = await hre.ethers.getContractAt("PolicyPool", poolAddress);
218
215
  if (runAs) policyPool = policyPool.connect(runAs);
219
- await policyPool.addComponent(contract.address, 1);
216
+ await policyPool.addComponent(contract, 1);
220
217
  }
221
- return contract.address;
218
+ return contract;
222
219
  }
223
220
 
224
221
  async function deployPremiumsAccount({ poolAddress, juniorEtk, seniorEtk, runAs, ...opts }, hre) {
@@ -235,9 +232,9 @@ async function deployPremiumsAccount({ poolAddress, juniorEtk, seniorEtk, runAs,
235
232
  if (opts.addComponent) {
236
233
  let policyPool = await hre.ethers.getContractAt("PolicyPool", poolAddress);
237
234
  if (runAs) policyPool = policyPool.connect(runAs);
238
- await policyPool.addComponent(contract.address, 3);
235
+ await policyPool.addComponent(contract, 3);
239
236
  }
240
- return contract.address;
237
+ return contract;
241
238
  }
242
239
 
243
240
  async function deployRiskModule(
@@ -264,8 +261,11 @@ async function deployRiskModule(
264
261
  },
265
262
  hre
266
263
  ) {
267
- extraArgs = extraArgs || [];
268
- extraConstructorArgs = extraConstructorArgs || [];
264
+ extraArgs = typeof extraArgs === "string" ? JSON.parse(extraArgs) : extraArgs || [];
265
+
266
+ extraConstructorArgs =
267
+ typeof extraConstructorArgs === "string" ? JSON.parse(extraConstructorArgs) : extraConstructorArgs || [];
268
+
269
269
  const { contract } = await deployProxyContract(
270
270
  {
271
271
  contractClass: rmClass,
@@ -285,7 +285,6 @@ async function deployRiskModule(
285
285
  hre
286
286
  );
287
287
  const rm = runAs === undefined ? contract : contract.connect(runAs);
288
-
289
288
  if (opts.addComponent) {
290
289
  if (moc != 1.0) {
291
290
  moc = _W(moc);
@@ -308,9 +307,9 @@ async function deployRiskModule(
308
307
  }
309
308
  let policyPool = await hre.ethers.getContractAt("PolicyPool", poolAddress);
310
309
  if (runAs) policyPool = policyPool.connect(runAs);
311
- await policyPool.addComponent(contract.address, 2);
310
+ await policyPool.addComponent(contract, 2);
312
311
  }
313
- return contract.address;
312
+ return contract;
314
313
  }
315
314
 
316
315
  async function deploySignedQuoteRM(opts, hre) {
@@ -323,9 +322,9 @@ async function setAssetManager({ reserve, amAddress, liquidityMin, liquidityMidd
323
322
  const tx = await reserveContract.setAssetManager(amAddress, false);
324
323
  console.log(`Asset Manager ${amAddress} set to reserve ${reserve}`);
325
324
  if (liquidityMin !== undefined || liquidityMiddle !== undefined || liquidityMax !== undefined) {
326
- liquidityMin = liquidityMin === undefined ? ethers.constants.MaxUint256 : _A(liquidityMin);
327
- liquidityMiddle = liquidityMiddle === undefined ? ethers.constants.MaxUint256 : _A(liquidityMiddle);
328
- liquidityMax = liquidityMax === undefined ? ethers.constants.MaxUint256 : _A(liquidityMax);
325
+ liquidityMin = liquidityMin === undefined ? ethers.MaxUint256 : _A(liquidityMin);
326
+ liquidityMiddle = liquidityMiddle === undefined ? ethers.MaxUint256 : _A(liquidityMiddle);
327
+ liquidityMax = liquidityMax === undefined ? ethers.MaxUint256 : _A(liquidityMax);
329
328
  const amContract = await hre.ethers.getContractAt(
330
329
  "ERC4626AssetManager", // Not relevant if it's ERC4626AssetManager, only need setLiquidityThresholds
331
330
  amAddress
@@ -350,7 +349,7 @@ async function deployERC4626AssetManager({ asset, vault, amClass, ...opts }, hre
350
349
  },
351
350
  hre
352
351
  )
353
- ).contract.address;
352
+ ).contract;
354
353
  }
355
354
 
356
355
  async function deployAaveAssetManager({ asset, aave, amClass, ...opts }, hre) {
@@ -363,7 +362,7 @@ async function deployAaveAssetManager({ asset, aave, amClass, ...opts }, hre) {
363
362
  },
364
363
  hre
365
364
  )
366
- ).contract.address;
365
+ ).contract;
367
366
  }
368
367
 
369
368
  async function deployWhitelist(
@@ -390,17 +389,17 @@ async function deployWhitelist(
390
389
  );
391
390
  if (eToken !== undefined) {
392
391
  const etk = await hre.ethers.getContractAt("EToken", eToken);
393
- await etk.setWhitelist(contract.address);
392
+ await etk.setWhitelist(contract);
394
393
  }
395
394
  if (eToken2 !== undefined) {
396
395
  const etk = await hre.ethers.getContractAt("EToken", eToken2);
397
- await etk.setWhitelist(contract.address);
396
+ await etk.setWhitelist(contract);
398
397
  }
399
398
  if (eToken3 !== undefined) {
400
399
  const etk = await hre.ethers.getContractAt("EToken", eToken3);
401
- await etk.setWhitelist(contract.address);
400
+ await etk.setWhitelist(contract);
402
401
  }
403
- return contract.address;
402
+ return contract;
404
403
  }
405
404
 
406
405
  async function trustfullPolicy({ rmAddress, payout, premium, lossProb, expiration, customer }, hre) {
@@ -413,7 +412,7 @@ async function trustfullPolicy({ rmAddress, payout, premium, lossProb, expiratio
413
412
  customer = customer || (await getDefaultSigner(hre));
414
413
  premium = _A(premium);
415
414
 
416
- await currency.approve(policyPool.address, premium);
415
+ await currency.approve(policyPool, premium);
417
416
  lossProb = _W(lossProb);
418
417
  if (expiration === undefined) {
419
418
  expiration = 3600;
@@ -457,7 +456,7 @@ async function flightDelayPolicy(
457
456
  customer = customer || (await getDefaultSigner(hre));
458
457
  premium = _A(premium);
459
458
 
460
- await currency.approve(policyPool.address, premium);
459
+ await currency.approve(policyPool, premium);
461
460
  lossProb = _W(lossProb);
462
461
  payout = _A(payout);
463
462
 
@@ -484,7 +483,7 @@ async function listETokens({ poolAddress }, hre) {
484
483
  for (let i = 0; i < etkCount; i++) {
485
484
  const etk = await hre.ethers.getContractAt("EToken", await policyPool.getETokenAt(i));
486
485
  const etkName = await etk.name();
487
- console.log(`eToken at ${etk.address}: ${etkName}`);
486
+ console.log(`eToken at ${etk.target}: ${etkName}`);
488
487
  }
489
488
  }
490
489
 
@@ -493,8 +492,8 @@ async function deposit({ etkAddress, amount }, hre) {
493
492
  const policyPool = await hre.ethers.getContractAt("PolicyPool", await etk.policyPool());
494
493
  const currency = await hre.ethers.getContractAt("IERC20Metadata", await policyPool.currency());
495
494
  amount = _A(amount);
496
- await currency.approve(policyPool.address, amount);
497
- const tx = await policyPool.deposit(etk.address, amount, { gasLimit: 999999 });
495
+ await currency.approve(policyPool, amount);
496
+ const tx = await policyPool.deposit(etk, amount, { gasLimit: 999999 });
498
497
  console.log(tx);
499
498
  }
500
499
 
@@ -512,11 +511,13 @@ function add_task() {
512
511
  .setAction(async function (taskArgs, hre) {
513
512
  if (taskArgs.currencyAddress === undefined) {
514
513
  taskArgs.saveAddr = "CURRENCY";
515
- taskArgs.currencyAddress = await deployTestCurrency(taskArgs, hre);
514
+ const currency = await deployTestCurrency(taskArgs, hre);
515
+ taskArgs.currencyAddress = await ethers.resolveAddress(currency);
516
516
  }
517
517
  if (taskArgs.accessAddress === undefined) {
518
518
  taskArgs.saveAddr = "ACCESSMANAGER";
519
- taskArgs.accessAddress = await deployAccessManager(taskArgs, hre);
519
+ const access = await deployAccessManager(taskArgs, hre);
520
+ taskArgs.accessAddress = await ethers.resolveAddress(access);
520
521
  }
521
522
  taskArgs.saveAddr = "POOL";
522
523
  await deployPolicyPool(taskArgs, hre);
@@ -540,7 +541,7 @@ function add_task() {
540
541
  .addOptionalParam("saveAddr", "Save created contract address", "POOL", types.str)
541
542
  .addOptionalParam("nftName", "Name of Policies NFT Token", "Ensuro Policies NFT", types.str)
542
543
  .addOptionalParam("nftSymbol", "Symbol of Policies NFT Token", "EPOL", types.str)
543
- .addOptionalParam("treasuryAddress", "Treasury Address", ethers.constants.AddressZero, types.address)
544
+ .addOptionalParam("treasuryAddress", "Treasury Address", ethers.ZeroAddress, types.address)
544
545
  .addParam("currencyAddress", "Currency Address", types.address)
545
546
  .addParam("accessAddress", "AccessManager Address", types.address)
546
547
  .setAction(deployPolicyPool);
@@ -583,6 +584,8 @@ function add_task() {
583
584
  .addOptionalParam("exposureLimit", "Exposure (sum of payouts) limit for the RM", 1e6, types.float)
584
585
  .addOptionalParam("maxDuration", "Maximum policy duration in hours", 24 * 365, types.int)
585
586
  .addOptionalParam("moc", "Margin of Conservativism", 1.0, types.float)
587
+ .addOptionalParam("extraConstructorArgs", "Additional constructor args", undefined, types.str)
588
+ .addOptionalParam("extraArgs", "Additional initializer args", undefined, types.str)
586
589
  .addParam("wallet", "RM address", types.address)
587
590
  .setAction(deployRiskModule);
588
591
 
@@ -694,7 +697,7 @@ function add_task() {
694
697
  .addOptionalParam(
695
698
  "component",
696
699
  "Address of the component if it's a component role",
697
- ethers.constants.AddressZero,
700
+ ethers.ZeroAddress,
698
701
  types.address
699
702
  )
700
703
  .setAction(grantRoleTask);
package/js/enums.js CHANGED
@@ -4,7 +4,29 @@ const WhitelistStatus = {
4
4
  blacklisted: 2,
5
5
  };
6
6
 
7
+ const ComponentKind = {
8
+ eToken: 1,
9
+ riskModule: 2,
10
+ premiumsAccount: 3,
11
+ };
12
+
13
+ const ComponentStatus = {
14
+ inactive: 0,
15
+ active: 1,
16
+ deprecated: 2,
17
+ suspended: 3,
18
+ };
19
+
20
+ const ETokenParameter = {
21
+ // From IEToken.Parameter
22
+ liquidityRequirement: 0,
23
+ minUtilizationRate: 1,
24
+ maxUtilizationRate: 2,
25
+ internalLoanInterestRate: 3,
26
+ };
27
+
7
28
  const RiskModuleParameter = {
29
+ // From IRiskModule.Parameter
8
30
  moc: 0,
9
31
  jrCollRatio: 1,
10
32
  collRatio: 2,
@@ -17,14 +39,10 @@ const RiskModuleParameter = {
17
39
  maxDuration: 9,
18
40
  };
19
41
 
20
- const ComponentKind = {
21
- eToken: 1,
22
- riskModule: 2,
23
- premiumsAccount: 3,
24
- };
25
-
26
42
  module.exports = {
27
- WhitelistStatus,
28
- RiskModuleParameter,
29
43
  ComponentKind,
44
+ ComponentStatus,
45
+ ETokenParameter,
46
+ RiskModuleParameter,
47
+ WhitelistStatus,
30
48
  };
package/js/test-utils.js CHANGED
@@ -1,11 +1,13 @@
1
1
  const hre = require("hardhat");
2
2
  const { _W, grantRole, getTransactionEvent } = require("../js/utils");
3
3
  const { RiskModuleParameter } = require("../js/enums");
4
+ const helpers = require("@nomicfoundation/hardhat-network-helpers");
4
5
 
5
- const { AddressZero } = hre.ethers.constants;
6
+ const { ethers } = hre;
7
+ const { ZeroAddress } = ethers;
6
8
 
7
9
  async function initCurrency(options, initial_targets, initial_balances) {
8
- const Currency = await hre.ethers.getContractFactory("TestCurrency");
10
+ const Currency = await ethers.getContractFactory(options.contractClass || "TestCurrency");
9
11
  let currency = await Currency.deploy(
10
12
  options.name || "Test Currency",
11
13
  options.symbol || "TEST",
@@ -15,7 +17,27 @@ async function initCurrency(options, initial_targets, initial_balances) {
15
17
  initial_targets = initial_targets || [];
16
18
  await Promise.all(
17
19
  initial_targets.map(async function (user, index) {
18
- await currency.transfer(user.address, initial_balances[index]);
20
+ await currency.transfer(user, initial_balances[index]);
21
+ })
22
+ );
23
+ return currency;
24
+ }
25
+
26
+ /**
27
+ *
28
+ * @param currencyAddress The currency contract address, for example the USDC address
29
+ * @param currencyOrigin An account that holds at least sum(initialBalances) of currency tokens
30
+ * @param initialTargets Array of addresses that will receive the initial balances
31
+ * @param initialBalances Initial balances for each address
32
+ */
33
+ async function initForkCurrency(currencyAddress, currencyOrigin, initialTargets, initialBalances) {
34
+ const currency = await ethers.getContractAt("IERC20", currencyAddress);
35
+ await helpers.impersonateAccount(currencyOrigin);
36
+ await helpers.setBalance(currencyOrigin, ethers.parseEther("100"));
37
+ const whale = await ethers.getSigner(currencyOrigin);
38
+ await Promise.all(
39
+ initialTargets.map(async function (user, index) {
40
+ await currency.connect(whale).transfer(user, initialBalances[index]);
19
41
  })
20
42
  );
21
43
  return currency;
@@ -41,6 +63,11 @@ async function createRiskModule(
41
63
  extraArgs = extraArgs || [];
42
64
  extraConstructorArgs = extraConstructorArgs || [];
43
65
  const _A = pool._A || _W;
66
+ maxPayoutPerPolicy = maxPayoutPerPolicy !== undefined ? _A(maxPayoutPerPolicy) : _A(1000);
67
+ exposureLimit = exposureLimit !== undefined ? _A(exposureLimit) : _A(1000000);
68
+
69
+ const poolAddr = await ethers.resolveAddress(pool);
70
+ const paAddr = await ethers.resolveAddress(premiumsAccount);
44
71
  const rm = await hre.upgrades.deployProxy(
45
72
  contractFactory,
46
73
  [
@@ -48,18 +75,18 @@ async function createRiskModule(
48
75
  _W(collRatio) || _W(1),
49
76
  _W(ensuroPPFee) || _W(0),
50
77
  _W(srRoc) || _W("0.1"),
51
- _A(maxPayoutPerPolicy) || _A(1000),
52
- _A(exposureLimit) || _A(1000000),
78
+ maxPayoutPerPolicy,
79
+ exposureLimit,
53
80
  wallet || "0xdD2FD4581271e230360230F9337D5c0430Bf44C0", // Random address
54
81
  ...extraArgs,
55
82
  ],
56
83
  {
57
84
  kind: "uups",
58
- constructorArgs: [pool.address, premiumsAccount.address, ...extraConstructorArgs],
85
+ constructorArgs: [poolAddr, paAddr, ...extraConstructorArgs],
59
86
  }
60
87
  );
61
88
 
62
- await rm.deployed();
89
+ await rm.waitForDeployment();
63
90
 
64
91
  if (moc !== undefined && moc != 1.0) {
65
92
  moc = _W(moc);
@@ -98,7 +125,7 @@ async function addRiskModule(
98
125
  extraConstructorArgs,
99
126
  });
100
127
 
101
- await pool.addComponent(rm.address, 2);
128
+ await pool.addComponent(rm, 2);
102
129
  return rm;
103
130
  }
104
131
 
@@ -106,9 +133,10 @@ async function createEToken(
106
133
  pool,
107
134
  { etkName, etkSymbol, maxUtilizationRate, poolLoanInterestRate, extraArgs, extraConstructorArgs }
108
135
  ) {
109
- const EToken = await hre.ethers.getContractFactory("EToken");
136
+ const EToken = await ethers.getContractFactory("EToken");
110
137
  extraArgs = extraArgs || [];
111
138
  extraConstructorArgs = extraConstructorArgs || [];
139
+ const poolAddr = await ethers.resolveAddress(pool);
112
140
  const etk = await hre.upgrades.deployProxy(
113
141
  EToken,
114
142
  [
@@ -121,11 +149,11 @@ async function createEToken(
121
149
  {
122
150
  kind: "uups",
123
151
  unsafeAllow: ["delegatecall"], // This holds, because EToken is a reserve and uses delegatecall
124
- constructorArgs: [pool.address, ...extraConstructorArgs],
152
+ constructorArgs: [poolAddr, ...extraConstructorArgs],
125
153
  }
126
154
  );
127
155
 
128
- await etk.deployed();
156
+ await etk.waitForDeployment();
129
157
  return etk;
130
158
  }
131
159
 
@@ -141,7 +169,7 @@ async function addEToken(
141
169
  extraArgs,
142
170
  extraConstructorArgs,
143
171
  });
144
- await pool.addComponent(etk.address, 1);
172
+ await pool.addComponent(etk, 1);
145
173
  return etk;
146
174
  }
147
175
 
@@ -162,19 +190,21 @@ const randomAddress = "0x89cDb70Fee571251a66E34caa1673cE40f7549Dc";
162
190
  * - .dontGrantL123Roles: if specified, doesn't grants LEVEL1, 2 and 3 roles.
163
191
  */
164
192
  async function deployPool(options) {
165
- const PolicyPool = await hre.ethers.getContractFactory("PolicyPool");
166
- const AccessManager = await hre.ethers.getContractFactory("AccessManager");
193
+ const PolicyPool = await ethers.getContractFactory("PolicyPool");
194
+ const AccessManager = await ethers.getContractFactory("AccessManager");
167
195
 
168
196
  let accessManager;
169
197
 
170
198
  if (options.access === undefined) {
171
199
  // Deploy AccessManager
172
200
  accessManager = await hre.upgrades.deployProxy(AccessManager, [], { kind: "uups" });
173
- await accessManager.deployed();
201
+ await accessManager.waitForDeployment();
174
202
  } else {
175
- accessManager = await hre.ethers.getContractAt("AccessManager", options.access);
203
+ accessManager = await ethers.getContractAt("AccessManager", options.access);
176
204
  }
177
205
 
206
+ const currencyAddr = await ethers.resolveAddress(options.currency);
207
+ const amAddr = await ethers.resolveAddress(accessManager);
178
208
  const policyPool = await hre.upgrades.deployProxy(
179
209
  PolicyPool,
180
210
  [
@@ -183,12 +213,12 @@ async function deployPool(options) {
183
213
  options.treasuryAddress || randomAddress,
184
214
  ],
185
215
  {
186
- constructorArgs: [accessManager.address, options.currency],
216
+ constructorArgs: [amAddr, currencyAddr],
187
217
  kind: "uups",
188
218
  }
189
219
  );
190
220
 
191
- await policyPool.deployed();
221
+ await policyPool.waitForDeployment();
192
222
 
193
223
  for (const role of options.grantRoles || []) {
194
224
  await grantRole(hre, accessManager, role);
@@ -204,28 +234,76 @@ async function deployPool(options) {
204
234
  }
205
235
 
206
236
  async function deployPremiumsAccount(pool, options, addToPool = true) {
207
- const PremiumsAccount = await hre.ethers.getContractFactory("PremiumsAccount");
237
+ const PremiumsAccount = await ethers.getContractFactory("PremiumsAccount");
238
+ const poolAddr = await ethers.resolveAddress(pool);
239
+ const jrEtkAddr = options.jrEtk ? await ethers.resolveAddress(options.jrEtk) : ZeroAddress;
240
+ const srEtkAddr = options.srEtk ? await ethers.resolveAddress(options.srEtk) : ZeroAddress;
208
241
  const premiumsAccount = await hre.upgrades.deployProxy(PremiumsAccount, [], {
209
- constructorArgs: [pool.address, options.jrEtkAddr || AddressZero, options.srEtkAddr || AddressZero],
242
+ constructorArgs: [poolAddr, jrEtkAddr, srEtkAddr],
210
243
  kind: "uups",
211
244
  unsafeAllow: ["delegatecall"], // This holds, because EToken is a reserve and uses delegatecall
212
245
  });
213
246
 
214
- await premiumsAccount.deployed();
247
+ await premiumsAccount.waitForDeployment();
215
248
 
216
- if (addToPool) await pool.addComponent(premiumsAccount.address, 3);
249
+ if (addToPool) await pool.addComponent(premiumsAccount, 3);
217
250
 
218
251
  return premiumsAccount;
219
252
  }
220
253
 
221
254
  async function makePolicy(pool, rm, cust, payout, premium, lossProb, expiration, internalId, method = "newPolicy") {
222
- let tx = await rm.connect(cust)[method](payout, premium, lossProb, expiration, cust.address, internalId);
255
+ let tx = await rm.connect(cust)[method](payout, premium, lossProb, expiration, cust, internalId);
223
256
  let receipt = await tx.wait();
224
257
  const newPolicyEvt = getTransactionEvent(pool.interface, receipt, "NewPolicy");
225
258
 
226
259
  return newPolicyEvt;
227
260
  }
228
261
 
262
+ /**
263
+ * Resets hardhat network to fork on the specified block and url
264
+ */
265
+ async function setupChain(block, alchemyUrlEnv = "ALCHEMY_URL") {
266
+ const alchemyUrl = process.env[alchemyUrlEnv];
267
+ if (alchemyUrl === undefined) throw new Error(`Define envvar ${alchemyUrlEnv} for this test`);
268
+
269
+ if (block === undefined) throw new Error("Block can't be undefined use null for the current block");
270
+ if (block === null) block = undefined;
271
+ return hre.network.provider.request({
272
+ method: "hardhat_reset",
273
+ params: [
274
+ {
275
+ forking: {
276
+ jsonRpcUrl: alchemyUrl,
277
+ blockNumber: block,
278
+ },
279
+ },
280
+ ],
281
+ });
282
+ }
283
+
284
+ const skipForkTests = process.env.SKIP_FORK_TESTS === "true";
285
+
286
+ /**
287
+ * Chai test case wrapper for tests that require forking a live chain.
288
+ *
289
+ * It validates that the chain node URL is set, forks the chain at the specified block and adds the
290
+ * block number to the test name.
291
+ */
292
+ const fork = {
293
+ it: (name, blockNumber, test, alchemyUrlEnv = "ALCHEMY_URL") => {
294
+ const fullName = `[FORK ${blockNumber}] ${name}`;
295
+
296
+ // eslint-disable-next-line func-style
297
+ const wrapped = async (...args) => {
298
+ await setupChain(blockNumber, alchemyUrlEnv);
299
+
300
+ return test(...args);
301
+ };
302
+
303
+ return (skipForkTests ? it.skip : it)(fullName, wrapped);
304
+ },
305
+ };
306
+
229
307
  if (process.env.ENABLE_HH_WARNINGS !== "yes") hre.upgrades.silenceWarnings();
230
308
 
231
309
  module.exports = {
@@ -235,6 +313,10 @@ module.exports = {
235
313
  createRiskModule,
236
314
  deployPool,
237
315
  deployPremiumsAccount,
316
+ fork,
238
317
  initCurrency,
318
+ initForkCurrency,
239
319
  makePolicy,
320
+ setupChain,
321
+ skipForkTests,
240
322
  };