@ensuro/core 2.0.0-beta3 → 2.0.0-beta6

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 (40) hide show
  1. package/build/contracts/AccessManager.sol/AccessManager.json +487 -0
  2. package/build/contracts/EToken.sol/EToken.json +4 -4
  3. package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +4 -4
  4. package/build/contracts/PolicyNFT.sol/PolicyNFT.json +2 -2
  5. package/build/contracts/PolicyPool.sol/PolicyPool.json +148 -15
  6. package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +2 -2
  7. package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +4 -4
  8. package/build/contracts/Reserve.sol/Reserve.json +2 -2
  9. package/build/contracts/RiskModule.sol/RiskModule.json +2 -2
  10. package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +4 -4
  11. package/build/contracts/interfaces/{IPolicyPoolConfig.sol/IPolicyPoolConfig.json → IAccessManager.sol/IAccessManager.json} +2 -67
  12. package/build/contracts/interfaces/IPolicyPool.sol/IPolicyPool.json +15 -2
  13. package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +2 -2
  14. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +19 -6
  15. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +6 -6
  16. package/contracts/AccessManager.sol +72 -0
  17. package/contracts/EToken.sol +6 -13
  18. package/contracts/PolicyNFT.sol +3 -3
  19. package/contracts/PolicyPool.sol +108 -43
  20. package/contracts/PolicyPoolComponent.sol +11 -11
  21. package/contracts/PremiumsAccount.sol +1 -1
  22. package/contracts/RiskModule.sol +4 -8
  23. package/contracts/interfaces/{IPolicyPoolConfig.sol → IAccessManager.sol} +2 -21
  24. package/contracts/interfaces/IPolicyPool.sol +10 -5
  25. package/contracts/mocks/PolicyPoolMock.sol +15 -13
  26. package/js/test-utils.js +178 -122
  27. package/package.json +1 -1
  28. package/build/contracts/FlightDelayRiskModule.sol/FlightDelayRiskModule.json +0 -890
  29. package/build/contracts/PolicyPoolConfig.sol/PolicyPoolConfig.json +0 -665
  30. package/build/contracts/dependencies/ChainlinkClientUpgradeable.sol/ChainlinkClientUpgradeable.json +0 -63
  31. package/build/contracts/mocks/LinkTokenMock.sol/LinkTokenMock.json +0 -370
  32. package/build/contracts/upgraded/IPolicyNFTv1.sol/IPolicyNFTv1.json +0 -322
  33. package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1.json +0 -584
  34. package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1_Upgrade.json +0 -615
  35. package/contracts/FlightDelayRiskModule.sol +0 -217
  36. package/contracts/PolicyPoolConfig.sol +0 -185
  37. package/contracts/dependencies/ChainlinkClientUpgradeable.sol +0 -371
  38. package/contracts/mocks/LinkTokenMock.sol +0 -30
  39. package/contracts/upgraded/IPolicyNFTv1.sol +0 -15
  40. package/contracts/upgraded/PolicyNFTv1.sol +0 -126
@@ -2,15 +2,13 @@
2
2
  pragma solidity ^0.8.0;
3
3
 
