From 26ca14cbd537ac38d52b19df71f33b1a6591e5a8 Mon Sep 17 00:00:00 2001
From: Nam Chu Hoai <nambrot@googlemail.com>
Date: Thu, 2 Nov 2023 20:07:51 -0400
Subject: [PATCH 1/9] Add validators

---
 typescript/infra/scripts/verify-validators.ts |  9 +---
 typescript/infra/src/agents/aws/validator.ts  | 38 ++++----------
 typescript/sdk/src/consts/multisigIsm.ts      | 46 +++++++++--------
 typescript/utils/src/checkpoints.ts           |  2 +-
 typescript/utils/src/domains.ts               |  4 +-
 typescript/utils/src/types.ts                 |  2 +-
 typescript/utils/src/validator.ts             | 51 +++++++++++--------
 7 files changed, 69 insertions(+), 83 deletions(-)

diff --git a/typescript/infra/scripts/verify-validators.ts b/typescript/infra/scripts/verify-validators.ts
index 57404712a4..31ce7352b0 100644
--- a/typescript/infra/scripts/verify-validators.ts
+++ b/typescript/infra/scripts/verify-validators.ts
@@ -7,9 +7,7 @@ import { deployEnvToSdkEnv } from '../src/config/environment';
 import { getArgs, getEnvironmentConfig, getValidatorsByChain } from './utils';
 
 async function main() {
-  const { environment, withMessageId } = await getArgs()
-    .boolean('with-message-id')
-    .default('with-message-id', true).argv;
+  const { environment } = await getArgs().argv;
   const config = getEnvironmentConfig(environment);
   const multiProvider = await config.getMultiProvider();
   const core = HyperlaneCore.fromEnvironment(
@@ -36,10 +34,7 @@ async function main() {
       const address = prospectiveValidator.address;
       const bucket = prospectiveValidator.s3Bucket.bucket;
       try {
-        const metrics = await prospectiveValidator.compare(
-          controlValidator,
-          withMessageId,
-        );
+        const metrics = await prospectiveValidator.compare(controlValidator);
         const valid =
           metrics.filter((metric) => metric.status !== CheckpointStatus.VALID)
             .length === 0;
diff --git a/typescript/infra/src/agents/aws/validator.ts b/typescript/infra/src/agents/aws/validator.ts
index d6582ccd7e..1dc3dd735e 100644
--- a/typescript/infra/src/agents/aws/validator.ts
+++ b/typescript/infra/src/agents/aws/validator.ts
@@ -27,14 +27,12 @@ interface CheckpointMetric {
 
 interface SignedCheckpoint {
   checkpoint: Checkpoint;
-  messageId?: HexString;
+  messageId: HexString;
   signature: SignatureLike;
 }
 
 type S3CheckpointReceipt = S3Receipt<SignedCheckpoint>;
 
-const checkpointKey = (checkpointIndex: number) =>
-  `checkpoint_${checkpointIndex}.json`;
 const checkpointWithMessageIdKey = (checkpointIndex: number) =>
   `checkpoint_${checkpointIndex}_with_id.json`;
 const LATEST_KEY = 'checkpoint_latest_index.json';
@@ -99,11 +97,7 @@ export class S3Validator extends BaseValidator {
     return latestCheckpointIndex.data;
   }
 
-  async compare(
-    other: S3Validator,
-    withId = false,
-    count = 5,
-  ): Promise<CheckpointMetric[]> {
+  async compare(other: S3Validator, count = 5): Promise<CheckpointMetric[]> {
     const latestCheckpointIndex = await this.s3Bucket.getS3Obj<number>(
       LATEST_KEY,
     );
@@ -140,11 +134,8 @@ export class S3Validator extends BaseValidator {
     const stop = Math.max(maxIndex - count, 0);
 
     for (; checkpointIndex > stop; checkpointIndex--) {
-      const expected = await other.getCheckpointReceipt(
-        checkpointIndex,
-        withId,
-      );
-      const actual = await this.getCheckpointReceipt(checkpointIndex, withId);
+      const expected = await other.getCheckpointReceipt(checkpointIndex);
+      const actual = await this.getCheckpointReceipt(checkpointIndex);
 
       const metric: CheckpointMetric = {
         status: CheckpointStatus.MISSING,
@@ -178,10 +169,10 @@ export class S3Validator extends BaseValidator {
           ) {
             metric.violation = `index mismatch: expected ${expected.data.checkpoint.index}, received ${actual.data.checkpoint.index}`;
           } else if (
-            expected.data.checkpoint.mailbox_address !==
-            actual.data.checkpoint.mailbox_address
+            expected.data.checkpoint.merkle_tree_hook_address !==
+            actual.data.checkpoint.merkle_tree_hook_address
           ) {
-            metric.violation = `mailbox address mismatch: expected ${expected.data.checkpoint.mailbox_address}, received ${actual.data.checkpoint.mailbox_address}`;
+            metric.violation = `mailbox address mismatch: expected ${expected.data.checkpoint.merkle_tree_hook_address}, received ${actual.data.checkpoint.merkle_tree_hook_address}`;
           } else if (
             expected.data.checkpoint.mailbox_domain !==
             actual.data.checkpoint.mailbox_domain
@@ -209,26 +200,15 @@ export class S3Validator extends BaseValidator {
 
   private async getCheckpointReceipt(
     index: number,
-    withId = false,
   ): Promise<S3CheckpointReceipt | undefined> {
-    const key = withId
-      ? checkpointWithMessageIdKey(index)
-      : checkpointKey(index);
+    const key = checkpointWithMessageIdKey(index);
     const s3Object = await this.s3Bucket.getS3Obj<
       S3Checkpoint | S3CheckpointWithId
     >(key);
     if (!s3Object) {
       return;
     }
-    if (isS3Checkpoint(s3Object.data)) {
-      return {
-        data: {
-          checkpoint: s3Object.data.value,
-          signature: s3Object.data.signature,
-        },
-        modified: s3Object.modified,
-      };
-    } else if (isS3CheckpointWithId(s3Object.data)) {
+    if (isS3CheckpointWithId(s3Object.data)) {
       return {
         data: {
           checkpoint: s3Object.data.value.checkpoint,
diff --git a/typescript/sdk/src/consts/multisigIsm.ts b/typescript/sdk/src/consts/multisigIsm.ts
index e6c9608e24..53ba756272 100644
--- a/typescript/sdk/src/consts/multisigIsm.ts
+++ b/typescript/sdk/src/consts/multisigIsm.ts
@@ -7,24 +7,25 @@ export const defaultMultisigIsmConfigs: ChainMap<MultisigConfig> = {
     threshold: 2,
     validators: [
       '0x63478422679303c3e4fc611b771fa4a707ef7f4a',
-      '0x2f4e808744df049d8acc050628f7bdd8265807f9',
-      '0x7bf30afcb6a7d92146d5a910ea4c154fba38d25e',
+      '0x622e43baf06ad808ca8399360d9a2d9a1a12688b', // dsrv
+      '0xf2c1e3888eb618f1f1a071ef3618f134715a9a49', // everstake
     ],
   },
   ethereum: {
-    threshold: 2,
+    threshold: 3,
     validators: [
       '0x03c842db86a6a3e524d4a6615390c1ea8e2b9541',
-      '0x4346776b10f5e0d9995d884b7a1dbaee4e24c016',
-      '0x749d6e7ad949e522c92181dc77f7bbc1c5d71506',
+      '0x94438a7de38d4548ae54df5c6010c4ebc5239eae', // dsrv
+      '0x5450447aee7b544c462c9352bef7cad049b0c2dc', // zeeprime
+      '0xce327111035dd38698c92c3778884dbbb0ca8103', // everstake
     ],
   },
   avalanche: {
     threshold: 2,
     validators: [
       '0x3fb8263859843bffb02950c492d492cae169f4cf',
-      '0xe58c63ad669b946e7c8211299f22679deecc9c83',
-      '0x6c754f1e9cd8287088b46a7c807303d55d728b49',
+      '0x402e0f8c6e4210d408b6ac00d197d4a099fcd25a', // dsrv
+      '0x716a1d4d3166c6151b05ce0450e0d77d94588eac', // everstake
     ],
   },
   polygon: {
@@ -32,47 +33,48 @@ export const defaultMultisigIsmConfigs: ChainMap<MultisigConfig> = {
     validators: [
       '0x12ecb319c7f4e8ac5eb5226662aeb8528c5cefac',
       '0x8dd8f8d34b5ecaa5f66de24b01acd7b8461c3916',
-      '0xdbf3666de031bea43ec35822e8c33b9a9c610322',
+      '0x722aa4d45387009684582bca8281440d16b8b40f', // everstake
     ],
   },
   bsc: {
     threshold: 2,
     validators: [
       '0x570af9b7b36568c8877eebba6c6727aa9dab7268',
-      '0x7bf928d5d262365d31d64eaa24755d48c3cae313',
-      '0x03047213365800f065356b4a2fe97c3c3a52296a',
+      '0x8292b1a53907ece0f76af8a50724e9492bcdc8a3', // bsc
+      '0xeaf5cf9100f36a4baeea779f8745dda86159103c', // everstake
     ],
   },
   arbitrum: {
-    threshold: 2,
+    threshold: 3,
     validators: [
       '0x4d966438fe9e2b1e7124c87bbb90cb4f0f6c59a1',
-      '0x6333e110b8a261cab28acb43030bcde59f26978a',
-      '0x3369e12edd52570806f126eb50be269ba5e65843',
+      '0xec68258a7c882ac2fc46b81ce80380054ffb4ef2', // dsrv
+      '0x5450447aee7b544c462c9352bef7cad049b0c2dc', // zeeprime
+      '0x092e1c19da58e87ea65198785ee83867fe4bb418', // everstake
     ],
   },
   optimism: {
     threshold: 2,
     validators: [
       '0x20349eadc6c72e94ce38268b96692b1a5c20de4f',
-      '0x04d040cee072272789e2d1f29aef73b3ad098db5',
-      '0x779a17e035018396724a6dec8a59bda1b5adf738',
+      '0x5b7d47b76c69740462432f6a5a0ca5005e014157', // dsrv
+      '0x22b1ad4322cdb5f2c76ebf4e5a93803d480fcf0d', // everstake
     ],
   },
   moonbeam: {
     threshold: 2,
     validators: [
       '0x2225e2f4e9221049456da93b71d2de41f3b6b2a8',
-      '0x4fe067bb455358e295bfcfb92519a6f9de94b98e',
-      '0xcc4a78aa162482bea43313cd836ba7b560b44fc4',
+      '0x645428d198d2e76cbd9c1647f5c80740bb750b97', // dsrv
+      '0xaed886392df07897743d8e272d438f00c4c9a2ae', // everstake
     ],
   },
   gnosis: {
     threshold: 2,
     validators: [
       '0xd4df66a859585678f2ea8357161d896be19cc1ca',
-      '0x06a833508579f8b59d756b3a1e72451fc70840c3',
-      '0xb93a72cee19402553c9dd7fed2461aebd04e2454',
+      '0x19fb7e04a1be6b39b6966a0b0c60b929a93ed672', // dsrv
+      '0xdb96116d13a2fadde9742d7cc88474a5ed39a03a', // everstake
     ],
   },
   // solana: {
@@ -85,7 +87,7 @@ export const defaultMultisigIsmConfigs: ChainMap<MultisigConfig> = {
     validators: [
       '0xb9453d675e0fa3c178a17b4ce1ad5b1a279b3af9',
       '0x4512985a574cb127b2af2d4bb676876ce804e3f8',
-      '0xb144bb2f599a5af095bc30367856f27ea8a8adc7',
+      '0x41188cb5a5493a961c467ba38a3f8b1f1d35ee63', // everstake
     ],
   },
   scroll: {
@@ -93,7 +95,7 @@ export const defaultMultisigIsmConfigs: ChainMap<MultisigConfig> = {
     validators: [
       '0xad557170a9f2f21c35e03de07cb30dcbcc3dff63',
       '0xb37fe43a9f47b7024c2d5ae22526cc66b5261533',
-      '0x7210fa0a6be39a75cb14d682ebfb37e2b53ecbe5',
+      '0x276de8e2b88e659c4e5ad30d62d9de42c3da3403', // everstake
     ],
   },
   polygonzkevm: {
@@ -101,7 +103,7 @@ export const defaultMultisigIsmConfigs: ChainMap<MultisigConfig> = {
     validators: [
       '0x86f2a44592bb98da766e880cfd70d3bbb295e61a',
       '0xc84076030bdabaabb9e61161d833dd84b700afda',
-      '0x6a1da2e0b7ae26aaece1377c0a4dbe25b85fa3ca',
+      '0x57231619fea13d85270ca6943298046c75a6dd01', // everstake
     ],
   },
   // ----------------- Testnets -----------------
diff --git a/typescript/utils/src/checkpoints.ts b/typescript/utils/src/checkpoints.ts
index 010b7d0cce..e313187688 100644
--- a/typescript/utils/src/checkpoints.ts
+++ b/typescript/utils/src/checkpoints.ts
@@ -30,7 +30,7 @@ export function isS3CheckpointWithId(obj: any): obj is S3CheckpointWithId {
 export function isCheckpoint(obj: any): obj is Checkpoint {
   const isValidRoot = utils.isHexString(obj.root);
   const isValidIndex = Number.isSafeInteger(obj.index);
-  const isValidMailbox = utils.isHexString(obj.mailbox_address);
+  const isValidMailbox = utils.isHexString(obj.merkle_tree_hook_address);
   const isValidDomain = Number.isSafeInteger(obj.mailbox_domain);
   return isValidIndex && isValidRoot && isValidMailbox && isValidDomain;
 }
diff --git a/typescript/utils/src/domains.ts b/typescript/utils/src/domains.ts
index 2a2ba3efdc..21327d9515 100644
--- a/typescript/utils/src/domains.ts
+++ b/typescript/utils/src/domains.ts
@@ -2,9 +2,9 @@ import { utils } from 'ethers';
 
 import { addressToBytes32 } from './addresses';
 
-export function domainHash(domain: number, mailbox: string): string {
+export function domainHash(domain: number, merkle_tree_hook: string): string {
   return utils.solidityKeccak256(
     ['uint32', 'bytes32', 'string'],
-    [domain, addressToBytes32(mailbox), 'HYPERLANE'],
+    [domain, addressToBytes32(merkle_tree_hook), 'HYPERLANE'],
   );
 }
diff --git a/typescript/utils/src/types.ts b/typescript/utils/src/types.ts
index 525f26feb2..770a3ccaa5 100644
--- a/typescript/utils/src/types.ts
+++ b/typescript/utils/src/types.ts
@@ -43,7 +43,7 @@ export type Checkpoint = {
   root: string;
   index: number; // safe because 2 ** 32 leaves < Number.MAX_VALUE
   mailbox_domain: Domain;
-  mailbox_address: Address;
+  merkle_tree_hook_address: Address;
 };
 
 /**
diff --git a/typescript/utils/src/validator.ts b/typescript/utils/src/validator.ts
index 6c6fca7b63..5b76de2846 100644
--- a/typescript/utils/src/validator.ts
+++ b/typescript/utils/src/validator.ts
@@ -16,29 +16,34 @@ import {
 export class BaseValidator {
   localDomain: Domain;
   address: Address;
-  mailbox: Address;
+  merkle_tree_hook_address: Address;
 
-  constructor(address: Address, localDomain: Domain, mailbox: Address) {
+  constructor(
+    address: Address,
+    localDomain: Domain,
+    merkle_tree_hook_address: Address,
+  ) {
     this.localDomain = localDomain;
     this.address = address;
-    this.mailbox = mailbox;
+    this.merkle_tree_hook_address = merkle_tree_hook_address;
   }
 
   domainHash() {
-    return domainHash(this.localDomain, this.mailbox);
+    return domainHash(this.localDomain, this.merkle_tree_hook_address);
   }
 
-  message(checkpoint: Checkpoint, messageId?: HexString) {
-    const types = ['bytes32', 'bytes32', 'uint32'];
-    const values = [this.domainHash(), checkpoint.root, checkpoint.index];
-    if (messageId) {
-      types.push('bytes32');
-      values.push(messageId);
-    }
+  message(checkpoint: Checkpoint, messageId: HexString) {
+    const types = ['bytes32', 'bytes32', 'uint32', 'bytes32'];
+    const values = [
+      this.domainHash(),
+      checkpoint.root,
+      checkpoint.index,
+      messageId,
+    ];
     return ethers.utils.solidityPack(types, values);
   }
 
-  messageHash(checkpoint: Checkpoint, messageId?: HexString) {
+  messageHash(checkpoint: Checkpoint, messageId: HexString) {
     const message = this.message(checkpoint, messageId);
     return ethers.utils.arrayify(ethers.utils.keccak256(message));
   }
@@ -46,7 +51,7 @@ export class BaseValidator {
   recoverAddressFromCheckpoint(
     checkpoint: Checkpoint,
     signature: SignatureLike,
-    messageId?: HexString,
+    messageId: HexString,
   ): Address {
     const msgHash = this.messageHash(checkpoint, messageId);
     return ethers.utils.verifyMessage(msgHash, signature);
@@ -55,7 +60,7 @@ export class BaseValidator {
   matchesSigner(
     checkpoint: Checkpoint,
     signature: SignatureLike,
-    messageId?: HexString,
+    messageId: HexString,
   ) {
     return (
       this.recoverAddressFromCheckpoint(
@@ -72,32 +77,36 @@ export class Validator extends BaseValidator {
     protected signer: ethers.Signer,
     address: Address,
     localDomain: Domain,
-    mailbox: Address,
+    merkle_tree_hook_address: Address,
   ) {
-    super(address, localDomain, mailbox);
+    super(address, localDomain, merkle_tree_hook_address);
   }
 
   static async fromSigner(
     signer: ethers.Signer,
     localDomain: Domain,
-    mailbox: Address,
+    merkle_tree_hook_address: Address,
   ) {
     return new Validator(
       signer,
       await signer.getAddress(),
       localDomain,
-      mailbox,
+      merkle_tree_hook_address,
     );
   }
 
-  async signCheckpoint(root: HexString, index: number): Promise<S3Checkpoint> {
+  async signCheckpoint(
+    root: HexString,
+    index: number,
+    messageId: string,
+  ): Promise<S3Checkpoint> {
     const checkpoint = {
       root,
       index,
-      mailbox_address: this.mailbox,
+      merkle_tree_hook_address: this.merkle_tree_hook_address,
       mailbox_domain: this.localDomain,
     };
-    const msgHash = this.messageHash(checkpoint);
+    const msgHash = this.messageHash(checkpoint, messageId);
     const signature = await this.signer.signMessage(msgHash);
     return {
       value: checkpoint,

From d3abad23ac73ef8d97dcc5bd132cd392e53f97c2 Mon Sep 17 00:00:00 2001
From: Yorke Rhodes <yorke@hyperlane.xyz>
Date: Thu, 9 Nov 2023 15:39:56 -0500
Subject: [PATCH 2/9] Fix checkpoint domain hash

---
 typescript/infra/src/agents/aws/validator.ts |  2 +-
 typescript/utils/index.ts                    |  2 +-
 typescript/utils/src/validator.ts            | 76 +++-----------------
 3 files changed, 13 insertions(+), 67 deletions(-)

diff --git a/typescript/infra/src/agents/aws/validator.ts b/typescript/infra/src/agents/aws/validator.ts
index 1dc3dd735e..fd8ffa4b6f 100644
--- a/typescript/infra/src/agents/aws/validator.ts
+++ b/typescript/infra/src/agents/aws/validator.ts
@@ -5,7 +5,6 @@ import {
   S3Checkpoint,
   S3CheckpointWithId,
   SignatureLike,
-  isS3Checkpoint,
   isS3CheckpointWithId,
 } from '@hyperlane-xyz/utils';
 
@@ -68,6 +67,7 @@ export class S3Validator extends BaseValidator {
         const address = announcement?.data.value.validator;
         const mailbox = announcement?.data.value.mailbox_address;
         const localDomain = announcement?.data.value.mailbox_domain;
+
         return new S3Validator(
           address,
           localDomain,
diff --git a/typescript/utils/index.ts b/typescript/utils/index.ts
index a60d68b8d0..6c419bbbaf 100644
--- a/typescript/utils/index.ts
+++ b/typescript/utils/index.ts
@@ -116,4 +116,4 @@ export {
   TokenCaip19Id,
 } from './src/types';
 export { assert } from './src/validation';
-export { BaseValidator, Validator } from './src/validator';
+export { BaseValidator } from './src/validator';
diff --git a/typescript/utils/src/validator.ts b/typescript/utils/src/validator.ts
index 5b76de2846..f30b6d5eed 100644
--- a/typescript/utils/src/validator.ts
+++ b/typescript/utils/src/validator.ts
@@ -1,41 +1,30 @@
 import { ethers } from 'ethers';
 
 import { domainHash } from './domains';
-import {
-  Address,
-  Checkpoint,
-  Domain,
-  HexString,
-  S3Checkpoint,
-  SignatureLike,
-} from './types';
+import { Address, Checkpoint, Domain, HexString, SignatureLike } from './types';
 
 /**
  * Utilities for validators to construct and verify checkpoints.
  */
 export class BaseValidator {
-  localDomain: Domain;
-  address: Address;
-  merkle_tree_hook_address: Address;
-
   constructor(
-    address: Address,
-    localDomain: Domain,
-    merkle_tree_hook_address: Address,
-  ) {
-    this.localDomain = localDomain;
-    this.address = address;
-    this.merkle_tree_hook_address = merkle_tree_hook_address;
+    public readonly address: Address,
+    public readonly localDomain: Domain,
+    public readonly mailbox_address: Address,
+  ) {}
+
+  announceDomainHash() {
+    return domainHash(this.localDomain, this.mailbox_address);
   }
 
-  domainHash() {
-    return domainHash(this.localDomain, this.merkle_tree_hook_address);
+  checkpointDomainHash(merkle_tree_address: Address) {
+    return domainHash(this.localDomain, merkle_tree_address);
   }
 
   message(checkpoint: Checkpoint, messageId: HexString) {
     const types = ['bytes32', 'bytes32', 'uint32', 'bytes32'];
     const values = [
-      this.domainHash(),
+      this.checkpointDomainHash(checkpoint.merkle_tree_hook_address),
       checkpoint.root,
       checkpoint.index,
       messageId,
@@ -71,46 +60,3 @@ export class BaseValidator {
     );
   }
 }
-
-export class Validator extends BaseValidator {
-  constructor(
-    protected signer: ethers.Signer,
-    address: Address,
-    localDomain: Domain,
-    merkle_tree_hook_address: Address,
-  ) {
-    super(address, localDomain, merkle_tree_hook_address);
-  }
-
-  static async fromSigner(
-    signer: ethers.Signer,
-    localDomain: Domain,
-    merkle_tree_hook_address: Address,
-  ) {
-    return new Validator(
-      signer,
-      await signer.getAddress(),
-      localDomain,
-      merkle_tree_hook_address,
-    );
-  }
-
-  async signCheckpoint(
-    root: HexString,
-    index: number,
-    messageId: string,
-  ): Promise<S3Checkpoint> {
-    const checkpoint = {
-      root,
-      index,
-      merkle_tree_hook_address: this.merkle_tree_hook_address,
-      mailbox_domain: this.localDomain,
-    };
-    const msgHash = this.messageHash(checkpoint, messageId);
-    const signature = await this.signer.signMessage(msgHash);
-    return {
-      value: checkpoint,
-      signature,
-    };
-  }
-}

From 827764c22a0dad7774b1a267f19cb7d5a02dd817 Mon Sep 17 00:00:00 2001
From: Yorke Rhodes <yorke@hyperlane.xyz>
Date: Thu, 9 Nov 2023 16:03:00 -0500
Subject: [PATCH 3/9] Adjust output to table

---
 typescript/infra/scripts/verify-validators.ts | 79 +++++++++----------
 1 file changed, 37 insertions(+), 42 deletions(-)

diff --git a/typescript/infra/scripts/verify-validators.ts b/typescript/infra/scripts/verify-validators.ts
index 31ce7352b0..2433a6b4f3 100644
--- a/typescript/infra/scripts/verify-validators.ts
+++ b/typescript/infra/scripts/verify-validators.ts
@@ -1,7 +1,7 @@
 import { HyperlaneCore } from '@hyperlane-xyz/sdk';
-import { objMap } from '@hyperlane-xyz/utils';
+import { objMap, promiseObjAll } from '@hyperlane-xyz/utils';
 
-import { CheckpointStatus, S3Validator } from '../src/agents/aws/validator';
+import { S3Validator } from '../src/agents/aws/validator';
 import { deployEnvToSdkEnv } from '../src/config/environment';
 
 import { getArgs, getEnvironmentConfig, getValidatorsByChain } from './utils';
@@ -15,46 +15,41 @@ async function main() {
     multiProvider,
   );
 
-  objMap(getValidatorsByChain(config.core), async (chain, set) => {
-    const validatorAnnounce = core.getContracts(chain).validatorAnnounce;
-    const storageLocations =
-      await validatorAnnounce.getAnnouncedStorageLocations([...set]);
-    const validators = await Promise.all(
-      [...set].map((validator, i) => {
-        // Only use the latest announcement for now
-        if (storageLocations[i].length != 1) {
-          throw new Error('Only support single announcement');
-        }
-        return S3Validator.fromStorageLocation(storageLocations[i][0]);
-      }),
-    );
-    const controlValidator = validators[0];
-    for (let i = 1; i < validators.length; i++) {
-      const prospectiveValidator = validators[i];
-      const address = prospectiveValidator.address;
-      const bucket = prospectiveValidator.s3Bucket.bucket;
-      try {
-        const metrics = await prospectiveValidator.compare(controlValidator);
-        const valid =
-          metrics.filter((metric) => metric.status !== CheckpointStatus.VALID)
-            .length === 0;
-        if (!valid) {
-          console.log(
-            `${address}@${bucket} has >=1 non-valid checkpoints for ${chain}`,
-          );
-          console.log(JSON.stringify(metrics, null, 2));
-        } else {
-          console.log(
-            `${address}@${bucket} has valid checkpoints for ${chain}`,
-          );
-        }
-      } catch (error) {
-        console.error(`Comparing validator ${address}@${bucket} failed:`);
-        console.error(error);
-        throw error;
-      }
-    }
-  });
+  await promiseObjAll(
+    objMap(getValidatorsByChain(config.core), async (chain, set) => {
+      const validatorAnnounce = core.getContracts(chain).validatorAnnounce;
+      const storageLocations =
+        await validatorAnnounce.getAnnouncedStorageLocations([...set]);
+      const validators = await Promise.all(
+        [...set].map((_validator, i) => {
+          // Only use the latest announcement for now
+          if (storageLocations[i].length != 1) {
+            throw new Error('Only support single announcement');
+          }
+          return S3Validator.fromStorageLocation(storageLocations[i][0]);
+        }),
+      );
+      const controlValidator = validators[0];
+      await Promise.all(
+        validators.slice(1).map(async (prospectiveValidator) => {
+          const address = prospectiveValidator.address;
+          const bucket = prospectiveValidator.s3Bucket.bucket;
+          try {
+            const metrics = await prospectiveValidator.compare(
+              controlValidator,
+            );
+            console.log(
+              `${chain} ${bucket} validators against control ${controlValidator.s3Bucket.bucket}`,
+            );
+            console.table(metrics);
+          } catch (error) {
+            console.error(`Comparing validator ${address}@${bucket} failed:`);
+            throw error;
+          }
+        }),
+      );
+    }),
+  );
 }
 
 main().catch(console.error);

From 6687b81e281a724b6956370f702d1552f8bb5c7d Mon Sep 17 00:00:00 2001
From: nambrot <nambrot@googlemail.com>
Date: Thu, 9 Nov 2023 16:58:42 -0500
Subject: [PATCH 4/9] Fix HelloWorld checker

---
 typescript/infra/scripts/deploy.ts                  |  2 +-
 typescript/infra/src/config/helloworld/config.ts    |  4 ++++
 typescript/sdk/src/router/HyperlaneRouterChecker.ts | 12 +++---------
 typescript/sdk/src/router/types.ts                  |  2 --
 4 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/typescript/infra/scripts/deploy.ts b/typescript/infra/scripts/deploy.ts
index 3bb6903638..bf4f6eb6ee 100644
--- a/typescript/infra/scripts/deploy.ts
+++ b/typescript/infra/scripts/deploy.ts
@@ -212,7 +212,7 @@ async function main() {
       : undefined;
 
   // prompt for confirmation
-  if (environment === 'mainnet3' || environment === 'testnet4') {
+  if ((environment === 'mainnet3' || environment === 'testnet4') && !fork) {
     console.log(JSON.stringify(config, null, 2));
     const { value: confirmed } = await prompt({
       type: 'confirm',
diff --git a/typescript/infra/src/config/helloworld/config.ts b/typescript/infra/src/config/helloworld/config.ts
index 9d384d7d7a..5377200bbb 100644
--- a/typescript/infra/src/config/helloworld/config.ts
+++ b/typescript/infra/src/config/helloworld/config.ts
@@ -12,6 +12,10 @@ export async function helloWorldRouterConfig(
   multiProvider: MultiProvider,
 ): Promise<ChainMap<RouterConfig>> {
   const routerConfig = await getRouterConfig(environment, multiProvider, true);
+  if (context === Contexts.Hyperlane) {
+    return routerConfig;
+  }
+
   return objMap(routerConfig, (chain, config) => ({
     ...config,
     interchainSecurityModule: routingIsm(environment, chain, context),
diff --git a/typescript/sdk/src/router/HyperlaneRouterChecker.ts b/typescript/sdk/src/router/HyperlaneRouterChecker.ts
index 5c02684d81..7d3ded9a17 100644
--- a/typescript/sdk/src/router/HyperlaneRouterChecker.ts
+++ b/typescript/sdk/src/router/HyperlaneRouterChecker.ts
@@ -73,19 +73,13 @@ export class HyperlaneRouterChecker<
         );
 
         if (!matches) {
-          this.app.logger(
-            `Deploying ISM; ISM config of actual ${actual} does not match expected config ${JSON.stringify(
-              value,
-            )}`,
-          );
-          const deployedIsm = await this.ismFactory.deploy(chain, value);
           const violation: ConnectionClientViolation = {
             chain,
             type: violationType,
             contract: router,
             actual,
-            expected: deployedIsm.address,
-            description: `ISM config does not match deployed ISM at ${deployedIsm.address}`,
+            expected: value,
+            description: `ISM config does not match deployed ISM`,
           };
           this.addViolation(violation);
         }
@@ -136,7 +130,7 @@ export class HyperlaneRouterChecker<
           type: ClientViolationType.InterchainSecurityModule,
           contract: router,
           actual: ism,
-          expected: defaultIsm,
+          expected: zeroAddress,
         });
       }
     } else {
diff --git a/typescript/sdk/src/router/types.ts b/typescript/sdk/src/router/types.ts
index a990503c70..a6de581d2d 100644
--- a/typescript/sdk/src/router/types.ts
+++ b/typescript/sdk/src/router/types.ts
@@ -63,8 +63,6 @@ export enum ClientViolationType {
 export interface ClientViolation extends CheckerViolation {
   type: ClientViolationType;
   contract: MailboxClient;
-  actual: string;
-  expected: string;
   description?: string;
 }
 

From c2ec7eb03090f0dc83c8d146b92a6712e39d6a54 Mon Sep 17 00:00:00 2001
From: Yorke Rhodes <yorke@hyperlane.xyz>
Date: Thu, 9 Nov 2023 17:45:52 -0500
Subject: [PATCH 5/9] Make fork tests instant mine

---
 typescript/infra/fork.sh                            | 2 +-
 typescript/infra/scripts/check-deploy.ts            | 7 ++++++-
 typescript/infra/scripts/deploy.ts                  | 5 ++++-
 typescript/sdk/src/metadata/ChainMetadataManager.ts | 2 --
 4 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/typescript/infra/fork.sh b/typescript/infra/fork.sh
index 2848e36f8c..d9c54199df 100755
--- a/typescript/infra/fork.sh
+++ b/typescript/infra/fork.sh
@@ -23,7 +23,7 @@ trap 'kill $(jobs -p)' EXIT
 # exit 1 on any subsequent failures
 set -e
 
-anvil --fork-url $RPC_URL --block-time 1 --silent > /dev/null &
+anvil --fork-url $RPC_URL --silent > /dev/null &
 ANVIL_PID=$!
 
 while ! cast bn &> /dev/null; do
diff --git a/typescript/infra/scripts/check-deploy.ts b/typescript/infra/scripts/check-deploy.ts
index 2b570c4779..d1f7d1434a 100644
--- a/typescript/infra/scripts/check-deploy.ts
+++ b/typescript/infra/scripts/check-deploy.ts
@@ -43,12 +43,17 @@ function getArgs() {
 async function check() {
   const { fork, govern, module, environment, context } = await getArgs();
   const config = getEnvironmentConfig(environment);
-  const multiProvider = await config.getMultiProvider();
+  let multiProvider = await config.getMultiProvider();
 
   // must rotate to forked provider before building core contracts
   if (fork) {
     await useLocalProvider(multiProvider, fork);
+
     if (govern) {
+      multiProvider = multiProvider.extendChainMetadata({
+        [fork]: { blocks: { confirmations: 0 } },
+      });
+
       const owner = config.core[fork].owner;
       const signer = await impersonateAccount(owner);
       multiProvider.setSigner(fork, signer);
diff --git a/typescript/infra/scripts/deploy.ts b/typescript/infra/scripts/deploy.ts
index bf4f6eb6ee..8e1efb4d75 100644
--- a/typescript/infra/scripts/deploy.ts
+++ b/typescript/infra/scripts/deploy.ts
@@ -54,9 +54,12 @@ async function main() {
     environment,
   } = await withContext(withModuleAndFork(getArgs())).argv;
   const envConfig = getEnvironmentConfig(environment);
-  const multiProvider = await envConfig.getMultiProvider();
+  let multiProvider = await envConfig.getMultiProvider();
 
   if (fork) {
+    multiProvider = multiProvider.extendChainMetadata({
+      [fork]: { blocks: { confirmations: 0 } },
+    });
     await useLocalProvider(multiProvider, fork);
 
     // TODO: make this more generic
diff --git a/typescript/sdk/src/metadata/ChainMetadataManager.ts b/typescript/sdk/src/metadata/ChainMetadataManager.ts
index 237cdccb24..d00f4e4598 100644
--- a/typescript/sdk/src/metadata/ChainMetadataManager.ts
+++ b/typescript/sdk/src/metadata/ChainMetadataManager.ts
@@ -329,8 +329,6 @@ export class ChainMetadataManager<MetaExt = {}> {
   ): ChainMetadataManager<MetaExt & NewExt> {
     const newMetadata: ChainMap<ChainMetadata<MetaExt & NewExt>> = {};
     for (const [name, meta] of Object.entries(this.metadata)) {
-      if (!additionalMetadata[name])
-        throw new Error(`No additional data provided for chain ${name}`);
       newMetadata[name] = { ...meta, ...additionalMetadata[name] };
     }
     return new ChainMetadataManager(newMetadata);

From e7e6bcba0e70a742115494b7f2b263433d03d4a4 Mon Sep 17 00:00:00 2001
From: Yorke Rhodes <yorke@hyperlane.xyz>
Date: Thu, 9 Nov 2023 18:30:12 -0500
Subject: [PATCH 6/9] Kill jobs more reliably

---
 typescript/infra/fork.sh | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/typescript/infra/fork.sh b/typescript/infra/fork.sh
index d9c54199df..cb909d043b 100755
--- a/typescript/infra/fork.sh
+++ b/typescript/infra/fork.sh
@@ -18,7 +18,7 @@ else
 fi
 
 # kill all child processes on exit
-trap 'kill $(jobs -p)' EXIT
+trap 'jobs -p | xargs -r kill' EXIT
 
 # exit 1 on any subsequent failures
 set -e
@@ -44,5 +44,3 @@ yarn ts-node ./scripts/check-deploy.ts -e $ENVIRONMENT -f $FORK_CHAIN --govern -
 
 echo "=== Run $MODULE checker against forked $ENVIRONMENT after governance ==="
 yarn ts-node ./scripts/check-deploy.ts -e $ENVIRONMENT -f $FORK_CHAIN -m $MODULE
-
-kill $ANVIL_PID

From 9b015afd1aec708484257965efdb3065e9a4d391 Mon Sep 17 00:00:00 2001
From: Yorke Rhodes <yorke@hyperlane.xyz>
Date: Thu, 9 Nov 2023 18:30:32 -0500
Subject: [PATCH 7/9] Simplify config building

---
 typescript/infra/scripts/check-deploy.ts      | 33 ++-----
 typescript/infra/scripts/deploy.ts            | 98 ++++---------------
 typescript/infra/scripts/utils.ts             | 72 --------------
 .../infra/src/config/helloworld/config.ts     | 23 -----
 4 files changed, 24 insertions(+), 202 deletions(-)
 delete mode 100644 typescript/infra/src/config/helloworld/config.ts

diff --git a/typescript/infra/scripts/check-deploy.ts b/typescript/infra/scripts/check-deploy.ts
index d1f7d1434a..c09889cf25 100644
--- a/typescript/infra/scripts/check-deploy.ts
+++ b/typescript/infra/scripts/check-deploy.ts
@@ -9,13 +9,10 @@ import {
   InterchainAccountChecker,
   InterchainQuery,
   InterchainQueryChecker,
-  filterChainMapToProtocol,
 } from '@hyperlane-xyz/sdk';
-import { ProtocolType } from '@hyperlane-xyz/utils';
 
 import { Contexts } from '../config/contexts';
 import { deployEnvToSdkEnv } from '../src/config/environment';
-import { helloWorldRouterConfig } from '../src/config/helloworld/config';
 import { HyperlaneAppGovernor } from '../src/govern/HyperlaneAppGovernor';
 import { HyperlaneCoreGovernor } from '../src/govern/HyperlaneCoreGovernor';
 import { HyperlaneIgpGovernor } from '../src/govern/HyperlaneIgpGovernor';
@@ -27,7 +24,6 @@ import { getHelloWorldApp } from './helloworld/utils';
 import {
   Modules,
   getEnvironmentConfig,
-  getProxiedRouterConfig,
   getArgs as getRootArgs,
   withContext,
   withModuleAndFork,
@@ -60,11 +56,13 @@ async function check() {
     }
   }
 
-  let governor: HyperlaneAppGovernor<any, any>;
   const env = deployEnvToSdkEnv[environment];
+  const core = HyperlaneCore.fromEnvironment(env, multiProvider);
+  const ismFactory = HyperlaneIsmFactory.fromEnvironment(env, multiProvider);
+  const routerConfig = core.getRouterConfig(config.owners);
+
+  let governor: HyperlaneAppGovernor<any, any>;
   if (module === Modules.CORE) {
-    const core = HyperlaneCore.fromEnvironment(env, multiProvider);
-    const ismFactory = HyperlaneIsmFactory.fromEnvironment(env, multiProvider);
     const checker = new HyperlaneCoreChecker(
       multiProvider,
       core,
@@ -77,11 +75,6 @@ async function check() {
     const checker = new HyperlaneIgpChecker(multiProvider, igp, config.igp);
     governor = new HyperlaneIgpGovernor(checker, config.owners);
   } else if (module === Modules.INTERCHAIN_ACCOUNTS) {
-    const routerConfig = filterChainMapToProtocol(
-      await getProxiedRouterConfig(environment, multiProvider),
-      ProtocolType.Ethereum,
-      multiProvider,
-    );
     const ica = InterchainAccount.fromEnvironment(env, multiProvider);
     const checker = new InterchainAccountChecker(
       multiProvider,
@@ -90,10 +83,6 @@ async function check() {
     );
     governor = new ProxiedRouterGovernor(checker, config.owners);
   } else if (module === Modules.INTERCHAIN_QUERY_SYSTEM) {
-    const routerConfig = await getProxiedRouterConfig(
-      environment,
-      multiProvider,
-    );
     const iqs = InterchainQuery.fromEnvironment(env, multiProvider);
     const checker = new InterchainQueryChecker(
       multiProvider,
@@ -108,19 +97,11 @@ async function check() {
       Role.Deployer,
       Contexts.Hyperlane, // Owner should always be from the hyperlane context
     );
-    const hwConfig = await helloWorldRouterConfig(
-      environment,
-      context,
-      multiProvider,
-    );
-    const ismFactory = HyperlaneIsmFactory.fromEnvironment(
-      deployEnvToSdkEnv[environment],
-      multiProvider,
-    );
+    const ismFactory = HyperlaneIsmFactory.fromEnvironment(env, multiProvider);
     const checker = new HelloWorldChecker(
       multiProvider,
       app,
-      hwConfig,
+      routerConfig,
       ismFactory,
     );
     governor = new ProxiedRouterGovernor(checker, config.owners);
diff --git a/typescript/infra/scripts/deploy.ts b/typescript/infra/scripts/deploy.ts
index 8e1efb4d75..21ad3e4dbd 100644
--- a/typescript/infra/scripts/deploy.ts
+++ b/typescript/infra/scripts/deploy.ts
@@ -4,9 +4,6 @@ import { prompt } from 'prompts';
 import { HelloWorldDeployer } from '@hyperlane-xyz/helloworld';
 import {
   ChainMap,
-  Chains,
-  HypERC20Config,
-  HypERC20Deployer,
   HyperlaneCore,
   HyperlaneCoreDeployer,
   HyperlaneDeployer,
@@ -15,14 +12,8 @@ import {
   HyperlaneProxyFactoryDeployer,
   InterchainAccountDeployer,
   InterchainQueryDeployer,
-  IsmType,
   LiquidityLayerDeployer,
-  TokenType,
 } from '@hyperlane-xyz/sdk';
-import {
-  TokenConfig,
-  TokenDecimals,
-} from '@hyperlane-xyz/sdk/dist/token/config';
 import { objMap } from '@hyperlane-xyz/utils';
 
 import { Contexts } from '../config/contexts';
@@ -40,8 +31,6 @@ import {
   getContractAddressesSdkFilepath,
   getEnvironmentConfig,
   getModuleDirectory,
-  getProxiedRouterConfig,
-  getRouterConfig,
   withContext,
   withModuleAndFork,
 } from './utils';
@@ -56,22 +45,29 @@ async function main() {
   const envConfig = getEnvironmentConfig(environment);
   let multiProvider = await envConfig.getMultiProvider();
 
+  // TODO: make this more generic
+  const deployerAddress =
+    environment === 'testnet4'
+      ? '0xfaD1C94469700833717Fa8a3017278BC1cA8031C'
+      : '0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba';
+
   if (fork) {
     multiProvider = multiProvider.extendChainMetadata({
       [fork]: { blocks: { confirmations: 0 } },
     });
     await useLocalProvider(multiProvider, fork);
 
-    // TODO: make this more generic
-    const deployerAddress =
-      environment === 'testnet4'
-        ? '0xfaD1C94469700833717Fa8a3017278BC1cA8031C'
-        : '0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba';
-
     const signer = await impersonateAccount(deployerAddress);
     multiProvider.setSharedSigner(signer);
   }
 
+  const ismFactory = HyperlaneIsmFactory.fromAddressesMap(
+    getAddresses(environment, Modules.PROXY_FACTORY),
+    multiProvider,
+  );
+  const env = deployEnvToSdkEnv[environment];
+  const core = HyperlaneCore.fromEnvironment(env, multiProvider);
+
   let config: ChainMap<unknown> = {};
   let deployer: HyperlaneDeployer<any, any>;
   if (module === Modules.PROXY_FACTORY) {
@@ -79,70 +75,18 @@ async function main() {
     deployer = new HyperlaneProxyFactoryDeployer(multiProvider);
   } else if (module === Modules.CORE) {
     config = envConfig.core;
-    const ismFactory = HyperlaneIsmFactory.fromAddressesMap(
-      getAddresses(environment, Modules.PROXY_FACTORY),
-      multiProvider,
-    );
     deployer = new HyperlaneCoreDeployer(multiProvider, ismFactory);
-  } else if (module === Modules.WARP) {
-    const owner = '0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba';
-    const neutronRouter =
-      '0x9c504f7d878445228bef5684f9028cb388f63e58bf1077db75876c7651b9a71f';
-    const ismFactory = HyperlaneIsmFactory.fromAddressesMap(
-      getAddresses(environment, Modules.PROXY_FACTORY),
-      multiProvider,
-    );
-    const tokenConfig: TokenConfig & TokenDecimals = {
-      type: TokenType.synthetic,
-      name: 'TIA',
-      symbol: 'TIA.n',
-      decimals: 6,
-      totalSupply: 0,
-    };
-    const core = HyperlaneCore.fromEnvironment(
-      deployEnvToSdkEnv[environment],
-      multiProvider,
-    );
-    const routerConfig = core.getRouterConfig(owner);
-    const targetChains = [Chains.arbitrum];
-    config = Object.fromEntries(
-      targetChains.map((chain) => {
-        const warpRouterConfig: HypERC20Config = {
-          ...routerConfig[chain],
-          ...tokenConfig,
-          interchainSecurityModule: {
-            type: IsmType.MESSAGE_ID_MULTISIG,
-            validators: [
-              '0xa9b8c1f4998f781f958c63cfcd1708d02f004ff0',
-              '0xb65438a014fb05fbadcfe35bc6e25d372b6ba460',
-              '0xc79503a3e3011535a9c60f6d21f76f59823a38bd',
-              '0x42fa752defe92459370a052b6387a87f7de9b80c',
-              '0x54b2cca5091b098a1a993dec03c4d1ee9af65999',
-              '0x47aa126e05933b95c5eb90b26e6b668d84f4b25a',
-            ],
-            threshold: 4,
-          },
-          // foreignDeployment: neutronRouter,
-          gas: 600_000,
-        };
-        return [chain, warpRouterConfig];
-      }),
-    );
-    deployer = new HypERC20Deployer(multiProvider, ismFactory);
   } else if (module === Modules.INTERCHAIN_GAS_PAYMASTER) {
     config = envConfig.igp;
     deployer = new HyperlaneIgpDeployer(multiProvider);
   } else if (module === Modules.INTERCHAIN_ACCOUNTS) {
-    config = await getProxiedRouterConfig(environment, multiProvider);
+    config = core.getRouterConfig(envConfig.owners);
     deployer = new InterchainAccountDeployer(multiProvider);
   } else if (module === Modules.INTERCHAIN_QUERY_SYSTEM) {
-    config = await getProxiedRouterConfig(environment, multiProvider);
+    config = core.getRouterConfig(envConfig.owners);
     deployer = new InterchainQueryDeployer(multiProvider);
   } else if (module === Modules.LIQUIDITY_LAYER) {
-    const routerConfig = await getProxiedRouterConfig(
-      environment,
-      multiProvider,
-    );
+    const routerConfig = core.getRouterConfig(envConfig.owners);
     if (!envConfig.liquidityLayerConfig) {
       throw new Error(`No liquidity layer config for ${environment}`);
     }
@@ -168,15 +112,7 @@ async function main() {
     }));
     deployer = new TestQuerySenderDeployer(multiProvider);
   } else if (module === Modules.HELLO_WORLD) {
-    config = await getRouterConfig(
-      environment,
-      multiProvider,
-      true, // use deployer as owner
-    );
-    const ismFactory = HyperlaneIsmFactory.fromAddressesMap(
-      getAddresses(environment, Modules.PROXY_FACTORY),
-      multiProvider,
-    );
+    config = core.getRouterConfig(deployerAddress);
     deployer = new HelloWorldDeployer(multiProvider, ismFactory);
   } else {
     console.log(`Skipping ${module}, deployer unimplemented`);
diff --git a/typescript/infra/scripts/utils.ts b/typescript/infra/scripts/utils.ts
index dca0b5a42a..825193ece0 100644
--- a/typescript/infra/scripts/utils.ts
+++ b/typescript/infra/scripts/utils.ts
@@ -8,11 +8,7 @@ import {
   ChainName,
   Chains,
   CoreConfig,
-  HyperlaneCore,
-  HyperlaneIgp,
   MultiProvider,
-  ProxiedRouterConfig,
-  RouterConfig,
   RpcConsensusType,
   collectValidators,
 } from '@hyperlane-xyz/sdk';
@@ -287,74 +283,6 @@ export async function assertCorrectKubeContext(coreConfig: EnvironmentConfig) {
   }
 }
 
-export async function getRouterConfig(
-  environment: DeployEnvironment,
-  multiProvider: MultiProvider,
-  useMultiProviderOwners = false,
-): Promise<ChainMap<RouterConfig>> {
-  const core = HyperlaneCore.fromEnvironment(
-    deployEnvToSdkEnv[environment],
-    multiProvider,
-  );
-  // TODO: replace this with core.getRouterConfig
-  const igp = HyperlaneIgp.fromEnvironment(
-    deployEnvToSdkEnv[environment],
-    multiProvider,
-  );
-
-  const owners = getEnvironmentConfig(environment).owners;
-  const config: ChainMap<RouterConfig> = {};
-  const knownChains = multiProvider.intersect(
-    core.chains().concat(igp.chains()),
-  ).intersection;
-
-  for (const chain of knownChains) {
-    // CI will not have signers for all known chains. To avoid failing, we
-    // default to the owner configured in the environment if we cannot get a
-    // signer address.
-    const getSignerAddress = (chain: ChainName) => {
-      const signer = multiProvider.tryGetSigner(chain);
-      if (!signer) {
-        const owner = owners[chain];
-        console.warn(
-          `Unable to get signer for chain, ${chain}, defaulting to configured owner ${owner}`,
-        );
-        return owner;
-      }
-      return signer.getAddress();
-    };
-
-    // MultiProvider signers are only used for Ethereum chains.
-    const owner =
-      useMultiProviderOwners &&
-      multiProvider.getChainMetadata(chain).protocol === ProtocolType.Ethereum
-        ? await getSignerAddress(chain)
-        : owners[chain];
-    config[chain] = {
-      owner: owner,
-      mailbox: core.getContracts(chain).mailbox.address,
-      // hook: igp.getContracts(chain).interchainGasPaymaster.address,
-    };
-  }
-  return config;
-}
-
-export async function getProxiedRouterConfig(
-  environment: DeployEnvironment,
-  multiProvider: MultiProvider,
-  useMultiProviderOwners = false,
-): Promise<ChainMap<ProxiedRouterConfig>> {
-  const config = await getRouterConfig(
-    environment,
-    multiProvider,
-    useMultiProviderOwners,
-  );
-  return objMap(config, (chain, routerConfig) => ({
-    timelock: environments[environment].core[chain].upgrade?.timelock,
-    ...routerConfig,
-  }));
-}
-
 export function getValidatorsByChain(
   config: ChainMap<CoreConfig>,
 ): ChainMap<Set<string>> {
diff --git a/typescript/infra/src/config/helloworld/config.ts b/typescript/infra/src/config/helloworld/config.ts
deleted file mode 100644
index 5377200bbb..0000000000
--- a/typescript/infra/src/config/helloworld/config.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { ChainMap, MultiProvider, RouterConfig } from '@hyperlane-xyz/sdk';
-import { objMap } from '@hyperlane-xyz/utils';
-
-import { Contexts } from '../../../config/contexts';
-import { routingIsm } from '../../../config/routingIsm';
-import { getRouterConfig } from '../../../scripts/utils';
-import { DeployEnvironment } from '../environment';
-
-export async function helloWorldRouterConfig(
-  environment: DeployEnvironment,
-  context: Contexts,
-  multiProvider: MultiProvider,
-): Promise<ChainMap<RouterConfig>> {
-  const routerConfig = await getRouterConfig(environment, multiProvider, true);
-  if (context === Contexts.Hyperlane) {
-    return routerConfig;
-  }
-
-  return objMap(routerConfig, (chain, config) => ({
-    ...config,
-    interchainSecurityModule: routingIsm(environment, chain, context),
-  }));
-}

From aa925428c5c01dccf626ae39b663ef64c6362401 Mon Sep 17 00:00:00 2001
From: Yorke Rhodes <yorke@hyperlane.xyz>
Date: Thu, 9 Nov 2023 18:36:16 -0500
Subject: [PATCH 8/9] Remove redundant helloworld deploy script

---
 typescript/infra/scripts/helloworld/deploy.ts | 103 ------------------
 1 file changed, 103 deletions(-)
 delete mode 100644 typescript/infra/scripts/helloworld/deploy.ts

diff --git a/typescript/infra/scripts/helloworld/deploy.ts b/typescript/infra/scripts/helloworld/deploy.ts
deleted file mode 100644
index 9d4fc317e0..0000000000
--- a/typescript/infra/scripts/helloworld/deploy.ts
+++ /dev/null
@@ -1,103 +0,0 @@
-import path from 'path';
-
-import { HelloWorldDeployer } from '@hyperlane-xyz/helloworld';
-import {
-  HyperlaneIsmFactory,
-  filterChainMapExcludeProtocol,
-  serializeContractsMap,
-} from '@hyperlane-xyz/sdk';
-import {
-  ProtocolType,
-  hexOrBase58ToHex,
-  objMap,
-  objMerge,
-} from '@hyperlane-xyz/utils';
-
-import { Contexts } from '../../config/contexts';
-import { deployEnvToSdkEnv } from '../../src/config/environment';
-import { helloWorldRouterConfig } from '../../src/config/helloworld/config';
-import { Role } from '../../src/roles';
-import { readJSON, writeJSON } from '../../src/utils/utils';
-import {
-  getEnvironmentConfig,
-  getEnvironmentDirectory,
-  getArgs as getRootArgs,
-  withContext,
-} from '../utils';
-
-function getArgs() {
-  return withContext(getRootArgs())
-    .boolean('govern')
-    .default('govern', false)
-    .alias('g', 'govern').argv;
-}
-
-async function main() {
-  const { environment, context } = await getArgs();
-  const coreConfig = getEnvironmentConfig(environment);
-  // Always deploy from the hyperlane deployer
-  const multiProvider = await coreConfig.getMultiProvider(
-    Contexts.Hyperlane,
-    Role.Deployer,
-  );
-  const configMap = await helloWorldRouterConfig(
-    environment,
-    context,
-    multiProvider,
-  );
-  const ismFactory = HyperlaneIsmFactory.fromEnvironment(
-    deployEnvToSdkEnv[environment],
-    multiProvider,
-  );
-  const deployer = new HelloWorldDeployer(multiProvider, ismFactory);
-  const dir = path.join(
-    getEnvironmentDirectory(environment),
-    'helloworld',
-    context,
-  );
-
-  let existingVerificationInputs = {};
-  try {
-    const addresses = readJSON(dir, 'addresses.json');
-    deployer.cacheAddressesMap(addresses);
-    existingVerificationInputs = readJSON(dir, 'verification.json');
-  } catch (e) {
-    console.info(`Could not load previous deployment, file may not exist`);
-  }
-
-  const configMapWithForeignDeployments = objMerge(
-    configMap,
-    objMap(
-      filterChainMapExcludeProtocol(
-        deployer.cachedAddresses,
-        ProtocolType.Ethereum,
-        multiProvider,
-      ),
-      (_chain, addresses) => ({
-        foreignDeployment: hexOrBase58ToHex(addresses.router),
-      }),
-    ),
-  );
-
-  try {
-    await deployer.deploy(configMapWithForeignDeployments);
-  } catch (e) {
-    console.error(`Encountered error during deploy`);
-    console.error(e);
-  }
-
-  writeJSON(dir, 'addresses.json', {
-    // To include foreign deployments that may be present in the addresses.json already
-    ...deployer.cachedAddresses,
-    ...serializeContractsMap(deployer.deployedContracts),
-  });
-  writeJSON(
-    dir,
-    'verification.json',
-    deployer.mergeWithExistingVerificationInputs(existingVerificationInputs),
-  );
-}
-
-main()
-  .then(() => console.info('Deployment complete'))
-  .catch(console.error);

From 0ca9ebbd923792b47027c55896d16b07b902c27c Mon Sep 17 00:00:00 2001
From: Yorke Rhodes <yorke@hyperlane.xyz>
Date: Thu, 9 Nov 2023 18:56:59 -0500
Subject: [PATCH 9/9] Fix e2e deploy

---
 typescript/infra/scripts/deploy.ts | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/typescript/infra/scripts/deploy.ts b/typescript/infra/scripts/deploy.ts
index 21ad3e4dbd..8e109110ff 100644
--- a/typescript/infra/scripts/deploy.ts
+++ b/typescript/infra/scripts/deploy.ts
@@ -43,6 +43,8 @@ async function main() {
     environment,
   } = await withContext(withModuleAndFork(getArgs())).argv;
   const envConfig = getEnvironmentConfig(environment);
+  const env = deployEnvToSdkEnv[environment];
+
   let multiProvider = await envConfig.getMultiProvider();
 
   // TODO: make this more generic
@@ -61,13 +63,6 @@ async function main() {
     multiProvider.setSharedSigner(signer);
   }
 
-  const ismFactory = HyperlaneIsmFactory.fromAddressesMap(
-    getAddresses(environment, Modules.PROXY_FACTORY),
-    multiProvider,
-  );
-  const env = deployEnvToSdkEnv[environment];
-  const core = HyperlaneCore.fromEnvironment(env, multiProvider);
-
   let config: ChainMap<unknown> = {};
   let deployer: HyperlaneDeployer<any, any>;
   if (module === Modules.PROXY_FACTORY) {
@@ -75,17 +70,24 @@ async function main() {
     deployer = new HyperlaneProxyFactoryDeployer(multiProvider);
   } else if (module === Modules.CORE) {
     config = envConfig.core;
+    const ismFactory = HyperlaneIsmFactory.fromAddressesMap(
+      getAddresses(environment, Modules.PROXY_FACTORY),
+      multiProvider,
+    );
     deployer = new HyperlaneCoreDeployer(multiProvider, ismFactory);
   } else if (module === Modules.INTERCHAIN_GAS_PAYMASTER) {
     config = envConfig.igp;
     deployer = new HyperlaneIgpDeployer(multiProvider);
   } else if (module === Modules.INTERCHAIN_ACCOUNTS) {
+    const core = HyperlaneCore.fromEnvironment(env, multiProvider);
     config = core.getRouterConfig(envConfig.owners);
     deployer = new InterchainAccountDeployer(multiProvider);
   } else if (module === Modules.INTERCHAIN_QUERY_SYSTEM) {
+    const core = HyperlaneCore.fromEnvironment(env, multiProvider);
     config = core.getRouterConfig(envConfig.owners);
     deployer = new InterchainQueryDeployer(multiProvider);
   } else if (module === Modules.LIQUIDITY_LAYER) {
+    const core = HyperlaneCore.fromEnvironment(env, multiProvider);
     const routerConfig = core.getRouterConfig(envConfig.owners);
     if (!envConfig.liquidityLayerConfig) {
       throw new Error(`No liquidity layer config for ${environment}`);
@@ -112,8 +114,9 @@ async function main() {
     }));
     deployer = new TestQuerySenderDeployer(multiProvider);
   } else if (module === Modules.HELLO_WORLD) {
+    const core = HyperlaneCore.fromEnvironment(env, multiProvider);
     config = core.getRouterConfig(deployerAddress);
-    deployer = new HelloWorldDeployer(multiProvider, ismFactory);
+    deployer = new HelloWorldDeployer(multiProvider);
   } else {
     console.log(`Skipping ${module}, deployer unimplemented`);
     return;