@gearbox-protocol/sdk 18.2.0-next.1 → 18.2.0-next.11
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/compressors/subcompressors/liquidation/treehouseLiquidationSubcompressor.js +179 -0
- package/dist/cjs/abi/compressors/subcompressors/withdrawal/treehouseWithdrawalSubcompressor.js +534 -0
- package/dist/cjs/abi/router/treehouseWorker.js +885 -0
- package/dist/cjs/dev/AccountOpener.js +1 -1
- package/dist/cjs/dev/withdrawalUtils.js +1 -1
- package/dist/cjs/history/trace/extractTransfers.js +1 -1
- package/dist/cjs/onchain/accounts/CreditAccountsServiceV310.js +2 -2
- package/dist/cjs/onchain/accounts/liquidations/LiquidationsService.js +1 -1
- package/dist/cjs/onchain/accounts/withdrawal-compressor/RedemptionLoggerV310Contract.js +1 -2
- package/dist/cjs/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV310Contract.js +1 -2
- package/dist/cjs/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV311Contract.js +1 -2
- package/dist/cjs/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.js +1 -1
- package/dist/cjs/onchain/base/TokensMeta.js +3 -3
- package/dist/cjs/onchain/core/createAddressProvider.js +1 -1
- package/dist/cjs/onchain/market/adapters/abi/actionAbi.js +1 -0
- package/dist/cjs/onchain/market/adapters/abi/conctructorAbi.js +3 -0
- package/dist/cjs/onchain/market/adapters/contracts/AccountMigratorAdapterContract.js +1 -1
- package/dist/cjs/onchain/market/adapters/contracts/ERC4626AdapterContract.js +1 -1
- package/dist/cjs/onchain/market/adapters/types.js +3 -0
- package/dist/cjs/onchain/market/credit/CreditFacadeV310BaseContract.js +1 -1
- package/dist/cjs/onchain/market/pool/PoolV310Contract.js +1 -1
- package/dist/cjs/onchain/market/rwa/createDegenNFT.js +1 -1
- package/dist/cjs/onchain/market/zapper/IETHZapperContract.js +1 -2
- package/dist/cjs/onchain/market/zapper/ZapperContract.js +1 -1
- package/dist/cjs/onchain/preview/preview/previewPoolPositionOperation.js +2 -2
- package/dist/cjs/onchain/utils/viem/simulateWithPriceUpdates.js +1 -1
- package/dist/cjs/permissionless/api/index.js +26 -0
- package/dist/cjs/permissionless/api/oracles/PermissionlessOracles.js +585 -47
- package/dist/cjs/permissionless/api/oracles/enrich.js +99 -0
- package/dist/cjs/permissionless/api/oracles/index.js +28 -0
- package/dist/cjs/permissionless/api/oracles/schemas.js +102 -35
- package/dist/cjs/permissionless/api/oracles/score/formula.js +99 -0
- package/dist/cjs/permissionless/api/oracles/score/index.js +8 -0
- package/dist/cjs/permissionless/api/oracles/score/run.js +88 -0
- package/dist/cjs/permissionless/api/oracles/score/types.js +1 -0
- package/dist/cjs/permissionless/api/oracles/stress/classify.js +258 -0
- package/dist/cjs/permissionless/api/oracles/stress/index.js +22 -0
- package/dist/cjs/permissionless/api/oracles/stress/override.js +125 -0
- package/dist/cjs/permissionless/api/oracles/stress/run.js +432 -0
- package/dist/cjs/permissionless/api/oracles/stress/score.js +98 -0
- package/dist/cjs/permissionless/api/oracles/stress/types.js +1 -0
- package/dist/cjs/permissionless/api/schemas.js +0 -3
- package/dist/cjs/permissionless/bindings/index.js +1 -1
- package/dist/cjs/permissionless/index.js +29 -1
- package/dist/cjs/permissionless/utils/index.js +2 -0
- package/dist/cjs/permissionless/utils/price-update/get-prices.js +64 -0
- package/dist/cjs/permissionless/utils/price-update/index.js +2 -0
- package/dist/cjs/testnets/TestnetsAPI.js +179 -0
- package/dist/cjs/testnets/errors/TestnetNotFoundError.js +15 -0
- package/dist/cjs/testnets/errors/TestnetRequestFailedError.js +24 -0
- package/dist/cjs/testnets/errors/TestnetStatusError.js +19 -0
- package/dist/cjs/testnets/errors/TestnetValidationError.js +24 -0
- package/dist/cjs/testnets/errors/TestnetWaitTimeoutError.js +30 -0
- package/dist/cjs/testnets/errors/TestnetsError.js +34 -0
- package/dist/cjs/testnets/errors/index.js +13 -0
- package/dist/cjs/testnets/index.js +32 -0
- package/dist/cjs/testnets/package.json +1 -0
- package/dist/cjs/testnets/schemas.js +242 -0
- package/dist/cjs/testnets/types.js +1 -0
- package/dist/esm/abi/compressors/subcompressors/liquidation/treehouseLiquidationSubcompressor.js +178 -0
- package/dist/esm/abi/compressors/subcompressors/withdrawal/treehouseWithdrawalSubcompressor.js +533 -0
- package/dist/esm/abi/router/treehouseWorker.js +884 -0
- package/dist/esm/onchain/market/adapters/abi/actionAbi.js +1 -0
- package/dist/esm/onchain/market/adapters/abi/conctructorAbi.js +3 -0
- package/dist/esm/onchain/market/adapters/types.js +3 -0
- package/dist/esm/permissionless/api/index.js +7 -1
- package/dist/esm/permissionless/api/oracles/PermissionlessOracles.js +587 -49
- package/dist/esm/permissionless/api/oracles/enrich.js +94 -0
- package/dist/esm/permissionless/api/oracles/index.js +10 -1
- package/dist/esm/permissionless/api/oracles/schemas.js +95 -35
- package/dist/esm/permissionless/api/oracles/score/formula.js +96 -0
- package/dist/esm/permissionless/api/oracles/score/index.js +4 -0
- package/dist/esm/permissionless/api/oracles/score/run.js +87 -0
- package/dist/esm/permissionless/api/oracles/score/types.js +1 -0
- package/dist/esm/permissionless/api/oracles/stress/classify.js +256 -0
- package/dist/esm/permissionless/api/oracles/stress/index.js +6 -0
- package/dist/esm/permissionless/api/oracles/stress/override.js +119 -0
- package/dist/esm/permissionless/api/oracles/stress/run.js +427 -0
- package/dist/esm/permissionless/api/oracles/stress/score.js +95 -0
- package/dist/esm/permissionless/api/oracles/stress/types.js +1 -0
- package/dist/esm/permissionless/api/schemas.js +2 -4
- package/dist/esm/permissionless/bindings/index.js +1 -1
- package/dist/esm/permissionless/index.js +9 -3
- package/dist/esm/permissionless/utils/index.js +2 -2
- package/dist/esm/permissionless/utils/price-update/get-prices.js +63 -1
- package/dist/esm/permissionless/utils/price-update/index.js +2 -2
- package/dist/esm/testnets/TestnetsAPI.js +178 -0
- package/dist/esm/testnets/errors/TestnetNotFoundError.js +14 -0
- package/dist/esm/testnets/errors/TestnetRequestFailedError.js +23 -0
- package/dist/esm/testnets/errors/TestnetStatusError.js +18 -0
- package/dist/esm/testnets/errors/TestnetValidationError.js +23 -0
- package/dist/esm/testnets/errors/TestnetWaitTimeoutError.js +29 -0
- package/dist/esm/testnets/errors/TestnetsError.js +33 -0
- package/dist/esm/testnets/errors/index.js +7 -0
- package/dist/esm/testnets/index.js +11 -0
- package/dist/esm/testnets/package.json +1 -0
- package/dist/esm/testnets/schemas.js +228 -0
- package/dist/esm/testnets/types.js +1 -0
- package/dist/types/abi/compressors/subcompressors/liquidation/treehouseLiquidationSubcompressor.d.ts +148 -0
- package/dist/types/abi/compressors/subcompressors/withdrawal/treehouseWithdrawalSubcompressor.d.ts +440 -0
- package/dist/types/abi/router/treehouseWorker.d.ts +728 -0
- package/dist/types/onchain/market/adapters/types.d.ts +4 -1
- package/dist/types/permissionless/api/index.d.ts +10 -2
- package/dist/types/permissionless/api/oracles/PermissionlessOracles.d.ts +232 -35
- package/dist/types/permissionless/api/oracles/enrich.d.ts +59 -0
- package/dist/types/permissionless/api/oracles/index.d.ts +12 -2
- package/dist/types/permissionless/api/oracles/schemas.d.ts +209 -22
- package/dist/types/permissionless/api/oracles/score/formula.d.ts +46 -0
- package/dist/types/permissionless/api/oracles/score/index.d.ts +4 -0
- package/dist/types/permissionless/api/oracles/score/run.d.ts +21 -0
- package/dist/types/permissionless/api/oracles/score/types.d.ts +85 -0
- package/dist/types/permissionless/api/oracles/stress/classify.d.ts +57 -0
- package/dist/types/permissionless/api/oracles/stress/index.d.ts +6 -0
- package/dist/types/permissionless/api/oracles/stress/override.d.ts +59 -0
- package/dist/types/permissionless/api/oracles/stress/run.d.ts +73 -0
- package/dist/types/permissionless/api/oracles/stress/score.d.ts +57 -0
- package/dist/types/permissionless/api/oracles/stress/types.d.ts +272 -0
- package/dist/types/permissionless/api/oracles/types.d.ts +408 -63
- package/dist/types/permissionless/api/schemas.d.ts +0 -2
- package/dist/types/permissionless/index.d.ts +11 -3
- package/dist/types/permissionless/utils/index.d.ts +2 -2
- package/dist/types/permissionless/utils/price-update/get-prices.d.ts +33 -0
- package/dist/types/permissionless/utils/price-update/index.d.ts +2 -2
- package/dist/types/testnets/TestnetsAPI.d.ts +108 -0
- package/dist/types/testnets/errors/TestnetNotFoundError.d.ts +12 -0
- package/dist/types/testnets/errors/TestnetRequestFailedError.d.ts +11 -0
- package/dist/types/testnets/errors/TestnetStatusError.d.ts +15 -0
- package/dist/types/testnets/errors/TestnetValidationError.d.ts +16 -0
- package/dist/types/testnets/errors/TestnetWaitTimeoutError.d.ts +21 -0
- package/dist/types/testnets/errors/TestnetsError.d.ts +47 -0
- package/dist/types/testnets/errors/index.d.ts +7 -0
- package/dist/types/testnets/index.d.ts +11 -0
- package/dist/types/testnets/schemas.d.ts +554 -0
- package/dist/types/testnets/types.d.ts +717 -0
- package/package.json +9 -3
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_abi_compressors_priceFeedCompressor = require("../../../../abi/compressors/priceFeedCompressor.js");
|
|
3
|
+
const require_permissionless_api_oracles_stress_classify = require("./classify.js");
|
|
4
|
+
const require_permissionless_api_oracles_stress_override = require("./override.js");
|
|
5
|
+
const require_permissionless_api_oracles_stress_score = require("./score.js");
|
|
6
|
+
let viem = require("viem");
|
|
7
|
+
//#region src/permissionless/api/oracles/stress/run.ts
|
|
8
|
+
/**
|
|
9
|
+
* The two ends the question is asked at, which is what "infinitely large and
|
|
10
|
+
* infinitely small" comes to once a type has to hold it.
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_SCENARIOS = [{
|
|
13
|
+
label: "unbounded up",
|
|
14
|
+
multiplier: require_permissionless_api_oracles_stress_override.UNBOUNDED_UP
|
|
15
|
+
}, {
|
|
16
|
+
label: "unbounded down",
|
|
17
|
+
multiplier: require_permissionless_api_oracles_stress_override.UNBOUNDED_DOWN
|
|
18
|
+
}];
|
|
19
|
+
const aggregatorAbi = (0, viem.parseAbi)(["function latestRoundData() view returns (uint80, int256, uint256, uint256, uint80)"]);
|
|
20
|
+
/**
|
|
21
|
+
* What a Gearbox LP feed exposes about the rate it reads.
|
|
22
|
+
*
|
|
23
|
+
* `lpContract` is the contract the rate comes off — the wstETH token, the
|
|
24
|
+
* vault, the Curve pool — and is what a rate source is perturbed at.
|
|
25
|
+
* The two bounds are the window the feed will accept a rate inside, which is
|
|
26
|
+
* both this test's baseline and, as it turns out, most of its answer.
|
|
27
|
+
*/
|
|
28
|
+
const lpFeedAbi = (0, viem.parseAbi)([
|
|
29
|
+
"function lpContract() view returns (address)",
|
|
30
|
+
"function lowerBound() view returns (uint256)",
|
|
31
|
+
"function upperBound() view returns (uint256)"
|
|
32
|
+
]);
|
|
33
|
+
/**
|
|
34
|
+
* The Gearbox LP feeds: a protocol's exchange rate, clamped to a window the
|
|
35
|
+
* feed holds, times the price of what the rate is denominated in.
|
|
36
|
+
*/
|
|
37
|
+
const RATE_FEED_TYPE = /::(ERC4626|CURVE_\w+|WSTETH|YEARN|MELLOW\w*|BALANCER\w*)$/;
|
|
38
|
+
/** The compressor's `bytes32` contract type, as the string it encodes. */
|
|
39
|
+
function typeName(raw) {
|
|
40
|
+
return (0, viem.hexToString)(raw).replace(/\0+$/, "");
|
|
41
|
+
}
|
|
42
|
+
/** `price × amount` in USD, both of them as the chain reports them. */
|
|
43
|
+
function usd(amount, price) {
|
|
44
|
+
if (amount === null || price === null || price <= 0n) return null;
|
|
45
|
+
return amount * Number((0, viem.formatUnits)(price, 8));
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The feed trees of every oracle the chain's markets use, flattened.
|
|
49
|
+
*
|
|
50
|
+
* One call per oracle and not per feed: the compressor answers an oracle's
|
|
51
|
+
* entire tree at once, with every node's type, description, children and
|
|
52
|
+
* current answer, which is the whole of what this test needs off the chain.
|
|
53
|
+
* A node carried by several oracles is one node — the trees overlap heavily,
|
|
54
|
+
* since the aggregators under them are the same handful.
|
|
55
|
+
*/
|
|
56
|
+
async function readForest(client, compressor, oracles) {
|
|
57
|
+
const states = await client.multicall({
|
|
58
|
+
contracts: oracles.map((oracle) => ({
|
|
59
|
+
address: compressor,
|
|
60
|
+
abi: require_abi_compressors_priceFeedCompressor.priceFeedCompressorAbi,
|
|
61
|
+
functionName: "getPriceOracleState",
|
|
62
|
+
args: [oracle]
|
|
63
|
+
})),
|
|
64
|
+
allowFailure: true
|
|
65
|
+
});
|
|
66
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
67
|
+
const answers = /* @__PURE__ */ new Map();
|
|
68
|
+
const unreadableOracles = [];
|
|
69
|
+
states.forEach((state, i) => {
|
|
70
|
+
if (state.status !== "success") {
|
|
71
|
+
unreadableOracles.push(oracles[i]);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const { priceFeedTree } = state.result;
|
|
75
|
+
for (const node of priceFeedTree) {
|
|
76
|
+
const address = node.baseParams.addr.toLowerCase();
|
|
77
|
+
if (nodes.has(address)) continue;
|
|
78
|
+
nodes.set(address, {
|
|
79
|
+
address,
|
|
80
|
+
contractType: typeName(node.baseParams.contractType),
|
|
81
|
+
version: Number(node.baseParams.version),
|
|
82
|
+
description: node.description,
|
|
83
|
+
underlyingFeeds: node.underlyingFeeds.map((feed) => feed.toLowerCase())
|
|
84
|
+
});
|
|
85
|
+
answers.set(address, node.answer.success ? node.answer.price : null);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
nodes,
|
|
90
|
+
answers,
|
|
91
|
+
unreadableOracles
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Where each rate-bearing feed reads its rate, and what it will accept.
|
|
96
|
+
*
|
|
97
|
+
* The baseline a rate source is perturbed from is the feed's own `lowerBound`
|
|
98
|
+
* and not the rate itself. Reading the rate would mean knowing which getter
|
|
99
|
+
* each protocol publishes it under — `stEthPerToken`, `convertToAssets`,
|
|
100
|
+
* `get_virtual_price`, `pricePerShare` — and in exactly which units, which is
|
|
101
|
+
* a table that goes stale. The bound is within the feed's own accepted window
|
|
102
|
+
* of the live rate by construction, so it is the same figure to within that
|
|
103
|
+
* window, which is two percent or so. That is immaterial against the
|
|
104
|
+
* multipliers the ends of the sweep use, and at the fine end of the threshold
|
|
105
|
+
* search the bound *is* the answer: an LP feed clamps the rate it accepts, so
|
|
106
|
+
* where it breaks is where its bound is.
|
|
107
|
+
*/
|
|
108
|
+
async function readRateTargets(client, feeds) {
|
|
109
|
+
const targets = /* @__PURE__ */ new Map();
|
|
110
|
+
const baselines = /* @__PURE__ */ new Map();
|
|
111
|
+
const bounds = /* @__PURE__ */ new Map();
|
|
112
|
+
if (feeds.length === 0) return {
|
|
113
|
+
targets,
|
|
114
|
+
baselines,
|
|
115
|
+
bounds
|
|
116
|
+
};
|
|
117
|
+
const results = await client.multicall({
|
|
118
|
+
contracts: feeds.flatMap((address) => [
|
|
119
|
+
{
|
|
120
|
+
address,
|
|
121
|
+
abi: lpFeedAbi,
|
|
122
|
+
functionName: "lpContract"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
address,
|
|
126
|
+
abi: lpFeedAbi,
|
|
127
|
+
functionName: "lowerBound"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
address,
|
|
131
|
+
abi: lpFeedAbi,
|
|
132
|
+
functionName: "upperBound"
|
|
133
|
+
}
|
|
134
|
+
]),
|
|
135
|
+
allowFailure: true
|
|
136
|
+
});
|
|
137
|
+
feeds.forEach((feed, i) => {
|
|
138
|
+
const contract = results[3 * i];
|
|
139
|
+
const lower = results[3 * i + 1];
|
|
140
|
+
const upper = results[3 * i + 2];
|
|
141
|
+
if (contract?.status !== "success" || lower?.status !== "success") return;
|
|
142
|
+
const target = contract.result.toLowerCase();
|
|
143
|
+
targets.set(feed, target);
|
|
144
|
+
baselines.set(target, lower.result);
|
|
145
|
+
if (upper?.status === "success") bounds.set(feed, {
|
|
146
|
+
lower: lower.result,
|
|
147
|
+
upper: upper.result
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
return {
|
|
151
|
+
targets,
|
|
152
|
+
baselines,
|
|
153
|
+
bounds
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* What every feed answers with one group's sources overridden.
|
|
158
|
+
*
|
|
159
|
+
* One `eth_call` for the whole chain: the overrides go in once and the feeds
|
|
160
|
+
* are read through a multicall inside them, so a group costs a round trip per
|
|
161
|
+
* scenario rather than a round trip per feed. A feed that reverts comes back
|
|
162
|
+
* `null`, which is an outcome and not an error.
|
|
163
|
+
*/
|
|
164
|
+
async function readUnder(client, feeds, sources, multiplier, updatedAt) {
|
|
165
|
+
const overrides = require_permissionless_api_oracles_stress_override.groupOverride(sources, multiplier, updatedAt);
|
|
166
|
+
const results = await client.multicall({
|
|
167
|
+
contracts: feeds.map((address) => ({
|
|
168
|
+
address,
|
|
169
|
+
abi: aggregatorAbi,
|
|
170
|
+
functionName: "latestRoundData"
|
|
171
|
+
})),
|
|
172
|
+
allowFailure: true,
|
|
173
|
+
stateOverride: overrides.length > 0 ? overrides : void 0
|
|
174
|
+
});
|
|
175
|
+
return new Map(feeds.map((feed, i) => {
|
|
176
|
+
const result = results[i];
|
|
177
|
+
return [feed, result?.status === "success" ? result.result[1] ?? null : null];
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* A perturbation too small for any protection to be aimed at, which is what
|
|
182
|
+
* makes it a control.
|
|
183
|
+
*
|
|
184
|
+
* A tenth of a percent is inside every bound these feeds carry and under every
|
|
185
|
+
* deviation threshold, so a slot that does not budge under it is a slot the
|
|
186
|
+
* override never reached — and every other figure about it is then unknown
|
|
187
|
+
* rather than reassuring.
|
|
188
|
+
*/
|
|
189
|
+
const CALIBRATION_MULTIPLIER = 1.001;
|
|
190
|
+
/**
|
|
191
|
+
* How many of a group's reachable slots actually responded to being driven.
|
|
192
|
+
*
|
|
193
|
+
* Exact inequality on the answer and not a factor: at a tenth of a percent the
|
|
194
|
+
* point is only whether the number moved at all.
|
|
195
|
+
*/
|
|
196
|
+
async function countResponsive(client, roots, slots, members, base, updatedAt) {
|
|
197
|
+
const nudged = await readUnder(client, roots, members, CALIBRATION_MULTIPLIER, updatedAt);
|
|
198
|
+
return slots.filter((slot) => {
|
|
199
|
+
return (base.get(slot.priceFeed) ?? null) !== (nudged.get(slot.priceFeed) ?? null);
|
|
200
|
+
}).length;
|
|
201
|
+
}
|
|
202
|
+
/** `stressed / base`, or `null` where either end is missing. */
|
|
203
|
+
function factorOf(base, stressed) {
|
|
204
|
+
if (base === null || stressed === null || base === 0n) return null;
|
|
205
|
+
return Number(stressed) / Number(base);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* What a group did to one chain, market slot by market slot.
|
|
209
|
+
*
|
|
210
|
+
* The ratio and not the price: a slot is scored by how the collateral moved
|
|
211
|
+
* against the market's own underlying, because that is what an account is
|
|
212
|
+
* valued by. A group that moves both legs equally has moved nothing, and this
|
|
213
|
+
* is where that shows up — the underlying's own feed is one of the feeds read
|
|
214
|
+
* under the same override, so both legs come from the same call.
|
|
215
|
+
*/
|
|
216
|
+
function outcomeOf(scenario, slots, base, stressed, quotaUsd, chainTotalUsd) {
|
|
217
|
+
const movedPositions = /* @__PURE__ */ new Set();
|
|
218
|
+
const out = slots.map((slot) => {
|
|
219
|
+
const feed = {
|
|
220
|
+
feed: slot.priceFeed,
|
|
221
|
+
base: base.get(slot.priceFeed) ?? null,
|
|
222
|
+
stressed: stressed.get(slot.priceFeed) ?? null,
|
|
223
|
+
factor: factorOf(base.get(slot.priceFeed) ?? null, stressed.get(slot.priceFeed) ?? null)
|
|
224
|
+
};
|
|
225
|
+
const underlying = slot.underlyingPriceFeed;
|
|
226
|
+
const underlyingFactor = underlying === null ? 1 : factorOf(base.get(underlying) ?? null, stressed.get(underlying) ?? null) ?? null;
|
|
227
|
+
return {
|
|
228
|
+
market: slot.market,
|
|
229
|
+
marketName: slot.marketName,
|
|
230
|
+
curatorName: slot.curatorName,
|
|
231
|
+
token: slot.token,
|
|
232
|
+
tokenSymbol: slot.tokenSymbol,
|
|
233
|
+
reserve: slot.reserve,
|
|
234
|
+
isUnderlying: slot.isUnderlying,
|
|
235
|
+
feed,
|
|
236
|
+
ratioFactor: feed.factor === null || underlyingFactor === null || underlyingFactor === 0 ? null : feed.factor / underlyingFactor,
|
|
237
|
+
quotaUsedUsd: quotaUsd.get(slotKey(slot)) ?? null
|
|
238
|
+
};
|
|
239
|
+
});
|
|
240
|
+
const ratios = out.map((slot) => slot.ratioFactor).filter((r) => r !== null && Number.isFinite(r));
|
|
241
|
+
let movedUsd = 0;
|
|
242
|
+
slots.forEach((slot, i) => {
|
|
243
|
+
const outcome = out[i];
|
|
244
|
+
if (!(outcome !== void 0 && (outcome.ratioFactor !== null && outcome.ratioFactor !== 1 || outcome.feed.stressed === null && outcome.feed.base !== null)) || movedPositions.has(positionKey(slot))) return;
|
|
245
|
+
movedPositions.add(positionKey(slot));
|
|
246
|
+
movedUsd += outcome.quotaUsedUsd ?? 0;
|
|
247
|
+
});
|
|
248
|
+
return {
|
|
249
|
+
scenario,
|
|
250
|
+
slots: out,
|
|
251
|
+
worstInflation: ratios.length > 0 ? Math.max(...ratios) : null,
|
|
252
|
+
worstDeflation: ratios.length > 0 ? Math.min(...ratios) : null,
|
|
253
|
+
brokenSlots: out.filter((slot) => slot.feed.stressed === null && slot.feed.base !== null).length,
|
|
254
|
+
deadSlots: out.filter((slot) => slot.feed.base === null).length,
|
|
255
|
+
valueAtRisk: chainTotalUsd > 0 ? movedUsd / chainTotalUsd : 0
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/** What identifies a slot across the reads that describe it. */
|
|
259
|
+
function slotKey(slot) {
|
|
260
|
+
return `${slot.market}:${slot.token}:${slot.reserve}`;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* What identifies the *position* a slot prices, which is not the slot.
|
|
264
|
+
*
|
|
265
|
+
* A quota belongs to a `(market, token)` pair, and that pair has two slots:
|
|
266
|
+
* the main feed and the reserve one. Summing money over slots would count
|
|
267
|
+
* every such pair twice, so anything denominated in money is summed over this
|
|
268
|
+
* instead, and the slot figures stay per slot.
|
|
269
|
+
*/
|
|
270
|
+
function positionKey(slot) {
|
|
271
|
+
return `${slot.market}:${slot.token}`;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* The quota riding on a set of slots, counted once per position.
|
|
275
|
+
*
|
|
276
|
+
* The sum a reader takes to be money at risk, so the double counting a
|
|
277
|
+
* token's two slots would introduce is removed here rather than left for them
|
|
278
|
+
* to notice.
|
|
279
|
+
*/
|
|
280
|
+
function quotaOver(slots, quotaUsd) {
|
|
281
|
+
const counted = /* @__PURE__ */ new Set();
|
|
282
|
+
let total = 0;
|
|
283
|
+
for (const slot of slots) {
|
|
284
|
+
const key = positionKey(slot);
|
|
285
|
+
if (counted.has(key)) continue;
|
|
286
|
+
counted.add(key);
|
|
287
|
+
total += quotaUsd.get(slotKey(slot)) ?? 0;
|
|
288
|
+
}
|
|
289
|
+
return total;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* The smallest multiple of a group's sources that moves some market past a
|
|
293
|
+
* ratio of `target`, found by bisection.
|
|
294
|
+
*
|
|
295
|
+
* Eight steps over twelve orders of magnitude, which lands the answer inside a
|
|
296
|
+
* factor of about ten percent — enough to say whether a source has to be
|
|
297
|
+
* wrong by a percent or by a thousandfold before anything breaks, which is the
|
|
298
|
+
* question. `null` is a group that does not get there at the far end either.
|
|
299
|
+
*/
|
|
300
|
+
async function bisect(read, from, to, target, steps = 8) {
|
|
301
|
+
if (!target(await read(to))) return null;
|
|
302
|
+
let lo = from;
|
|
303
|
+
let hi = to;
|
|
304
|
+
for (let i = 0; i < steps; i++) {
|
|
305
|
+
const mid = Math.sqrt(lo * hi);
|
|
306
|
+
if (target(await read(mid))) hi = mid;
|
|
307
|
+
else lo = mid;
|
|
308
|
+
}
|
|
309
|
+
return hi;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Every source behind one chain's markets, put through the sweep a group at a
|
|
313
|
+
* time.
|
|
314
|
+
*
|
|
315
|
+
* Takes the slots as read, so the caller decides whether that read came from
|
|
316
|
+
* the backend or from somewhere else, and takes a client rather than making
|
|
317
|
+
* one, so the whole thing is testable against a stub.
|
|
318
|
+
**/
|
|
319
|
+
async function runStressTest({ client, chainId, slots, compressor, scenarios = DEFAULT_SCENARIOS, thresholds = true, groups: only, logger }) {
|
|
320
|
+
const { nodes, answers, unreadableOracles } = await readForest(client, compressor, [...new Set(slots.map((slot) => slot.priceOracle.toLowerCase()))]);
|
|
321
|
+
for (const oracle of unreadableOracles) logger?.warn(`price oracle ${oracle} of chain ${chainId} would not report its feed tree; the markets on it are left out`);
|
|
322
|
+
const { targets, baselines: rateBaselines } = await readRateTargets(client, [...nodes.values()].filter((node) => RATE_FEED_TYPE.test(node.contractType)).map((node) => node.address));
|
|
323
|
+
const { sources, unresolved } = require_permissionless_api_oracles_stress_classify.classifySources(chainId, [...nodes.values()], targets, (target) => rateBaselines.get(target) ?? answers.get(target) ?? null);
|
|
324
|
+
for (const node of unresolved) logger?.warn(`feed ${node.address} of chain ${chainId} would not say what it reads its rate from; its protocol is left out of the partition`);
|
|
325
|
+
const roots = [.../* @__PURE__ */ new Set([...slots.map((slot) => slot.priceFeed), ...slots.map((slot) => slot.underlyingPriceFeed).filter((feed) => feed !== null)])];
|
|
326
|
+
const reach = require_permissionless_api_oracles_stress_classify.sourcesByFeed(roots, nodes, sources);
|
|
327
|
+
const quotaUsd = /* @__PURE__ */ new Map();
|
|
328
|
+
for (const slot of slots) {
|
|
329
|
+
const price = slot.underlyingPriceFeed === null ? null : answers.get(slot.underlyingPriceFeed) ?? null;
|
|
330
|
+
quotaUsd.set(slotKey(slot), usd(slot.quotaUsed, price));
|
|
331
|
+
}
|
|
332
|
+
const totalUsd = quotaOver(slots, quotaUsd);
|
|
333
|
+
const updatedAt = BigInt(Math.floor(Date.now() / 1e3));
|
|
334
|
+
const base = await readUnder(client, roots, [], 1, updatedAt);
|
|
335
|
+
const byGroup = /* @__PURE__ */ new Map();
|
|
336
|
+
for (const source of sources) byGroup.set(source.group, [...byGroup.get(source.group) ?? [], source]);
|
|
337
|
+
const unidentifiedUsd = quotaOver(slots.filter((slot) => {
|
|
338
|
+
const reached = reach.get(slot.priceFeed);
|
|
339
|
+
return sources.some((source) => !source.identified && reached?.has(source.target));
|
|
340
|
+
}), quotaUsd);
|
|
341
|
+
const reports = [];
|
|
342
|
+
for (const [group, members] of byGroup) {
|
|
343
|
+
if (only && !only.includes(group)) continue;
|
|
344
|
+
const targetSet = new Set(members.map((source) => source.target));
|
|
345
|
+
const reachable = slots.filter((slot) => [...reach.get(slot.priceFeed) ?? []].some((source) => targetSet.has(source)));
|
|
346
|
+
const reachableUsd = quotaOver(reachable, quotaUsd);
|
|
347
|
+
const roles = /* @__PURE__ */ new Map();
|
|
348
|
+
for (const slot of reachable) {
|
|
349
|
+
const key = positionKey(slot);
|
|
350
|
+
roles.set(key, (roles.get(key) ?? /* @__PURE__ */ new Set()).add(slot.reserve));
|
|
351
|
+
}
|
|
352
|
+
const undefendedPositions = [...roles.values()].filter((set) => set.has(true) && set.has(false)).length;
|
|
353
|
+
const silentSources = members.filter((source) => source.perturbable && source.baseline === null).length;
|
|
354
|
+
const drivable = members.filter((source) => source.perturbable && source.baseline !== null);
|
|
355
|
+
if (reachable.length === 0 || drivable.length === 0) {
|
|
356
|
+
reports.push({
|
|
357
|
+
chainId,
|
|
358
|
+
group,
|
|
359
|
+
sources: members,
|
|
360
|
+
identified: members.every((source) => source.identified),
|
|
361
|
+
reachableSlots: reachable.length,
|
|
362
|
+
reachableUsd,
|
|
363
|
+
undefendedPositions,
|
|
364
|
+
outcomes: [],
|
|
365
|
+
breakingPoints: [],
|
|
366
|
+
responsive: 0,
|
|
367
|
+
silentSources,
|
|
368
|
+
score: 10,
|
|
369
|
+
verdict: require_permissionless_api_oracles_stress_score.verdictOf(group, 10, [], reachable.length, reachableUsd, 0, silentSources, undefendedPositions, members.some((source) => !source.perturbable))
|
|
370
|
+
});
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
const outcomes = [];
|
|
374
|
+
for (const scenario of scenarios) {
|
|
375
|
+
const stressed = await readUnder(client, roots, members, scenario.multiplier, updatedAt);
|
|
376
|
+
outcomes.push(outcomeOf(scenario, reachable, base, stressed, quotaUsd, totalUsd));
|
|
377
|
+
}
|
|
378
|
+
const breakingPoints = [];
|
|
379
|
+
if (thresholds) {
|
|
380
|
+
const worstRatio = async (multiplier) => {
|
|
381
|
+
const stressed = await readUnder(client, roots, members, multiplier, updatedAt);
|
|
382
|
+
const outcome = outcomeOf({
|
|
383
|
+
label: "probe",
|
|
384
|
+
multiplier
|
|
385
|
+
}, reachable, base, stressed, quotaUsd, totalUsd);
|
|
386
|
+
return Math.max(outcome.worstInflation ?? 1, 1 / (outcome.worstDeflation ?? 1));
|
|
387
|
+
};
|
|
388
|
+
const up = await bisect(worstRatio, 1, require_permissionless_api_oracles_stress_override.UNBOUNDED_UP, (worst) => worst >= 2);
|
|
389
|
+
const down = await bisect(worstRatio, 1, require_permissionless_api_oracles_stress_override.UNBOUNDED_DOWN, (worst) => worst >= 2);
|
|
390
|
+
breakingPoints.push({
|
|
391
|
+
market: reachable[0]?.market ?? "0x",
|
|
392
|
+
token: reachable[0]?.token ?? "0x",
|
|
393
|
+
inflation: up,
|
|
394
|
+
deflation: down
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
const responsive = await countResponsive(client, roots, reachable, members, base, updatedAt);
|
|
398
|
+
const score = require_permissionless_api_oracles_stress_score.scoreGroup(outcomes);
|
|
399
|
+
reports.push({
|
|
400
|
+
chainId,
|
|
401
|
+
group,
|
|
402
|
+
sources: members,
|
|
403
|
+
identified: members.every((source) => source.identified),
|
|
404
|
+
reachableSlots: reachable.length,
|
|
405
|
+
reachableUsd,
|
|
406
|
+
undefendedPositions,
|
|
407
|
+
outcomes,
|
|
408
|
+
breakingPoints,
|
|
409
|
+
responsive,
|
|
410
|
+
silentSources,
|
|
411
|
+
score,
|
|
412
|
+
verdict: require_permissionless_api_oracles_stress_score.verdictOf(group, score, outcomes, reachable.length, reachableUsd, responsive, silentSources, undefendedPositions, false)
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
return {
|
|
416
|
+
chainId,
|
|
417
|
+
slots: slots.length,
|
|
418
|
+
roots: roots.length,
|
|
419
|
+
nodes: nodes.size,
|
|
420
|
+
deadSlots: slots.filter((slot) => (base.get(slot.priceFeed) ?? null) === null).length,
|
|
421
|
+
sources,
|
|
422
|
+
totalUsd,
|
|
423
|
+
unidentifiedUsd,
|
|
424
|
+
groups: reports.sort((a, b) => a.score - b.score || b.reachableUsd - a.reachableUsd)
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
//#endregion
|
|
428
|
+
exports.DEFAULT_SCENARIOS = DEFAULT_SCENARIOS;
|
|
429
|
+
exports.RATE_FEED_TYPE = RATE_FEED_TYPE;
|
|
430
|
+
exports.readForest = readForest;
|
|
431
|
+
exports.readRateTargets = readRateTargets;
|
|
432
|
+
exports.runStressTest = runStressTest;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/permissionless/api/oracles/stress/score.ts
|
|
3
|
+
/**
|
|
4
|
+
* Turning what a group did into a mark out of ten.
|
|
5
|
+
*
|
|
6
|
+
* Any single number over a thing this shaped is a judgement, so the one here
|
|
7
|
+
* is spelled out rather than tuned: what it weighs, and why each term is
|
|
8
|
+
* weighed that way, is in the comments below, and every figure it is computed
|
|
9
|
+
* from stays in the report so a reader who disagrees can reweigh them.
|
|
10
|
+
**/
|
|
11
|
+
/**
|
|
12
|
+
* How bad one slot's outcome is, on nought to one.
|
|
13
|
+
*
|
|
14
|
+
* Two kinds of harm, which are not the same kind of problem:
|
|
15
|
+
*
|
|
16
|
+
* - a wrong price. The collateral is valued against the market's underlying,
|
|
17
|
+
* so what matters is the ratio and not either leg: a market whose
|
|
18
|
+
* collateral and underlying both doubled has not moved. Overvalued
|
|
19
|
+
* collateral is borrowed against and the loan is never repaid; undervalued
|
|
20
|
+
* collateral is liquidated out from under an account that was solvent.
|
|
21
|
+
* Both are counted, because a reader asking what a source can do to them
|
|
22
|
+
* is exposed to each.
|
|
23
|
+
*
|
|
24
|
+
* - a price that stopped. The slot reverted where it used to answer, which
|
|
25
|
+
* freezes the market: nothing can be borrowed and, worse, nothing can be
|
|
26
|
+
* liquidated. Scored at half a full mispricing — it is a liveness failure
|
|
27
|
+
* rather than a licence to drain, and it is also loud, where a wrong number
|
|
28
|
+
* is silent.
|
|
29
|
+
*
|
|
30
|
+
* A hundredfold move in the ratio is full harm. Ten times is a half, and the
|
|
31
|
+
* curve is logarithmic between them because the damage is: a position is
|
|
32
|
+
* liquidatable somewhere around a tenth of a move, and everything past that is
|
|
33
|
+
* degrees of already-gone.
|
|
34
|
+
*/
|
|
35
|
+
function slotHarm(slot) {
|
|
36
|
+
if (slot.feed.stressed === null && slot.feed.base !== null) return .5;
|
|
37
|
+
const factor = slot.ratioFactor;
|
|
38
|
+
if (factor === null || factor === 1 || !Number.isFinite(factor)) return factor !== null && !Number.isFinite(factor) ? 1 : 0;
|
|
39
|
+
return Math.min(1, Math.abs(Math.log10(factor)) / 2);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The group's mark, over every scenario it was put through.
|
|
43
|
+
*
|
|
44
|
+
* Two views of the same slots, because either alone misleads. Weighing harm by
|
|
45
|
+
* the quota riding on it is what a reader with money in the protocol wants —
|
|
46
|
+
* a source that can only move a market with nothing in it has not done much.
|
|
47
|
+
* But a market with nothing in it today is where tomorrow's deposit goes, so
|
|
48
|
+
* the worst slot regardless of size is carried too, at a smaller weight.
|
|
49
|
+
*
|
|
50
|
+
* Ten is a group that moved nothing. Nought is one that revalued everything
|
|
51
|
+
* the chain has out.
|
|
52
|
+
*/
|
|
53
|
+
function scoreGroup(outcomes) {
|
|
54
|
+
let weighted = 0;
|
|
55
|
+
let worst = 0;
|
|
56
|
+
for (const outcome of outcomes) {
|
|
57
|
+
const total = outcome.slots.reduce((sum, slot) => sum + (slot.quotaUsedUsd ?? 0), 0);
|
|
58
|
+
let scenarioWeighted = 0;
|
|
59
|
+
for (const slot of outcome.slots) {
|
|
60
|
+
const harm = slotHarm(slot);
|
|
61
|
+
worst = Math.max(worst, harm);
|
|
62
|
+
if (total > 0) scenarioWeighted += (slot.quotaUsedUsd ?? 0) / total * harm;
|
|
63
|
+
}
|
|
64
|
+
weighted = Math.max(weighted, scenarioWeighted);
|
|
65
|
+
}
|
|
66
|
+
const damage = .7 * weighted + .3 * worst;
|
|
67
|
+
return Math.round((1 - damage) * 100) / 10;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The one line the score stands for.
|
|
71
|
+
*
|
|
72
|
+
* Says which of the two failures the group causes, because the remedies
|
|
73
|
+
* differ: a wrong price is answered with bounds and a second feed, a dead one
|
|
74
|
+
* with a reserve feed and a staleness period.
|
|
75
|
+
*/
|
|
76
|
+
function verdictOf(group, score, outcomes, reachableSlots, reachableUsd, responsive, silentSources, undefendedPositions, selfContained) {
|
|
77
|
+
const money = () => `$${Math.round(reachableUsd).toLocaleString("en-US")} of quota`;
|
|
78
|
+
if (reachableSlots === 0) return `${group} prices nothing any market reads.`;
|
|
79
|
+
if (selfContained) return `${group} carries its price in its own code and is not published to, so there is no source to lie: ${money()} behind ${reachableSlots} slot(s), at the mercy of whoever can replace the contract rather than of whoever reports to it.`;
|
|
80
|
+
if (outcomes.length === 0) return `${group} is not answering as it stands — ${silentSources} silent source(s) — so nothing could be perturbed: ${money()} behind ${reachableSlots} slot(s) is priced through something already not reporting.`;
|
|
81
|
+
if (responsive === 0) return `${group}: not one of its ${reachableSlots} slot(s) moved under a perturbation of a tenth of a percent, so this test never drove it. Treat every figure for it as unknown, not as safe.`;
|
|
82
|
+
const broken = Math.max(...outcomes.map((o) => o.brokenSlots), 0);
|
|
83
|
+
const inflation = Math.max(...outcomes.map((o) => o.worstInflation ?? 1), 1);
|
|
84
|
+
const deflation = Math.min(...outcomes.map((o) => o.worstDeflation ?? 1), 1);
|
|
85
|
+
const ends = [inflation > 1.01 ? `${inflation.toExponential(1)}× too high` : null, deflation < .99 ? `${deflation.toExponential(1)}× of what it should be` : null].filter((end) => end !== null);
|
|
86
|
+
const dead = Math.max(...outcomes.map((o) => o.deadSlots), 0);
|
|
87
|
+
const live = reachableSlots - dead;
|
|
88
|
+
const moves = ends.length > 0 ? `drives the collateral-to-underlying ratio of up to ${live} live slot(s) to ${ends.join(" and ")}` : `moves no ratio by more than a percent, with ${responsive} slot(s) proven to respond at all`;
|
|
89
|
+
const freeze = broken > 0 ? `, and stops ${broken} of them answering` : "";
|
|
90
|
+
const undefended = undefendedPositions > 0 ? ` Its reach includes ${undefendedPositions} position(s) whose main and reserve feed both read it, so the fallback fails with it.` : "";
|
|
91
|
+
const standing = dead > 0 ? ` ${dead} of its slot(s) are priced through a feed that is not answering right now, before any of this.` : "";
|
|
92
|
+
const silent = silentSources > 0 ? ` (${silentSources} of its sources are already silent and were not perturbed)` : "";
|
|
93
|
+
return `${group} (${score}/10): ${money()} behind it; ${moves}${freeze}.${undefended}${standing}${silent}`;
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
exports.scoreGroup = scoreGroup;
|
|
97
|
+
exports.slotHarm = slotHarm;
|
|
98
|
+
exports.verdictOf = verdictOf;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
@@ -12,8 +12,6 @@ let zod_v4 = require("zod/v4");
|
|
|
12
12
|
**/
|
|
13
13
|
/** An address, in whatever case the backend serves it. */
|
|
14
14
|
const addressSchema = zod_v4.z.custom((value) => typeof value === "string" && (0, viem.isAddress)(value, { strict: false }), { message: "invalid address" });
|
|
15
|
-
/** A `0x`-prefixed hex string, as viem's `Hex`. */
|
|
16
|
-
const hexSchema = zod_v4.z.custom((value) => typeof value === "string" && (0, viem.isHex)(value), { message: "invalid hex string" });
|
|
17
15
|
/**
|
|
18
16
|
* A record keyed by address. Spelled out here because zod types a record key
|
|
19
17
|
* by the schema's output, which the branded `Address` is not inferred as.
|
|
@@ -25,4 +23,3 @@ function addressRecord(value) {
|
|
|
25
23
|
//#endregion
|
|
26
24
|
exports.addressRecord = addressRecord;
|
|
27
25
|
exports.addressSchema = addressSchema;
|
|
28
|
-
exports.hexSchema = hexSchema;
|
|
@@ -2,6 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
const require_permissionless_bindings_bytecode_repository = require("./bytecode-repository.js");
|
|
3
3
|
const require_permissionless_bindings_pricefeeds_index = require("./pricefeeds/index.js");
|
|
4
4
|
const require_permissionless_bindings_price_feed_store = require("./price-feed-store.js");
|
|
5
|
+
const require_permissionless_bindings_address_provider = require("./address-provider.js");
|
|
5
6
|
const require_permissionless_bindings_compressors_token_compressor = require("./compressors/token-compressor.js");
|
|
6
7
|
const require_permissionless_bindings_compressors_withdrawal_compressor = require("./compressors/withdrawal-compressor.js");
|
|
7
8
|
require("./compressors/index.js");
|
|
@@ -9,7 +10,6 @@ const require_permissionless_bindings_router_routing_manager = require("./router
|
|
|
9
10
|
require("./router/index.js");
|
|
10
11
|
const require_permissionless_bindings_treasury_splitter = require("./treasury-splitter.js");
|
|
11
12
|
const require_permissionless_bindings_instance_manager = require("./instance-manager.js");
|
|
12
|
-
const require_permissionless_bindings_address_provider = require("./address-provider.js");
|
|
13
13
|
const require_permissionless_bindings_market_configurator_factory = require("./market-configurator-factory.js");
|
|
14
14
|
const require_permissionless_bindings_cross_chain_multisig = require("./cross-chain-multisig.js");
|
|
15
15
|
const require_permissionless_bindings_types = require("./types.js");
|
|
@@ -11,7 +11,14 @@ const require_permissionless_bindings_price_feed_store = require("./bindings/pri
|
|
|
11
11
|
const require_permissionless_deployment_addresses = require("./deployment/addresses.js");
|
|
12
12
|
const require_permissionless_utils_abi_encoder = require("./utils/abi-encoder.js");
|
|
13
13
|
const require_permissionless_api_deploy_PermissionlessDeploy = require("./api/deploy/PermissionlessDeploy.js");
|
|
14
|
+
const require_permissionless_bindings_address_provider = require("./bindings/address-provider.js");
|
|
14
15
|
const require_permissionless_utils_price_update_get_prices = require("./utils/price-update/get-prices.js");
|
|
16
|
+
const require_permissionless_api_oracles_stress_classify = require("./api/oracles/stress/classify.js");
|
|
17
|
+
const require_permissionless_api_oracles_stress_override = require("./api/oracles/stress/override.js");
|
|
18
|
+
const require_permissionless_api_oracles_stress_score = require("./api/oracles/stress/score.js");
|
|
19
|
+
const require_permissionless_api_oracles_stress_run = require("./api/oracles/stress/run.js");
|
|
20
|
+
const require_permissionless_api_oracles_score_formula = require("./api/oracles/score/formula.js");
|
|
21
|
+
const require_permissionless_api_oracles_score_run = require("./api/oracles/score/run.js");
|
|
15
22
|
const require_permissionless_api_oracles_PermissionlessOracles = require("./api/oracles/PermissionlessOracles.js");
|
|
16
23
|
const require_permissionless_bindings_compressors_token_compressor = require("./bindings/compressors/token-compressor.js");
|
|
17
24
|
const require_permissionless_bindings_compressors_withdrawal_compressor = require("./bindings/compressors/withdrawal-compressor.js");
|
|
@@ -23,7 +30,6 @@ const require_permissionless_utils_price_update_get_updatable_feeds = require(".
|
|
|
23
30
|
const require_permissionless_api_transactions_InstanceOwnerTransactions = require("./api/transactions/InstanceOwnerTransactions.js");
|
|
24
31
|
const require_permissionless_api_GearboxPermissionless = require("./api/GearboxPermissionless.js");
|
|
25
32
|
require("./api/index.js");
|
|
26
|
-
const require_permissionless_bindings_address_provider = require("./bindings/address-provider.js");
|
|
27
33
|
const require_permissionless_bindings_market_configurator_factory = require("./bindings/market-configurator-factory.js");
|
|
28
34
|
const require_permissionless_bindings_cross_chain_multisig = require("./bindings/cross-chain-multisig.js");
|
|
29
35
|
const require_permissionless_utils_create2 = require("./utils/create2.js");
|
|
@@ -46,6 +52,7 @@ exports.AccessMode = require_permissionless_bindings_types.AccessMode;
|
|
|
46
52
|
exports.AddressProviderContract = require_permissionless_bindings_address_provider.AddressProviderContract;
|
|
47
53
|
exports.Addresses = require_permissionless_deployment_addresses.Addresses;
|
|
48
54
|
exports.ArchiveTransport = require_permissionless_chains_archive_transport.ArchiveTransport;
|
|
55
|
+
exports.BOUND_WEIGHT = require_permissionless_api_oracles_score_formula.BOUND_WEIGHT;
|
|
49
56
|
exports.BYTECODE_REPOSITORY = require_permissionless_utils_literals.BYTECODE_REPOSITORY;
|
|
50
57
|
exports.BytecodeRepositoryContract = require_permissionless_bindings_bytecode_repository.BytecodeRepositoryContract;
|
|
51
58
|
exports.CROSS_CHAIN_GOVERNANCE = require_permissionless_utils_literals.CROSS_CHAIN_GOVERNANCE;
|
|
@@ -53,10 +60,12 @@ exports.CROSS_CHAIN_MULTISIG = require_permissionless_utils_literals.CROSS_CHAIN
|
|
|
53
60
|
exports.ChainsNamespace = require_permissionless_api_chains_ChainsNamespace.ChainsNamespace;
|
|
54
61
|
exports.CrossChainMultisigContract = require_permissionless_bindings_cross_chain_multisig.CrossChainMultisigContract;
|
|
55
62
|
exports.DEFAULT_DEPLOY_SALT = require_permissionless_api_deploy_PermissionlessDeploy.DEFAULT_DEPLOY_SALT;
|
|
63
|
+
exports.DEFAULT_SCENARIOS = require_permissionless_api_oracles_stress_run.DEFAULT_SCENARIOS;
|
|
56
64
|
exports.GET_PRICES_CHUNK_SIZE = require_permissionless_api_oracles_PermissionlessOracles.GET_PRICES_CHUNK_SIZE;
|
|
57
65
|
exports.GET_PRICES_GAS_LIMIT_BY_CHAIN_ID = require_permissionless_api_oracles_PermissionlessOracles.GET_PRICES_GAS_LIMIT_BY_CHAIN_ID;
|
|
58
66
|
exports.GearboxPermissionless = require_permissionless_api_GearboxPermissionless.GearboxPermissionless;
|
|
59
67
|
exports.GovernorContract = require_permissionless_bindings_governance_governor.GovernorContract;
|
|
68
|
+
exports.INDEPENDENCE_WEIGHT = require_permissionless_api_oracles_score_formula.INDEPENDENCE_WEIGHT;
|
|
60
69
|
exports.INSTANCE_MANAGER = require_permissionless_utils_literals.INSTANCE_MANAGER;
|
|
61
70
|
exports.InstanceManagerContract = require_permissionless_bindings_instance_manager.InstanceManagerContract;
|
|
62
71
|
exports.InstanceOwnerTransactions = require_permissionless_api_transactions_InstanceOwnerTransactions.InstanceOwnerTransactions;
|
|
@@ -78,16 +87,20 @@ exports.PriceFeedNotInStoreError = require_permissionless_api_errors.PriceFeedNo
|
|
|
78
87
|
exports.PriceFeedSaltMissingError = require_permissionless_api_errors.PriceFeedSaltMissingError;
|
|
79
88
|
exports.PriceFeedStalenessUnknownError = require_permissionless_api_errors.PriceFeedStalenessUnknownError;
|
|
80
89
|
exports.PriceFeedStoreContract = require_permissionless_bindings_price_feed_store.PriceFeedStoreContract;
|
|
90
|
+
exports.RATE_FEED_TYPE = require_permissionless_api_oracles_stress_run.RATE_FEED_TYPE;
|
|
81
91
|
exports.RoutingManagerContract = require_permissionless_bindings_router_routing_manager.RoutingManagerContract;
|
|
82
92
|
exports.TOKEN_COMPRESSOR = require_permissionless_utils_literals.TOKEN_COMPRESSOR;
|
|
83
93
|
exports.TimeLockContract = require_permissionless_bindings_governance_timelock.TimeLockContract;
|
|
84
94
|
exports.TokenCompressorContract = require_permissionless_bindings_compressors_token_compressor.TokenCompressorContract;
|
|
85
95
|
exports.TreasurySplitterContract = require_permissionless_bindings_treasury_splitter.TreasurySplitterContract;
|
|
96
|
+
exports.UNBOUNDED_DOWN = require_permissionless_api_oracles_stress_override.UNBOUNDED_DOWN;
|
|
97
|
+
exports.UNBOUNDED_UP = require_permissionless_api_oracles_stress_override.UNBOUNDED_UP;
|
|
86
98
|
exports.WithdrawalCompressorContract = require_permissionless_bindings_compressors_withdrawal_compressor.WithdrawalCompressorContract;
|
|
87
99
|
exports.calculateChecksum = require_permissionless_utils_governance_batch.calculateChecksum;
|
|
88
100
|
exports.checkCreate2Deployment = require_permissionless_utils_create2.checkCreate2Deployment;
|
|
89
101
|
exports.checkCreate2DeploymentAddress = require_permissionless_utils_create2.checkCreate2DeploymentAddress;
|
|
90
102
|
exports.chunkedLogsTransport = require_permissionless_chains_chunked_log_transport.chunkedLogsTransport;
|
|
103
|
+
exports.classifySources = require_permissionless_api_oracles_stress_classify.classifySources;
|
|
91
104
|
exports.convertPercent = require_permissionless_utils_format.convertPercent;
|
|
92
105
|
exports.convertQueueBatchToExecuteTx = require_permissionless_utils_governance_timelock_txs.convertQueueBatchToExecuteTx;
|
|
93
106
|
exports.convertRawTxToSafeMultisigTx = require_permissionless_utils_governance_batch.convertRawTxToSafeMultisigTx;
|
|
@@ -102,14 +115,29 @@ exports.formatBytecodeVersion = require_permissionless_utils_format.formatByteco
|
|
|
102
115
|
exports.getBlockNumberByTimestamp = require_permissionless_utils_block_utils.getBlockNumberByTimestamp;
|
|
103
116
|
exports.getCreate2AddressPublicFactory = require_permissionless_utils_create2.getCreate2AddressPublicFactory;
|
|
104
117
|
exports.getCreate2DeploymentAddress = require_permissionless_utils_create2.getCreate2DeploymentAddress;
|
|
118
|
+
exports.getFeedDecimals = require_permissionless_utils_price_update_get_prices.getFeedDecimals;
|
|
119
|
+
exports.getLatestPrices = require_permissionless_utils_price_update_get_prices.getLatestPrices;
|
|
105
120
|
exports.getPriceUpdateTx = require_permissionless_utils_price_update_get_price_update_tx.getPriceUpdateTx;
|
|
106
121
|
exports.getPrices = require_permissionless_utils_price_update_get_prices.getPrices;
|
|
107
122
|
exports.getSafeBatch = require_permissionless_utils_governance_batch.getSafeBatch;
|
|
108
123
|
exports.getSafeBatches = require_permissionless_utils_governance_batch.getSafeBatches;
|
|
109
124
|
exports.getUpdatablePriceFeeds = require_permissionless_utils_price_update_get_updatable_feeds.getUpdatablePriceFeeds;
|
|
125
|
+
exports.groupOverride = require_permissionless_api_oracles_stress_override.groupOverride;
|
|
110
126
|
exports.handleSalt = require_permissionless_utils_create2.handleSalt;
|
|
111
127
|
exports.normalizeSignature = require_permissionless_utils_signature.normalizeSignature;
|
|
128
|
+
exports.perturb = require_permissionless_api_oracles_stress_override.perturb;
|
|
112
129
|
exports.priceFeedSalt = require_permissionless_api_deploy_PermissionlessDeploy.priceFeedSalt;
|
|
113
130
|
exports.priceFeedSetupParams = require_permissionless_bindings_pricefeeds_index.priceFeedSetupParams;
|
|
131
|
+
exports.rateStub = require_permissionless_api_oracles_stress_override.rateStub;
|
|
132
|
+
exports.readForest = require_permissionless_api_oracles_stress_run.readForest;
|
|
133
|
+
exports.readRateTargets = require_permissionless_api_oracles_stress_run.readRateTargets;
|
|
134
|
+
exports.roundDataStub = require_permissionless_api_oracles_stress_override.roundDataStub;
|
|
135
|
+
exports.runAssetScores = require_permissionless_api_oracles_score_run.runAssetScores;
|
|
136
|
+
exports.runStressTest = require_permissionless_api_oracles_stress_run.runStressTest;
|
|
137
|
+
exports.scoreGroup = require_permissionless_api_oracles_stress_score.scoreGroup;
|
|
138
|
+
exports.scoreMarket = require_permissionless_api_oracles_score_formula.scoreMarket;
|
|
114
139
|
exports.shortenHash = require_permissionless_utils_format.shortenHash;
|
|
115
140
|
exports.significantTrunc = require_permissionless_utils_format.significantTrunc;
|
|
141
|
+
exports.slotHarm = require_permissionless_api_oracles_stress_score.slotHarm;
|
|
142
|
+
exports.sourcesByFeed = require_permissionless_api_oracles_stress_classify.sourcesByFeed;
|
|
143
|
+
exports.verdictOf = require_permissionless_api_oracles_stress_score.verdictOf;
|
|
@@ -35,6 +35,8 @@ exports.formatBytecodeVersion = require_permissionless_utils_format.formatByteco
|
|
|
35
35
|
exports.getBlockNumberByTimestamp = require_permissionless_utils_block_utils.getBlockNumberByTimestamp;
|
|
36
36
|
exports.getCreate2AddressPublicFactory = require_permissionless_utils_create2.getCreate2AddressPublicFactory;
|
|
37
37
|
exports.getCreate2DeploymentAddress = require_permissionless_utils_create2.getCreate2DeploymentAddress;
|
|
38
|
+
exports.getFeedDecimals = require_permissionless_utils_price_update_get_prices.getFeedDecimals;
|
|
39
|
+
exports.getLatestPrices = require_permissionless_utils_price_update_get_prices.getLatestPrices;
|
|
38
40
|
exports.getPriceUpdateTx = require_permissionless_utils_price_update_get_price_update_tx.getPriceUpdateTx;
|
|
39
41
|
exports.getPrices = require_permissionless_utils_price_update_get_prices.getPrices;
|
|
40
42
|
exports.getSafeBatch = require_permissionless_utils_governance_batch.getSafeBatch;
|