4
4
  import {IAccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
5
- import {ILPWhitelist} from "./ILPWhitelist.sol";
6
- import {IRiskModule} from "./IRiskModule.sol";
7
5
 
8
6
  /**
9
- * @title IPolicyPoolAccess - Interface for the contract that handles roles for the PolicyPool and components
7
+ * @title IAccessManager - Interface for the contract that handles roles for the PolicyPool and components
10
8
  * @dev Interface for the contract that handles roles for the PolicyPool and components
11
9
  * @author Ensuro
12
10
  */
13
- interface IPolicyPoolConfig is IAccessControlUpgradeable {
11
+ interface IAccessManager is IAccessControlUpgradeable {
14
12
  enum GovernanceActions {
15
13
  none,
16
14
  setTreasury, // Changes PolicyPool treasury address
@@ -61,15 +59,6 @@ interface IPolicyPoolConfig is IAccessControlUpgradeable {
61
59
  last
62
60
  }
63
61
 
64
- enum RiskModuleStatus {
65
- inactive, // newPolicy and resolvePolicy rejected
66
- active, // newPolicy and resolvePolicy accepted
67
- deprecated, // newPolicy rejected, resolvePolicy accepted
68
- suspended // newPolicy and resolvePolicy rejected (temporarily)
69
- }
70
-
71
- event RiskModuleStatusChanged(IRiskModule indexed riskModule, RiskModuleStatus newStatus);
72
-
73
62
  function checkRole(bytes32 role, address account) external view;
74
63
 
75
64
  function checkComponentRole(
@@ -83,12 +72,4 @@ interface IPolicyPoolConfig is IAccessControlUpgradeable {
83
72
  bytes32 role2,
84
73
  address account
85
74
  ) external view;
86
-
87
- function connect() external;
88
-
89
- function treasury() external view returns (address);
90
-
91
- function checkAcceptsNewPolicy(IRiskModule riskModule) external view;
92
-
93
- function checkAcceptsResolvePolicy(IRiskModule riskModule) external view;
94
75
  }
@@ -4,7 +4,7 @@ pragma solidity ^0.8.0;
4
4
  import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
5
5
  import {Policy} from "../Policy.sol";
6
6
  import {IEToken} from "./IEToken.sol";
7
- import {IPolicyPoolConfig} from "./IPolicyPoolConfig.sol";
7
+ import {IAccessManager} from "./IAccessManager.sol";
8
8
 
9
9
  interface IPolicyPool {
10
10
  /**
@@ -14,11 +14,10 @@ interface IPolicyPool {
14
14
  function currency() external view returns (IERC20Metadata);
15
15
 
16
16
  /**
17
- * @dev Reference to the {PolicyPoolConfig} contract, this contract manages the access controls and installed risk
18
- * modules.
19
- * @return The address of the PolicyPoolConfig contract
17
+ * @dev Reference to the {AccessManager} contract, this contract manages the access controls.
18
+ * @return The address of the AccessManager contract
20
19
  */
21
- function config() external view returns (IPolicyPoolConfig);
20
+ function access() external view returns (IAccessManager);
22
21
 
23
22
  /**
24
23
  * @dev Reference to the {PolicyNFT} contract. This contract it's an ERC721 Token that handles the ownership of the
@@ -27,6 +26,12 @@ interface IPolicyPool {
27
26
  */
28
27
  function policyNFT() external view returns (address);
29
28
 
29
+ /**
30
+ * @dev Address of the treasury, that receives protocol fees.
31
+ * @return The address of the treasury
32
+ */
33
+ function treasury() external view returns (address);
34
+
30
35
  /**
31
36
  * @dev Creates a new Policy. Must be called from an active RiskModule
32
37
  *
@@ -4,7 +4,7 @@ pragma solidity ^0.8.0;
4
4
  import {IPolicyPool} from "../interfaces/IPolicyPool.sol";
5
5
  import {IRiskModule} from "../interfaces/IRiskModule.sol";
6
6
  import {IEToken} from "../interfaces/IEToken.sol";
7
- import {IPolicyPoolConfig} from "../interfaces/IPolicyPoolConfig.sol";
7
+ import {IAccessManager} from "../interfaces/IAccessManager.sol";
8
8
  import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
9
9
  import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
10
10
  import {Policy} from "../Policy.sol";
@@ -17,7 +17,7 @@ contract PolicyPoolMock is IPolicyPool {
17
17
  0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
18
18
 
19
19
  IERC20Metadata internal _currency;
20
- IPolicyPoolConfig internal _config;
20
+ IAccessManager internal _access;
21
21
 
22
22
  mapping(uint256 => Policy.PolicyData) internal policies;
23
23
  mapping(uint256 => bytes32) internal policyHashes;
@@ -25,24 +25,27 @@ contract PolicyPoolMock is IPolicyPool {
25
25
  event NewPolicy(IRiskModule indexed riskModule, Policy.PolicyData policy);
26
26
  event PolicyResolved(IRiskModule indexed riskModule, uint256 indexed policyId, uint256 payout);
27
27
 
28
- constructor(IERC20Metadata currency_, IPolicyPoolConfig config_) {
28
+ constructor(IERC20Metadata currency_, IAccessManager access_) {
29
29
  _currency = currency_;
30
- _config = config_;
31
- _config.connect();
30
+ _access = access_;
32
31
  }
33
32
 
34
33
  function currency() external view override returns (IERC20Metadata) {
35
34
  return _currency;
36
35
  }
37
36
 
38
- function config() external view override returns (IPolicyPoolConfig) {
39
- return _config;
37
+ function access() external view override returns (IAccessManager) {
38
+ return _access;
40
39
  }
41
40
 
42
41
  function policyNFT() external pure override returns (address) {
43
42
  return address(0);
44
43
  }
45
44
 
45
+ function treasury() external pure override returns (address) {
46
+ return address(0);
47
+ }
48
+
46
49
  function newPolicy(
47
50
  Policy.PolicyData memory policy,
48
51
  address, /* customer */
@@ -100,23 +103,22 @@ contract PolicyPoolMockForward is ForwardProxy {
100
103
  0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
101
104
 
102
105
  IERC20Metadata internal _currency;
103
- IPolicyPoolConfig internal _config;
106
+ IAccessManager internal _access;
104
107
 
105
108
  constructor(
106
109
  address forwardTo,
107
110
  IERC20Metadata currency_,
108
- IPolicyPoolConfig config_
111
+ IAccessManager access_
109
112
  ) ForwardProxy(forwardTo) {
110
113
  _currency = currency_;
111
- _config = config_;
112
- _config.connect();
114
+ _access = access_;
113
115
  }
114
116
 
115
117
  function currency() external view returns (IERC20Metadata) {
116
118
  return _currency;
117
119
  }
118
120
 
119
- function config() external view returns (IPolicyPoolConfig) {
120
- return _config;
121
+ function access() external view returns (IAccessManager) {
122
+ return _access;
121
123
  }
122
124
  }
package/js/test-utils.js CHANGED
@@ -1,61 +1,84 @@
1
1
  const { expect } = require("chai");
2
2
  const { BigNumber } = require("ethers");
3
- const {LogDescription} = require("ethers/lib/utils");
3
+ const { LogDescription } = require("ethers/lib/utils");
4
4
  exports.WEEK = 3600 * 24 * 7;
5
5
  exports.DAY = 3600 * 24;
6
6
 
7
- exports.initCurrency = async function(options, initial_targets, initial_balances) {
7
+ exports.initCurrency = async function (options, initial_targets, initial_balances) {
8
8
  const Currency = await ethers.getContractFactory("TestCurrency");
9
9
  let currency = await Currency.deploy(
10
10
  options.name || "Test Currency",
11
11
  options.symbol || "TEST",
12
12
  options.initial_supply,
13
- options.decimals || 18,
13
+ options.decimals || 18
14
14
  );
15
15
  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
- }));
16
+ await Promise.all(
17
+ initial_targets.map(async function (user, index) {
18
+ await currency.transfer(user.address, initial_balances[index]);
19
+ })
20
+ );
19
21
  return currency;
20
- }
22
+ };
21
23
 
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
- }
24
+ exports.approve_multiple = async function (currency, spender, sources, amounts) {
25
+ return Promise.all(
26
+ sources.map(async function (source, index) {
27
+ await currency.connect(source).approve(spender.address, amounts[index]);
28
+ })
29
+ );
30
+ };
27
31
 
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
- }
32
+ exports.check_balances = async function (currency, users, amounts) {
33
+ return Promise.all(
34
+ users.map(async function (user, index) {
35
+ expect(await currency.balanceOf(user.address)).to.equal(amounts[index]);
36
+ })
37
+ );
38
+ };
33
39
 
34
- exports.now = function() {
40
+ exports.now = function () {
35
41
  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
- }) {
42
+ };
43
+
44
+ exports.addRiskModule = async function (
45
+ pool,
46
+ premiumsAccount,
47
+ contractFactory,
48
+ {
49
+ rmName,
50
+ scrPercentage,
51
+ scrInterestRate,
52
+ ensuroFee,
53
+ maxScrPerPolicy,
54
+ scrLimit,
55
+ moc,
56
+ wallet,
57
+ extraArgs,
58
+ extraConstructorArgs,
59
+ }
60
+ ) {
42
61
  extraArgs = extraArgs || [];
43
62
  extraConstructorArgs = extraConstructorArgs || [];
44
63
  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
- });
64
+ const rm = await hre.upgrades.deployProxy(
65
+ contractFactory,
66
+ [
67
+ rmName || "RiskModule",
68
+ _W(scrPercentage) || _W(1),
69
+ _W(ensuroFee) || _W(0),
70
+ _W(scrInterestRate) || _W(0.1),
71
+ _A(maxScrPerPolicy) || _A(1000),
72
+ _A(scrLimit) || _A(1000000),
73
+ wallet || "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", // Random address
74
+ ...extraArgs,
75
+ ],
76
+ {
77
+ kind: "uups",
78
+ unsafeAllow: ["delegatecall"],
79
+ constructorArgs: [pool.address, premiumsAccount.address, ...extraConstructorArgs],
80
+ }
81
+ );
59
82
 
