@gearbox-protocol/sdk 18.2.0-next.12 → 18.2.0-next.14
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/dist/cjs/abi/310/iKillSwitchProxy.js +130 -0
- package/dist/cjs/permissionless/api/index.js +2 -1
- package/dist/cjs/permissionless/api/oracles/PermissionlessOracles.js +40 -5
- package/dist/cjs/permissionless/api/oracles/index.js +2 -1
- package/dist/cjs/permissionless/api/oracles/score/formula.js +19 -24
- package/dist/cjs/permissionless/api/oracles/score/index.js +1 -1
- package/dist/cjs/permissionless/api/oracles/score/run.js +186 -105
- package/dist/cjs/permissionless/api/oracles/stress/index.js +1 -0
- package/dist/cjs/permissionless/api/oracles/stress/run.js +63 -13
- package/dist/cjs/permissionless/bindings/bytecode-repository.js +8 -0
- package/dist/cjs/permissionless/bindings/governance/governor.js +1 -1
- package/dist/cjs/permissionless/bindings/index.js +7 -2
- package/dist/cjs/permissionless/bindings/kill-switch-proxy.js +188 -0
- package/dist/cjs/permissionless/bindings/market-configurator-factory.js +39 -1
- package/dist/cjs/permissionless/bindings/market-configurator.js +142 -0
- package/dist/cjs/permissionless/index.js +10 -3
- package/dist/cjs/permissionless/utils/index.js +1 -0
- package/dist/cjs/permissionless/utils/literals.js +2 -0
- package/dist/esm/abi/310/iKillSwitchProxy.js +129 -0
- package/dist/esm/permissionless/api/index.js +4 -4
- package/dist/esm/permissionless/api/oracles/PermissionlessOracles.js +41 -6
- package/dist/esm/permissionless/api/oracles/index.js +4 -4
- package/dist/esm/permissionless/api/oracles/score/formula.js +20 -24
- package/dist/esm/permissionless/api/oracles/score/index.js +3 -3
- package/dist/esm/permissionless/api/oracles/score/run.js +187 -107
- package/dist/esm/permissionless/api/oracles/stress/index.js +2 -2
- package/dist/esm/permissionless/api/oracles/stress/run.js +64 -15
- package/dist/esm/permissionless/bindings/bytecode-repository.js +8 -0
- package/dist/esm/permissionless/bindings/governance/governor.js +1 -1
- package/dist/esm/permissionless/bindings/index.js +4 -3
- package/dist/esm/permissionless/bindings/kill-switch-proxy.js +184 -0
- package/dist/esm/permissionless/bindings/market-configurator-factory.js +37 -0
- package/dist/esm/permissionless/bindings/market-configurator.js +143 -1
- package/dist/esm/permissionless/index.js +8 -7
- package/dist/esm/permissionless/utils/index.js +2 -2
- package/dist/esm/permissionless/utils/literals.js +2 -1
- package/dist/types/abi/310/iKillSwitchProxy.d.ts +114 -0
- package/dist/types/permissionless/api/index.d.ts +5 -5
- package/dist/types/permissionless/api/oracles/PermissionlessOracles.d.ts +30 -6
- package/dist/types/permissionless/api/oracles/index.d.ts +5 -5
- package/dist/types/permissionless/api/oracles/score/formula.d.ts +14 -17
- package/dist/types/permissionless/api/oracles/score/index.d.ts +4 -4
- package/dist/types/permissionless/api/oracles/score/run.d.ts +28 -10
- package/dist/types/permissionless/api/oracles/score/types.d.ts +33 -28
- package/dist/types/permissionless/api/oracles/stress/index.d.ts +2 -2
- package/dist/types/permissionless/api/oracles/stress/run.d.ts +11 -0
- package/dist/types/permissionless/bindings/bytecode-repository.d.ts +10 -1
- package/dist/types/permissionless/bindings/index.d.ts +4 -3
- package/dist/types/permissionless/bindings/kill-switch-proxy.d.ts +205 -0
- package/dist/types/permissionless/bindings/market-configurator-factory.d.ts +30 -0
- package/dist/types/permissionless/bindings/market-configurator.d.ts +30 -1
- package/dist/types/permissionless/bindings/types.d.ts +27 -0
- package/dist/types/permissionless/index.d.ts +9 -8
- package/dist/types/permissionless/utils/index.d.ts +2 -2
- package/dist/types/permissionless/utils/literals.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_onchain_utils_json = require("../../onchain/utils/json.js");
|
|
3
|
+
const require_onchain_base_BaseContract = require("../../onchain/base/BaseContract.js");
|
|
4
|
+
require("../../onchain/index.js");
|
|
5
|
+
const require_permissionless_utils_literals = require("../utils/literals.js");
|
|
6
|
+
const require_abi_310_iKillSwitchProxy = require("../../abi/310/iKillSwitchProxy.js");
|
|
7
|
+
const require_permissionless_bindings_market_configurator = require("./market-configurator.js");
|
|
8
|
+
let viem = require("viem");
|
|
9
|
+
//#region src/permissionless/bindings/kill-switch-proxy.ts
|
|
10
|
+
const abi = require_abi_310_iKillSwitchProxy.iKillSwitchProxyAbi;
|
|
11
|
+
/**
|
|
12
|
+
* Minor version of kill switch proxy, the latest allowed patch of it is deployed
|
|
13
|
+
*/
|
|
14
|
+
const KILL_SWITCH_PROXY_MINOR_VERSION = 310;
|
|
15
|
+
/**
|
|
16
|
+
* Salt of kill switch proxy deployed together with market configurator,
|
|
17
|
+
* makes each curator's market configurator get its own proxy
|
|
18
|
+
*/
|
|
19
|
+
function killSwitchProxySalt(curatorName) {
|
|
20
|
+
return (0, viem.keccak256)((0, viem.toHex)(curatorName));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Thrown when bytecode repository has no allowed kill switch proxy bytecode,
|
|
24
|
+
* so its address can't be computed and it can't be deployed
|
|
25
|
+
*/
|
|
26
|
+
var KillSwitchProxyNotAllowedError = class extends viem.BaseError {
|
|
27
|
+
name = "KillSwitchProxyNotAllowedError";
|
|
28
|
+
bytecodeRepository;
|
|
29
|
+
constructor(bytecodeRepository) {
|
|
30
|
+
super(`${require_permissionless_utils_literals.KILL_SWITCH_PROXY} v310 is not allowed in bytecode repository ${bytecodeRepository}.`, { metaMessages: ["Its bytecode must be uploaded, audited and allowed before it can be deployed."] });
|
|
31
|
+
this.bytecodeRepository = bytecodeRepository;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Kill switch proxy forwards calls of its `caller` via `proxyCall` until `owner` kills it.
|
|
36
|
+
* It is used as market configurator's emergency admin, so that emergency powers
|
|
37
|
+
* can be revoked instantly without going through the timelock.
|
|
38
|
+
*/
|
|
39
|
+
var KillSwitchProxyContract = class KillSwitchProxyContract extends require_onchain_base_BaseContract.BaseContract {
|
|
40
|
+
constructor(addr, client) {
|
|
41
|
+
super({ client }, {
|
|
42
|
+
abi,
|
|
43
|
+
addr,
|
|
44
|
+
name: "KillSwitchProxy"
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Encodes `constructor(address _owner, address _caller)` params
|
|
49
|
+
* @throws if any address is zero or owner equals caller (constructor reverts in that case)
|
|
50
|
+
*/
|
|
51
|
+
static encodeConstructorParams(args) {
|
|
52
|
+
const { owner, caller } = args;
|
|
53
|
+
if ((0, viem.isAddressEqual)(owner, viem.zeroAddress) || (0, viem.isAddressEqual)(caller, viem.zeroAddress)) throw new Error(`${require_permissionless_utils_literals.KILL_SWITCH_PROXY} owner and caller must be non-zero`);
|
|
54
|
+
if ((0, viem.isAddressEqual)(owner, caller)) throw new Error(`${require_permissionless_utils_literals.KILL_SWITCH_PROXY} owner must differ from caller ${caller}, provide another kill switch owner`);
|
|
55
|
+
const [constructorAbi] = abi;
|
|
56
|
+
return (0, viem.encodeAbiParameters)(constructorAbi.inputs, [owner, caller]);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Returns whether some patch of kill switch proxy v3.10 is allowed in bytecode repository
|
|
60
|
+
*/
|
|
61
|
+
static async isAvailable(bcr) {
|
|
62
|
+
try {
|
|
63
|
+
await KillSwitchProxyContract.#getVersion(bcr);
|
|
64
|
+
return true;
|
|
65
|
+
} catch (e) {
|
|
66
|
+
if (e instanceof KillSwitchProxyNotAllowedError) return false;
|
|
67
|
+
throw e;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Computes address of kill switch proxy and prepares its deployment via bytecode repository
|
|
72
|
+
* @param bcr - bytecode repository
|
|
73
|
+
* @param args.deployer - address that will send deployment transaction, it is mixed into the salt
|
|
74
|
+
* @param args.owner - address that can kill the proxy
|
|
75
|
+
* @param args.caller - address that can call through the proxy
|
|
76
|
+
* @param args.salt - deployment salt
|
|
77
|
+
* @throws {KillSwitchProxyNotAllowedError} if kill switch proxy is not allowed in bytecode repository
|
|
78
|
+
*/
|
|
79
|
+
static async prepareDeploy(bcr, args) {
|
|
80
|
+
const { deployer, owner, caller, salt } = args;
|
|
81
|
+
const encodedParams = KillSwitchProxyContract.encodeConstructorParams({
|
|
82
|
+
owner,
|
|
83
|
+
caller
|
|
84
|
+
});
|
|
85
|
+
const version = await KillSwitchProxyContract.#getVersion(bcr);
|
|
86
|
+
const [isAlreadyDeployed, address] = await bcr.isAlreadyDeployedAddress({
|
|
87
|
+
contractType: require_permissionless_utils_literals.KILL_SWITCH_PROXY,
|
|
88
|
+
version,
|
|
89
|
+
encodedParams,
|
|
90
|
+
salt,
|
|
91
|
+
owner: deployer
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
address,
|
|
95
|
+
version,
|
|
96
|
+
encodedParams,
|
|
97
|
+
salt,
|
|
98
|
+
isAlreadyDeployed,
|
|
99
|
+
isKilled: isAlreadyDeployed ? await new KillSwitchProxyContract(address, bcr.client).isKilled() : false,
|
|
100
|
+
tx: bcr.deployTx({
|
|
101
|
+
contractType: require_permissionless_utils_literals.KILL_SWITCH_PROXY,
|
|
102
|
+
version: BigInt(version),
|
|
103
|
+
encodedParams,
|
|
104
|
+
salt
|
|
105
|
+
})
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
static async #getVersion(bcr) {
|
|
109
|
+
try {
|
|
110
|
+
return await bcr.getLatestPatchVersion(require_permissionless_utils_literals.KILL_SWITCH_PROXY, 310);
|
|
111
|
+
} catch (e) {
|
|
112
|
+
const revert = e instanceof viem.BaseError ? e.walk((err) => err instanceof viem.ContractFunctionRevertedError) : null;
|
|
113
|
+
if (revert instanceof viem.ContractFunctionRevertedError && revert.data?.errorName === "VersionNotFoundException") throw new KillSwitchProxyNotAllowedError(bcr.address);
|
|
114
|
+
throw e;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async isKilled() {
|
|
118
|
+
return await this.contract.read.isKilled();
|
|
119
|
+
}
|
|
120
|
+
async state() {
|
|
121
|
+
const [caller, owner, isKilled] = await this.client.multicall({
|
|
122
|
+
allowFailure: false,
|
|
123
|
+
contracts: [
|
|
124
|
+
{
|
|
125
|
+
address: this.address,
|
|
126
|
+
abi,
|
|
127
|
+
functionName: "caller"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
address: this.address,
|
|
131
|
+
abi,
|
|
132
|
+
functionName: "owner"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
address: this.address,
|
|
136
|
+
abi,
|
|
137
|
+
functionName: "isKilled"
|
|
138
|
+
}
|
|
139
|
+
],
|
|
140
|
+
batchSize: 0
|
|
141
|
+
});
|
|
142
|
+
return {
|
|
143
|
+
caller,
|
|
144
|
+
owner,
|
|
145
|
+
isKilled
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Wraps transaction into `proxyCall`, must be sent by proxy's caller
|
|
150
|
+
*/
|
|
151
|
+
proxyCallTx(tx) {
|
|
152
|
+
return this.createRawTx({
|
|
153
|
+
functionName: "proxyCall",
|
|
154
|
+
args: [tx.to, tx.callData],
|
|
155
|
+
description: tx.description ? `KillSwitchProxy.proxyCall(${tx.description})` : void 0
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Permanently disables `proxyCall`, must be sent by proxy's owner
|
|
160
|
+
*/
|
|
161
|
+
killTx() {
|
|
162
|
+
return this.createRawTx({ functionName: "kill" });
|
|
163
|
+
}
|
|
164
|
+
parseFunctionParams(params) {
|
|
165
|
+
const { functionName, args } = params;
|
|
166
|
+
switch (functionName) {
|
|
167
|
+
case "proxyCall": {
|
|
168
|
+
const [target, data] = args;
|
|
169
|
+
const decoded = new require_permissionless_bindings_market_configurator.MarketConfiguratorContract(target, this.client).parseFunctionData(data);
|
|
170
|
+
if (decoded.functionName.startsWith("Unknown function")) return {
|
|
171
|
+
target,
|
|
172
|
+
data
|
|
173
|
+
};
|
|
174
|
+
return {
|
|
175
|
+
target,
|
|
176
|
+
functionName: decoded.functionName,
|
|
177
|
+
data: require_onchain_utils_json.json_stringify(decoded.args)
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
default: return super.parseFunctionParams(params);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
//#endregion
|
|
185
|
+
exports.KILL_SWITCH_PROXY_MINOR_VERSION = KILL_SWITCH_PROXY_MINOR_VERSION;
|
|
186
|
+
exports.KillSwitchProxyContract = KillSwitchProxyContract;
|
|
187
|
+
exports.KillSwitchProxyNotAllowedError = KillSwitchProxyNotAllowedError;
|
|
188
|
+
exports.killSwitchProxySalt = killSwitchProxySalt;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_onchain_base_BaseContract = require("../../onchain/base/BaseContract.js");
|
|
3
3
|
require("../../onchain/index.js");
|
|
4
|
+
const require_permissionless_utils_literals = require("../utils/literals.js");
|
|
5
|
+
const require_permissionless_bindings_bytecode_repository = require("./bytecode-repository.js");
|
|
6
|
+
require("../deployment/addresses.js");
|
|
7
|
+
const require_abi_310_iMarketConfiguratorFactory = require("../../abi/310/iMarketConfiguratorFactory.js");
|
|
8
|
+
const require_permissionless_bindings_kill_switch_proxy = require("./kill-switch-proxy.js");
|
|
4
9
|
//#region src/permissionless/bindings/market-configurator-factory.ts
|
|
5
|
-
const abi =
|
|
10
|
+
const abi = require_abi_310_iMarketConfiguratorFactory.iMarketConfiguratorFactoryAbi;
|
|
6
11
|
var MarketConfiguratorFactoryContract = class extends require_onchain_base_BaseContract.BaseContract {
|
|
7
12
|
constructor(addr, client) {
|
|
8
13
|
super({ client }, {
|
|
@@ -22,6 +27,39 @@ var MarketConfiguratorFactoryContract = class extends require_onchain_base_BaseC
|
|
|
22
27
|
]
|
|
23
28
|
});
|
|
24
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Builds transactions that deploy market configurator with kill switch proxy as its emergency admin:
|
|
32
|
+
* 1. kill switch proxy deployment via bytecode repository (skipped if already deployed)
|
|
33
|
+
* 2. market configurator creation with proxy as emergency admin
|
|
34
|
+
*
|
|
35
|
+
* Transactions must be sent in this order by `admin`, e.g. as one Safe batch.
|
|
36
|
+
* When `deployGovernor` is true, proxy also becomes governor's veto admin.
|
|
37
|
+
*
|
|
38
|
+
* @param args.admin - address that sends transactions, becomes market configurator admin
|
|
39
|
+
* @param args.emergencyAdmin - address that executes emergency actions through the proxy
|
|
40
|
+
* @param args.killSwitchOwner - address that can kill the proxy, defaults to `admin`
|
|
41
|
+
* @throws {KillSwitchProxyNotAllowedError} if kill switch proxy is not allowed in bytecode repository,
|
|
42
|
+
* use {@link createMarketConfiguratorTx} to deploy market configurator without it
|
|
43
|
+
*/
|
|
44
|
+
async createMarketConfiguratorWithKillSwitchTxs(args) {
|
|
45
|
+
const { admin, emergencyAdmin, killSwitchOwner, ...rest } = args;
|
|
46
|
+
const bcr = new require_permissionless_bindings_bytecode_repository.BytecodeRepositoryContract("0x1cE2B1BE96a082b1b1539F80d5D8f82Ec06a0f9A", this.client);
|
|
47
|
+
const proxy = await require_permissionless_bindings_kill_switch_proxy.KillSwitchProxyContract.prepareDeploy(bcr, {
|
|
48
|
+
deployer: admin,
|
|
49
|
+
owner: killSwitchOwner ?? admin,
|
|
50
|
+
caller: emergencyAdmin,
|
|
51
|
+
salt: require_permissionless_bindings_kill_switch_proxy.killSwitchProxySalt(args.curatorName)
|
|
52
|
+
});
|
|
53
|
+
if (proxy.isKilled) throw new Error(`${require_permissionless_utils_literals.KILL_SWITCH_PROXY} ${proxy.address} is already deployed and killed`);
|
|
54
|
+
return {
|
|
55
|
+
killSwitchProxy: proxy.address,
|
|
56
|
+
isKillSwitchProxyDeployed: proxy.isAlreadyDeployed,
|
|
57
|
+
txs: [...proxy.isAlreadyDeployed ? [] : [proxy.tx], this.createMarketConfiguratorTx({
|
|
58
|
+
...rest,
|
|
59
|
+
emergencyAdmin: proxy.address
|
|
60
|
+
})]
|
|
61
|
+
};
|
|
62
|
+
}
|
|
25
63
|
async getMarketConfigurators() {
|
|
26
64
|
return [...await this.contract.read.getMarketConfigurators()];
|
|
27
65
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_abi_310_generated = require("../../abi/310/generated.js");
|
|
3
3
|
const require_onchain_utils_json = require("../../onchain/utils/json.js");
|
|
4
|
+
const require_onchain_utils_createRawTx = require("../../onchain/utils/createRawTx.js");
|
|
4
5
|
const require_onchain_base_BaseContract = require("../../onchain/base/BaseContract.js");
|
|
5
6
|
require("../../onchain/index.js");
|
|
7
|
+
const require_permissionless_utils_literals = require("../utils/literals.js");
|
|
6
8
|
const require_permissionless_bindings_address_provider = require("./address-provider.js");
|
|
9
|
+
const require_abi_310_iKillSwitchProxy = require("../../abi/310/iKillSwitchProxy.js");
|
|
7
10
|
const require_abi_310_configure_creditSuiteParams = require("../../abi/310/configure/creditSuiteParams.js");
|
|
8
11
|
const require_permissionless_plugins_irm_constructor_params_abi = require("../plugins/irm/constructor-params-abi.js");
|
|
9
12
|
const require_permissionless_plugins_loss_policies_constructor_params_abi = require("../plugins/loss-policies/constructor-params-abi.js");
|
|
@@ -396,6 +399,83 @@ var MarketConfiguratorContract = class extends require_onchain_base_BaseContract
|
|
|
396
399
|
return;
|
|
397
400
|
}
|
|
398
401
|
}
|
|
402
|
+
/**
|
|
403
|
+
* Returns emergency admin of the market configurator.
|
|
404
|
+
* If it is a `KILL_SWITCH_PROXY`, emergency transactions must be sent by proxy's caller via `proxyCall`,
|
|
405
|
+
* otherwise directly by emergency admin itself
|
|
406
|
+
* @param emergencyAdmin - emergency admin address, read from the market configurator if not provided
|
|
407
|
+
*/
|
|
408
|
+
async getEmergencyAdmin(emergencyAdmin) {
|
|
409
|
+
const address = emergencyAdmin ?? await this.contract.read.emergencyAdmin();
|
|
410
|
+
const [contractType, caller, owner, isKilled] = await this.client.multicall({
|
|
411
|
+
allowFailure: true,
|
|
412
|
+
contracts: [
|
|
413
|
+
{
|
|
414
|
+
address,
|
|
415
|
+
abi: require_abi_310_iKillSwitchProxy.iKillSwitchProxyAbi,
|
|
416
|
+
functionName: "contractType"
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
address,
|
|
420
|
+
abi: require_abi_310_iKillSwitchProxy.iKillSwitchProxyAbi,
|
|
421
|
+
functionName: "caller"
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
address,
|
|
425
|
+
abi: require_abi_310_iKillSwitchProxy.iKillSwitchProxyAbi,
|
|
426
|
+
functionName: "owner"
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
address,
|
|
430
|
+
abi: require_abi_310_iKillSwitchProxy.iKillSwitchProxyAbi,
|
|
431
|
+
functionName: "isKilled"
|
|
432
|
+
}
|
|
433
|
+
],
|
|
434
|
+
batchSize: 0
|
|
435
|
+
});
|
|
436
|
+
let isKillSwitch = false;
|
|
437
|
+
if (contractType.status === "success") try {
|
|
438
|
+
isKillSwitch = (0, viem.hexToString)(contractType.result, { size: 32 }) === require_permissionless_utils_literals.KILL_SWITCH_PROXY;
|
|
439
|
+
} catch {}
|
|
440
|
+
if (!isKillSwitch) return {
|
|
441
|
+
type: "direct",
|
|
442
|
+
address,
|
|
443
|
+
executor: address
|
|
444
|
+
};
|
|
445
|
+
if (caller.status !== "success" || owner.status !== "success" || isKilled.status !== "success") throw new Error(`failed to read state of ${require_permissionless_utils_literals.KILL_SWITCH_PROXY} emergency admin ${address}`);
|
|
446
|
+
return {
|
|
447
|
+
type: "killSwitch",
|
|
448
|
+
address,
|
|
449
|
+
caller: caller.result,
|
|
450
|
+
owner: owner.result,
|
|
451
|
+
isKilled: isKilled.result,
|
|
452
|
+
executor: caller.result
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Routes emergency transaction to the market configurator through its emergency admin:
|
|
457
|
+
* returns transaction as is for direct emergency admin, or wraps it into `proxyCall` of kill switch proxy
|
|
458
|
+
* @param tx - emergency transaction to the market configurator, e.g. built by `emergencyConfigurePool`
|
|
459
|
+
* @param emergencyAdmin - result of {@link getEmergencyAdmin}
|
|
460
|
+
* @throws if transaction is not addressed to this market configurator or kill switch proxy is killed
|
|
461
|
+
*/
|
|
462
|
+
wrapEmergencyTx(tx, emergencyAdmin) {
|
|
463
|
+
if (!(0, viem.isAddressEqual)(tx.to, this.address)) throw new Error(`emergency tx target ${tx.to} is not market configurator ${this.address}`);
|
|
464
|
+
if (emergencyAdmin.type === "direct") return tx;
|
|
465
|
+
if (emergencyAdmin.isKilled) throw new Error(`${require_permissionless_utils_literals.KILL_SWITCH_PROXY} ${emergencyAdmin.address} of market configurator ${this.address} is killed`);
|
|
466
|
+
return require_onchain_utils_createRawTx.createRawTx(emergencyAdmin.address, {
|
|
467
|
+
abi: require_abi_310_iKillSwitchProxy.iKillSwitchProxyAbi,
|
|
468
|
+
functionName: "proxyCall",
|
|
469
|
+
args: [this.address, tx.callData]
|
|
470
|
+
}, tx.description ? `KillSwitchProxy.proxyCall(${tx.description})` : void 0);
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Reads emergency admin and routes emergency transaction through it, see {@link wrapEmergencyTx}
|
|
474
|
+
* @param tx - emergency transaction to the market configurator, e.g. built by `emergencyConfigurePool`
|
|
475
|
+
*/
|
|
476
|
+
async emergencyTx(tx) {
|
|
477
|
+
return this.wrapEmergencyTx(tx, await this.getEmergencyAdmin());
|
|
478
|
+
}
|
|
399
479
|
grantRole(role, address) {
|
|
400
480
|
return this.createRawTx({
|
|
401
481
|
functionName: "grantRole",
|
|
@@ -609,9 +689,53 @@ var MarketConfiguratorContract = class extends require_onchain_base_BaseContract
|
|
|
609
689
|
role: (0, viem.hexToString)(role, { size: 32 })
|
|
610
690
|
};
|
|
611
691
|
}
|
|
692
|
+
case "emergencyConfigurePool":
|
|
693
|
+
case "emergencyConfigurePriceOracle":
|
|
694
|
+
case "emergencyConfigureLossPolicy":
|
|
695
|
+
case "emergencyConfigureRateKeeper":
|
|
696
|
+
case "emergencyConfigureInterestRateModel": {
|
|
697
|
+
const [pool, calldata] = args;
|
|
698
|
+
const decoded = this.#decodeEmergencyConfig(functionName, calldata);
|
|
699
|
+
return decoded ? {
|
|
700
|
+
pool,
|
|
701
|
+
data: require_onchain_utils_json.json_stringify(decoded)
|
|
702
|
+
} : {
|
|
703
|
+
pool,
|
|
704
|
+
calldata
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
case "emergencyConfigureCreditSuite": {
|
|
708
|
+
const [creditManager, calldata] = args;
|
|
709
|
+
const decoded = this.#decodeEmergencyConfig(functionName, calldata);
|
|
710
|
+
return decoded ? {
|
|
711
|
+
creditManager,
|
|
712
|
+
data: require_onchain_utils_json.json_stringify(decoded)
|
|
713
|
+
} : {
|
|
714
|
+
creditManager,
|
|
715
|
+
calldata
|
|
716
|
+
};
|
|
717
|
+
}
|
|
612
718
|
default: return super.parseFunctionParams(params);
|
|
613
719
|
}
|
|
614
720
|
}
|
|
721
|
+
/**
|
|
722
|
+
* Emergency actions share selectors with regular configuration actions only partially
|
|
723
|
+
* (e.g., `pause`, `forbidToken`, `setPriceFeed`), so decoding is best-effort
|
|
724
|
+
*/
|
|
725
|
+
#decodeEmergencyConfig(functionName, calldata) {
|
|
726
|
+
const factory = {
|
|
727
|
+
emergencyConfigurePool: this.poolFactory,
|
|
728
|
+
emergencyConfigureCreditSuite: this.creditFactory,
|
|
729
|
+
emergencyConfigurePriceOracle: this.priceOracleFactory,
|
|
730
|
+
emergencyConfigureLossPolicy: this.lossPolicyFactory,
|
|
731
|
+
emergencyConfigureRateKeeper: this.rateKeeperFactory
|
|
732
|
+
}[functionName];
|
|
733
|
+
try {
|
|
734
|
+
return factory?.decodeConfig(calldata) ?? null;
|
|
735
|
+
} catch {
|
|
736
|
+
return null;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
615
739
|
emergencyConfigurePool(pool, calldata) {
|
|
616
740
|
return this.createRawTx({
|
|
617
741
|
functionName: "emergencyConfigurePool",
|
|
@@ -636,6 +760,24 @@ var MarketConfiguratorContract = class extends require_onchain_base_BaseContract
|
|
|
636
760
|
args: [pool, calldata]
|
|
637
761
|
});
|
|
638
762
|
}
|
|
763
|
+
/**
|
|
764
|
+
* Note: current interest rate model factory forbids all emergency configuration calls
|
|
765
|
+
*/
|
|
766
|
+
emergencyConfigureInterestRateModel(pool, calldata) {
|
|
767
|
+
return this.createRawTx({
|
|
768
|
+
functionName: "emergencyConfigureInterestRateModel",
|
|
769
|
+
args: [pool, calldata]
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* Note: current rate keeper factory forbids all emergency configuration calls
|
|
774
|
+
*/
|
|
775
|
+
emergencyConfigureRateKeeper(pool, calldata) {
|
|
776
|
+
return this.createRawTx({
|
|
777
|
+
functionName: "emergencyConfigureRateKeeper",
|
|
778
|
+
args: [pool, calldata]
|
|
779
|
+
});
|
|
780
|
+
}
|
|
639
781
|
};
|
|
640
782
|
//#endregion
|
|
641
783
|
exports.MarketConfiguratorContract = MarketConfiguratorContract;
|
|
@@ -30,13 +30,14 @@ const require_permissionless_utils_price_update_get_updatable_feeds = require(".
|
|
|
30
30
|
const require_permissionless_api_transactions_InstanceOwnerTransactions = require("./api/transactions/InstanceOwnerTransactions.js");
|
|
31
31
|
const require_permissionless_api_GearboxPermissionless = require("./api/GearboxPermissionless.js");
|
|
32
32
|
require("./api/index.js");
|
|
33
|
-
const require_permissionless_bindings_market_configurator_factory = require("./bindings/market-configurator-factory.js");
|
|
34
|
-
const require_permissionless_bindings_cross_chain_multisig = require("./bindings/cross-chain-multisig.js");
|
|
35
33
|
const require_permissionless_utils_create2 = require("./utils/create2.js");
|
|
36
34
|
const require_permissionless_utils_format = require("./utils/format.js");
|
|
37
35
|
const require_permissionless_core_raw_tx = require("./core/raw-tx.js");
|
|
38
36
|
const require_permissionless_bindings_types = require("./bindings/types.js");
|
|
39
37
|
const require_permissionless_bindings_market_configurator = require("./bindings/market-configurator.js");
|
|
38
|
+
const require_permissionless_bindings_kill_switch_proxy = require("./bindings/kill-switch-proxy.js");
|
|
39
|
+
const require_permissionless_bindings_market_configurator_factory = require("./bindings/market-configurator-factory.js");
|
|
40
|
+
const require_permissionless_bindings_cross_chain_multisig = require("./bindings/cross-chain-multisig.js");
|
|
40
41
|
const require_permissionless_bindings_governance_governor = require("./bindings/governance/governor.js");
|
|
41
42
|
const require_permissionless_bindings_governance_timelock = require("./bindings/governance/timelock.js");
|
|
42
43
|
require("./bindings/index.js");
|
|
@@ -67,6 +68,10 @@ exports.GovernorContract = require_permissionless_bindings_governance_governor.G
|
|
|
67
68
|
exports.INSTANCE_MANAGER = require_permissionless_utils_literals.INSTANCE_MANAGER;
|
|
68
69
|
exports.InstanceManagerContract = require_permissionless_bindings_instance_manager.InstanceManagerContract;
|
|
69
70
|
exports.InstanceOwnerTransactions = require_permissionless_api_transactions_InstanceOwnerTransactions.InstanceOwnerTransactions;
|
|
71
|
+
exports.KILL_SWITCH_PROXY = require_permissionless_utils_literals.KILL_SWITCH_PROXY;
|
|
72
|
+
exports.KILL_SWITCH_PROXY_MINOR_VERSION = require_permissionless_bindings_kill_switch_proxy.KILL_SWITCH_PROXY_MINOR_VERSION;
|
|
73
|
+
exports.KillSwitchProxyContract = require_permissionless_bindings_kill_switch_proxy.KillSwitchProxyContract;
|
|
74
|
+
exports.KillSwitchProxyNotAllowedError = require_permissionless_bindings_kill_switch_proxy.KillSwitchProxyNotAllowedError;
|
|
70
75
|
exports.MAINNET_CCM_CONSTRUCTOR_PARAMS = require_permissionless_deployment_mainnet.MAINNET_CCM_CONSTRUCTOR_PARAMS;
|
|
71
76
|
exports.MAINNET_DEPLOYMENT_BLOCK = require_permissionless_deployment_mainnet.MAINNET_DEPLOYMENT_BLOCK;
|
|
72
77
|
exports.MAINNET_DEPLOYMENT_CCM_SALT = require_permissionless_deployment_mainnet.MAINNET_DEPLOYMENT_CCM_SALT;
|
|
@@ -86,7 +91,6 @@ exports.PriceFeedSaltMissingError = require_permissionless_api_errors.PriceFeedS
|
|
|
86
91
|
exports.PriceFeedStalenessUnknownError = require_permissionless_api_errors.PriceFeedStalenessUnknownError;
|
|
87
92
|
exports.PriceFeedStoreContract = require_permissionless_bindings_price_feed_store.PriceFeedStoreContract;
|
|
88
93
|
exports.RATE_FEED_TYPE = require_permissionless_api_oracles_stress_run.RATE_FEED_TYPE;
|
|
89
|
-
exports.REVERT_SCORE = require_permissionless_api_oracles_score_formula.REVERT_SCORE;
|
|
90
94
|
exports.RoutingManagerContract = require_permissionless_bindings_router_routing_manager.RoutingManagerContract;
|
|
91
95
|
exports.SCORE_MULTIPLIER = require_permissionless_api_oracles_score_formula.SCORE_MULTIPLIER;
|
|
92
96
|
exports.TOKEN_COMPRESSOR = require_permissionless_utils_literals.TOKEN_COMPRESSOR;
|
|
@@ -126,16 +130,19 @@ exports.getSafeBatches = require_permissionless_utils_governance_batch.getSafeBa
|
|
|
126
130
|
exports.getUpdatablePriceFeeds = require_permissionless_utils_price_update_get_updatable_feeds.getUpdatablePriceFeeds;
|
|
127
131
|
exports.groupOverride = require_permissionless_api_oracles_stress_override.groupOverride;
|
|
128
132
|
exports.handleSalt = require_permissionless_utils_create2.handleSalt;
|
|
133
|
+
exports.killSwitchProxySalt = require_permissionless_bindings_kill_switch_proxy.killSwitchProxySalt;
|
|
129
134
|
exports.normalizeSignature = require_permissionless_utils_signature.normalizeSignature;
|
|
130
135
|
exports.perturb = require_permissionless_api_oracles_stress_override.perturb;
|
|
131
136
|
exports.priceFeedSalt = require_permissionless_api_deploy_PermissionlessDeploy.priceFeedSalt;
|
|
132
137
|
exports.priceFeedSetupParams = require_permissionless_bindings_pricefeeds_index.priceFeedSetupParams;
|
|
133
138
|
exports.rateStub = require_permissionless_api_oracles_stress_override.rateStub;
|
|
139
|
+
exports.readFeedTrees = require_permissionless_api_oracles_stress_run.readFeedTrees;
|
|
134
140
|
exports.readForest = require_permissionless_api_oracles_stress_run.readForest;
|
|
135
141
|
exports.readRateTargets = require_permissionless_api_oracles_stress_run.readRateTargets;
|
|
136
142
|
exports.readUnder = require_permissionless_api_oracles_stress_run.readUnder;
|
|
137
143
|
exports.roundDataStub = require_permissionless_api_oracles_stress_override.roundDataStub;
|
|
138
144
|
exports.runAssetScores = require_permissionless_api_oracles_score_run.runAssetScores;
|
|
145
|
+
exports.runFeedPairScore = require_permissionless_api_oracles_score_run.runFeedPairScore;
|
|
139
146
|
exports.runStressTest = require_permissionless_api_oracles_stress_run.runStressTest;
|
|
140
147
|
exports.scoreGroup = require_permissionless_api_oracles_stress_score.scoreGroup;
|
|
141
148
|
exports.scoreOfFactor = require_permissionless_api_oracles_score_formula.scoreOfFactor;
|
|
@@ -16,6 +16,7 @@ exports.BYTECODE_REPOSITORY = require_permissionless_utils_literals.BYTECODE_REP
|
|
|
16
16
|
exports.CROSS_CHAIN_GOVERNANCE = require_permissionless_utils_literals.CROSS_CHAIN_GOVERNANCE;
|
|
17
17
|
exports.CROSS_CHAIN_MULTISIG = require_permissionless_utils_literals.CROSS_CHAIN_MULTISIG;
|
|
18
18
|
exports.INSTANCE_MANAGER = require_permissionless_utils_literals.INSTANCE_MANAGER;
|
|
19
|
+
exports.KILL_SWITCH_PROXY = require_permissionless_utils_literals.KILL_SWITCH_PROXY;
|
|
19
20
|
exports.MARKET_CONFIGURATOR_FACTORY = require_permissionless_utils_literals.MARKET_CONFIGURATOR_FACTORY;
|
|
20
21
|
exports.PRICE_FEED_STORE = require_permissionless_utils_literals.PRICE_FEED_STORE;
|
|
21
22
|
exports.PUBLIC_CREATE2_FACTORY = require_permissionless_utils_create2.PUBLIC_CREATE2_FACTORY;
|
|
@@ -7,11 +7,13 @@ const TOKEN_COMPRESSOR = "GLOBAL::TOKEN_COMPRESSOR";
|
|
|
7
7
|
const CROSS_CHAIN_MULTISIG = "CROSS_CHAIN_MULTISIG";
|
|
8
8
|
const PRICE_FEED_STORE = "PRICE_FEED_STORE";
|
|
9
9
|
const MARKET_CONFIGURATOR_FACTORY = "MARKET_CONFIGURATOR_FACTORY";
|
|
10
|
+
const KILL_SWITCH_PROXY = "KILL_SWITCH_PROXY";
|
|
10
11
|
//#endregion
|
|
11
12
|
exports.BYTECODE_REPOSITORY = BYTECODE_REPOSITORY;
|
|
12
13
|
exports.CROSS_CHAIN_GOVERNANCE = CROSS_CHAIN_GOVERNANCE;
|
|
13
14
|
exports.CROSS_CHAIN_MULTISIG = CROSS_CHAIN_MULTISIG;
|
|
14
15
|
exports.INSTANCE_MANAGER = INSTANCE_MANAGER;
|
|
16
|
+
exports.KILL_SWITCH_PROXY = KILL_SWITCH_PROXY;
|
|
15
17
|
exports.MARKET_CONFIGURATOR_FACTORY = MARKET_CONFIGURATOR_FACTORY;
|
|
16
18
|
exports.PRICE_FEED_STORE = PRICE_FEED_STORE;
|
|
17
19
|
exports.TOKEN_COMPRESSOR = TOKEN_COMPRESSOR;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
//#region src/abi/310/iKillSwitchProxy.ts
|
|
2
|
+
const iKillSwitchProxyAbi = [
|
|
3
|
+
{
|
|
4
|
+
type: "constructor",
|
|
5
|
+
inputs: [{
|
|
6
|
+
name: "_owner",
|
|
7
|
+
internalType: "address",
|
|
8
|
+
type: "address"
|
|
9
|
+
}, {
|
|
10
|
+
name: "_caller",
|
|
11
|
+
internalType: "address",
|
|
12
|
+
type: "address"
|
|
13
|
+
}],
|
|
14
|
+
stateMutability: "nonpayable"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type: "function",
|
|
18
|
+
inputs: [],
|
|
19
|
+
name: "caller",
|
|
20
|
+
outputs: [{
|
|
21
|
+
name: "",
|
|
22
|
+
internalType: "address",
|
|
23
|
+
type: "address"
|
|
24
|
+
}],
|
|
25
|
+
stateMutability: "view"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: "function",
|
|
29
|
+
inputs: [],
|
|
30
|
+
name: "contractType",
|
|
31
|
+
outputs: [{
|
|
32
|
+
name: "",
|
|
33
|
+
internalType: "bytes32",
|
|
34
|
+
type: "bytes32"
|
|
35
|
+
}],
|
|
36
|
+
stateMutability: "view"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
type: "function",
|
|
40
|
+
inputs: [],
|
|
41
|
+
name: "isKilled",
|
|
42
|
+
outputs: [{
|
|
43
|
+
name: "",
|
|
44
|
+
internalType: "bool",
|
|
45
|
+
type: "bool"
|
|
46
|
+
}],
|
|
47
|
+
stateMutability: "view"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
type: "function",
|
|
51
|
+
inputs: [],
|
|
52
|
+
name: "kill",
|
|
53
|
+
outputs: [],
|
|
54
|
+
stateMutability: "nonpayable"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: "function",
|
|
58
|
+
inputs: [],
|
|
59
|
+
name: "owner",
|
|
60
|
+
outputs: [{
|
|
61
|
+
name: "",
|
|
62
|
+
internalType: "address",
|
|
63
|
+
type: "address"
|
|
64
|
+
}],
|
|
65
|
+
stateMutability: "view"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
type: "function",
|
|
69
|
+
inputs: [{
|
|
70
|
+
name: "target",
|
|
71
|
+
internalType: "address",
|
|
72
|
+
type: "address"
|
|
73
|
+
}, {
|
|
74
|
+
name: "data",
|
|
75
|
+
internalType: "bytes",
|
|
76
|
+
type: "bytes"
|
|
77
|
+
}],
|
|
78
|
+
name: "proxyCall",
|
|
79
|
+
outputs: [{
|
|
80
|
+
name: "result",
|
|
81
|
+
internalType: "bytes",
|
|
82
|
+
type: "bytes"
|
|
83
|
+
}],
|
|
84
|
+
stateMutability: "nonpayable"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
type: "function",
|
|
88
|
+
inputs: [],
|
|
89
|
+
name: "version",
|
|
90
|
+
outputs: [{
|
|
91
|
+
name: "",
|
|
92
|
+
internalType: "uint256",
|
|
93
|
+
type: "uint256"
|
|
94
|
+
}],
|
|
95
|
+
stateMutability: "view"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
type: "event",
|
|
99
|
+
anonymous: false,
|
|
100
|
+
inputs: [],
|
|
101
|
+
name: "Killed"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: "error",
|
|
105
|
+
inputs: [{
|
|
106
|
+
name: "caller",
|
|
107
|
+
internalType: "address",
|
|
108
|
+
type: "address"
|
|
109
|
+
}],
|
|
110
|
+
name: "CallerIsNotOwnerException"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: "error",
|
|
114
|
+
inputs: [],
|
|
115
|
+
name: "KilledException"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
type: "error",
|
|
119
|
+
inputs: [],
|
|
120
|
+
name: "OnlyCallerException"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
type: "error",
|
|
124
|
+
inputs: [],
|
|
125
|
+
name: "OwnerSameAsCallerException"
|
|
126
|
+
}
|
|
127
|
+
];
|
|
128
|
+
//#endregion
|
|
129
|
+
export { iKillSwitchProxyAbi };
|
|
@@ -9,13 +9,13 @@ import "./deploy/index.js";
|
|
|
9
9
|
import { classifySources, sourcesByFeed } from "./oracles/stress/classify.js";
|
|
10
10
|
import { UNBOUNDED_DOWN, UNBOUNDED_UP, groupOverride, perturb, rateStub, roundDataStub } from "./oracles/stress/override.js";
|
|
11
11
|
import { scoreGroup, slotHarm, verdictOf } from "./oracles/stress/score.js";
|
|
12
|
-
import { DEFAULT_SCENARIOS, RATE_FEED_TYPE, readForest, readRateTargets, readUnder, runStressTest } from "./oracles/stress/run.js";
|
|
13
|
-
import {
|
|
14
|
-
import { runAssetScores } from "./oracles/score/run.js";
|
|
12
|
+
import { DEFAULT_SCENARIOS, RATE_FEED_TYPE, readFeedTrees, readForest, readRateTargets, readUnder, runStressTest } from "./oracles/stress/run.js";
|
|
13
|
+
import { SCORE_MULTIPLIER, factorOf, finalPrice, scoreOfFactor, worstOf } from "./oracles/score/formula.js";
|
|
14
|
+
import { runAssetScores, runFeedPairScore } from "./oracles/score/run.js";
|
|
15
15
|
import { GET_PRICES_CHUNK_SIZE, GET_PRICES_GAS_LIMIT_BY_CHAIN_ID, PermissionlessOracles } from "./oracles/PermissionlessOracles.js";
|
|
16
16
|
import { InstanceOwnerTransactions } from "./transactions/InstanceOwnerTransactions.js";
|
|
17
17
|
import { GearboxPermissionless } from "./GearboxPermissionless.js";
|
|
18
18
|
import "./oracles/index.js";
|
|
19
19
|
import "./transactions/index.js";
|
|
20
20
|
import "./types.js";
|
|
21
|
-
export { ChainsNamespace, DEFAULT_DEPLOY_SALT, DEFAULT_SCENARIOS, GET_PRICES_CHUNK_SIZE, GET_PRICES_GAS_LIMIT_BY_CHAIN_ID, GearboxPermissionless, InstanceOwnerTransactions, PermissionlessAnalytics, PermissionlessChainUnreachableError, PermissionlessDeploy, PermissionlessNotAttachedError, PermissionlessOracles, PriceFeedNotInStoreError, PriceFeedSaltMissingError, PriceFeedStalenessUnknownError, RATE_FEED_TYPE,
|
|
21
|
+
export { ChainsNamespace, DEFAULT_DEPLOY_SALT, DEFAULT_SCENARIOS, GET_PRICES_CHUNK_SIZE, GET_PRICES_GAS_LIMIT_BY_CHAIN_ID, GearboxPermissionless, InstanceOwnerTransactions, PermissionlessAnalytics, PermissionlessChainUnreachableError, PermissionlessDeploy, PermissionlessNotAttachedError, PermissionlessOracles, PriceFeedNotInStoreError, PriceFeedSaltMissingError, PriceFeedStalenessUnknownError, RATE_FEED_TYPE, SCORE_MULTIPLIER, UNBOUNDED_DOWN, UNBOUNDED_UP, classifySources, deriveEffectiveStalenessPeriod, factorOf, finalPrice, groupOverride, perturb, priceFeedSalt, rateStub, readFeedTrees, readForest, readRateTargets, readUnder, roundDataStub, runAssetScores, runFeedPairScore, runStressTest, scoreGroup, scoreOfFactor, slotHarm, sourcesByFeed, verdictOf, worstOf };
|