@ensuro/core 2.9.0 → 2.9.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/js/deploy.js CHANGED
@@ -3,7 +3,7 @@ const fs = require("fs");
3
3
  const ethers = require("ethers");
4
4
  const { task, types } = require("hardhat/config");
5
5
  const { WhitelistStatus } = require("../js/enums");
6
- const { amountFunction, _W, grantRole, grantComponentRole, getDefaultSigner } = require("../js/utils");
6
+ const { amountFunction, _W, grantRole, grantComponentRole, getDefaultSigner } = require("@ensuro/utils/js/utils");
7
7
 
8
8
  const reservesOpts = {
9
9
  unsafeAllow: ["delegatecall"],
package/js/test-utils.js CHANGED
@@ -1,48 +1,10 @@
1
1
  const hre = require("hardhat");
2
- const { _W, grantRole, getTransactionEvent } = require("../js/utils");
3
- const { RiskModuleParameter } = require("../js/enums");
4
- const helpers = require("@nomicfoundation/hardhat-network-helpers");
2
+ const { _W, grantRole, getTransactionEvent } = require("@ensuro/utils/js/utils");
3
+ const { RiskModuleParameter } = require("./enums");
5
4
 
6
5
  const { ethers } = hre;
7
6
  const { ZeroAddress } = ethers;
8
7
 
9
- async function initCurrency(options, initial_targets, initial_balances) {
10
- const Currency = await ethers.getContractFactory(options.contractClass || "TestCurrency");
11
- let currency = await Currency.deploy(
12
- options.name || "Test Currency",
13
- options.symbol || "TEST",
14
- options.initial_supply,
15
- options.decimals || 18
16
- );
17
- initial_targets = initial_targets || [];
18
- await Promise.all(
19
- initial_targets.map(async function (user, 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]);
41
- })
42
- );
43
- return currency;
44
- }
45
-
46
8
  async function createRiskModule(
47
9
  pool,
48
10
  premiumsAccount,
@@ -258,52 +220,6 @@ async function makePolicy(pool, rm, cust, payout, premium, lossProb, expiration,
258
220
  return newPolicyEvt;
259
221
  }
260
222
 
261
- /**
262
- * Resets hardhat network to fork on the specified block and url
263
- */
264
- async function setupChain(block, alchemyUrlEnv = "ALCHEMY_URL") {
265
- const alchemyUrl = process.env[alchemyUrlEnv];
266
- if (alchemyUrl === undefined) throw new Error(`Define envvar ${alchemyUrlEnv} for this test`);
267
-
268
- if (block === undefined) throw new Error("Block can't be undefined use null for the current block");
269
- if (block === null) block = undefined;
270
- return hre.network.provider.request({
271
- method: "hardhat_reset",
272
- params: [
273
- {
274
- forking: {
275
- jsonRpcUrl: alchemyUrl,
276
- blockNumber: block,
277
- },
278
- },
279
- ],
280
- });
281
- }
282
-
283
- const skipForkTests = process.env.SKIP_FORK_TESTS === "true";
284
-
285
- /**
286
- * Chai test case wrapper for tests that require forking a live chain.
287
- *
288
- * It validates that the chain node URL is set, forks the chain at the specified block and adds the
289
- * block number to the test name.
290
- */
291
- const fork = {
292
- it: (name, blockNumber, test, alchemyUrlEnv = "ALCHEMY_URL") => {
293
- const fullName = `[FORK ${blockNumber}] ${name}`;
294
-
295
- // eslint-disable-next-line func-style
296
- const wrapped = async (...args) => {
297
- await setupChain(blockNumber, alchemyUrlEnv);
298
-
299
- return test(...args);
300
- };
301
-
302
- return (skipForkTests ? it.skip : it)(fullName, wrapped);
303
- },
304
- };
305
-
306
- if (process.env.ENABLE_HH_WARNINGS !== "yes" && hre.upgrades !== undefined) hre.upgrades.silenceWarnings();
307
223
 
308
224
  module.exports = {
309
225
  addEToken,
@@ -312,10 +228,5 @@ module.exports = {
312
228
  createRiskModule,
313
229
  deployPool,
314
230
  deployPremiumsAccount,
315
- fork,
316
- initCurrency,
317
- initForkCurrency,
318
231
  makePolicy,
319
- setupChain,
320
- skipForkTests,
321
232
  };
package/js/utils.js CHANGED
@@ -1,182 +1,7 @@
1
- const { findAll } = require("solidity-ast/utils");
2
1
  const ethers = require("ethers");
3
2
  const helpers = require("@nomicfoundation/hardhat-network-helpers");
4
- const { DAY, IMPLEMENTATION_SLOT } = require("./constants");
5
-
6
- const _E = ethers.parseEther;
7
- const WAD = 10n ** 18n; // 1e18
8
- const RAY = 10n ** 27n; // 1e27
9
-
10
- function getAddress(addressable) {
11
- return addressable.address || addressable.target || addressable;
12
- }
13
-
14
- async function getStorageLayout(hre, contractSrc, contractName) {
15
- const buildInfo = await hre.artifacts.getBuildInfo(`${contractSrc}:${contractName}`);
16
- if (buildInfo === undefined) throw new Error(`Contract ${contractSrc}:${contractName} not in artifacts`);
17
-
18
- const solcOutput = buildInfo.output;
19
-
20
- const storageLayouts = {};
21
-
22
- for (const def of findAll("ContractDefinition", solcOutput.sources[contractSrc].ast)) {
23
- storageLayouts[def.name] = solcOutput.contracts[contractSrc][def.name].storageLayout;
24
- }
25
-
26
- return storageLayouts[contractName];
27
- }
28
-
29
- /**
30
- * Creates a fixed-point conversion function for the desired number of decimals
31
- * @param decimals The number of decimals. Must be >= 6.
32
- * @returns The amount function created. The function can receive strings (recommended),
33
- * floats/doubles (not recommended) and integers.
34
- *
35
- * Floats will be rounded to 6 decimal before scaling.
36
- */
37
- function amountFunction(decimals) {
38
- return function (value) {
39
- if (value === undefined) return undefined;
40
-
41
- if (typeof value === "string" || value instanceof String) {
42
- return ethers.parseUnits(value, decimals);
43
- }
44
-
45
- if (!Number.isInteger(value)) {
46
- return BigInt(Math.round(value * 1e6).toString()) * BigInt(Math.pow(10, decimals - 6).toString());
47
- }
48
-
49
- return BigInt(value.toString()) * BigInt("10") ** BigInt(decimals.toString());
50
- };
51
- }
52
-
53
- /** Wad function */
54
- const _W = amountFunction(18);
55
-
56
- /** Ray function */
57
- const _R = amountFunction(27);
58
-
59
- /**
60
- * Returns a role identifier by computing the keccak of the role name.
61
- */
62
- function getRole(role) {
63
- if (role.startsWith("0x")) return role;
64
- return role === "DEFAULT_ADMIN_ROLE" ? ethers.ZeroHash : ethers.keccak256(ethers.toUtf8Bytes(role));
65
- }
66
-
67
- /**
68
- * Builds the component role identifier
69
- *
70
- * Mimics the behaviour of the AccessManager.getComponentRole method
71
- *
72
- * Component roles are roles created doing XOR between the component
73
- * address and the original role.
74
- *
75
- * Example:
76
- * getComponentRole("0xc6e7DF5E7b4f2A278906862b61205850344D4e7d", "ORACLE_ADMIN_ROLE")
77
- * // "0x05e01b185238b49f750d03d945e38a7f6c3be8b54de0ee42d481eb7814f0d3a8"
78
- */
79
- function getComponentRole(componentAddress, role) {
80
- if (!role.startsWith("0x")) role = getRole(role);
81
-
82
- // 32 byte array
83
- const bytesRole = ethers.getBytes(role);
84
-
85
- // 20 byte array
86
- const bytesAddress = ethers.getBytes(componentAddress);
87
-
88
- // xor each byte, padding bytesAddress with zeros at the end
89
- // eslint-disable-next-line no-bitwise
90
- return ethers.hexlify(bytesRole.map((elem, idx) => elem ^ (bytesAddress[idx] || 0)));
91
- }
92
-
93
- async function getDefaultSigner(hre) {
94
- const signers = await hre.ethers.getSigners();
95
- return signers[0];
96
- }
97
-
98
- /**
99
- * Grant a component role to a user.
100
- */
101
- // eslint-disable-next-line no-empty-function
102
- async function grantComponentRole(hre, contract, component, role, user, txOverrides = {}, log = () => {}) {
103
- let userAddress;
104
- if (user === undefined) {
105
- user = await getDefaultSigner(hre);
106
- userAddress = user.address;
107
- } else {
108
- userAddress = user.address === undefined ? user : user.address;
109
- }
110
- const roleHex = getRole(role);
111
- const componentAddress = component.address || component;
112
- const componentRole = await contract.getComponentRole(componentAddress, roleHex);
113
- if (!(await contract.hasRole(componentRole, userAddress))) {
114
- await contract.grantComponentRole(componentAddress, roleHex, userAddress, txOverrides);
115
- log(`Role ${role} (${roleHex}) Component ${componentAddress} granted to ${userAddress}`);
116
- } else {
117
- log(`Role ${role} (${roleHex}) Component ${componentAddress} already granted to ${userAddress}`);
118
- }
119
- }
120
-
121
- /**
122
- * Grant a role to a user
123
- */
124
- // eslint-disable-next-line no-empty-function
125
- async function grantRole(hre, contract, role, user, txOverrides = {}, log = () => {}) {
126
- let userAddress;
127
- if (user === undefined) {
128
- user = await getDefaultSigner(hre);
129
- userAddress = user.address;
130
- } else {
131
- userAddress = user.address === undefined ? user : user.address;
132
- }
133
- const roleHex = getRole(role);
134
- if (!(await contract.hasRole(roleHex, userAddress))) {
135
- await contract.grantRole(roleHex, userAddress, txOverrides);
136
- log(`Role ${role} (${roleHex}) granted to ${userAddress}`);
137
- } else {
138
- log(`Role ${role} (${roleHex}) already granted to ${userAddress}`);
139
- }
140
- }
141
-
142
- /**
143
- * Finds an event in the receipt
144
- * @param {Interface} interface The interface of the contract that contains the requested event
145
- * @param {TransactionReceipt} receipt Transaction receipt containing the events in the logs
146
- * @param {String} eventName The name of the event we are interested in
147
- * @param {Boolean} firstOnly If false, returns all the events matching the name
148
- * @param {String} contractAddress If not null, if returns only those events generated by the specified contract
149
- * @returns {LogDescription}
150
- */
151
- function getTransactionEvent(interface, receipt, eventName, firstOnly = true, contractAddress = null) {
152
- const ret = [];
153
- // for each log in the transaction receipt
154
- for (const log of receipt.logs) {
155
- let parsedLog;
156
- if (contractAddress !== null && contractAddress !== log.address) continue;
157
- try {
158
- parsedLog = interface.parseLog(log);
159
- } catch (error) {
160
- continue;
161
- }
162
- if (parsedLog?.name == eventName) {
163
- if (firstOnly) return parsedLog;
164
- ret.push(parsedLog);
165
- }
166
- }
167
- return firstOnly ? null : ret;
168
- }
169
-
170
- /**
171
- * Builds AccessControl error message for comparison in tests
172
- */
173
- function accessControlMessage(user, component, role) {
174
- const userAddr = getAddress(user);
175
- const compAddr = component !== null ? getAddress(component) : component;
176
- const roleHash = component !== null ? getComponentRole(compAddr, role) : getRole(role);
177
-
178
- return `AccessControl: account ${userAddr.toLowerCase()} is missing role ${roleHash}`;
179
- }
3
+ const { DAY } = require("@ensuro/utils/js/constants");
4
+ const { amountFunction, getAddress, _W } = require("@ensuro/utils/js/utils");
180
5
 
181
6
  /**
182
7
  * Create a policy id by combining the riskmodule address and the internal id.
@@ -339,47 +164,16 @@ function defaultBucketParams({ moc, jrCollRatio, collRatio, ensuroPpFee, ensuroC
339
164
  };
340
165
  }
341
166
 
342
- async function readImplementationAddress(hre, contractAddress) {
343
- const implStorage = await hre.ethers.provider.getStorageAt(contractAddress, IMPLEMENTATION_SLOT);
344
- return ethers.utils.getAddress(ethers.utils.hexDataSlice(implStorage, 12));
345
- }
346
-
347
- /**
348
- * Converts a string value to uint256(keccak(value))
349
- * @param {string} value
350
- * @returns {ethers.BigNumber}
351
- */
352
- function uintKeccak(value) {
353
- return BigInt(ethers.keccak256(ethers.toUtf8Bytes(value)));
354
- }
355
-
356
167
  module.exports = {
357
- _E,
358
- _R,
359
- _W,
360
- accessControlMessage,
361
- amountFunction,
362
168
  defaultPolicyParams,
363
169
  defaultPolicyParamsWithBucket,
364
170
  defaultPolicyParamsWithParams,
365
171
  defaultBucketParams,
366
- getAddress,
367
- getComponentRole,
368
- getDefaultSigner,
369
- getRole,
370
- getStorageLayout,
371
- getTransactionEvent,
372
- grantComponentRole,
373
- grantRole,
374
172
  makeBucketQuoteMessage,
375
173
  makeFullQuoteMessage,
376
174
  paramsAsUint256,
377
175
  makePolicyId,
378
176
  makeQuoteMessage,
379
177
  makeSignedQuote,
380
- RAY,
381
- readImplementationAddress,
382
178
  recoverAddress,
383
- uintKeccak,
384
- WAD,
385
179
  };
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.9.0",
4
+ "version": "2.9.1",
5
5
  "files": [
6
6
  "**/*.sol",
7
7
  "/build",