@ensuro/core 2.0.0-beta1 → 2.0.0-beta11

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 (84) hide show
  1. package/README.md +36 -14
  2. package/build/contracts/AccessManager.sol/AccessManager.json +564 -0
  3. package/build/contracts/ERC4626AssetManager.sol/ERC4626AssetManager.json +238 -0
  4. package/build/contracts/EToken.sol/EToken.json +147 -46
  5. package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +23 -4
  6. package/build/contracts/LiquidityThresholdAssetManager.sol/LiquidityThresholdAssetManager.json +222 -0
  7. package/build/contracts/Policy.sol/Policy.json +2 -2
  8. package/build/contracts/PolicyPool.sol/PolicyPool.json +437 -61
  9. package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +21 -2
  10. package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +142 -16
  11. package/build/contracts/Reserve.sol/Reserve.json +85 -8
  12. package/build/contracts/RiskModule.sol/RiskModule.json +21 -2
  13. package/build/contracts/SignedQuoteRiskModule.sol/SignedQuoteRiskModule.json +979 -0
  14. package/build/contracts/TimeScaled.sol/TimeScaled.json +3 -17
  15. package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +24 -5
  16. package/build/contracts/{WadRayMath.sol → dependencies/WadRayMath.sol}/WadRayMath.json +3 -3
  17. package/build/contracts/interfaces/{IPolicyPoolConfig.sol/IPolicyPoolConfig.json → IAccessManager.sol/IAccessManager.json} +77 -59
  18. package/build/contracts/interfaces/IAssetManager.sol/IAssetManager.json +128 -0
  19. package/build/contracts/interfaces/IEToken.sol/IEToken.json +13 -0
  20. package/build/contracts/interfaces/IPolicyPool.sol/IPolicyPool.json +40 -16
  21. package/build/contracts/interfaces/IPolicyPoolComponent.sol/IPolicyPoolComponent.json +19 -0
  22. package/build/contracts/interfaces/IPremiumsAccount.sol/IPremiumsAccount.json +13 -0
  23. package/build/contracts/mocks/FixedRateVault.sol/FixedRateVault.json +736 -0
  24. package/build/contracts/mocks/ForwardProxy.sol/ForwardProxy.json +2 -2
  25. package/build/contracts/mocks/InterfaceIdCalculator.sol/InterfaceIdCalculator.json +180 -0
  26. package/build/contracts/mocks/PolicyHolderMock.sol/PolicyHolderMock.json +28 -2
  27. package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +21 -2
  28. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +118 -19
  29. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +6 -6
  30. package/build/contracts/mocks/RiskModuleMock.sol/RiskModuleMock.json +783 -0
  31. package/build/contracts/mocks/TestCurrency.sol/TestCurrency.json +2 -2
  32. package/build/contracts/mocks/TestNFT.sol/TestNFT.json +2 -2
  33. package/contracts/AccessManager.sol +132 -0
  34. package/contracts/ERC4626AssetManager.sol +55 -0
  35. package/contracts/EToken.sol +208 -102
  36. package/contracts/LPManualWhitelist.sol +19 -3
  37. package/contracts/LiquidityThresholdAssetManager.sol +175 -0
  38. package/contracts/Policy.sol +5 -3
  39. package/contracts/PolicyPool.sol +381 -116
  40. package/contracts/PolicyPoolComponent.sol +61 -44
  41. package/contracts/PremiumsAccount.sol +324 -86
  42. package/contracts/Reserve.sol +199 -4
  43. package/contracts/RiskModule.sol +62 -31
  44. package/contracts/SignedQuoteRiskModule.sol +248 -0
  45. package/contracts/TimeScaled.sol +19 -15
  46. package/contracts/TrustfulRiskModule.sol +69 -2
  47. package/contracts/dependencies/WadRayMath.sol +126 -0
  48. package/contracts/interfaces/IAccessManager.sol +148 -0
  49. package/contracts/interfaces/IAssetManager.sol +89 -0
  50. package/contracts/interfaces/IEToken.sol +25 -2
  51. package/contracts/interfaces/ILPWhitelist.sol +17 -0
  52. package/contracts/interfaces/IPolicyPool.sol +21 -14
  53. package/contracts/interfaces/IPolicyPoolComponent.sol +5 -1
  54. package/contracts/interfaces/IPremiumsAccount.sol +5 -0
  55. package/contracts/interfaces/IRiskModule.sol +67 -4
  56. package/contracts/mocks/FixedRateVault.sol +85 -0
  57. package/contracts/mocks/InterfaceIdCalculator.sol +32 -0
  58. package/contracts/mocks/PolicyHolderMock.sol +21 -0
  59. package/contracts/mocks/PolicyPoolComponentMock.sol +10 -0
  60. package/contracts/mocks/PolicyPoolMock.sol +41 -15
  61. package/contracts/mocks/RiskModuleMock.sol +75 -0
  62. package/js/deploy.js +704 -0
  63. package/js/test-utils.js +339 -159
  64. package/package.json +1 -1
  65. package/build/contracts/FlightDelayRiskModule.sol/FlightDelayRiskModule.json +0 -890
  66. package/build/contracts/PolicyNFT.sol/PolicyNFT.json +0 -583
  67. package/build/contracts/PolicyPoolConfig.sol/PolicyPoolConfig.json +0 -691
  68. package/build/contracts/dependencies/ChainlinkClientUpgradeable.sol/ChainlinkClientUpgradeable.json +0 -63
  69. package/build/contracts/interfaces/IPolicyNFT.sol/IPolicyNFT.json +0 -321
  70. package/build/contracts/mocks/LinkTokenMock.sol/LinkTokenMock.json +0 -370
  71. package/build/contracts/mocks/TestCurrencyUUPS.sol/TestCurrencyUUPS.json +0 -353
  72. package/build/contracts/upgraded/IPolicyNFTv1.sol/IPolicyNFTv1.json +0 -322
  73. package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1.json +0 -584
  74. package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1_Upgrade.json +0 -615
  75. package/contracts/FlightDelayRiskModule.sol +0 -217
  76. package/contracts/PolicyNFT.sol +0 -96
  77. package/contracts/PolicyPoolConfig.sol +0 -204
  78. package/contracts/WadRayMath.sol +0 -135
  79. package/contracts/dependencies/ChainlinkClientUpgradeable.sol +0 -371
  80. package/contracts/interfaces/IPolicyNFT.sol +0 -15
  81. package/contracts/interfaces/IPolicyPoolConfig.sol +0 -96
  82. package/contracts/mocks/LinkTokenMock.sol +0 -30
  83. package/contracts/upgraded/IPolicyNFTv1.sol +0 -15
  84. package/contracts/upgraded/PolicyNFTv1.sol +0 -126