60
83
  await rm.deployed();
61
84
 
@@ -63,66 +86,63 @@ exports.addRiskModule = async function(pool, premiumsAccount, contractFactory, {
63
86
  moc = _W(moc);
64
87
  await rm.setParam(0, moc);
65
88
  }
66
- const policyPoolConfig = await hre.ethers.getContractAt("PolicyPoolConfig", await pool.config());
67
- await policyPoolConfig.addRiskModule(rm.address);
89
+ await pool.addRiskModule(rm.address);
68
90
  return rm;
69
- }
91
+ };
70
92
 
71
- exports.addEToken = async function(pool, {
72
- etkName, etkSymbol, maxUtilizationRate,
73
- poolLoanInterestRate, extraArgs, extraConstructorArgs
74
- }) {
93
+ exports.addEToken = async function (
94
+ pool,
95
+ { etkName, etkSymbol, maxUtilizationRate, poolLoanInterestRate, extraArgs, extraConstructorArgs }
96
+ ) {
75
97
  const EToken = await ethers.getContractFactory("EToken");
76
98
  extraArgs = extraArgs || [];
77
99
  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
- });
100
+ const etk = await hre.upgrades.deployProxy(
101
+ EToken,
102
+ [
103
+ etkName || "EToken",
104
+ etkSymbol || "eUSD1YEAR",
105
+ _W(maxUtilizationRate) || _W(1),
106
+ _W(poolLoanInterestRate) || _W("0.05"),
107
+ ...extraArgs,
108
+ ],
109
+ {
110
+ kind: "uups",
111
+ unsafeAllow: ["delegatecall"],
112
+ constructorArgs: [pool.address, ...extraConstructorArgs],
113
+ }
114
+ );
89
115
 
