@ensuro/core 2.0.0-beta2 → 2.0.0-beta5

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 (41) hide show
  1. package/README.md +2 -1
  2. package/build/contracts/AccessManager.sol/AccessManager.json +487 -0
  3. package/build/contracts/EToken.sol/EToken.json +4 -4
  4. package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +4 -4
  5. package/build/contracts/PolicyNFT.sol/PolicyNFT.json +2 -2
  6. package/build/contracts/PolicyPool.sol/PolicyPool.json +148 -15
  7. package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +2 -2
  8. package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +4 -4
  9. package/build/contracts/Reserve.sol/Reserve.json +2 -2
  10. package/build/contracts/RiskModule.sol/RiskModule.json +2 -2
  11. package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +4 -4
  12. package/build/contracts/interfaces/{IPolicyPoolConfig.sol/IPolicyPoolConfig.json → IAccessManager.sol/IAccessManager.json} +2 -67
  13. package/build/contracts/interfaces/IPolicyPool.sol/IPolicyPool.json +15 -2
  14. package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +2 -2
  15. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +19 -6
  16. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +6 -6
  17. package/contracts/AccessManager.sol +72 -0
  18. package/contracts/EToken.sol +6 -13
  19. package/contracts/PolicyNFT.sol +3 -3
  20. package/contracts/PolicyPool.sol +108 -43
  21. package/contracts/PolicyPoolComponent.sol +11 -11
  22. package/contracts/PremiumsAccount.sol +1 -1
  23. package/contracts/RiskModule.sol +4 -8
  24. package/contracts/interfaces/{IPolicyPoolConfig.sol → IAccessManager.sol} +2 -21
  25. package/contracts/interfaces/IPolicyPool.sol +10 -5
  26. package/contracts/mocks/PolicyPoolMock.sol +15 -13
  27. package/js/test-utils.js +177 -119
  28. package/package.json +1 -1
  29. package/build/contracts/FlightDelayRiskModule.sol/FlightDelayRiskModule.json +0 -890
  30. package/build/contracts/PolicyPoolConfig.sol/PolicyPoolConfig.json +0 -665
  31. package/build/contracts/dependencies/ChainlinkClientUpgradeable.sol/ChainlinkClientUpgradeable.json +0 -63
  32. package/build/contracts/mocks/LinkTokenMock.sol/LinkTokenMock.json +0 -370
  33. package/build/contracts/upgraded/IPolicyNFTv1.sol/IPolicyNFTv1.json +0 -322
  34. package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1.json +0 -584
  35. package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1_Upgrade.json +0 -615
  36. package/contracts/FlightDelayRiskModule.sol +0 -217
  37. package/contracts/PolicyPoolConfig.sol +0 -185
  38. package/contracts/dependencies/ChainlinkClientUpgradeable.sol +0 -371
  39. package/contracts/mocks/LinkTokenMock.sol +0 -30
  40. package/contracts/upgraded/IPolicyNFTv1.sol +0 -15
  41. 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,40 @@ 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, [
178
+ // Deploy AccessManager
179
+ const accessManager = await hre.upgrades.deployProxy(AccessManager, [
160
180
  options.policyPoolDetAddress || ethers.constants.AddressZero,
161
- options.treasuryAddress || ethers.constants.AddressZero
162
181
  ], {kind: 'uups'});
163
182
 
164
- await policyPoolConfig.deployed();
183
+ await accessManager.deployed();
165
184
 
166
- const policyPool = await hre.upgrades.deployProxy(PolicyPool, [], {
167
- constructorArgs: [policyPoolConfig.address, policyNFT.address, options.currency],
168
- kind: 'uups',
169
- unsafeAllow: ["delegatecall"],
170
- });
185
+ const policyPool = await hre.upgrades.deployProxy(
186
+ PolicyPool,
187
+ [options.treasuryAddress || ethers.constants.AddressZero],
188
+ {
189
+ constructorArgs: [accessManager.address, policyNFT.address, options.currency],
190
+ kind: 'uups',
191
+ unsafeAllow: ["delegatecall"],
192
+ }
193
+ );
171
194
 
172
195
  await policyPool.deployed();
173
196
 
174
197
  for (const role of (options.grantRoles || [])) {
175
- await grantRole(hre, policyPoolConfig, role);
198
+ await grantRole(hre, accessManager, role);
176
199
  }
177
200
 
178
- await grantRole(hre, policyPoolConfig, "LEVEL1_ROLE");
179
- await grantRole(hre, policyPoolConfig, "LEVEL2_ROLE");
180
- await grantRole(hre, policyPoolConfig, "LEVEL3_ROLE");
201
+ await grantRole(hre, accessManager, "LEVEL1_ROLE");
202
+ await grantRole(hre, accessManager, "LEVEL2_ROLE");
203
+ await grantRole(hre, accessManager, "LEVEL3_ROLE");
181
204
  return policyPool;
182
- }
205
+ };
183
206
 
184
207
  exports.deployPremiumsAccount = async function (hre, pool, options) {
185
208
  const PremiumsAccount = await ethers.getContractFactory("PremiumsAccount");
@@ -189,14 +212,14 @@ exports.deployPremiumsAccount = async function (hre, pool, options) {
189
212
  options.jrEtkAddr || ethers.constants.AddressZero,
190
213
  options.srEtkAddr || ethers.constants.AddressZero,
191
214
  ],
192
- kind: 'uups',
215
+ kind: "uups",
193
216
  unsafeAllow: ["delegatecall"],
194
217
  });