package/js/test-utils.js CHANGED
@@ -1,61 +1,87 @@
1
1
  const { expect } = require("chai");
2
+ const hre = require("hardhat");
2
3
  const { BigNumber } = require("ethers");
3
- const {LogDescription} = require("ethers/lib/utils");
4
+ const { LogDescription } = require("ethers/lib/utils");
5
+ const { findAll } = require("solidity-ast/utils");
6
+
4
7
  exports.WEEK = 3600 * 24 * 7;
5
8
  exports.DAY = 3600 * 24;
6
9
 
7
- exports.initCurrency = async function(options, initial_targets, initial_balances) {
8
- const Currency = await ethers.getContractFactory("TestCurrency");
10
+ exports.initCurrency = async function (options, initial_targets, initial_balances) {
11
+ const Currency = await hre.ethers.getContractFactory("TestCurrency");
9
12
  let currency = await Currency.deploy(
10
13
  options.name || "Test Currency",
11
14
  options.symbol || "TEST",
12
15
  options.initial_supply,
13
- options.decimals || 18,
16
+ options.decimals || 18
14
17
  );
15
18
  initial_targets = initial_targets || [];
16
- await Promise.all(initial_targets.map(async function (user, index) {
17
- await currency.transfer(user.address, initial_balances[index]);
18
- }));
19
+ await Promise.all(
20
+ initial_targets.map(async function (user, index) {
21
+ await currency.transfer(user.address, initial_balances[index]);
22
+ })
23
+ );
19
24
  return currency;
20
- }
25
+ };
21
26
 
