feat: update validators and ICA owners for recent deployments (#4467)

feat: update validators for latest chain deployment
- add merkly validators to new chains
- add luganodes to default fraxtal ISM
- add renzo to default mode ISM
- add solana validators
- add eclipse validators

feat: configure ICA ownership for recently deployed chains:
- jul26 batch
	- xlayer cheesechain worldchain
	- zircuit is already safe-owned
- aug5 batch
- cyber degenchain kroma lisk lukso merlin metis mint proofofplay real
sanko tangle xai
	- taiko is already safe-owned
- aug26 batch
	- astar astarzkevm bitlayer coredao dogechain flare molten shibarium

drive-by:
- improve formatting on check-validator-announce script
dan/token-config-schema
Paul Balaji 2 months ago committed by GitHub
parent 0e2f94ba10
commit 741477a0b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 33
      typescript/infra/config/environments/mainnet3/owners.ts
  2. 91
      typescript/infra/scripts/check-validator-announce.ts
  3. 4
      typescript/infra/src/govern/HyperlaneAppGovernor.ts
  4. 114
      typescript/sdk/src/consts/multisigIsm.ts
  5. 2
      typescript/sdk/src/ism/EvmIsmReader.ts

@ -66,6 +66,39 @@ export const icas: Partial<
> = {
viction: '0x23ed65DE22ac29Ec1C16E75EddB0cE3A187357b4',
inevm: '0xFDF9EDcb2243D51f5f317b9CEcA8edD2bEEE036e',
// Jul 26, 2024 batch
// -------------------------------------
xlayer: '0x1571c482fe9E76bbf50829912b1c746792966369',
cheesechain: '0xEe2C5320BE9bC7A1492187cfb289953b53E3ff1b',
worldchain: '0x1996DbFcFB433737fE404F58D2c32A7f5f334210',
// zircuit: '0x0d67c56E818a02ABa58cd2394b95EF26db999aA3', // already has a safe
// Aug 5, 2024 batch
cyber: '0x984Fe5a45Ac4aaeC4E4655b50f776aB79c9Be19F',
degenchain: '0x22d952d3b9F493442731a3c7660aCaD98e55C00A',
kroma: '0xc1e20A0D78E79B94D71d4bDBC8FD0Af7c856Dd7A',
lisk: '0x22d952d3b9F493442731a3c7660aCaD98e55C00A',
lukso: '0xc1e20A0D78E79B94D71d4bDBC8FD0Af7c856Dd7A',
merlin: '0xCf867cEaeeE8CBe65C680c734D29d26440931D5b',
metis: '0xb51e63CD0842D670a13c88B159fCFc268DA652A3',
mint: '0xb51e63CD0842D670a13c88B159fCFc268DA652A3',
proofofplay: '0xb51e63CD0842D670a13c88B159fCFc268DA652A3',
real: '0xc761e68BF3A94326FD0D305e3ccb4cdaab2edA19',
sanko: '0x5DAcd2f1AafC749F2935A160865Ab1568eC23752',
tangle: '0xCC2aeb692197C7894E561d31ADFE8F79746f7d9F',
xai: '0x22d952d3b9F493442731a3c7660aCaD98e55C00A',
// taiko: '0x483D218D2FEe7FC7204ba15F00C7901acbF9697D', // already has a safe
// Aug 26, 2024 batch
astar: '0x6b241544eBa7d89B51b72DF85a0342dAa37371Ca',
astarzkevm: '0x526c6DAee1175A1A2337E703B63593acb327Dde4',
bitlayer: '0xe6239316cA60814229E801fF0B9DD71C9CA29008',
coredao: '0x84802CdF47565C95d8ffd59E7c4B1cf027F5452F',
dogechain: '0x84802CdF47565C95d8ffd59E7c4B1cf027F5452F',
flare: '0x689b8DaBBF2f9Fd83D37427A062B30edF463e20b',
molten: '0x84802CdF47565C95d8ffd59E7c4B1cf027F5452F',
shibarium: '0x6348FAe3a8374dbAAaE84EEe5458AE4063Fe2be7',
} as const;
export const DEPLOYER = '0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba';

@ -1,4 +1,4 @@
import { defaultMultisigConfigs } from '@hyperlane-xyz/sdk';
import { ChainMap, defaultMultisigConfigs } from '@hyperlane-xyz/sdk';
import { eqAddress } from '@hyperlane-xyz/utils';
import { isEthereumProtocolChain } from '../src/utils/utils.js';
@ -6,6 +6,19 @@ import { isEthereumProtocolChain } from '../src/utils/utils.js';
import { getArgs, withChains } from './agent-utils.js';
import { getEnvironmentConfig, getHyperlaneCore } from './core-utils.js';
const minimumValidatorCount = 3;
const getMinimumThreshold = (validatorCount: number): number =>
Math.floor(validatorCount / 2) + 1;
const thresholdOK = 'threshold OK';
const totalOK = 'total OK';
enum CheckResult {
OK = '✅',
WARNING = '🚨',
}
async function main() {
const { environment, chains } = await withChains(getArgs()).argv;
const config = getEnvironmentConfig(environment);
@ -15,6 +28,8 @@ async function main() {
chains && chains.length > 0 ? chains : config.supportedChainNames
).filter(isEthereumProtocolChain);
const chainsWithUnannouncedValidators: ChainMap<string[]> = {};
const results = await Promise.all(
targetNetworks.map(async (chain) => {
const validatorAnnounce = core.getContracts(chain).validatorAnnounce;
@ -22,20 +37,88 @@ async function main() {
await validatorAnnounce.getAnnouncedValidators();
const validators = defaultMultisigConfigs[chain].validators || [];
const missingValidators = validators.filter(
const unannouncedValidators = validators.filter(
(validator) =>
!announcedValidators.some((x) => eqAddress(x, validator)),
);
if (unannouncedValidators.length > 0) {
chainsWithUnannouncedValidators[chain] = unannouncedValidators;
}
const validatorCount = validators.length;
const unannouncedValidatorCount = unannouncedValidators.length;
const threshold = defaultMultisigConfigs[chain].threshold;
const minimumThreshold = getMinimumThreshold(validatorCount);
return {
chain,
status:
missingValidators.length === 0 ? '✅' : missingValidators.join(', '),
threshold,
[thresholdOK]:
threshold < minimumThreshold || threshold > validatorCount
? CheckResult.WARNING
: CheckResult.OK,
total: validatorCount,
[totalOK]:
validatorCount < minimumValidatorCount
? CheckResult.WARNING
: CheckResult.OK,
unannounced:
unannouncedValidatorCount > 0 ? unannouncedValidatorCount : '',
};
}),
);
console.table(results);
const invalidThresholdChains = results
.filter((r) => r[thresholdOK] === CheckResult.WARNING)
.map((r) => r.chain);
const lowValidatorCountChains = results
.filter((r) => r[totalOK] === CheckResult.WARNING)
.map((r) => ({
chain: r.chain,
neededValidators: minimumValidatorCount - r.total,
}));
if (invalidThresholdChains.length > 0) {
console.log('\n⚠ Chains with invalid thresholds:');
invalidThresholdChains.forEach((chain) => {
const validatorCount = defaultMultisigConfigs[chain].validators.length;
const minimumThreshold = getMinimumThreshold(validatorCount);
console.log(
` - ${chain}:`,
`threshold should be ${minimumThreshold} ≤ t ≤ ${validatorCount}`,
);
});
} else {
console.log('\n✅ Thresholds look good!');
}
if (lowValidatorCountChains.length > 0) {
console.log('\n⚠ Chains with low validator counts:');
lowValidatorCountChains.forEach((c) => {
console.log(
` - ${c.chain}: needs ${c.neededValidators} more validator${
c.neededValidators === 1 ? '' : 's'
}`,
);
});
} else {
console.log('\n✅ Validator counts look good!');
}
const unnanouncedChains = Object.keys(chainsWithUnannouncedValidators);
if (unnanouncedChains.length > 0) {
console.log('\n⚠ Chains with unannounced validators:');
unnanouncedChains.forEach((chain) => {
console.log(` - ${chain}: ${chainsWithUnannouncedValidators[chain]}`);
});
} else {
console.log('\n✅ All validators announced!');
}
}
main().catch(console.error);

@ -168,9 +168,7 @@ export abstract class HyperlaneAppGovernor<
const safeOwner =
this.checker.configMap[chain].ownerOverrides?._safeAddress;
if (!safeOwner) {
console.warn(`No Safe owner found for chain ${chain}`);
} else {
if (safeOwner) {
await retryAsync(
() =>
sendCallsForType(

@ -38,13 +38,21 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
astar: {
threshold: 1,
validators: ['0x4d1b2cade01ee3493f44304653d8e352c66ec3e7'],
threshold: 2,
validators: [
'0x4d1b2cade01ee3493f44304653d8e352c66ec3e7',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
astarzkevm: {
threshold: 1,
validators: ['0x89ecdd6caf138934bf3a2fb7b323984d72fd66de'],
threshold: 2,
validators: [
'0x89ecdd6caf138934bf3a2fb7b323984d72fd66de',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
avalanche: {
@ -73,8 +81,12 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
bitlayer: {
threshold: 1,
validators: ['0x1d9b0f4ea80dbfc71cb7d64d8005eccf7c41e75f'],
threshold: 2,
validators: [
'0x1d9b0f4ea80dbfc71cb7d64d8005eccf7c41e75f',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
blast: {
@ -148,8 +160,12 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
coredao: {
threshold: 1,
validators: ['0xbd6e158a3f5830d99d7d2bce192695bc4a148de2'],
threshold: 2,
validators: [
'0xbd6e158a3f5830d99d7d2bce192695bc4a148de2',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
cyber: {
@ -171,13 +187,22 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
dogechain: {
threshold: 1,
validators: ['0xe43f742c37858746e6d7e458bc591180d0cba440'],
threshold: 2,
validators: [
'0xe43f742c37858746e6d7e458bc591180d0cba440',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
eclipsemainnet: {
threshold: 1,
validators: ['0xebb52d7eaa3ff7a5a6260bfe5111ce52d57401d0'],
threshold: 3,
validators: [
'0xebb52d7eaa3ff7a5a6260bfe5111ce52d57401d0',
'0x3571223e745dc0fcbdefa164c9b826b90c0d2dac', // luganodes
'0xea83086a62617a7228ce4206fae2ea8b0ab23513', // imperator
'0x4d4629f5bfeabe66edc7a78da26ef5273c266f97', // eclipse
],
},
eclipsetestnet: {
@ -213,13 +238,21 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
everclear: {
threshold: 1,
validators: ['0xeff20ae3d5ab90abb11e882cfce4b92ea6c74837'],
threshold: 2,
validators: [
'0xeff20ae3d5ab90abb11e882cfce4b92ea6c74837',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0xD79DFbF56ee2268f061cc613027a44A880f61Ba2', // everclear
],
},
flare: {
threshold: 1,
validators: ['0xb65e52be342dba3ab2c088ceeb4290c744809134'],
threshold: 2,
validators: [
'0xb65e52be342dba3ab2c088ceeb4290c744809134',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
fraxtal: {
@ -227,6 +260,7 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
validators: [
'0x4bce180dac6da60d0f3a2bdf036ffe9004f944c1',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x25b3a88f7cfd3c9f7d7e32b295673a16a6ddbd91', // luganodes
],
},
@ -313,6 +347,7 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
validators: [
'0xa5e953701dcddc5b958b5defb677a829d908df6d',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x101cE77261245140A0871f9407d6233C8230Ec47', // blockhunters
],
},
@ -366,16 +401,22 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
mode: {
threshold: 2,
threshold: 3,
validators: [
'0x7eb2e1920a4166c19d6884c1cec3d2cf356fc9b7',
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
'0x7e29608c6e5792bbf9128599ca309be0728af7b4', // renzo
'0x101cE77261245140A0871f9407d6233C8230Ec47', // blockhunters
],
},
molten: {
threshold: 1,
validators: ['0xad5aa33f0d67f6fa258abbe75458ea4908f1dc9f'],
threshold: 2,
validators: [
'0xad5aa33f0d67f6fa258abbe75458ea4908f1dc9f',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
moonbeam: {
@ -402,8 +443,12 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
oortmainnet: {
threshold: 1,
validators: ['0x9b7ff56cd9aa69006f73f1c5b8c63390c706a5d7'],
threshold: 2,
validators: [
'0x9b7ff56cd9aa69006f73f1c5b8c63390c706a5d7',
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
'0x032dE4f94676bF9314331e7D83E8Db4aC74c9E21', // oort
],
},
optimism: {
@ -479,6 +524,7 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
validators: [
'0x1400b9737007f7978d8b4bbafb4a69c83f0641a7',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
@ -511,10 +557,12 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
sei: {
threshold: 2,
threshold: 3,
validators: [
'0x9920d2dbf6c85ffc228fdc2e810bf895732c6aa5',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x101cE77261245140A0871f9407d6233C8230Ec47', // blockhunters
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
@ -528,8 +576,12 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
shibarium: {
threshold: 1,
validators: ['0xfa33391ee38597cbeef72ccde8c9e13e01e78521'],
threshold: 2,
validators: [
'0xfa33391ee38597cbeef72ccde8c9e13e01e78521',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},
solanadevnet: {
@ -542,8 +594,14 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
solanamainnet: {
threshold: 1,
validators: ['0x28464752829b3ea59a497fca0bdff575c534c3ff'],
threshold: 3,
validators: [
'0x28464752829b3ea59a497fca0bdff575c534c3ff',
'0x2b7514a2f77bd86bbf093fe6bb67d8611f51c659', // luganodes
'0xd90ea26ff731d967c5ea660851f7d63cb04ab820', // dsrv
'0x38c7a4ca1273ead2e867d096adbcdd0e2acb21d8', // everstake
'0xcb6bcbd0de155072a7ff486d9d7286b0f71dcc2d', // eclipse
],
},
solanatestnet: {
@ -628,10 +686,12 @@ export const defaultMultisigConfigs: ChainMap<MultisigConfig> = {
},
zetachain: {
threshold: 2,
threshold: 3,
validators: [
'0xa3bca0b80317dbf9c7dce16a16ac89f4ff2b23ef',
'0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f', // merkly
'0x101cE77261245140A0871f9407d6233C8230Ec47', // blockhunters
'0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36', // mitosis
],
},

@ -112,7 +112,7 @@ export class EvmIsmReader extends HyperlaneReader implements IsmReader {
throw new Error(`Unknown ISM ModuleType: ${moduleType}`);
}
} catch (e: any) {
const errorMessage = `Failed to derive ISM module type ${moduleType} (${address}):\n\t${e}`;
const errorMessage = `Failed to derive ISM module type ${moduleType} on ${this.chain} (${address}) :\n\t${e}`;
this.logger.debug(errorMessage);
throw new Error(errorMessage);
} finally {

Loading…
Cancel
Save