90
116
  await etk.deployed();
91
117
  await pool.addEToken(etk.address);
92
118
  return etk;
93
- }
119
+ };
94
120
 
95
- exports.expected_change = async function(protocol_attribute, initial, change) {
121
+ exports.expected_change = async function (protocol_attribute, initial, change) {
96
122
  change = BigNumber.from(change);
97
123
  let actual_value = await protocol_attribute();
98
124
  expect(actual_value.sub(initial)).to.equal(change);
99
125
  return actual_value;
100
- }
126
+ };
101
127
 
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;
128
+ exports.impersonate = async function (address, setBalanceTo) {
129
+ const ok = await hre.network.provider.request({ method: "hardhat_impersonateAccount", params: [address] });
130
+ if (!ok) throw "Error impersonatting " + address;
108
131
 
109
132
  if (setBalanceTo !== undefined)
110
- await hre.network.provider.request(
111
- {method: "hardhat_setBalance", params: [address, setBalanceTo.toHexString()]}
112
- );
133
+ await hre.network.provider.request({ method: "hardhat_setBalance", params: [address, setBalanceTo.toHexString()] });
113
134
 
114
135
  return await ethers.getSigner(address);
115
- }
116
-
136
+ };
117
137
 
118
138
  /**
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) {
139
+ * Finds an event in the receipt
140
+ * @param {Interface} interface The interface of the contract that contains the requested event
141
+ * @param {TransactionReceipt} receipt Transaction receipt containing the events in the logs
142
+ * @param {String} eventName The name of the event we are interested in
143
+ * @returns {LogDescription}
144
+ */
145
+ exports.getTransactionEvent = function (interface, receipt, eventName) {
126
146
  // for each log in the transaction receipt
127
147
  for (const log of receipt.events) {
128
148
  let parsedLog;
@@ -135,12 +155,12 @@ exports.getTransactionEvent = function(interface, receipt, eventName) {
135
155
  return parsedLog;
136
156
  }
137
157
  }
138
- return null; // not found
139
- }
158
+ return null; // not found
159
+ };
140
160
 