22
- exports.approve_multiple = async function(currency, spender, sources, amounts) {
23
- return Promise.all(sources.map(async function (source, index) {
24
- await currency.connect(source).approve(spender.address, amounts[index]);
25
- }));
26
- }
27
+ exports.approve_multiple = async function (currency, spender, sources, amounts) {
28
+ return Promise.all(
29
+ sources.map(async function (source, index) {
30
+ await currency.connect(source).approve(spender.address, amounts[index]);
31
+ })
32
+ );
33
+ };
27
34
 
28
- exports.check_balances = async function(currency, users, amounts) {
29
- return Promise.all(users.map(async function (user, index) {
30
- expect(await currency.balanceOf(user.address)).to.equal(amounts[index]);
31
- }));
32
- }
35
+ exports.check_balances = async function (currency, users, amounts) {
36
+ return Promise.all(
37
+ users.map(async function (user, index) {
38
+ expect(await currency.balanceOf(user.address)).to.equal(amounts[index]);
39
+ })
40
+ );
41
+ };
33
42
 
34
- exports.now = function() {
43
+ exports.now = function () {
35
44
  return Math.floor(new Date().getTime() / 1000);
36
- }
37
-
38
- exports.addRiskModule = async function(pool, premiumsAccount, contractFactory, {
39
- rmName, scrPercentage, scrInterestRate, ensuroFee, maxScrPerPolicy,
40
- scrLimit, moc, wallet, extraArgs, extraConstructorArgs
41
- }) {
45
+ };
46
+
47
+ const createRiskModule = async function (
48
+ pool,
49
+ premiumsAccount,
50
+ contractFactory,
51
+ {
52
+ rmName,
53
+ scrPercentage,
54
+ scrInterestRate,
55
+ ensuroFee,
56
+ maxScrPerPolicy,
57
+ scrLimit,
58
+ moc,
59
+ wallet,
60
+ extraArgs,
61
+ extraConstructorArgs,
62
+ }
63
+ ) {
42
64
  extraArgs = extraArgs || [];
43
65
  extraConstructorArgs = extraConstructorArgs || [];
44
66
  const _A = pool._A || _W;
45
- const rm = await hre.upgrades.deployProxy(contractFactory, [
46
- rmName || "RiskModule",
47
- _W(scrPercentage) || _W(1),
48
- _W(ensuroFee) || _W(0),
49
- _W(scrInterestRate) || _W(0.1),
50
- _A(maxScrPerPolicy) || _A(1000),
51
- _A(scrLimit) || _A(1000000),
52
- wallet || "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", // Random address
53
- ...extraArgs
54
- ], {
55
- kind: 'uups',
56
- unsafeAllow: ["delegatecall"],
57
- constructorArgs: [pool.address, premiumsAccount.address, ...extraConstructorArgs]
58
- });
67
+ const rm = await hre.upgrades.deployProxy(
68
+ contractFactory,
69
+ [
70
+ rmName || "RiskModule",
71
+ _W(scrPercentage) || _W(1),
72
+ _W(ensuroFee) || _W(0),
73
+ _W(scrInterestRate) || _W("0.1"),
74
+ _A(maxScrPerPolicy) || _A(1000),
75
+ _A(scrLimit) || _A(1000000),
76
+ wallet || "0xdD2FD4581271e230360230F9337D5c0430Bf44C0", // Random address
77
+ ...extraArgs,
78
+ ],
79
+ {
80
+ kind: "uups",
81
+ unsafeAllow: ["delegatecall"],
82
+ constructorArgs: [pool.address, premiumsAccount.address, ...extraConstructorArgs],
83
+ }
84
+ );
59
85
 
60
86
  await rm.deployed();
61
87
 
@@ -63,66 +89,115 @@ exports.addRiskModule = async function(pool, premiumsAccount, contractFactory, {
63
89
  moc = _W(moc);
64
90
  await rm.setParam(0, moc);
65
91
  }
66
- const policyPoolConfig = await hre.ethers.getContractAt("PolicyPoolConfig", await pool.config());
67
- await policyPoolConfig.addRiskModule(rm.address);
68
92
  return rm;
69
- }
93
+ };
94
+
95
+ exports.createRiskModule = createRiskModule;
96
+
97
+ exports.addRiskModule = async function (
98
+ pool,
99
+ premiumsAccount,
100
+ contractFactory,
101
+ {
102
+ rmName,
103
+ scrPercentage,
104
+ scrInterestRate,
105
+ ensuroFee,
106
+ maxScrPerPolicy,
107
+ scrLimit,
108
+ moc,
109
+ wallet,
110
+ extraArgs,
111
+ extraConstructorArgs,
112
+ }
113
+ ) {
114
+ const rm = await createRiskModule(pool, premiumsAccount, contractFactory, {
115
+ rmName,
116
+ scrPercentage,
117
+ scrInterestRate,
118
+ ensuroFee,
119
+ maxScrPerPolicy,
120
+ scrLimit,
121
+ moc,
122
+ wallet,
123
+ extraArgs,
124
+ extraConstructorArgs,
125
+ });
126
+
127
+ await pool.addComponent(rm.address, 2);
128
+ return rm;
129
+ };
70
130
 
71
- exports.addEToken = async function(pool, {
72
- etkName, etkSymbol, maxUtilizationRate,
73
- poolLoanInterestRate, extraArgs, extraConstructorArgs
74
- }) {
75
- const EToken = await ethers.getContractFactory("EToken");
131
+ const createEToken = async function (
132
+ pool,
133
+ { etkName, etkSymbol, maxUtilizationRate, poolLoanInterestRate, extraArgs, extraConstructorArgs }
134
+ ) {
135
+ const EToken = await hre.ethers.getContractFactory("EToken");
76
136
  extraArgs = extraArgs || [];
77
137
  extraConstructorArgs = extraConstructorArgs || [];
78
- const etk = await hre.upgrades.deployProxy(EToken, [
79
- etkName || "EToken",
80
- etkSymbol || "eUSD1YEAR",
81
- _W(maxUtilizationRate) || _W(1),
82
- _W(poolLoanInterestRate) || _W("0.05"),
83
- ...extraArgs
84
- ], {
85
- kind: 'uups',
86
- unsafeAllow: ["delegatecall"],
87
- constructorArgs: [pool.address, ...extraConstructorArgs]
88
- });
138
+ const etk = await hre.upgrades.deployProxy(
139
+ EToken,
140
+ [
141
+ etkName === undefined ? "EToken" : etkName,
142
+ etkSymbol === undefined ? "eUSD1YEAR" : etkSymbol,
143
+ _W(maxUtilizationRate) || _W(1),
144
+ _W(poolLoanInterestRate) || _W("0.05"),
145
+ ...extraArgs,
146
+ ],
147
+ {
148
+ kind: "uups",
149
+ unsafeAllow: ["delegatecall"],
150
+ constructorArgs: [pool.address, ...extraConstructorArgs],
151
+ }
152
+ );
89
153
 
90
154
  await etk.deployed();
91
- await pool.addEToken(etk.address);
92
155
  return etk;
93
- }
156
+ };
157
+
158
+ exports.createEToken = createEToken;
159
+
160
+ exports.addEToken = async function (
161
+ pool,
162
+ { etkName, etkSymbol, maxUtilizationRate, poolLoanInterestRate, extraArgs, extraConstructorArgs }
163
+ ) {
164
+ const etk = await createEToken(pool, {
165
+ etkName,
166
+ etkSymbol,
167
+ maxUtilizationRate,
168
+ poolLoanInterestRate,
169
+ extraArgs,
170
+ extraConstructorArgs,
171
+ });
172
+ await pool.addComponent(etk.address, 1);
173
+ return etk;
174
+ };
94
175
 
95
- exports.expected_change = async function(protocol_attribute, initial, change) {
176
+ exports.expected_change = async function (protocol_attribute, initial, change) {
96
177
  change = BigNumber.from(change);
97
178
  let actual_value = await protocol_attribute();
98
179
  expect(actual_value.sub(initial)).to.equal(change);
99
180
  return actual_value;
100
- }
181
+ };
101
182
 
102
- exports.impersonate = async function(address, setBalanceTo) {
103
- const ok = await hre.network.provider.request(
104
- {method: "hardhat_impersonateAccount", params: [address]}
105
- );
106
- if (!ok)
107
- throw "Error impersonatting " + address;
183
+ exports.impersonate = async function (address, setBalanceTo) {
184
+ const ok = await hre.network.provider.request({ method: "hardhat_impersonateAccount", params: [address] });
185
+ if (!ok) throw "Error impersonatting " + address;
108
186
 
109
187
  if (setBalanceTo !== undefined)
110
- await hre.network.provider.request(
111
- {method: "hardhat_setBalance", params: [address, setBalanceTo.toHexString()]}
112
- );
113
-
114
- return await ethers.getSigner(address);
115
- }
188
+ await hre.network.provider.request({ method: "hardhat_setBalance", params: [address, setBalanceTo.toHexString()] });
116
189
 
190
+ return await hre.ethers.getSigner(address);
191
+ };
117
192
 
118
193
  /**
119
- * Finds an event in the receipt
120
- * @param {Interface} interface The interface of the contract that contains the requested event
121
- * @param {TransactionReceipt} receipt Transaction receipt containing the events in the logs
122
- * @param {String} eventName The name of the event we are interested in
123
- * @returns {LogDescription}
124
- */
125
- exports.getTransactionEvent = function(interface, receipt, eventName) {
194
+ * Finds an event in the receipt
195
+ * @param {Interface} interface The interface of the contract that contains the requested event
196
+ * @param {TransactionReceipt} receipt Transaction receipt containing the events in the logs
197
+ * @param {String} eventName The name of the event we are interested in
198
+ * @returns {LogDescription}
199
+ */
200
+ const getTransactionEvent = function (interface, receipt, eventName) {
126
201
  // for each log in the transaction receipt
127
202
  for (const log of receipt.events) {
128
203
  let parsedLog;
@@ -135,68 +210,88 @@ exports.getTransactionEvent = function(interface, receipt, eventName) {
135
210
  return parsedLog;
136
211
  }
137
212
  }
138
- return null; // not found
139
- }
213
+ return null; // not found
214
+ };
140
215
 
141
- exports.deployPool = async function(hre, options) {
142
- const PolicyPool = await ethers.getContractFactory("PolicyPool");
143
- const PolicyPoolConfig = await ethers.getContractFactory("PolicyPoolConfig");
144
- const PolicyNFT = await ethers.getContractFactory("PolicyNFT");
216
+ exports.getTransactionEvent = getTransactionEvent;
145
217
 
146
- // Deploy PolicyNFT
147
- const policyNFT = await hre.upgrades.deployProxy(
148
- PolicyNFT,
218
+ const randomAddress = "0x89cDb70Fee571251a66E34caa1673cE40f7549Dc";
219
+
220
+ /**
221
+ * Deploys de PolicyPool contract and AccessManager
222
+ *
223
+ * By default deployes de PolicyPool and AccessManager and grants LEVEL 1, 2, 3 permissions
224
+ *
225
+ * options:
226
+ * - .currency: mandatory, the address of the currency used in the PolicyPool
227
+ * - .access: if specified, doesn't create an AccessManager, uses this address.toLowerCase
228
+ * - .nftName: default "Policy NFT"
229
+ * - .nftSymbol: default "EPOL"
230
+ * - .treasuryAddress: default randomAddress
231
+ * - .grantRoles: default []. List of additional roles to grant
232
+ * - .dontGrantL123Roles: if specified, doesn't grants LEVEL1, 2 and 3 roles.
233
+ */
234
+ exports.deployPool = async function (hre, options) {
235
+ const PolicyPool = await hre.ethers.getContractFactory("PolicyPool");
236
+ const AccessManager = await hre.ethers.getContractFactory("AccessManager");
237
+
238
+ let accessManager;
239
+
240
+ if (options.access === undefined) {
241
+ // Deploy AccessManager
242
+ accessManager = await hre.upgrades.deployProxy(AccessManager, [], { kind: "uups" });
243
+ await accessManager.deployed();
244
+ } else {
245
+ accessManager = await hre.ethers.getContractAt("AccessManager", options.access);
246
+ }
247
+
248
+ const policyPool = await hre.upgrades.deployProxy(
249
+ PolicyPool,
149
250
  [
150
- options.nftName || "Policy NFT",
151
- options.nftSymbol || "EPOL",
152
- options.policyPoolDetAddress || ethers.constants.AddressZero
251
+ options.nftName === undefined ? "Policy NFT" : options.nftName,
252
+ options.nftSymbol === undefined ? "EPOL" : options.nftSymbol,
253
+ options.treasuryAddress || randomAddress,
153
254
  ],
154
- {kind: 'uups'}
255
+ {
256
+ constructorArgs: [accessManager.address, options.currency],
257
+ kind: "uups",
258
+ unsafeAllow: ["delegatecall"],
259
+ }
155
260
  );
156
- await policyNFT.deployed();
157
-
158
- // Deploy PolicyPoolConfig
159
- const policyPoolConfig = await hre.upgrades.deployProxy(PolicyPoolConfig, [
160
- options.policyPoolDetAddress || ethers.constants.AddressZero,
161
- options.treasuryAddress || ethers.constants.AddressZero
162
- ], {kind: 'uups'});
163
-
164
- await policyPoolConfig.deployed();
165
-
166
- const policyPool = await hre.upgrades.deployProxy(PolicyPool, [], {
167
- constructorArgs: [policyPoolConfig.address, policyNFT.address, options.currency],
168
- kind: 'uups',
169
- unsafeAllow: ["delegatecall"],
170
- });
171
261
 
172
262
  await policyPool.deployed();
173
263
 
174
- for (const role of (options.grantRoles || [])) {
175
- await grantRole(hre, policyPoolConfig, role);
264
+ for (const role of options.grantRoles || []) {
265
+ await grantRole(hre, accessManager, role);
266
+ }
267
+
268
+ if (options.dontGrantL123Roles === undefined) {
269
+ await grantRole(hre, accessManager, "LEVEL1_ROLE");
270
+ await grantRole(hre, accessManager, "LEVEL2_ROLE");
271
+ await grantRole(hre, accessManager, "LEVEL3_ROLE");
176
272
  }
177
273
 
178
- await grantRole(hre, policyPoolConfig, "LEVEL1_ROLE");
179
- await grantRole(hre, policyPoolConfig, "LEVEL2_ROLE");
180
- await grantRole(hre, policyPoolConfig, "LEVEL3_ROLE");
181
274
  return policyPool;
182
- }
275
+ };
183
276
 
184
- exports.deployPremiumsAccount = async function (hre, pool, options) {
185
- const PremiumsAccount = await ethers.getContractFactory("PremiumsAccount");
277
+ exports.deployPremiumsAccount = async function (hre, pool, options, addToPool = true) {
278
+ const PremiumsAccount = await hre.ethers.getContractFactory("PremiumsAccount");
186
279
  const premiumsAccount = await hre.upgrades.deployProxy(PremiumsAccount, [], {
187
280
  constructorArgs: [
188
281
  pool.address,
189
- options.jrEtkAddr || ethers.constants.AddressZero,
190
- options.srEtkAddr || ethers.constants.AddressZero,
282
+ options.jrEtkAddr || hre.ethers.constants.AddressZero,
283
+ options.srEtkAddr || hre.ethers.constants.AddressZero,
191
284
  ],
192
- kind: 'uups',
285
+ kind: "uups",
193
286
  unsafeAllow: ["delegatecall"],
194
287
  });
195
288
 
196
289
  await premiumsAccount.deployed();
197
- await pool.addPremiumsAccount(premiumsAccount.address);
290
+
291
+ if (addToPool) await pool.addComponent(premiumsAccount.address, 3);
292
+
198
293
  return premiumsAccount;
199
- }
294
+ };
200
295
 
201
296
  async function _getDefaultSigner(hre) {
202
297
  const signers = await hre.ethers.getSigners();
@@ -211,68 +306,153 @@ async function grantRole(hre, contract, role, user) {
211
306
  } else {
212
307
  userAddress = user;
213
308
  }
214
- const roleHex = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(role));
215
- if (!await contract.hasRole(roleHex, userAddress)) {
216
- await contract.grantRole(roleHex, userAddress);
309
+ if (!(await contract.hasRole(getRole(role), userAddress))) {
310
+ await contract.grantRole(getRole(role), userAddress);
217
311
  }
218
312
  }
219
313
 
220
314
  exports.grantRole = grantRole;
221
315
 
222
- async function grantComponentRole(hre, contract, component, role, user) {
316
+ async function grantComponentRole(hre, accessManager, component, role, user) {
223
317
  let userAddress;
224
318
  if (user === undefined) {
225
319
  user = await _getDefaultSigner(hre);
226
320
  userAddress = user.address;
227
321
  } else {
228
- userAddress = user;
322
+ userAddress = user.address === undefined ? user : user.address;
229
323
  }
230
- const roleHex = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(role));
231
- const componentRole = await contract.getComponentRole(component.address, roleHex);
232
- if (!await contract.hasRole(componentRole, userAddress)) {
233
- await contract.grantComponentRole(component.address, roleHex, userAddress);
324
+ const componentRole = getComponentRole(component.address, getRole(role));
325
+ if (!(await accessManager.hasRole(componentRole, userAddress))) {
326
+ await accessManager.grantComponentRole(component.address, getRole(role), userAddress);
234
327
  }
235
328
  }
236
329
 
237
330
  exports.grantComponentRole = grantComponentRole;
238
331
 
239
- exports._E = ethers.utils.parseEther;
240
-
241
- const _BN = ethers.BigNumber.from;
242
- const WAD = _BN(1e10).mul(_BN(1e8)); // 1e10*1e8=1e18
243
- const RAY = WAD.mul(_BN(1e9)); // 1e18*1e9=1e27
332
+ const _E = hre.ethers.utils.parseEther;
333
+ exports._E = _E;
244
334
 
335
+ const _BN = hre.ethers.BigNumber.from;
245
336
  exports._BN = _BN;
246
337
 
247
- const _W = function(value) {
248
- if (value === undefined)
249
- return undefined;
250
- if (!Number.isInteger(value))
251
- return _BN(Math.round(value * 1e9)).mul(_BN(1e9));
252
- return _BN(value).mul(WAD);
338
+ const WAD = _BN(10).pow(18); // 1e18
339
+ exports.WAD = WAD;
340
+
341
+ const RAY = _BN(10).pow(27); // 1e27
342
+ exports.RAY = RAY;
343
+
344
+ /**
345
+ * Creates a fixed-point conversion function for the desired number of decimals
346
+ * @param decimals The number of decimals. Must be >= 6.
347
+ * @returns The amount function created. The function can receive strings (recommended),
348
+ * floats/doubles (not recommended) and integers.
349
+ *
350
+ * Floats will be rounded to 6 decimal before scaling.
351
+ */
352
+ function amountFunction(decimals) {
353
+ return function (value) {
354
+ if (value === undefined) return undefined;
355
+
356
+ if (typeof value === "string" || value instanceof String) {
357
+ return hre.ethers.utils.parseUnits(value, decimals);
358
+ }
359
+
360
+ if (!Number.isInteger(value)) {
361
+ return _BN(Math.round(value * 1e6)).mul(_BN(Math.pow(10, decimals - 6)));
362
+ }
363
+
364
+ return _BN(value).mul(_BN(10).pow(decimals));
365
+ };
253
366
  }
367
+ exports.amountFunction = amountFunction;
254
368
 
369
+ const _W = amountFunction(18);
255
370
  exports._W = _W;
256
371
 
257
- const _R = function(value) {
258
- if (value === undefined)
259
- return undefined;
260
- if (!Number.isInteger(value))
261
- return _BN(Math.round(value * 1e9)).mul(WAD);
262
- return _BN(value).mul(RAY);
372
+ const _R = amountFunction(27);
373
+ exports._R = _R;
374
+
375
+ /**
376
+ * Builds the component role identifier
377
+ *
378
+ * Mimics the behaviour of the PolicyPoolConfig.getComponentRole method
379
+ *
380
+ * Component roles are roles created doing XOR between the component
381
+ * address and the original role.
382
+ *
383
+ * Example:
384
+ * getComponentRole("0xc6e7DF5E7b4f2A278906862b61205850344D4e7d", "ORACLE_ADMIN_ROLE")
385
+ * // "0x05e01b185238b49f750d03d945e38a7f6c3be8b54de0ee42d481eb7814f0d3a8"
386
+ */
387
+ function getComponentRole(componentAddress, roleName) {
388
+ // 32 byte array
389
+ const bytesRole = hre.ethers.utils.arrayify(getRole(roleName));
390
+
391
+ // 20 byte array
392
+ const bytesAddress = hre.ethers.utils.arrayify(componentAddress);
393
+
394
+ // xor each byte, padding bytesAddress with zeros at the end
395
+ return hre.ethers.utils.hexlify(bytesRole.map((elem, idx) => elem ^ (bytesAddress[idx] || 0)));
263
396
  }
264
397
 
265
- exports._R = _R;
398
+ exports.getComponentRole = getComponentRole;
266
399
 
267
- exports.amountFunction = function (decimals) {
268
- // Decimals must be at least 6
269
- return function (value) {
270
- if (value === undefined)
271
- return undefined;
272
- if (typeof value === 'string' || value instanceof String) {
273
- return _BN(value).mul(_BN(Math.pow(10, decimals)));
274
- } else {
275
- return _BN(Math.round(value * 1e6)).mul(_BN(Math.pow(10, decimals - 6)));
276
- }
400
+ /*
401
+ Builds AccessControl error message for comparison in tests
402
+ */
403
+ function accessControlMessage(address, component, role) {
404
+ const roleHash = component !== null ? getComponentRole(component, role) : getRole(role);
405
+
406
+ return `AccessControl: account ${address.toLowerCase()} is missing role ${roleHash}`;
407
+ }
408
+
409
+ exports.accessControlMessage = accessControlMessage;
410
+
411
+ function makePolicyId(rm, internalId) {
412
+ return hre.ethers.BigNumber.from(rm.address).shl(96).add(internalId);
413
+ }
414
+
415
+ exports.makePolicyId = makePolicyId;
416
+
417
+ async function makePolicy(pool, rm, cust, payout, premium, lossProb, expiration, internalId) {
418
+ let tx = await rm.connect(cust).newPolicy(payout, premium, lossProb, expiration, cust.address, internalId);
419
+ let receipt = await tx.wait();
420
+ const newPolicyEvt = getTransactionEvent(pool.interface, receipt, "NewPolicy");
421
+
422
+ return newPolicyEvt;
423
+ }
424
+
425
+ exports.makePolicy = makePolicy;
426
+
427
+ async function blockchainNow(owner) {
428
+ return (await owner.provider.getBlock("latest")).timestamp;
429
+ }
430
+
431
+ exports.blockchainNow = blockchainNow;
432
+
433
+ function getRole(role) {
434
+ return role === "DEFAULT_ADMIN_ROLE"
435
+ ? "0x0000000000000000000000000000000000000000000000000000000000000000"
436
+ : hre.ethers.utils.keccak256(hre.ethers.utils.toUtf8Bytes(role));
437
+ }
438
+
439
+ exports.getRole = getRole;
440
+
441
+ async function getStorageLayout(contractSrc, contractName) {
442
+ const buildInfo = await hre.artifacts.getBuildInfo(`${contractSrc}:${contractName}`);
443
+ if (buildInfo === undefined) throw new Error(`Contract ${contractSrc}:${contractName} not in artifacts`);
444
+
445
+ const solcOutput = buildInfo.output;
446
+
447
+ const storageLayouts = {};
448
+
449
+ for (const def of findAll("ContractDefinition", solcOutput.sources[contractSrc].ast)) {
450
+ storageLayouts[def.name] = solcOutput.contracts[contractSrc][def.name].storageLayout;
277
451
  }
452
+
453
+ return storageLayouts[contractName];
278
454
  }
455
+
456
+ exports.getStorageLayout = getStorageLayout;
457
+
458
+ if (process.env.ENABLE_HH_WARNINGS !== "yes") hre.upgrades.silenceWarnings();
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.0.0-beta1",
4
+ "version": "2.0.0-beta11",
5
5
  "files": [
6
6
  "**/*.sol",
7
7
  "/build/contracts/*.json",