@ensuro/core 2.8.3 → 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/README.md +2 -3
- package/build/build-info.json +1 -0
- package/build/contracts/AccessManager.sol/AccessManager.json +2 -15
- package/build/contracts/ERC4626AssetManager.sol/ERC4626AssetManager.json +2 -2
- package/build/contracts/ERC4626PlusVaultAssetManager.sol/ERC4626PlusVaultAssetManager.json +2 -2
- package/build/contracts/EToken.sol/EToken.json +7 -85
- package/build/contracts/FullSignedBucketRiskModule.sol/FullSignedBucketRiskModule.json +1484 -0
- package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +7 -85
- package/build/contracts/Policy.sol/Policy.json +2 -2
- package/build/contracts/PolicyPool.sol/PolicyPool.json +2 -15
- package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +5 -83
- package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +7 -85
- package/build/contracts/Reserve.sol/Reserve.json +5 -83
- package/build/contracts/RiskModule.sol/RiskModule.json +5 -96
- package/build/contracts/SignedBucketRiskModule.sol/SignedBucketRiskModule.json +7 -150
- package/build/contracts/SignedQuoteRiskModule.sol/SignedQuoteRiskModule.json +7 -98
- package/build/contracts/TimeScaled.sol/TimeScaled.json +2 -2
- package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +7 -98
- package/build/contracts/dependencies/WadRayMath.sol/WadRayMath.json +2 -2
- package/build/contracts/migration/LPManualWhitelistV20.sol/LPManualWhitelistV20.json +5 -83
- package/build/contracts/migration/LPManualWhitelistV20Upgraded.sol/LPManualWhitelistV20Upgraded.json +7 -85
- package/build/contracts/mocks/FixedRateVault.sol/FixedRateVault.json +2 -2
- package/build/contracts/mocks/ForwardProxy.sol/ForwardProxy.json +2 -2
- package/build/contracts/mocks/InterfaceIdCalculator.sol/InterfaceIdCalculator.json +2 -2
- package/build/contracts/mocks/PolicyHolderMock.sol/PolicyHolderMock.json +2 -2
- package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +2 -2
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +2 -2
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +2 -2
- package/build/contracts/mocks/RiskModuleMock.sol/RiskModuleMock.json +7 -98
- package/build/contracts/mocks/TestCurrency.sol/TestCurrency.json +2 -2
- package/contracts/AccessManager.sol +0 -1
- package/contracts/EToken.sol +2 -20
- package/contracts/FullSignedBucketRiskModule.sol +204 -0
- package/contracts/PolicyPool.sol +0 -1
- package/contracts/PolicyPoolComponent.sol +7 -44
- package/contracts/PremiumsAccount.sol +3 -3
- package/contracts/RiskModule.sol +10 -21
- package/contracts/SignedBucketRiskModule.sol +15 -9
- package/contracts/SignedQuoteRiskModule.sol +7 -4
- package/js/deploy.js +1 -1
- package/js/test-utils.js +2 -92
- package/js/utils.js +67 -208
- package/package.json +1 -1
- package/scripts/deploySmokeTest-fork.sh +1 -1
- package/scripts/deploySmokeTest.sh +1 -1
- package/build/contracts/mocks/TestNFT.sol/TestNFT.json +0 -388
- package/contracts/mocks/TestNFT.sol +0 -23
- package/js/constants.js +0 -13
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
|
|
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.
|
|
@@ -203,6 +28,31 @@ function makeQuoteMessage({ rmAddress, payout, premium, lossProb, expiration, po
|
|
|
203
28
|
);
|
|
204
29
|
}
|
|
205
30
|
|
|
31
|
+
function paramsAsUint256(params) {
|
|
32
|
+
/* eslint no-bitwise: "off" */
|
|
33
|
+
return (
|
|
34
|
+
(params.moc << 240n) |
|
|
35
|
+
(params.jrCollRatio << 224n) |
|
|
36
|
+
(params.collRatio << 208n) |
|
|
37
|
+
(params.ensuroPpFee << 192n) |
|
|
38
|
+
(params.ensuroCocFee << 176n) |
|
|
39
|
+
(params.jrRoc << 160n) |
|
|
40
|
+
(params.srRoc << 144n)
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Create a packed quote message for later signing or hashing.
|
|
46
|
+
*
|
|
47
|
+
* Mimics the behaviour of the FullSignedBucketRiskModule._checkFullSignature method.
|
|
48
|
+
*/
|
|
49
|
+
function makeFullQuoteMessage({ rmAddress, payout, premium, lossProb, expiration, policyData, params, validUntil }) {
|
|
50
|
+
return ethers.solidityPacked(
|
|
51
|
+
["address", "uint256", "uint256", "uint256", "uint40", "bytes32", "uint256", "uint40"],
|
|
52
|
+
[rmAddress, payout, premium, lossProb, expiration, policyData, paramsAsUint256(params), validUntil]
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
206
56
|
/**
|
|
207
57
|
* Create a packed quote message for later signing or hashing.
|
|
208
58
|
*
|
|
@@ -263,6 +113,42 @@ async function defaultPolicyParams(
|
|
|
263
113
|
};
|
|
264
114
|
}
|
|
265
115
|
|
|
116
|
+
async function defaultPolicyParamsWithBucket(opts, _A = amountFunction(6)) {
|
|
117
|
+
const ret = await defaultPolicyParams(opts, _A);
|
|
118
|
+
return { bucketId: opts.bucketId || 0, ...ret };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function defaultPolicyParamsWithParams(opts, _A = amountFunction(6)) {
|
|
122
|
+
const ret = await defaultPolicyParams(opts, _A);
|
|
123
|
+
// struct PackedParams {
|
|
124
|
+
// uint16 moc; // Margin Of Conservativism - factor that multiplies lossProb - 4 decimals
|
|
125
|
+
// uint16 jrCollRatio; // Collateralization Ratio to compute Junior solvency as % of payout - 4 decimals
|
|
126
|
+
// uint16 collRatio; // Collateralization Ratio to compute solvency requirement as % of payout - 4 decimals
|
|
127
|
+
// uint16 ensuroPpFee; // % of pure premium that will go for Ensuro treasury - 4 decimals
|
|
128
|
+
// uint16 ensuroCocFee; // % of CoC that will go for Ensuro treasury - 4 decimals
|
|
129
|
+
// uint16 jrRoc; // Return on Capital paid to Junior LPs - Annualized Percentage - 4 decimals
|
|
130
|
+
// uint16 srRoc; // Return on Capital paid to Senior LPs - Annualized Percentage - 4 decimals
|
|
131
|
+
// uint32 maxPayoutPerPolicy; // Max Payout per Policy - 2 decimals
|
|
132
|
+
// uint32 exposureLimit; // Max exposure (sum of payouts) to be allocated to this module - 0 decimals
|
|
133
|
+
// uint16 maxDuration; // Max policy duration (in hours)
|
|
134
|
+
// }
|
|
135
|
+
const optsParams = opts.params || {};
|
|
136
|
+
const wadTo4Decimals = 10n ** 14n;
|
|
137
|
+
const params = {
|
|
138
|
+
moc: (optsParams.moc || _W(1)) / wadTo4Decimals,
|
|
139
|
+
jrCollRatio: (optsParams.jrCollRatio || 0n) / wadTo4Decimals,
|
|
140
|
+
collRatio: (optsParams.collRatio || _W(1)) / wadTo4Decimals,
|
|
141
|
+
ensuroPpFee: (optsParams.ensuroPpFee || 0n) / wadTo4Decimals,
|
|
142
|
+
ensuroCocFee: (optsParams.ensuroCocFee || 0n) / wadTo4Decimals,
|
|
143
|
+
jrRoc: (optsParams.jrRoc || 0n) / wadTo4Decimals,
|
|
144
|
+
srRoc: (optsParams.srRoc || _W("0.1")) / wadTo4Decimals, // 10%
|
|
145
|
+
maxPayoutPerPolicy: 0n, // Not used
|
|
146
|
+
exposureLimit: 0n, // Not used
|
|
147
|
+
maxDuration: 0n, // Not used
|
|
148
|
+
};
|
|
149
|
+
return { params, ...ret };
|
|
150
|
+
}
|
|
151
|
+
|
|
266
152
|
function defaultBucketParams({ moc, jrCollRatio, collRatio, ensuroPpFee, ensuroCocFee, jrRoc, srRoc }) {
|
|
267
153
|
return {
|
|
268
154
|
moc: moc !== undefined ? moc : _W("1.1"),
|
|
@@ -278,43 +164,16 @@ function defaultBucketParams({ moc, jrCollRatio, collRatio, ensuroPpFee, ensuroC
|
|
|
278
164
|
};
|
|
279
165
|
}
|
|
280
166
|
|
|
281
|
-
async function readImplementationAddress(hre, contractAddress) {
|
|
282
|
-
const implStorage = await hre.ethers.provider.getStorageAt(contractAddress, IMPLEMENTATION_SLOT);
|
|
283
|
-
return ethers.utils.getAddress(ethers.utils.hexDataSlice(implStorage, 12));
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Converts a string value to uint256(keccak(value))
|
|
288
|
-
* @param {string} value
|
|
289
|
-
* @returns {ethers.BigNumber}
|
|
290
|
-
*/
|
|
291
|
-
function uintKeccak(value) {
|
|
292
|
-
return BigInt(ethers.keccak256(ethers.toUtf8Bytes(value)));
|
|
293
|
-
}
|
|
294
|
-
|
|
295
167
|
module.exports = {
|
|
296
|
-
_E,
|
|
297
|
-
_R,
|
|
298
|
-
_W,
|
|
299
|
-
accessControlMessage,
|
|
300
|
-
amountFunction,
|
|
301
168
|
defaultPolicyParams,
|
|
169
|
+
defaultPolicyParamsWithBucket,
|
|
170
|
+
defaultPolicyParamsWithParams,
|
|
302
171
|
defaultBucketParams,
|
|
303
|
-
getAddress,
|
|
304
|
-
getComponentRole,
|
|
305
|
-
getDefaultSigner,
|
|
306
|
-
getRole,
|
|
307
|
-
getStorageLayout,
|
|
308
|
-
getTransactionEvent,
|
|
309
|
-
grantComponentRole,
|
|
310
|
-
grantRole,
|
|
311
172
|
makeBucketQuoteMessage,
|
|
173
|
+
makeFullQuoteMessage,
|
|
174
|
+
paramsAsUint256,
|
|
312
175
|
makePolicyId,
|
|
313
176
|
makeQuoteMessage,
|
|
314
177
|
makeSignedQuote,
|
|
315
|
-
RAY,
|
|
316
|
-
readImplementationAddress,
|
|
317
178
|
recoverAddress,
|
|
318
|
-
uintKeccak,
|
|
319
|
-
WAD,
|
|
320
179
|
};
|
package/package.json
CHANGED
|
@@ -26,7 +26,7 @@ POOL=`readAddress POOL`
|
|
|
26
26
|
ACCESSMANAGER=`readAddress ACCESSMANAGER`
|
|
27
27
|
echo "PolicyPool = $POOL / AccessManager = $ACCESSMANAGER"
|
|
28
28
|
|
|
29
|
-
for ROLE in LEVEL1 LEVEL2
|
|
29
|
+
for ROLE in LEVEL1 LEVEL2; do
|
|
30
30
|
npx hardhat --network $NETWORK ens:grantRole --contract-address $ACCESSMANAGER \
|
|
31
31
|
--role ${ROLE}_ROLE || die "Error granting ${ROLE}_ROLE"
|
|
32
32
|
done
|
|
@@ -17,7 +17,7 @@ POOL=`readAddress POOL`
|
|
|
17
17
|
ACCESSMANAGER=`readAddress ACCESSMANAGER`
|
|
18
18
|
echo "PolicyPool = $POOL / AccessManager = $ACCESSMANAGER"
|
|
19
19
|
|
|
20
|
-
for ROLE in LEVEL1 LEVEL2
|
|
20
|
+
for ROLE in LEVEL1 LEVEL2; do
|
|
21
21
|
npx hardhat --network $NETWORK ens:grantRole --contract-address $ACCESSMANAGER \
|
|
22
22
|
--role ${ROLE}_ROLE || die "Error granting ${ROLE}_ROLE"
|
|
23
23
|
done
|