141
- exports.deployPool = async function(hre, options) {
161
+ exports.deployPool = async function (hre, options) {
142
162
  const PolicyPool = await ethers.getContractFactory("PolicyPool");
143
- const PolicyPoolConfig = await ethers.getContractFactory("PolicyPoolConfig");
163
+ const AccessManager = await ethers.getContractFactory("AccessManager");
144
164
  const PolicyNFT = await ethers.getContractFactory("PolicyNFT");
145
165
 
146
166
  // Deploy PolicyNFT
@@ -149,37 +169,38 @@ exports.deployPool = async function(hre, options) {
149
169
  [
150
170
  options.nftName || "Policy NFT",
151
171
  options.nftSymbol || "EPOL",
152
- options.policyPoolDetAddress || ethers.constants.AddressZero
172
+ options.policyPoolDetAddress || ethers.constants.AddressZero,
153
173
  ],
154
- {kind: 'uups'}
174
+ { kind: "uups" }
155
175
  );
156
176
  await policyNFT.deployed();
157
177
 
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'});
178
+ // Deploy AccessManager
179
+ const accessManager = await hre.upgrades.deployProxy(AccessManager, [], { kind: "uups" });
163
180
 
164
- await policyPoolConfig.deployed();
181
+ await accessManager.deployed();
165
182
 
166
- const policyPool = await hre.upgrades.deployProxy(PolicyPool, [], {
167
- constructorArgs: [policyPoolConfig.address, policyNFT.address, options.currency],
168
- kind: 'uups',
169
- unsafeAllow: ["delegatecall"],
170
- });
183
+ const policyPool = await hre.upgrades.deployProxy(
184
+ PolicyPool,
185
+ [options.treasuryAddress || ethers.constants.AddressZero],
186
+ {
187
+ constructorArgs: [accessManager.address, policyNFT.address, options.currency],
188
+ kind: "uups",
189
+ unsafeAllow: ["delegatecall"],
190
+ }
191
+ );
171
192
 
172
193
  await policyPool.deployed();
173
194
 
174
- for (const role of (options.grantRoles || [])) {
175
- await grantRole(hre, policyPoolConfig, role);
195
+ for (const role of options.grantRoles || []) {
196
+ await grantRole(hre, accessManager, role);
176
197
  }
177
198
 
178
- await grantRole(hre, policyPoolConfig, "LEVEL1_ROLE");
179
- await grantRole(hre, policyPoolConfig, "LEVEL2_ROLE");
180
- await grantRole(hre, policyPoolConfig, "LEVEL3_ROLE");
199
+ await grantRole(hre, accessManager, "LEVEL1_ROLE");
200
+ await grantRole(hre, accessManager, "LEVEL2_ROLE");
201
+ await grantRole(hre, accessManager, "LEVEL3_ROLE");
181
202
  return policyPool;
182
- }
203
+ };
183
204
 
184
205
  exports.deployPremiumsAccount = async function (hre, pool, options) {
185
206
  const PremiumsAccount = await ethers.getContractFactory("PremiumsAccount");
@@ -189,14 +210,14 @@ exports.deployPremiumsAccount = async function (hre, pool, options) {
189
210
  options.jrEtkAddr || ethers.constants.AddressZero,
190
211
  options.srEtkAddr || ethers.constants.AddressZero,
191
212
  ],
192
- kind: 'uups',
213
+ kind: "uups",
193
214
  unsafeAllow: ["delegatecall"],
194
215
  });
195
216
 
196
217
  await premiumsAccount.deployed();
197
218
  await pool.addPremiumsAccount(premiumsAccount.address);
198
219
  return premiumsAccount;
199
- }
220
+ };
200
221
 
201
222
  async function _getDefaultSigner(hre) {
202
223
  const signers = await hre.ethers.getSigners();
@@ -212,7 +233,7 @@ async function grantRole(hre, contract, role, user) {
212
233
  userAddress = user;
213
234
  }
214
235
  const roleHex = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(role));
215
- if (!await contract.hasRole(roleHex, userAddress)) {
236
+ if (!(await contract.hasRole(roleHex, userAddress))) {
216
237
  await contract.grantRole(roleHex, userAddress);
217
238
  }
218
239
  }
