@ensuro/core 2.4.0 → 2.6.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.
package/js/test-utils.js CHANGED
@@ -1,12 +1,6 @@
1
- const { expect } = require("chai");
2
1
  const hre = require("hardhat");
3
- const { BigNumber } = require("ethers");
4
- const { LogDescription } = require("ethers/lib/utils");
5
- const { findAll } = require("solidity-ast/utils");
6
- const helpers = require("@nomicfoundation/hardhat-network-helpers");
7
-
8
- WEEK = 3600 * 24 * 7;
9
- DAY = 3600 * 24;
2
+ const { _W, grantRole, getTransactionEvent } = require("../js/utils");
3
+ const { RiskModuleParameter } = require("../js/enums");
10
4
 
11
5
  async function initCurrency(options, initial_targets, initial_balances) {
12
6
  const Currency = await hre.ethers.getContractFactory("TestCurrency");
@@ -25,36 +19,7 @@ async function initCurrency(options, initial_targets, initial_balances) {
25
19
  return currency;
26
20
  }
27
21
 
28
- async function approve_multiple(currency, spender, sources, amounts) {
29
- return Promise.all(
30
- sources.map(async function (source, index) {
31
- await currency.connect(source).approve(spender.address, amounts[index]);
32
- })
33
- );
34
- }
35
-
36
- async function check_balances(currency, users, amounts) {
37
- return Promise.all(
38
- users.map(async function (user, index) {
39
- expect(await currency.balanceOf(user.address)).to.equal(amounts[index]);
40
- })
41
- );
42
- }
43
-
44
- const RiskModuleParameter = {
45
- moc: 0,
46
- jrCollRatio: 1,
47
- collRatio: 2,
48
- ensuroPpFee: 3,
49
- ensuroCocFee: 4,
50
- jrRoc: 5,
51
- srRoc: 6,
52
- maxPayoutPerPolicy: 7,
53
- exposureLimit: 8,
54
- maxDuration: 9,
55
- };
56
-
57
- const createRiskModule = async function (
22
+ async function createRiskModule(
58
23
  pool,
59
24
  premiumsAccount,
60
25
  contractFactory,
@@ -99,7 +64,7 @@ const createRiskModule = async function (
99
64
  await rm.setParam(RiskModuleParameter.moc, moc);
100
65
  }
101
66
  return rm;
102
- };
67
+ }
103
68
 
104
69
  async function addRiskModule(
105
70
  pool,
@@ -135,7 +100,7 @@ async function addRiskModule(
135
100
  return rm;
136
101
  }
137
102
 
138
- const createEToken = async function (
103
+ async function createEToken(
139
104
  pool,
140
105
  { etkName, etkSymbol, maxUtilizationRate, poolLoanInterestRate, extraArgs, extraConstructorArgs }
141
106
  ) {
@@ -160,9 +125,9 @@ const createEToken = async function (
160
125
 
161
126
  await etk.deployed();
162
127
  return etk;
163
- };
128
+ }
164
129
 
165
- addEToken = async function addEToken(
130
+ async function addEToken(
166
131
  pool,
167
132
  { etkName, etkSymbol, maxUtilizationRate, poolLoanInterestRate, extraArgs, extraConstructorArgs }
168
133
  ) {
@@ -176,42 +141,12 @@ addEToken = async function addEToken(
176
141
  });
177
142
  await pool.addComponent(etk.address, 1);
178
143
  return etk;
179
- };
180
-
181
- async function expected_change(protocol_attribute, initial, change) {
182
- change = BigNumber.from(change);
183
- let actual_value = await protocol_attribute();
184
- expect(actual_value.sub(initial)).to.equal(change);
185
- return actual_value;
186
144
  }
187
145
 
188
- /**
189
- * Finds an event in the receipt
190
- * @param {Interface} interface The interface of the contract that contains the requested event
191
- * @param {TransactionReceipt} receipt Transaction receipt containing the events in the logs
192
- * @param {String} eventName The name of the event we are interested in
193
- * @returns {LogDescription}
194
- */
195
- const getTransactionEvent = function (interface, receipt, eventName) {
196
- // for each log in the transaction receipt
197
- for (const log of receipt.logs) {
198
- let parsedLog;
199
- try {
200
- parsedLog = interface.parseLog(log);
201
- } catch (error) {
202
- continue;
203
- }
204
- if (parsedLog.name == eventName) {
205
- return parsedLog;
206
- }
207
- }
208
- return null; // not found
209
- };
210
-
211
146
  const randomAddress = "0x89cDb70Fee571251a66E34caa1673cE40f7549Dc";
212
147
 
213
148
  /**
214
- * Deploys de PolicyPool contract and AccessManager
149
+ * Deploys the PolicyPool contract and AccessManager
215
150
  *
216
151
  * By default deployes de PolicyPool and AccessManager and grants LEVEL 1, 2, 3 permissions
217
152
  *
@@ -224,7 +159,7 @@ const randomAddress = "0x89cDb70Fee571251a66E34caa1673cE40f7549Dc";
224
159
  * - .grantRoles: default []. List of additional roles to grant
225
160
  * - .dontGrantL123Roles: if specified, doesn't grants LEVEL1, 2 and 3 roles.
226
161
  */
227
- async function deployPool(hre, options) {
162
+ async function deployPool(options) {
228
163
  const PolicyPool = await hre.ethers.getContractFactory("PolicyPool");
229
164
  const AccessManager = await hre.ethers.getContractFactory("AccessManager");
230
165
 
@@ -266,7 +201,7 @@ async function deployPool(hre, options) {
266
201
  return policyPool;
267
202
  }
268
203
 
269
- async function deployPremiumsAccount(hre, pool, options, addToPool = true) {
204
+ async function deployPremiumsAccount(pool, options, addToPool = true) {
270
205
  const PremiumsAccount = await hre.ethers.getContractFactory("PremiumsAccount");
271
206
  const premiumsAccount = await hre.upgrades.deployProxy(PremiumsAccount, [], {
272
207
  constructorArgs: [
@@ -285,112 +220,6 @@ async function deployPremiumsAccount(hre, pool, options, addToPool = true) {
285
220
  return premiumsAccount;
286
221
  }
287
222
 
288
- async function _getDefaultSigner(hre) {
289
- const signers = await hre.ethers.getSigners();
290
- return signers[0];
291
- }
292
-
293
- async function grantRole(hre, contract, role, user) {
294
- let userAddress;
295
- if (user === undefined) {
296
- user = await _getDefaultSigner(hre);
297
- userAddress = user.address;
298
- } else {
299
- userAddress = user;
300
- }
301
- if (!(await contract.hasRole(getRole(role), userAddress))) {
302
- await contract.grantRole(getRole(role), userAddress);
303
- }
304
- }
305
-
306
- async function grantComponentRole(hre, accessManager, component, role, user) {
307
- let userAddress;
308
- if (user === undefined) {
309
- user = await _getDefaultSigner(hre);
310
- userAddress = user.address;
311
- } else {
312
- userAddress = user.address === undefined ? user : user.address;
313
- }
314
- const componentRole = getComponentRole(component.address, getRole(role));
315
- if (!(await accessManager.hasRole(componentRole, userAddress))) {
316
- await accessManager.grantComponentRole(component.address, getRole(role), userAddress);
317
- }
318
- }
319
-
320
- const _E = hre.ethers.utils.parseEther;
321
-
322
- const _BN = hre.ethers.BigNumber.from;
323
-
324
- const WAD = _BN(10).pow(18); // 1e18
325
-
326
- const RAY = _BN(10).pow(27); // 1e27
327
-
328
- /**
329
- * Creates a fixed-point conversion function for the desired number of decimals
330
- * @param decimals The number of decimals. Must be >= 6.
331
- * @returns The amount function created. The function can receive strings (recommended),
332
- * floats/doubles (not recommended) and integers.
333
- *
334
- * Floats will be rounded to 6 decimal before scaling.
335
- */
336
- function amountFunction(decimals) {
337
- return function (value) {
338
- if (value === undefined) return undefined;
339
-
340
- if (typeof value === "string" || value instanceof String) {
341
- return hre.ethers.utils.parseUnits(value, decimals);
342
- }
343
-
344
- if (!Number.isInteger(value)) {
345
- return _BN(Math.round(value * 1e6)).mul(_BN(Math.pow(10, decimals - 6)));
346
- }
347
-
348
- return _BN(value).mul(_BN(10).pow(decimals));
349
- };
350
- }
351
-
352
- const _W = amountFunction(18);
353
-
354
- const _R = amountFunction(27);
355
-
356
- /**
357
- * Builds the component role identifier
358
- *
359
- * Mimics the behaviour of the PolicyPoolConfig.getComponentRole method
360
- *
361
- * Component roles are roles created doing XOR between the component
362
- * address and the original role.
363
- *
364
- * Example:
365
- * getComponentRole("0xc6e7DF5E7b4f2A278906862b61205850344D4e7d", "ORACLE_ADMIN_ROLE")
366
- * // "0x05e01b185238b49f750d03d945e38a7f6c3be8b54de0ee42d481eb7814f0d3a8"
367
- */
368
- function getComponentRole(componentAddress, role) {
369
- if (!role.startsWith("0x")) role = getRole(role);
370
-
371
- // 32 byte array
372
- const bytesRole = hre.ethers.utils.arrayify(role);
373
-
374
- // 20 byte array
375
- const bytesAddress = hre.ethers.utils.arrayify(componentAddress);
376
-
377
- // xor each byte, padding bytesAddress with zeros at the end
378
- return hre.ethers.utils.hexlify(bytesRole.map((elem, idx) => elem ^ (bytesAddress[idx] || 0)));
379
- }
380
-
381
- /*
382
- Builds AccessControl error message for comparison in tests
383
- */
384
- function accessControlMessage(address, component, role) {
385
- const roleHash = component !== null ? getComponentRole(component, role) : getRole(role);
386
-
387
- return `AccessControl: account ${address.toLowerCase()} is missing role ${roleHash}`;
388
- }
389
-
390
- function makePolicyId(rm, internalId) {
391
- return hre.ethers.BigNumber.from(rm.address).shl(96).add(internalId);
392
- }
393
-
394
223
  async function makePolicy(pool, rm, cust, payout, premium, lossProb, expiration, internalId, method = "newPolicy") {
395
224
  let tx = await rm.connect(cust)[method](payout, premium, lossProb, expiration, cust.address, internalId);
396
225
  let receipt = await tx.wait();
@@ -399,71 +228,15 @@ async function makePolicy(pool, rm, cust, payout, premium, lossProb, expiration,
399
228
  return newPolicyEvt;
400
229
  }
401
230
 
402
- function getRole(role) {
403
- return role === "DEFAULT_ADMIN_ROLE"
404
- ? "0x0000000000000000000000000000000000000000000000000000000000000000"
405
- : hre.ethers.utils.keccak256(hre.ethers.utils.toUtf8Bytes(role));
406
- }
407
-
408
- async function getStorageLayout(contractSrc, contractName) {
409
- const buildInfo = await hre.artifacts.getBuildInfo(`${contractSrc}:${contractName}`);
410
- if (buildInfo === undefined) throw new Error(`Contract ${contractSrc}:${contractName} not in artifacts`);
411
-
412
- const solcOutput = buildInfo.output;
413
-
414
- const storageLayouts = {};
415
-
416
- for (const def of findAll("ContractDefinition", solcOutput.sources[contractSrc].ast)) {
417
- storageLayouts[def.name] = solcOutput.contracts[contractSrc][def.name].storageLayout;
418
- }
419
-
420
- return storageLayouts[contractName];
421
- }
422
-
423
- function makeQuoteMessage({ rmAddress, payout, premium, lossProb, expiration, policyData, validUntil }) {
424
- return ethers.utils.solidityPack(
425
- ["address", "uint256", "uint256", "uint256", "uint40", "bytes32", "uint40"],
426
- [rmAddress, payout, premium, lossProb, expiration, policyData, validUntil]
427
- );
428
- }
429
-
430
- async function makeSignedQuote(signer, policyParams) {
431
- const quoteMessage = makeQuoteMessage(policyParams);
432
- return ethers.utils.splitSignature(await signer.signMessage(ethers.utils.arrayify(quoteMessage)));
433
- }
434
-
435
231
  if (process.env.ENABLE_HH_WARNINGS !== "yes") hre.upgrades.silenceWarnings();
436
232
 
437
233
  module.exports = {
438
- _BN,
439
- _E,
440
- _R,
441
- _W,
442
- accessControlMessage,
443
234
  addEToken,
444
235
  addRiskModule,
445
- amountFunction,
446
- approve_multiple,
447
- check_balances,
448
236
  createEToken,
449
237
  createRiskModule,
450
- DAY,
451
238
  deployPool,
452
239
  deployPremiumsAccount,
453
- expected_change,
454
- getComponentRole,
455
- getRole,
456
- getStorageLayout,
457
- getTransactionEvent,
458
- grantComponentRole,
459
- grantRole,
460
240
  initCurrency,
461
241
  makePolicy,
462
- makePolicyId,
463
- makeQuoteMessage,
464
- makeSignedQuote,
465
- RAY,
466
- RiskModuleParameter,
467
- WAD,
468
- WEEK,
469
242
  };
package/js/utils.js ADDED
@@ -0,0 +1,264 @@
1
+ const { findAll } = require("solidity-ast/utils");
2
+ const ethers = require("ethers");
3
+ const helpers = require("@nomicfoundation/hardhat-network-helpers");
4
+
5
+ const _E = ethers.utils.parseEther;
6
+ const _BN = ethers.BigNumber.from;
7
+ const WAD = _BN(10).pow(18); // 1e18
8
+ const RAY = _BN(10).pow(27); // 1e27
9
+
10
+ async function getStorageLayout(contractSrc, contractName, hre) {
11
+ const buildInfo = await hre.artifacts.getBuildInfo(`${contractSrc}:${contractName}`);
12
+ if (buildInfo === undefined) throw new Error(`Contract ${contractSrc}:${contractName} not in artifacts`);
13
+
14
+ const solcOutput = buildInfo.output;
15
+
16
+ const storageLayouts = {};
17
+
18
+ for (const def of findAll("ContractDefinition", solcOutput.sources[contractSrc].ast)) {
19
+ storageLayouts[def.name] = solcOutput.contracts[contractSrc][def.name].storageLayout;
20
+ }
21
+
22
+ return storageLayouts[contractName];
23
+ }
24
+
25
+ /**
26
+ * Creates a fixed-point conversion function for the desired number of decimals
27
+ * @param decimals The number of decimals. Must be >= 6.
28
+ * @returns The amount function created. The function can receive strings (recommended),
29
+ * floats/doubles (not recommended) and integers.
30
+ *
31
+ * Floats will be rounded to 6 decimal before scaling.
32
+ */
33
+ function amountFunction(decimals) {
34
+ return function (value) {
35
+ if (value === undefined) return undefined;
36
+
37
+ if (typeof value === "string" || value instanceof String) {
38
+ return ethers.utils.parseUnits(value, decimals);
39
+ }
40
+
41
+ if (!Number.isInteger(value)) {
42
+ return _BN(Math.round(value * 1e6)).mul(_BN(Math.pow(10, decimals - 6)));
43
+ }
44
+
45
+ return _BN(value).mul(_BN(10).pow(decimals));
46
+ };
47
+ }
48
+
49
+ /** Wad function */
50
+ const _W = amountFunction(18);
51
+
52
+ /** Ray function */
53
+ const _R = amountFunction(27);
54
+
55
+ /**
56
+ * Returns a role identifier by computing the keccak of the role name.
57
+ */
58
+ function getRole(role) {
59
+ if (role.startsWith("0x")) return role;
60
+ return role === "DEFAULT_ADMIN_ROLE"
61
+ ? ethers.constants.HashZero
62
+ : ethers.utils.keccak256(ethers.utils.toUtf8Bytes(role));
63
+ }
64
+
65
+ /**
66
+ * Builds the component role identifier
67
+ *
68
+ * Mimics the behaviour of the AccessManager.getComponentRole method
69
+ *
70
+ * Component roles are roles created doing XOR between the component
71
+ * address and the original role.
72
+ *
73
+ * Example:
74
+ * getComponentRole("0xc6e7DF5E7b4f2A278906862b61205850344D4e7d", "ORACLE_ADMIN_ROLE")
75
+ * // "0x05e01b185238b49f750d03d945e38a7f6c3be8b54de0ee42d481eb7814f0d3a8"
76
+ */
77
+ function getComponentRole(componentAddress, role) {
78
+ if (!role.startsWith("0x")) role = getRole(role);
79
+
80
+ // 32 byte array
81
+ const bytesRole = ethers.utils.arrayify(role);
82
+
83
+ // 20 byte array
84
+ const bytesAddress = ethers.utils.arrayify(componentAddress);
85
+
86
+ // xor each byte, padding bytesAddress with zeros at the end
87
+ // eslint-disable-next-line no-bitwise
88
+ return ethers.utils.hexlify(bytesRole.map((elem, idx) => elem ^ (bytesAddress[idx] || 0)));
89
+ }
90
+
91
+ async function getDefaultSigner(hre) {
92
+ const signers = await hre.ethers.getSigners();
93
+ return signers[0];
94
+ }
95
+
96
+ /**
97
+ * Grant a component role to a user.
98
+ */
99
+ // eslint-disable-next-line no-empty-function
100
+ async function grantComponentRole(hre, contract, component, role, user, txOverrides = {}, log = () => {}) {
101
+ let userAddress;
102
+ if (user === undefined) {
103
+ user = await getDefaultSigner(hre);
104
+ userAddress = user.address;
105
+ } else {
106
+ userAddress = user.address === undefined ? user : user.address;
107
+ }
108
+ const roleHex = getRole(role);
109
+ const componentAddress = component.address || component;
110
+ const componentRole = await contract.getComponentRole(componentAddress, roleHex);
111
+ if (!(await contract.hasRole(componentRole, userAddress))) {
112
+ await contract.grantComponentRole(componentAddress, roleHex, userAddress, txOverrides);
113
+ log(`Role ${role} (${roleHex}) Component ${componentAddress} granted to ${userAddress}`);
114
+ } else {
115
+ log(`Role ${role} (${roleHex}) Component ${componentAddress} already granted to ${userAddress}`);
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Grant a role to a user
121
+ */
122
+ // eslint-disable-next-line no-empty-function
123
+ async function grantRole(hre, contract, role, user, txOverrides = {}, log = () => {}) {
124
+ let userAddress;
125
+ if (user === undefined) {
126
+ user = await getDefaultSigner(hre);
127
+ userAddress = user.address;
128
+ } else {
129
+ userAddress = user.address === undefined ? user : user.address;
130
+ }
131
+ const roleHex = getRole(role);
132
+ if (!(await contract.hasRole(roleHex, userAddress))) {
133
+ await contract.grantRole(roleHex, userAddress, txOverrides);
134
+ log(`Role ${role} (${roleHex}) granted to ${userAddress}`);
135
+ } else {
136
+ log(`Role ${role} (${roleHex}) already granted to ${userAddress}`);
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Finds an event in the receipt
142
+ * @param {Interface} interface The interface of the contract that contains the requested event
143
+ * @param {TransactionReceipt} receipt Transaction receipt containing the events in the logs
144
+ * @param {String} eventName The name of the event we are interested in
145
+ * @returns {LogDescription}
146
+ */
147
+ function getTransactionEvent(interface, receipt, eventName) {
148
+ // for each log in the transaction receipt
149
+ for (const log of receipt.logs) {
150
+ let parsedLog;
151
+ try {
152
+ parsedLog = interface.parseLog(log);
153
+ } catch (error) {
154
+ continue;
155
+ }
156
+ if (parsedLog.name == eventName) {
157
+ return parsedLog;
158
+ }
159
+ }
160
+ return null; // not found
161
+ }
162
+
163
+ /**
164
+ * Builds AccessControl error message for comparison in tests
165
+ */
166
+ function accessControlMessage(address, component, role) {
167
+ const roleHash = component !== null ? getComponentRole(component, role) : getRole(role);
168
+
169
+ return `AccessControl: account ${address.toLowerCase()} is missing role ${roleHash}`;
170
+ }
171
+
172
+ /**
173
+ * Create a policy id by combining the riskmodule address and the internal id.
174
+ *
175
+ * Mimics the PolicyPool.newPolicy method of building the policy id.
176
+ */
177
+ function makePolicyId(rmAddress, internalId) {
178
+ return _BN(rmAddress).shl(96).add(internalId);
179
+ }
180
+
181
+ /**
182
+ * Create a packed quote message for later signing or hashing.
183
+ *
184
+ * Mimics the behaviour of the SignedQuoteRiskModule._newSignedPolicy method.
185
+ */
186
+ function makeQuoteMessage({ rmAddress, payout, premium, lossProb, expiration, policyData, validUntil }) {
187
+ return ethers.utils.solidityPack(
188
+ ["address", "uint256", "uint256", "uint256", "uint40", "bytes32", "uint40"],
189
+ [rmAddress, payout, premium, lossProb, expiration, policyData, validUntil]
190
+ );
191
+ }
192
+
193
+ /**
194
+ * Create a packed quote message for later signing or hashing.
195
+ *
196
+ * Mimics the behaviour of the SignedBucketRiskModule._newSignedPolicy method.
197
+ */
198
+ function makeBucketQuoteMessage({
199
+ rmAddress,
200
+ payout,
201
+ premium,
202
+ lossProb,
203
+ expiration,
204
+ policyData,
205
+ bucketId,
206
+ validUntil,
207
+ }) {
208
+ return ethers.utils.solidityPack(
209
+ ["address", "uint256", "uint256", "uint256", "uint40", "bytes32", "uint256", "uint40"],
210
+ [rmAddress, payout, premium, lossProb, expiration, policyData, bucketId, validUntil]
211
+ );
212
+ }
213
+
214
+ /**
215
+ * Creates and signs a quote message from its policy parameters.
216
+ *
217
+ * Mimics the behaviour of policy-quote-api.
218
+ */
219
+ async function makeSignedQuote(signer, policyParams, makeQuoteMessageFn = makeQuoteMessage) {
220
+ const quoteMessage = makeQuoteMessageFn(policyParams);
221
+ return ethers.utils.splitSignature(await signer.signMessage(ethers.utils.arrayify(quoteMessage)));
222
+ }
223
+
224
+ /**
225
+ * Build a default policy parameters object.
226
+ */
227
+ async function defaultPolicyParams(
228
+ { rmAddress, payout, premium, lossProb, expiration, policyData, validUntil },
229
+ _A = amountFunction(6)
230
+ ) {
231
+ const now = await helpers.time.latest();
232
+ return {
233
+ rmAddress,
234
+ payout: payout || _A(1000),
235
+ premium: premium || ethers.constants.MaxUint256,
236
+ lossProb: lossProb || _W(0.1),
237
+ expiration: expiration || now + 3600 * 24 * 30,
238
+ policyData: policyData || ethers.utils.hexlify(ethers.utils.randomBytes(32)),
239
+ validUntil: validUntil || now + 3600 * 24 * 30,
240
+ };
241
+ }
242
+
243
+ module.exports = {
244
+ _BN,
245
+ _E,
246
+ _R,
247
+ _W,
248
+ accessControlMessage,
249
+ amountFunction,
250
+ defaultPolicyParams,
251
+ getComponentRole,
252
+ getDefaultSigner,
253
+ getRole,
254
+ getStorageLayout,
255
+ getTransactionEvent,
256
+ grantComponentRole,
257
+ grantRole,
258
+ makeBucketQuoteMessage,
259
+ makePolicyId,
260
+ makeQuoteMessage,
261
+ makeSignedQuote,
262
+ RAY,
263
+ WAD,
264
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ensuro/core",
3
3
  "description": "Ensuro - Decentralized insurance protocol",
4
- "version": "2.4.0",
4
+ "version": "v2.6.0-beta1",
5
5
  "files": [
6
6
  "**/*.sol",
7
7
  "/build/contracts/*.json",
@@ -1,7 +1,5 @@
1
1
  const hre = require("hardhat");
2
- const { artifacts } = require("hardhat");
3
- const { findAll } = require("solidity-ast/utils");
4
- const { getStorageLayout } = require("../test/test-utils");
2
+ const { getStorageLayout } = require("../js/utils");
5
3
 
6
4
  /**
7
5
  * Script to print a contracts storage layout as a table.
@@ -9,11 +7,9 @@ const { getStorageLayout } = require("../test/test-utils");
9
7
  * Example usage: node scripts/storageLayout.js EToken
10
8
  */
11
9
 
12
- //
13
-
14
10
  async function main(contractSrc, contractName) {
15
11
  await hre.run("compile");
16
- const layout = await getStorageLayout(contractSrc, contractName);
12
+ const layout = await getStorageLayout(contractSrc, contractName, hre);
17
13
 
18
14
  const summary = layout.storage.map((item) => ({
19
15
  slot: parseInt(item.slot),
@@ -29,5 +25,6 @@ const [contractSrc, contractName] = [`contracts/${process.argv[2]}.sol`, process
29
25
 
30
26
  console.log(`Storage layout for ${contractSrc}:${contractName}`);
31
27
  main(contractSrc, contractName).then(() => {
28
+ // eslint-disable-next-line no-process-exit
32
29
  process.exit(0);
33
30
  });