195
218
 
196
219
  await premiumsAccount.deployed();
197
220
  await pool.addPremiumsAccount(premiumsAccount.address);
198
221
  return premiumsAccount;
199
- }
222
+ };
200
223
 
201
224
  async function _getDefaultSigner(hre) {
202
225
  const signers = await hre.ethers.getSigners();
@@ -212,7 +235,7 @@ async function grantRole(hre, contract, role, user) {
212
235
  userAddress = user;
213
236
  }
214
237
  const roleHex = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(role));
215
- if (!await contract.hasRole(roleHex, userAddress)) {
238
+ if (!(await contract.hasRole(roleHex, userAddress))) {
216
239
  await contract.grantRole(roleHex, userAddress);
217
240
  }
218
241
  }
@@ -229,7 +252,7 @@ async function grantComponentRole(hre, contract, component, role, user) {
229
252
  }
230
253
  const roleHex = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(role));
231
254
  const componentRole = await contract.getComponentRole(component.address, roleHex);
232
- if (!await contract.hasRole(componentRole, userAddress)) {
255
+ if (!(await contract.hasRole(componentRole, userAddress))) {
233
256
  await contract.grantComponentRole(component.address, roleHex, userAddress);
234
257
  }
235
258
  }
@@ -239,40 +262,75 @@ exports.grantComponentRole = grantComponentRole;
239
262
  exports._E = ethers.utils.parseEther;
240
263
 
241
264
  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
265
+ const WAD = _BN(1e10).mul(_BN(1e8)); // 1e10*1e8=1e18
266
+ const RAY = WAD.mul(_BN(1e9)); // 1e18*1e9=1e27
244
267
 
245
268
  exports._BN = _BN;
246
269
 
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));
270
+ const _W = function (value) {
271
+ if (value === undefined) return undefined;
272
+ if (!Number.isInteger(value)) return _BN(Math.round(value * 1e9)).mul(_BN(1e9));
252
273
  return _BN(value).mul(WAD);
253
- }
274
+ };
254
275
 
255
276
  exports._W = _W;
256
277
 
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);
278
+ const _R = function (value) {
279
+ if (value === undefined) return undefined;
280
+ if (!Number.isInteger(value)) return _BN(Math.round(value * 1e9)).mul(WAD);
262
281
  return _BN(value).mul(RAY);
263
- }
282
+ };
264
283
 
265
284
  exports._R = _R;
266
285
 
267
286
  exports.amountFunction = function (decimals) {
268
287
  // Decimals must be at least 6
269
288
  return function (value) {
270
- if (value === undefined)
271
- return undefined;
272
- if (typeof value === 'string' || value instanceof String) {
289
+ if (value === undefined) return undefined;
290
+ if (typeof value === "string" || value instanceof String) {
273
291
  return _BN(value).mul(_BN(Math.pow(10, decimals)));
274
292
  } else {
275
293
  return _BN(Math.round(value * 1e6)).mul(_BN(Math.pow(10, decimals - 6)));
276
294
  }
277
- }
295
+ };
296
+ };
297
+
298
+ /*
299
+ Builds the component role identifier
300
+
301
+ Mimics the behaviour of the PolicyPoolConfig.getComponentRole method
302
+
303
+ Component roles are roles created doing XOR between the component
304
+ address and the original role.
305
+
306
+ Example:
307
+ getComponentRole("0xc6e7DF5E7b4f2A278906862b61205850344D4e7d", "ORACLE_ADMIN_ROLE")
308
+ // "0x05e01b185238b49f750d03d945e38a7f6c3be8b54de0ee42d481eb7814f0d3a8"
309
+ */
310
+ function getComponentRole(componentAddress, roleName) {
311
+ // 32 byte array
312
+ const bytesRole = ethers.utils.arrayify(ethers.utils.keccak256(ethers.utils.toUtf8Bytes(roleName)));
313
+
314
+ // 20 byte array
315
+ const bytesAddress = ethers.utils.arrayify(componentAddress);
316
+
317
+ // xor each byte, padding bytesAddress with zeros at the end
318
+ return ethers.utils.hexlify(bytesRole.map((elem, idx) => elem ^ (bytesAddress[idx] || 0)));
278
319
  }
320
+
321
+ exports.getComponentRole = getComponentRole;
322
+
323
+ /*
324
+ Builds AccessControl error message for comparison in tests
325
+ */
326
+ function accessControlMessage(address, component, role) {
327
+ return `AccessControl: account ${address.toLowerCase()} is missing role ${getComponentRole(component, role)}`;
328
+ }
329
+
330
+ exports.accessControlMessage = accessControlMessage;
331
+
332
+ function makePolicyId(rm, internalId) {
333
+ return ethers.BigNumber.from(rm.address).shl(96).add(internalId);
334
+ }
335
+
336
+ 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-beta2",
4
+ "version": "2.0.0-beta5",
5
5
  "files": [
6
6
  "**/*.sol",
7
7
  "/build/contracts/*.json",