@@ -229,7 +250,7 @@ async function grantComponentRole(hre, contract, component, role, user) {
229
250
  }
230
251
  const roleHex = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(role));
231
252
  const componentRole = await contract.getComponentRole(component.address, roleHex);
232
- if (!await contract.hasRole(componentRole, userAddress)) {
253
+ if (!(await contract.hasRole(componentRole, userAddress))) {
233
254
  await contract.grantComponentRole(component.address, roleHex, userAddress);
234
255
  }
235
256
  }
@@ -239,40 +260,75 @@ exports.grantComponentRole = grantComponentRole;
239
260
  exports._E = ethers.utils.parseEther;
240
261
 
241
262
  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
263
+ const WAD = _BN(1e10).mul(_BN(1e8)); // 1e10*1e8=1e18
264
+ const RAY = WAD.mul(_BN(1e9)); // 1e18*1e9=1e27
244
265
 
245
266
  exports._BN = _BN;
246
267
 
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));
268
+ const _W = function (value) {
269
+ if (value === undefined) return undefined;
270
+ if (!Number.isInteger(value)) return _BN(Math.round(value * 1e9)).mul(_BN(1e9));
252
271
  return _BN(value).mul(WAD);
253
- }
272
+ };
254
273
 
255
274
  exports._W = _W;
256
275
 
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);
276
+ const _R = function (value) {
277
+ if (value === undefined) return undefined;
278
+ if (!Number.isInteger(value)) return _BN(Math.round(value * 1e9)).mul(WAD);
262
279
  return _BN(value).mul(RAY);
263
- }
280
+ };
264
281
 
265
282
  exports._R = _R;
266
283
 
267
284
  exports.amountFunction = function (decimals) {
268
285
  // Decimals must be at least 6
269
286
  return function (value) {
270
- if (value === undefined)
271
- return undefined;
272
- if (typeof value === 'string' || value instanceof String) {
287
+ if (value === undefined) return undefined;
288
+ if (typeof value === "string" || value instanceof String) {
273
289
  return _BN(value).mul(_BN(Math.pow(10, decimals)));
274
290
  } else {
275
291
  return _BN(Math.round(value * 1e6)).mul(_BN(Math.pow(10, decimals - 6)));
276
292
  }
277
- }
293
+ };
294
+ };
295
+
296
+ /*
297
+ Builds the component role identifier
298
+
299
+ Mimics the behaviour of the PolicyPoolConfig.getComponentRole method
300
+
301
+ Component roles are roles created doing XOR between the component
302
+ address and the original role.
303
+
304
+ Example:
305
+ getComponentRole("0xc6e7DF5E7b4f2A278906862b61205850344D4e7d", "ORACLE_ADMIN_ROLE")
306
+ // "0x05e01b185238b49f750d03d945e38a7f6c3be8b54de0ee42d481eb7814f0d3a8"
307
+ */
308
+ function getComponentRole(componentAddress, roleName) {
309
+ // 32 byte array
310
+ const bytesRole = ethers.utils.arrayify(ethers.utils.keccak256(ethers.utils.toUtf8Bytes(roleName)));
311
+
312
+ // 20 byte array
313
+ const bytesAddress = ethers.utils.arrayify(componentAddress);
314
+
315
+ // xor each byte, padding bytesAddress with zeros at the end
316
+ return ethers.utils.hexlify(bytesRole.map((elem, idx) => elem ^ (bytesAddress[idx] || 0)));
278
317
  }
318
+
319
+ exports.getComponentRole = getComponentRole;
320
+
321
+ /*
322
+ Builds AccessControl error message for comparison in tests
323
+ */
324
+ function accessControlMessage(address, component, role) {
325
+ return `AccessControl: account ${address.toLowerCase()} is missing role ${getComponentRole(component, role)}`;
326
+ }
327
+
328
+ exports.accessControlMessage = accessControlMessage;
329
+
330
+ function makePolicyId(rm, internalId) {
331
+ return ethers.BigNumber.from(rm.address).shl(96).add(internalId);
332
+ }
333
+
334
+ exports.makePolicyId = makePolicyId;
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-beta3",
4
+ "version": "2.0.0-beta6",
5
5
  "files": [
6
6
  "**/*.sol",
7
7
  "/build/contracts/*.json",