@rhinestone/shared-configs 2.0.1 → 2.1.0
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 +41 -0
- package/dist/configs/chains.json +452 -0
- package/dist/scripts/__tests__/validation.test.js +215 -0
- package/dist/scripts/audit-token-authorizations.d.ts +1 -0
- package/dist/scripts/audit-token-authorizations.js +541 -0
- package/dist/scripts/generate.js +3 -1
- package/dist/scripts/validation.js +97 -2
- package/dist/src/chains.d.ts +3 -1
- package/dist/src/chains.js +452 -0
- package/dist/src/generated/networks.d.ts +1105 -1105
- package/dist/src/generated/packageVersion.d.ts +1 -1
- package/dist/src/generated/packageVersion.js +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/types.d.ts +47 -2
- package/package.json +2 -1
|
@@ -42,6 +42,7 @@ exports.classifyChainStacks = classifyChainStacks;
|
|
|
42
42
|
exports.validateChainConfig = validateChainConfig;
|
|
43
43
|
exports.validateOftCoverage = validateOftCoverage;
|
|
44
44
|
exports.formatValidationIssues = formatValidationIssues;
|
|
45
|
+
const viem_1 = require("viem");
|
|
45
46
|
const celo_1 = require("viem/celo");
|
|
46
47
|
const viemChains = __importStar(require("viem/chains"));
|
|
47
48
|
const op_stack_1 = require("viem/op-stack");
|
|
@@ -72,12 +73,17 @@ const SWAP_QUOTERS = new Set([
|
|
|
72
73
|
]);
|
|
73
74
|
const VM_TYPES = new Set(['evm', 'svm', 'tvm']);
|
|
74
75
|
const PEG_GROUPS = new Set(['USD', 'ETH']);
|
|
76
|
+
const TOKEN_AUTHORIZATION_STANDARDS = new Set([
|
|
77
|
+
'erc3009',
|
|
78
|
+
'erc2612',
|
|
79
|
+
]);
|
|
75
80
|
const NETWORKS = new Set(['mainnet', 'testnet']);
|
|
76
81
|
const STACKS = new Set(['op-stack', 'zksync', 'celo', 'vanilla']);
|
|
77
82
|
// Registry keys are chain ids consumers index by directly, so they must be
|
|
78
83
|
// canonical positive integers — no leading zeros, which would let "01" and "1"
|
|
79
84
|
// both address chain 1.
|
|
80
85
|
const CHAIN_ID_KEY = /^[1-9][0-9]*$/;
|
|
86
|
+
const BYTES32 = /^0x[0-9a-fA-F]{64}$/;
|
|
81
87
|
// CAIP-2 (https://chainagnostic.org/CAIPs/caip-2): `<namespace>:<reference>`.
|
|
82
88
|
//
|
|
83
89
|
// Deliberately shape-only — the namespace set is not ours to close, and a chain
|
|
@@ -183,7 +189,7 @@ function settlementConfigProblems(chain) {
|
|
|
183
189
|
* only sanity-check the envelope, so this is the single place a malformed
|
|
184
190
|
* registry gets caught before it reaches anyone.
|
|
185
191
|
*/
|
|
186
|
-
function structuralProblems(chain) {
|
|
192
|
+
function structuralProblems(registryChainId, chain) {
|
|
187
193
|
const problems = [];
|
|
188
194
|
if (!isNonEmptyString(chain.name))
|
|
189
195
|
problems.push('name is not a non-empty string');
|
|
@@ -309,6 +315,95 @@ function structuralProblems(chain) {
|
|
|
309
315
|
if (!isAbsentOr(token.pegGroup, (v) => PEG_GROUPS.has(v))) {
|
|
310
316
|
problems.push(`${at}.pegGroup ${JSON.stringify(token.pegGroup)} is not a known peg group`);
|
|
311
317
|
}
|
|
318
|
+
const authorization = token.authorization;
|
|
319
|
+
if (authorization !== undefined) {
|
|
320
|
+
if (chain.vmType !== 'evm') {
|
|
321
|
+
problems.push(`${at}.authorization is only valid for EVM tokens`);
|
|
322
|
+
}
|
|
323
|
+
if (chain.virtual === true) {
|
|
324
|
+
problems.push(`${at}.authorization is not valid on a virtual chain; use the settlement chain's token`);
|
|
325
|
+
}
|
|
326
|
+
if (!isObject(authorization)) {
|
|
327
|
+
problems.push(`${at}.authorization is not an object`);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
const standards = authorization.standards;
|
|
331
|
+
if (!Array.isArray(standards) || standards.length === 0) {
|
|
332
|
+
problems.push(`${at}.authorization.standards is not a non-empty array`);
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
const seen = new Set();
|
|
336
|
+
for (const standard of standards) {
|
|
337
|
+
if (!TOKEN_AUTHORIZATION_STANDARDS.has(standard)) {
|
|
338
|
+
problems.push(`${at}.authorization.standards contains unknown value ${JSON.stringify(standard)}`);
|
|
339
|
+
}
|
|
340
|
+
else if (seen.has(standard)) {
|
|
341
|
+
problems.push(`${at}.authorization.standards contains duplicate value ${JSON.stringify(standard)}`);
|
|
342
|
+
}
|
|
343
|
+
if (typeof standard === 'string')
|
|
344
|
+
seen.add(standard);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
const domain = authorization.domain;
|
|
348
|
+
if (!isObject(domain)) {
|
|
349
|
+
problems.push(`${at}.authorization.domain is not an object`);
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
const verifyingContract = domain.verifyingContract;
|
|
353
|
+
if (!isNonEmptyString(domain.name)) {
|
|
354
|
+
problems.push(`${at}.authorization.domain.name is not a non-empty string`);
|
|
355
|
+
}
|
|
356
|
+
if (!isNonEmptyString(domain.version)) {
|
|
357
|
+
problems.push(`${at}.authorization.domain.version is not a non-empty string`);
|
|
358
|
+
}
|
|
359
|
+
if (typeof verifyingContract !== 'string' ||
|
|
360
|
+
!(0, viem_1.isAddress)(verifyingContract)) {
|
|
361
|
+
problems.push(`${at}.authorization.domain.verifyingContract is not an EVM address`);
|
|
362
|
+
}
|
|
363
|
+
else if (typeof token.address === 'string' &&
|
|
364
|
+
verifyingContract.toLowerCase() !== token.address.toLowerCase()) {
|
|
365
|
+
problems.push(`${at}.authorization.domain.verifyingContract does not match the token address`);
|
|
366
|
+
}
|
|
367
|
+
const hasChainId = domain.chainId !== undefined;
|
|
368
|
+
const hasSalt = domain.salt !== undefined;
|
|
369
|
+
if (hasChainId === hasSalt) {
|
|
370
|
+
problems.push(`${at}.authorization.domain must contain exactly one of chainId or salt`);
|
|
371
|
+
}
|
|
372
|
+
if (hasChainId) {
|
|
373
|
+
if (!isNonNegativeInt(domain.chainId)) {
|
|
374
|
+
problems.push(`${at}.authorization.domain.chainId is not a non-negative integer`);
|
|
375
|
+
}
|
|
376
|
+
else if (domain.chainId !== Number(registryChainId)) {
|
|
377
|
+
problems.push(`${at}.authorization.domain.chainId does not match registry chain ${registryChainId}`);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (hasSalt && !BYTES32.test(String(domain.salt))) {
|
|
381
|
+
problems.push(`${at}.authorization.domain.salt is not a bytes32 hex value`);
|
|
382
|
+
}
|
|
383
|
+
const pinnedSeparator = String(authorization.domainSeparator);
|
|
384
|
+
if (!BYTES32.test(pinnedSeparator)) {
|
|
385
|
+
problems.push(`${at}.authorization.domainSeparator is not a bytes32 hex value`);
|
|
386
|
+
}
|
|
387
|
+
else if (isNonEmptyString(domain.name) &&
|
|
388
|
+
isNonEmptyString(domain.version) &&
|
|
389
|
+
typeof verifyingContract === 'string' &&
|
|
390
|
+
(0, viem_1.isAddress)(verifyingContract) &&
|
|
391
|
+
hasChainId !== hasSalt &&
|
|
392
|
+
(!hasChainId || isNonNegativeInt(domain.chainId)) &&
|
|
393
|
+
(!hasSalt || BYTES32.test(String(domain.salt)))) {
|
|
394
|
+
const derived = (0, viem_1.domainSeparator)({
|
|
395
|
+
domain: domain,
|
|
396
|
+
});
|
|
397
|
+
if (derived.toLowerCase() !== pinnedSeparator.toLowerCase()) {
|
|
398
|
+
problems.push(`${at}.authorization.domainSeparator does not match the declared EIP-712 domain`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
if (typeof authorization.eoaOnly !== 'boolean') {
|
|
403
|
+
problems.push(`${at}.authorization.eoaOnly is not a boolean`);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
312
407
|
});
|
|
313
408
|
}
|
|
314
409
|
for (const [field, allowed] of [
|
|
@@ -958,7 +1053,7 @@ function validateChainConfig(chains) {
|
|
|
958
1053
|
});
|
|
959
1054
|
continue;
|
|
960
1055
|
}
|
|
961
|
-
for (const problem of structuralProblems(chain)) {
|
|
1056
|
+
for (const problem of structuralProblems(chainId, chain)) {
|
|
962
1057
|
issues.push({ severity: 'error', chainId, chainName, message: problem });
|
|
963
1058
|
}
|
|
964
1059
|
// Virtual chains (HyperCore) are reachable via their settlement chain, not
|
package/dist/src/chains.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChainNetwork, ChainStack, PegGroup, ProviderIds, ProviderName, SettlementConfig, SettlementLayer, SupportedChain, SwapQuoter, SwapQuoterConfig, VmType } from "./types";
|
|
1
|
+
import type { ChainNetwork, ChainStack, PegGroup, ProviderIds, ProviderName, SettlementConfig, SettlementLayer, SupportedChain, SwapQuoter, SwapQuoterConfig, TokenAuthorization, VmType } from "./types";
|
|
2
2
|
interface Token {
|
|
3
3
|
/** EVM: 0x-prefixed hex. SVM: base58 SPL mint. TVM: base58 (T-prefixed). */
|
|
4
4
|
address: string;
|
|
@@ -8,6 +8,8 @@ interface Token {
|
|
|
8
8
|
pegGroup?: PegGroup;
|
|
9
9
|
balanceSlot: number | null;
|
|
10
10
|
approvalSlot: number | null;
|
|
11
|
+
/** Token-native EIP-712 authorization support, when verified. */
|
|
12
|
+
authorization?: TokenAuthorization;
|
|
11
13
|
/** Bridge layers that can carry this token on this chain, when known. */
|
|
12
14
|
settlementLayers?: SettlementLayer[];
|
|
13
15
|
/** Rhino's own symbol for this token, where it differs from ours. */
|