From e7567329640fc8d349e9fd552ed6abfed24a5930 Mon Sep 17 00:00:00 2001 From: Asa Oines Date: Fri, 21 Apr 2023 13:55:38 -0400 Subject: [PATCH] Use proper ISM in ICA contracts (#2128) ### Description Currently, ICAs are configured without an ISM, which results in them falling back to the mailbox default. Instead, they should delegate security to whichever ISM was specified in the message. This PR updates the deployer to deploy the proper ISM by default, and the checker/governor with code that will allow the existing deployments to move to that ISM. ### Drive-by changes - My formatter seems to be making changes to src/sdk/index.ts ### Backward compatibility _Are these changes backward compatible?_ Yes _Are there any infrastructure implications, e.g. changes that would prohibit deploying older commits using this infra tooling?_ None ### Testing _What kind of testing have these changes undergone?_ None --- .../middleware/accounts/verification.json | 54 +++++++++++++++++++ .../middleware/accounts/verification.json | 54 +++++++++++++++++++ typescript/infra/scripts/check-deploy.ts | 23 +++++--- .../infra/src/govern/HyperlaneAppGovernor.ts | 12 ++--- .../src/govern/InterchainAccountGovernor.ts | 25 --------- .../src/govern/InterchainQueryGovernor.ts | 25 --------- .../infra/src/govern/ProxiedRouterGovernor.ts | 47 ++++++++++++++++ .../sdk/src/consts/environments/mainnet.json | 9 ++++ .../sdk/src/consts/environments/testnet.json | 9 ++++ typescript/sdk/src/deploy/types.ts | 2 + typescript/sdk/src/index.ts | 49 +++++++++-------- .../account/InterchainAccountChecker.ts | 27 +++++++++- .../account/InterchainAccountDeployer.ts | 24 ++++++--- .../account/accounts.hardhat-test.ts | 6 --- .../sdk/src/middleware/account/contracts.ts | 2 + .../sdk/src/router/HyperlaneRouterChecker.ts | 51 ++++++++++++------ typescript/sdk/src/router/types.ts | 19 ++++++- 17 files changed, 320 insertions(+), 118 deletions(-) delete mode 100644 typescript/infra/src/govern/InterchainAccountGovernor.ts delete mode 100644 typescript/infra/src/govern/InterchainQueryGovernor.ts create mode 100644 typescript/infra/src/govern/ProxiedRouterGovernor.ts diff --git a/typescript/infra/config/environments/mainnet2/middleware/accounts/verification.json b/typescript/infra/config/environments/mainnet2/middleware/accounts/verification.json index d96754dd0..d5aafe437 100644 --- a/typescript/infra/config/environments/mainnet2/middleware/accounts/verification.json +++ b/typescript/infra/config/environments/mainnet2/middleware/accounts/verification.json @@ -17,6 +17,12 @@ "address": "0xFCA9d3C334F12D2Ae30cdEC6283A1928A988BC55", "constructorArguments": "0000000000000000000000000000000000000000000000000000000000000038000000000000000000000000f9a4e3ba5e532906c241310f6832d2ee8d1c5609", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x1d3Bdf44887744007C7C62c85924c445C9e825DE", + "constructorArguments": "00000000000000000000000035231d4c2d8b8adcb5617a638a0c4548684c7c70", + "isProxy": false } ], "avalanche": [ @@ -37,6 +43,12 @@ "address": "0xbAD979697E99d722B4B0295a45D59D8371B7E9bd", "constructorArguments": "000000000000000000000000000000000000000000000000000000000000a86a00000000000000000000000077c509140a45b4b85e1a28f8c21aaeb3ca8788b3", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x88C01B64dCe0032796a1967E2b3447B397c6c7AC", + "constructorArguments": "00000000000000000000000035231d4c2d8b8adcb5617a638a0c4548684c7c70", + "isProxy": false } ], "polygon": [ @@ -57,6 +69,12 @@ "address": "0x4C96a1abc44dc846775CE702C9E9BE821D3b487c", "constructorArguments": "00000000000000000000000000000000000000000000000000000000000000890000000000000000000000004a4d878c41c7f71ecff182f526b7691adc6e4150", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0xCd8ACf2254641bD3Eaa32C1B8D36f0983de8C0E6", + "constructorArguments": "00000000000000000000000035231d4c2d8b8adcb5617a638a0c4548684c7c70", + "isProxy": false } ], "celo": [ @@ -77,6 +95,12 @@ "address": "0x155332Fad14bdE126255E6Ab6A09Fe88D2864294", "constructorArguments": "000000000000000000000000000000000000000000000000000000000000a4ec000000000000000000000000b193ebf06fad5d66492bb41dbbcd202640ae83ff", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x5e8ee6840caa4f367aff1FF28aA36D5B1b836d35", + "constructorArguments": "00000000000000000000000035231d4c2d8b8adcb5617a638a0c4548684c7c70", + "isProxy": false } ], "arbitrum": [ @@ -97,6 +121,12 @@ "address": "0xc67ABC50E7557609077E03e6aeA6834f3E4cf4cE", "constructorArguments": "000000000000000000000000000000000000000000000000000000000000a4b1000000000000000000000000ac2be81884c66e6c05b80c05c907b54c74ea2c49", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0xC1d10a99C382Dd224d7F513C7e0f74D7689071f4", + "constructorArguments": "00000000000000000000000035231d4c2d8b8adcb5617a638a0c4548684c7c70", + "isProxy": false } ], "optimism": [ @@ -117,6 +147,12 @@ "address": "0x5e8ee6840caa4f367aff1FF28aA36D5B1b836d35", "constructorArguments": "000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000652e2f475af7b1154817e09f5408f9011037492a", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x3de63b62BeF9Da290F51f856cA9F3dB4225EDc05", + "constructorArguments": "00000000000000000000000035231d4c2d8b8adcb5617a638a0c4548684c7c70", + "isProxy": false } ], "ethereum": [ @@ -137,6 +173,12 @@ "address": "0x7fd95Df406dDF612597F1B2C52340d7D96aeD071", "constructorArguments": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000005fd075c2157567f7f80e6cb20ddd75f40905bd87", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x943303Ad7D2B87BB363E0BACC901486337d9B316", + "constructorArguments": "00000000000000000000000035231d4c2d8b8adcb5617a638a0c4548684c7c70", + "isProxy": false } ], "moonbeam": [ @@ -157,6 +199,12 @@ "address": "0x859aD208A717F707bc57FD1fAfEa74311E5a3EeD", "constructorArguments": "00000000000000000000000000000000000000000000000000000000000005040000000000000000000000005b6311e0417cfd3fb10318108897e63777cfe8d7", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x88d346eEc75b6D22428bbaB569b6eBB0bE183c4F", + "constructorArguments": "00000000000000000000000035231d4c2d8b8adcb5617a638a0c4548684c7c70", + "isProxy": false } ], "gnosis": [ @@ -171,6 +219,12 @@ "address": "0x632b4F32d65F7b25B37a27C57dD510f8e4a58Bf9", "constructorArguments": "000000000000000000000000000000000000000000000000000000000000006400000000000000000000000032e77b20bf0cf034eb80ea9dd02de881016b01b3", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x8AB7A6FaC052518A39628497735C855a2Beb515B", + "constructorArguments": "00000000000000000000000035231d4c2d8b8adcb5617a638a0c4548684c7c70", + "isProxy": false } ] } diff --git a/typescript/infra/config/environments/testnet3/middleware/accounts/verification.json b/typescript/infra/config/environments/testnet3/middleware/accounts/verification.json index ae67dc089..cad5000f1 100644 --- a/typescript/infra/config/environments/testnet3/middleware/accounts/verification.json +++ b/typescript/infra/config/environments/testnet3/middleware/accounts/verification.json @@ -17,6 +17,12 @@ "address": "0x06d237b73a1f353B14475f15012e4309580C5395", "constructorArguments": "000000000000000000000000000000000000000000000000000000000000aef3000000000000000000000000db91d575f17d8aaf1afec0eadbd5ac9e5cef4ad0", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x0aA320a1bD450152B4C500613335CeBA4f6073cF", + "constructorArguments": "000000000000000000000000cc737a94fecaec165abcf12ded095bb13f037685", + "isProxy": false } ], "fuji": [ @@ -37,6 +43,12 @@ "address": "0x7D7D885ebeb3B46340E9CF9bD0cA847492C16D4a", "constructorArguments": "000000000000000000000000000000000000000000000000000000000000a869000000000000000000000000f82b58bf348a6cea6e19413e9de040db1a363128", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x333C9A8c70Ea4F0498Fb58bEe40DEa40e63a9962", + "constructorArguments": "000000000000000000000000cc737a94fecaec165abcf12ded095bb13f037685", + "isProxy": false } ], "mumbai": [ @@ -57,6 +69,12 @@ "address": "0x01E05434f5D5e8B0BA6a0d05AdDeD777Cc1ac8c3", "constructorArguments": "00000000000000000000000000000000000000000000000000000000000138810000000000000000000000006a9ced0e13e738517558aa283da0e93e5904d49b", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x40c2d6cA6F5A8857705C128b2c1A5f0Ae20880dc", + "constructorArguments": "000000000000000000000000cc737a94fecaec165abcf12ded095bb13f037685", + "isProxy": false } ], "bsctestnet": [ @@ -77,6 +95,12 @@ "address": "0x91B08a1b96d6ac153eB102Bd9Eb9F2D416d449A1", "constructorArguments": "0000000000000000000000000000000000000000000000000000000000000061000000000000000000000000951c74d83a85833b53a448caab7397bd3fa6cfb2", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x9034f60Dec10cFa162369444081685F542d0C24D", + "constructorArguments": "000000000000000000000000cc737a94fecaec165abcf12ded095bb13f037685", + "isProxy": false } ], "goerli": [ @@ -97,6 +121,12 @@ "address": "0xA748586f78dD2a4A90b02aD72ddc014Cc05C19b1", "constructorArguments": "0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000cb0ba89f564e31180a101df54b7971206e03ee9b", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x70835F3C2845394842DEA9f40cbe8087b2cE5712", + "constructorArguments": "000000000000000000000000cc737a94fecaec165abcf12ded095bb13f037685", + "isProxy": false } ], "moonbasealpha": [ @@ -117,6 +147,12 @@ "address": "0x443f8614728327Ce0cAb864DD463Fe2702b57597", "constructorArguments": "0000000000000000000000000000000000000000000000000000000000000507000000000000000000000000209ccdbe13bb913104117b1d6f7801684e98fa1f", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0xD699ff94f3FFd60A3a09bBff96181325B6C73FB8", + "constructorArguments": "000000000000000000000000cc737a94fecaec165abcf12ded095bb13f037685", + "isProxy": false } ], "optimismgoerli": [ @@ -137,6 +173,12 @@ "address": "0x860EDf9C38875ad7444BD6e6331866450c9589e4", "constructorArguments": "00000000000000000000000000000000000000000000000000000000000001a400000000000000000000000012ebd8cb561c68b587c392e0c5405b9866fd5820", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x82F5a960a4e4Cc0614253e4977bb3BE10344a30C", + "constructorArguments": "000000000000000000000000cc737a94fecaec165abcf12ded095bb13f037685", + "isProxy": false } ], "arbitrumgoerli": [ @@ -157,6 +199,12 @@ "address": "0x759c4Eb4575B651a9f0Fb46653dd7B2F32fD7310", "constructorArguments": "0000000000000000000000000000000000000000000000000000000000066eed0000000000000000000000004266d8dd66d8eb3934c8942968d1e54214d072d3", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0xA8978fdB093b1C5b892291A36e8527b34B749d6f", + "constructorArguments": "000000000000000000000000cc737a94fecaec165abcf12ded095bb13f037685", + "isProxy": false } ], "sepolia": [ @@ -171,6 +219,12 @@ "address": "0xe0B988062A0C6492177d64823Ab95a9c256c2a5F", "constructorArguments": "0000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000b057fb841027a8554521dccdec3c3474cac99ab5", "isProxy": false + }, + { + "name": "InterchainAccountIsm", + "address": "0x7483faD0Bc297667664A43A064bA7c9911659f57", + "constructorArguments": "000000000000000000000000cc737a94fecaec165abcf12ded095bb13f037685", + "isProxy": false } ] } diff --git a/typescript/infra/scripts/check-deploy.ts b/typescript/infra/scripts/check-deploy.ts index ecb5c3067..e5ed29a13 100644 --- a/typescript/infra/scripts/check-deploy.ts +++ b/typescript/infra/scripts/check-deploy.ts @@ -14,8 +14,7 @@ import { deployEnvToSdkEnv } from '../src/config/environment'; import { HyperlaneAppGovernor } from '../src/govern/HyperlaneAppGovernor'; import { HyperlaneCoreGovernor } from '../src/govern/HyperlaneCoreGovernor'; import { HyperlaneIgpGovernor } from '../src/govern/HyperlaneIgpGovernor'; -import { InterchainAccountGovernor } from '../src/govern/InterchainAccountGovernor'; -import { InterchainQueryGovernor } from '../src/govern/InterchainQueryGovernor'; +import { ProxiedRouterGovernor } from '../src/govern/ProxiedRouterGovernor'; import { impersonateAccount, useLocalProvider } from '../src/utils/fork'; import { @@ -60,15 +59,23 @@ async function check() { const checker = new HyperlaneIgpChecker(multiProvider, igp, config.igp); governor = new HyperlaneIgpGovernor(checker, config.owners); } else if (module === Modules.INTERCHAIN_ACCOUNTS) { - const config = await getRouterConfig(environment, multiProvider); + const routerConfig = await getRouterConfig(environment, multiProvider); const ica = InterchainAccount.fromEnvironment(env, multiProvider); - const checker = new InterchainAccountChecker(multiProvider, ica, config); - governor = new InterchainAccountGovernor(checker, config.owners); + const checker = new InterchainAccountChecker( + multiProvider, + ica, + routerConfig, + ); + governor = new ProxiedRouterGovernor(checker, config.owners); } else if (module === Modules.INTERCHAIN_QUERY_SYSTEM) { - const config = await getRouterConfig(environment, multiProvider); + const routerConfig = await getRouterConfig(environment, multiProvider); const iqs = InterchainQuery.fromEnvironment(env, multiProvider); - const checker = new InterchainQueryChecker(multiProvider, iqs, config); - governor = new InterchainQueryGovernor(checker, config.owners); + const checker = new InterchainQueryChecker( + multiProvider, + iqs, + routerConfig, + ); + governor = new ProxiedRouterGovernor(checker, config.owners); } else { console.log(`Skipping ${module}, checker or governor unimplemented`); return; diff --git a/typescript/infra/src/govern/HyperlaneAppGovernor.ts b/typescript/infra/src/govern/HyperlaneAppGovernor.ts index adf4e98d6..4a8313433 100644 --- a/typescript/infra/src/govern/HyperlaneAppGovernor.ts +++ b/typescript/infra/src/govern/HyperlaneAppGovernor.ts @@ -148,7 +148,7 @@ export abstract class HyperlaneAppGovernor< const signer = multiProvider.getSigner(chain); const signerAddress = await signer.getAddress(); - const canUseSubmissionType = async ( + const transactionSucceedsFromSender = async ( submitterAddress: types.Address, ): Promise => { try { @@ -158,7 +158,7 @@ export abstract class HyperlaneAppGovernor< return false; }; - if (await canUseSubmissionType(signerAddress)) { + if (await transactionSucceedsFromSender(signerAddress)) { return SubmissionType.SIGNER; } @@ -179,11 +179,11 @@ export abstract class HyperlaneAppGovernor< ), ); } - // 2b. Check if calling from the owner/safeAddress will succeed. if ( - this.canPropose[chain].get(safeAddress) && - (await canUseSubmissionType(safeAddress)) + (this.canPropose[chain].get(safeAddress) && + (await transactionSucceedsFromSender(safeAddress))) || + chain === 'moonbeam' ) { return SubmissionType.SAFE; } @@ -198,7 +198,7 @@ export abstract class HyperlaneAppGovernor< 'transferOwnership', [violation.expected], ), - description: `Transfer ownership of ${violation.contract.address} to ${violation.expected}`, + description: `Transfer ownership of ${violation.name} at ${violation.contract.address} to ${violation.expected}`, }); } } diff --git a/typescript/infra/src/govern/InterchainAccountGovernor.ts b/typescript/infra/src/govern/InterchainAccountGovernor.ts deleted file mode 100644 index 0dd7a603d..000000000 --- a/typescript/infra/src/govern/InterchainAccountGovernor.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { - ChainMap, - InterchainAccount, - InterchainAccountChecker, - InterchainAccountConfig, -} from '@hyperlane-xyz/sdk'; -import { types } from '@hyperlane-xyz/utils'; - -import { HyperlaneAppGovernor } from './HyperlaneAppGovernor'; - -export class InterchainAccountGovernor extends HyperlaneAppGovernor< - InterchainAccount, - InterchainAccountConfig -> { - constructor( - checker: InterchainAccountChecker, - owners: ChainMap, - ) { - super(checker, owners); - } - - protected async mapViolationsToCalls() { - throw new Error('governor not implemented for account middleware'); - } -} diff --git a/typescript/infra/src/govern/InterchainQueryGovernor.ts b/typescript/infra/src/govern/InterchainQueryGovernor.ts deleted file mode 100644 index de5b625f2..000000000 --- a/typescript/infra/src/govern/InterchainQueryGovernor.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { - ChainMap, - InterchainQuery, - InterchainQueryChecker, - InterchainQueryConfig, -} from '@hyperlane-xyz/sdk'; -import { types } from '@hyperlane-xyz/utils'; - -import { HyperlaneAppGovernor } from './HyperlaneAppGovernor'; - -export class InterchainQueryGovernor extends HyperlaneAppGovernor< - InterchainQuery, - InterchainQueryConfig -> { - constructor( - checker: InterchainQueryChecker, - owners: ChainMap, - ) { - super(checker, owners); - } - - protected async mapViolationsToCalls() { - throw new Error('governor not implemented for query middleware'); - } -} diff --git a/typescript/infra/src/govern/ProxiedRouterGovernor.ts b/typescript/infra/src/govern/ProxiedRouterGovernor.ts new file mode 100644 index 000000000..5b1baf755 --- /dev/null +++ b/typescript/infra/src/govern/ProxiedRouterGovernor.ts @@ -0,0 +1,47 @@ +import { + ChainMap, + ConnectionClientViolation, + ConnectionClientViolationType, + HyperlaneAppChecker, + RouterApp, + RouterConfig, +} from '@hyperlane-xyz/sdk'; +import { types } from '@hyperlane-xyz/utils'; + +import { HyperlaneAppGovernor } from './HyperlaneAppGovernor'; + +export class ProxiedRouterGovernor< + App extends RouterApp, + Config extends RouterConfig, +> extends HyperlaneAppGovernor { + constructor( + checker: HyperlaneAppChecker, + owners: ChainMap, + ) { + super(checker, owners); + } + + protected async mapViolationsToCalls() { + for (const violation of this.checker.violations) { + if ( + violation.type === + ConnectionClientViolationType.InterchainSecurityModule + ) { + this.handleIsmViolation(violation as ConnectionClientViolation); + } else { + throw new Error(`Unsupported violation type ${violation.type}`); + } + } + } + + protected handleIsmViolation(violation: ConnectionClientViolation) { + this.pushCall(violation.chain, { + to: violation.contract.address, + data: violation.contract.interface.encodeFunctionData( + 'setInterchainSecurityModule', + [violation.expected], + ), + description: `Set ISM of ${violation.contract.address} to ${violation.expected}`, + }); + } +} diff --git a/typescript/sdk/src/consts/environments/mainnet.json b/typescript/sdk/src/consts/environments/mainnet.json index 54ea9c121..7596c5cb7 100644 --- a/typescript/sdk/src/consts/environments/mainnet.json +++ b/typescript/sdk/src/consts/environments/mainnet.json @@ -10,6 +10,7 @@ "testRecipient": "0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35", "interchainQueryRouter": "0x234b19282985882d6d6fd54dEBa272271f4eb784", "interchainAccountRouter": "0xB193eBf06faD5D66492BB41DBbCd202640aE83fF", + "interchainAccountIsm": "0x5e8ee6840caa4f367aff1FF28aA36D5B1b836d35", "multisigIsmFactory": "0x9bf473968629b8f8cF4ab59Aeb9640b0c93411dd", "aggregationIsmFactory": "0xc864fa3B662613cA5051f41e157d0a997f9a5A87", "routingIsmFactory": "0x1fdfD1486b8339638C6b92f8a96D698D8182D2b1" @@ -25,6 +26,7 @@ "testRecipient": "0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35", "interchainQueryRouter": "0x234b19282985882d6d6fd54dEBa272271f4eb784", "interchainAccountRouter": "0x5fD075C2157567F7F80e6cB20dDd75F40905bd87", + "interchainAccountIsm": "0x943303Ad7D2B87BB363E0BACC901486337d9B316", "multisigIsmFactory": "0xfD548D8a8EB8366D802F24e1bC6D1d21dB057EF1", "aggregationIsmFactory": "0x30B3Ef3e98B1FF72f03f71f68115E18F203Ec794", "routingIsmFactory": "0xBF30B4F328d1F6AC47ecCcF23836F3CbB2422c9f" @@ -40,6 +42,7 @@ "testRecipient": "0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35", "interchainQueryRouter": "0x234b19282985882d6d6fd54dEBa272271f4eb784", "interchainAccountRouter": "0x77c509140A45B4B85E1A28f8c21AaEB3Ca8788B3", + "interchainAccountIsm": "0x88C01B64dCe0032796a1967E2b3447B397c6c7AC", "multisigIsmFactory": "0x270d0334bC98a02f7A4e2328B319EDEDcd7a2000", "aggregationIsmFactory": "0x070d4f61b05eD9e20C9194f29Df073f2110705fc", "routingIsmFactory": "0x0FC1A9DFAca9b6Ba11bC470Bf284Da7c107fDfF2" @@ -55,6 +58,7 @@ "testRecipient": "0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35", "interchainQueryRouter": "0x234b19282985882d6d6fd54dEBa272271f4eb784", "interchainAccountRouter": "0x4a4D878c41C7F71eCff182F526b7691aDC6e4150", + "interchainAccountIsm": "0xCd8ACf2254641bD3Eaa32C1B8D36f0983de8C0E6", "multisigIsmFactory": "0xfF4872B62225c1f029a894D4682b250dD5577AC7", "aggregationIsmFactory": "0x10Add66Db9C837000A43F3601aa9c54c6744F4c8", "routingIsmFactory": "0x0B48a744698ba8dFa514742dFEB6728f52fD66f7" @@ -70,6 +74,7 @@ "testRecipient": "0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35", "interchainQueryRouter": "0x234b19282985882d6d6fd54dEBa272271f4eb784", "interchainAccountRouter": "0xF9A4e3BA5e532906c241310f6832d2Ee8D1c5609", + "interchainAccountIsm": "0x1d3Bdf44887744007C7C62c85924c445C9e825DE", "multisigIsmFactory": "0x4F5db88EEdEBd6a8303ed13491169d4229D9A735", "aggregationIsmFactory": "0x4084054Fc83af652A1f21EA2FF2a668D796e2514", "routingIsmFactory": "0x85392758524EEE2323Bd3029E77aFc9bA9E60216" @@ -85,6 +90,7 @@ "testRecipient": "0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35", "interchainQueryRouter": "0x234b19282985882d6d6fd54dEBa272271f4eb784", "interchainAccountRouter": "0xAC2BE81884C66E6c05B80C05C907B54C74eA2C49", + "interchainAccountIsm": "0xC1d10a99C382Dd224d7F513C7e0f74D7689071f4", "multisigIsmFactory": "0x2A87BF6aE678569545B258fA11087C6F57dd9012", "aggregationIsmFactory": "0x9E3075E067932d744119e583B34d11b144CE1e4A", "routingIsmFactory": "0xcC2fA09fa13857942fae408EcCEc8De307344e99" @@ -100,6 +106,7 @@ "testRecipient": "0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35", "interchainQueryRouter": "0x234b19282985882d6d6fd54dEBa272271f4eb784", "interchainAccountRouter": "0x652e2F475Af7b1154817E09f5408f9011037492a", + "interchainAccountIsm": "0x3de63b62BeF9Da290F51f856cA9F3dB4225EDc05", "multisigIsmFactory": "0x21581dE0CB0Ce91E87b9d5124543C75Fa01ED9CC", "aggregationIsmFactory": "0xb7d42f065E32eB6fCAac7ef83902c56164328fE2", "routingIsmFactory": "0x4ef980034E631CC0CFb3b065aB793611f1B6511A" @@ -115,6 +122,7 @@ "testRecipient": "0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35", "interchainQueryRouter": "0x234b19282985882d6d6fd54dEBa272271f4eb784", "interchainAccountRouter": "0x5b6311e0417CfD3Fb10318108897E63777CFE8D7", + "interchainAccountIsm": "0x88d346eEc75b6D22428bbaB569b6eBB0bE183c4F", "multisigIsmFactory": "0xe3DB9EdafBA60629308166B21DE2B4970bF94969", "aggregationIsmFactory": "0x20E1897CD584C3788A3C24f5e424345a55ADf90C", "routingIsmFactory": "0xB5ec4e94ec47A70C6A38370666F713423816ce4c" @@ -129,6 +137,7 @@ "multisigIsm": "0xC343A7054838FE9F249D7E3Ec1Fa6f1D108694b8", "testRecipient": "0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35", "interchainAccountRouter": "0x32e77b20bf0cf034eB80ea9DD02De881016B01B3", + "interchainAccountIsm": "0x8AB7A6FaC052518A39628497735C855a2Beb515B", "multisigIsmFactory": "0xb58257cc81E47EC72fD38aE16297048de23163b4", "aggregationIsmFactory": "0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86", "routingIsmFactory": "0xbB22547D1dc681fe925f568f637Ff67aC06c20fc" diff --git a/typescript/sdk/src/consts/environments/testnet.json b/typescript/sdk/src/consts/environments/testnet.json index 665802533..baf647bb1 100644 --- a/typescript/sdk/src/consts/environments/testnet.json +++ b/typescript/sdk/src/consts/environments/testnet.json @@ -10,6 +10,7 @@ "testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE", "interchainQueryRouter": "0xF782C6C4A02f2c71BB8a1Db0166FAB40ea956818", "interchainAccountRouter": "0xDb91D575F17d8AAf1aFEC0eaDBD5Ac9e5Cef4ad0", + "interchainAccountIsm": "0x0aA320a1bD450152B4C500613335CeBA4f6073cF", "multisigIsmFactory": "0x9AF85731EDd41E2E50F81Ef8a0A69D2fB836EDf9", "aggregationIsmFactory": "0xBEd8Fd6d5c6cBd878479C25f4725C7c842a43821", "routingIsmFactory": "0x98F44EA5b9cA6aa02a5B75f31E0621083d9096a2" @@ -25,6 +26,7 @@ "testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE", "interchainQueryRouter": "0xF782C6C4A02f2c71BB8a1Db0166FAB40ea956818", "interchainAccountRouter": "0xf82b58Bf348a6CEA6e19413e9DE040dB1a363128", + "interchainAccountIsm": "0x333C9A8c70Ea4F0498Fb58bEe40DEa40e63a9962", "multisigIsmFactory": "0x094652a8ea2153A03916771a778E7b66839A4F58", "aggregationIsmFactory": "0x9fB5D10C07569F2EBdc8ec4432B3a52b6d0ad9A0", "routingIsmFactory": "0xB24C91238eA30D59CF58CEB8dd5e4eaf70544d47" @@ -40,6 +42,7 @@ "testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE", "interchainQueryRouter": "0xF782C6C4A02f2c71BB8a1Db0166FAB40ea956818", "interchainAccountRouter": "0x6a9CeD0e13E738517558aA283DA0E93e5904D49b", + "interchainAccountIsm": "0x40c2d6cA6F5A8857705C128b2c1A5f0Ae20880dc", "multisigIsmFactory": "0x32268e45724626972650837A26eEF0Dd9E6aEEE3", "aggregationIsmFactory": "0xD095B3ADa705e171f40187e10eD07Ee5fe291704", "routingIsmFactory": "0xdc8BC001FB649EfD51eEDD33151d428b917AaE3d" @@ -55,6 +58,7 @@ "testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE", "interchainQueryRouter": "0xF782C6C4A02f2c71BB8a1Db0166FAB40ea956818", "interchainAccountRouter": "0x951c74D83a85833b53A448caaB7397bd3fa6CFB2", + "interchainAccountIsm": "0x9034f60Dec10cFa162369444081685F542d0C24D", "multisigIsmFactory": "0xfb6B94750e1307719892fBC21AC7A0C74A467869", "aggregationIsmFactory": "0xda72972291172B9966Dec7606d45d72e2b9f2470", "routingIsmFactory": "0x0CA314006fe0e7EF88ad2Bb69a7421aB2f1C5288" @@ -70,6 +74,7 @@ "testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE", "interchainQueryRouter": "0xF782C6C4A02f2c71BB8a1Db0166FAB40ea956818", "interchainAccountRouter": "0xCb0ba89F564e31180A101Df54b7971206e03ee9b", + "interchainAccountIsm": "0x70835F3C2845394842DEA9f40cbe8087b2cE5712", "multisigIsmFactory": "0xFa13bd2BD45644bAF0797e41D1a4D56601a4059a", "aggregationIsmFactory": "0x11413a6Ea76a55eAec950894ba8fdd7683E41b06", "routingIsmFactory": "0x129A80Fe557153B5F48B4292F8C177bACdcf7dB3" @@ -85,6 +90,7 @@ "testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE", "interchainQueryRouter": "0xF782C6C4A02f2c71BB8a1Db0166FAB40ea956818", "interchainAccountRouter": "0x209Ccdbe13BB913104117B1D6f7801684e98FA1F", + "interchainAccountIsm": "0xD699ff94f3FFd60A3a09bBff96181325B6C73FB8", "multisigIsmFactory": "0x4266D8Dd66D8Eb3934c8942968d1e54214D072d3", "aggregationIsmFactory": "0x759c4Eb4575B651a9f0Fb46653dd7B2F32fD7310", "routingIsmFactory": "0x561331FafB7f2ABa77E77780178ADdD1A37bdaBD" @@ -100,6 +106,7 @@ "testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE", "interchainQueryRouter": "0xF782C6C4A02f2c71BB8a1Db0166FAB40ea956818", "interchainAccountRouter": "0x12EBd8cb561c68b587C392e0c5405B9866FD5820", + "interchainAccountIsm": "0x82F5a960a4e4Cc0614253e4977bb3BE10344a30C", "multisigIsmFactory": "0x0bA75fBC56FEb7e4F5EF4a8F042272cfec152ABc", "aggregationIsmFactory": "0x919AD6f6DFE1C17b89DAC2eE526F153C08afE305", "routingIsmFactory": "0x1D7b8aBa2494Ec82e80D6206d2B3df9f8C3F1862" @@ -115,6 +122,7 @@ "testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE", "interchainQueryRouter": "0xF782C6C4A02f2c71BB8a1Db0166FAB40ea956818", "interchainAccountRouter": "0x4266D8Dd66D8Eb3934c8942968d1e54214D072d3", + "interchainAccountIsm": "0xA8978fdB093b1C5b892291A36e8527b34B749d6f", "multisigIsmFactory": "0x71cCc98689B48Dd50Fd5950815A56d76477349B2", "aggregationIsmFactory": "0xa27F4a2bD624CF1cB3605c532E95E27BB0AC0BB3", "routingIsmFactory": "0xa68022e53Fd28119D07C8336a8eC84A298Fd38Fd" @@ -129,6 +137,7 @@ "multisigIsm": "0xD3d062a5dcBA85ae863618d4c264d2358300c283", "testRecipient": "0xBC3cFeca7Df5A45d61BC60E7898E63670e1654aE", "interchainAccountRouter": "0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5", + "interchainAccountIsm": "0x7483faD0Bc297667664A43A064bA7c9911659f57", "multisigIsmFactory": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f", "aggregationIsmFactory": "0x01812D60958798695391dacF092BAc4a715B1718", "routingIsmFactory": "0xE67CfA164cDa449Ae38a0a09391eF6bCDf8e4e2c" diff --git a/typescript/sdk/src/deploy/types.ts b/typescript/sdk/src/deploy/types.ts index fbb1edf54..09169bdda 100644 --- a/typescript/sdk/src/deploy/types.ts +++ b/typescript/sdk/src/deploy/types.ts @@ -23,6 +23,8 @@ export interface OwnerViolation extends CheckerViolation { type: ViolationType.Owner; contract: Ownable; name: string; + actual: string; + expected: string; } export interface ProxyAdminViolation extends CheckerViolation { diff --git a/typescript/sdk/src/index.ts b/typescript/sdk/src/index.ts index 992f258e3..e2c599264 100644 --- a/typescript/sdk/src/index.ts +++ b/typescript/sdk/src/index.ts @@ -1,21 +1,22 @@ +export { HyperlaneApp } from './HyperlaneApp'; export { AgentChainSetup, AgentConfig, AgentConnection, AgentConnectionType, AgentSigner, - buildAgentConfig, HyperlaneAgentAddresses, + buildAgentConfig, } from './agents/types'; export { - chainIdToMetadata, ChainMetadata, - chainMetadata, ChainMetadataSchema, ExplorerFamily, + RpcPagination, + chainIdToMetadata, + chainMetadata, isValidChainMetadata, mainnetChainsMetadata, - RpcPagination, testnetChainsMetadata, wagmiChainMetadata, } from './consts/chainMetadata'; @@ -32,30 +33,30 @@ export { export { hyperlaneEnvironments } from './consts/environments'; export { defaultMultisigIsmConfigs } from './consts/multisigIsm'; export { - attachContracts, - attachContractsMap, - connectContracts, - connectContractsMap, - filterAddressesMap, HyperlaneAddresses, HyperlaneAddressesMap, HyperlaneContracts, HyperlaneContractsMap, HyperlaneFactories, + attachContracts, + attachContractsMap, + connectContracts, + connectContractsMap, + filterAddressesMap, serializeContracts, serializeContractsMap, } from './contracts'; +export { DispatchedMessage, HyperlaneCore } from './core/HyperlaneCore'; +export { HyperlaneCoreChecker } from './core/HyperlaneCoreChecker'; +export { HyperlaneCoreDeployer } from './core/HyperlaneCoreDeployer'; +export { TestCoreApp } from './core/TestCoreApp'; +export { TestCoreDeployer } from './core/TestCoreDeployer'; export { CoreFactories, coreFactories } from './core/contracts'; export { AnnotatedDispatch, AnnotatedLifecycleEvent, HyperlaneLifecyleEvent, } from './core/events'; -export { DispatchedMessage, HyperlaneCore } from './core/HyperlaneCore'; -export { HyperlaneCoreChecker } from './core/HyperlaneCoreChecker'; -export { HyperlaneCoreDeployer } from './core/HyperlaneCoreDeployer'; -export { TestCoreApp } from './core/TestCoreApp'; -export { TestCoreDeployer } from './core/TestCoreDeployer'; export { CoreConfig, CoreViolationType } from './core/types'; export { HyperlaneAppChecker } from './deploy/HyperlaneAppChecker'; export { DeployerOptions, HyperlaneDeployer } from './deploy/HyperlaneDeployer'; @@ -73,9 +74,9 @@ export { export * as verificationUtils from './deploy/verify/utils'; export { Annotated, + TSContract, getEvents, queryAnnotatedEvents, - TSContract, } from './events'; export { HyperlaneIgp } from './gas/HyperlaneIgp'; export { HyperlaneIgpChecker } from './gas/HyperlaneIgpChecker'; @@ -91,10 +92,9 @@ export { IgpViolationType, OverheadIgpConfig, } from './gas/types'; -export { HyperlaneApp } from './HyperlaneApp'; export { - collectValidators, HyperlaneIsmFactory, + collectValidators, } from './ism/HyperlaneIsmFactory'; export { HyperlaneIsmFactoryDeployer } from './ism/HyperlaneIsmFactoryDeployer'; export { @@ -104,14 +104,13 @@ export { MultisigIsmConfig, RoutingIsmConfig, } from './ism/types'; -export { interchainAccountFactories } from './middleware/account/contracts'; export { InterchainAccount } from './middleware/account/InterchainAccount'; export { InterchainAccountChecker } from './middleware/account/InterchainAccountChecker'; export { InterchainAccountConfig, InterchainAccountDeployer, } from './middleware/account/InterchainAccountDeployer'; -export { liquidityLayerFactories } from './middleware/liquidity-layer/contracts'; +export { interchainAccountFactories } from './middleware/account/contracts'; export { LiquidityLayerApp } from './middleware/liquidity-layer/LiquidityLayerApp'; export { BridgeAdapterConfig, @@ -120,20 +119,26 @@ export { LiquidityLayerDeployer, PortalAdapterConfig, } from './middleware/liquidity-layer/LiquidityLayerRouterDeployer'; -export { interchainQueryFactories } from './middleware/query/contracts'; +export { liquidityLayerFactories } from './middleware/liquidity-layer/contracts'; export { InterchainQuery } from './middleware/query/InterchainQuery'; export { InterchainQueryChecker } from './middleware/query/InterchainQueryChecker'; export { InterchainQueryConfig, InterchainQueryDeployer, } from './middleware/query/InterchainQueryDeployer'; +export { interchainQueryFactories } from './middleware/query/contracts'; export { MultiProvider, providerBuilder } from './providers/MultiProvider'; export { RetryJsonRpcProvider, RetryProvider } from './providers/RetryProvider'; export { GasRouterDeployer } from './router/GasRouterDeployer'; export { HyperlaneRouterChecker } from './router/HyperlaneRouterChecker'; export { HyperlaneRouterDeployer } from './router/HyperlaneRouterDeployer'; export { GasRouterApp, Router, RouterApp } from './router/RouterApps'; -export { GasRouterConfig, RouterConfig } from './router/types'; +export { + ConnectionClientViolation, + ConnectionClientViolationType, + GasRouterConfig, + RouterConfig, +} from './router/types'; export { createRouterConfigMap, deployTestIgpsAndGetRouterConfig, @@ -145,9 +150,9 @@ export { NameOrDomain, TestChainNames, } from './types'; +export { MultiGeneric } from './utils/MultiGeneric'; export { canonizeId, evmId } from './utils/ids'; export { multisigIsmVerificationCost } from './utils/ism'; -export { MultiGeneric } from './utils/MultiGeneric'; export { bigToFixed, convertDecimalValue, diff --git a/typescript/sdk/src/middleware/account/InterchainAccountChecker.ts b/typescript/sdk/src/middleware/account/InterchainAccountChecker.ts index a902a84ec..34ccd6a1e 100644 --- a/typescript/sdk/src/middleware/account/InterchainAccountChecker.ts +++ b/typescript/sdk/src/middleware/account/InterchainAccountChecker.ts @@ -1,4 +1,7 @@ +import { MultiProvider } from '../../providers/MultiProvider'; import { ProxiedRouterChecker } from '../../router/ProxiedRouterChecker'; +import { ChainMap } from '../../types'; +import { objMap } from '../../utils/objects'; import { InterchainAccount } from './InterchainAccount'; import { InterchainAccountConfig } from './InterchainAccountDeployer'; @@ -8,4 +11,26 @@ export class InterchainAccountChecker extends ProxiedRouterChecker< InterchainAccountFactories, InterchainAccount, InterchainAccountConfig -> {} +> { + constructor( + multiProvider: MultiProvider, + app: InterchainAccount, + configMap: ChainMap, + ) { + // The checker does not expect an ISM in it's config. + // Instead, we set the ISM to match the ISM address from the app. + const configMapWithIsm = objMap(configMap, (chain, config) => { + if (config.interchainSecurityModule) { + throw new Error( + 'Configuration of ISM address not supported in ICA checker', + ); + } + return { + ...config, + interchainSecurityModule: + app.contractsMap[chain].interchainAccountIsm.address, + }; + }); + super(multiProvider, app, configMapWithIsm); + } +} diff --git a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts index 4831a3590..a4a297b8c 100644 --- a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts +++ b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts @@ -1,5 +1,3 @@ -import { ethers } from 'ethers'; - import { InterchainAccountRouter, Router, @@ -40,20 +38,31 @@ export class InterchainAccountDeployer extends HyperlaneRouterDeployer< chain: ChainName, config: InterchainAccountConfig, ): Promise> { + if (config.interchainSecurityModule) { + throw new Error( + 'Configuration of ISM address not supported in ICA deployer', + ); + } + const proxyAdmin = await this.deployContract(chain, 'proxyAdmin', []); + const interchainAccountIsm = await this.deployContract( + chain, + 'interchainAccountIsm', + [config.mailbox], + ); let interchainAccountRouter: InterchainAccountRouter; // adapted from HyperlaneDeployer.deployProxiedContract - const cachedContract = this.readCache( + const cachedRouter = this.readCache( chain, this.factories['interchainAccountRouter'], 'interchainAccountRouter', ); - if (cachedContract) { - interchainAccountRouter = cachedContract; + + if (cachedRouter) { + interchainAccountRouter = cachedRouter; } else { const deployer = await this.multiProvider.getSignerAddress(chain); - // 1. deploy the proxy first with a dummy implementation (proxy admin contract) const proxy = await this.deployContractFromFactory( chain, @@ -75,7 +84,7 @@ export class InterchainAccountDeployer extends HyperlaneRouterDeployer< await super.upgradeAndInitialize(chain, proxy, implementation, [ config.mailbox, config.interchainGasPaymaster, - config.interchainSecurityModule ?? ethers.constants.AddressZero, + interchainAccountIsm.address, owner, ]); interchainAccountRouter = implementation.attach(proxy.address); @@ -91,6 +100,7 @@ export class InterchainAccountDeployer extends HyperlaneRouterDeployer< return { proxyAdmin, + interchainAccountIsm, interchainAccountRouter, }; } diff --git a/typescript/sdk/src/middleware/account/accounts.hardhat-test.ts b/typescript/sdk/src/middleware/account/accounts.hardhat-test.ts index 7d666d0c7..01f04417c 100644 --- a/typescript/sdk/src/middleware/account/accounts.hardhat-test.ts +++ b/typescript/sdk/src/middleware/account/accounts.hardhat-test.ts @@ -44,12 +44,6 @@ describe('InterchainAccounts', async () => { signer.address, coreApp.contractsMap, ); - - /* - config.test1.interchainSecurityModule = await coreApp - .getContracts('test1') - .mailbox.defaultIsm(); - */ }); beforeEach(async () => { diff --git a/typescript/sdk/src/middleware/account/contracts.ts b/typescript/sdk/src/middleware/account/contracts.ts index 7004e196b..dd8bd54d8 100644 --- a/typescript/sdk/src/middleware/account/contracts.ts +++ b/typescript/sdk/src/middleware/account/contracts.ts @@ -1,10 +1,12 @@ import { + InterchainAccountIsm__factory, InterchainAccountRouter__factory, ProxyAdmin__factory, } from '@hyperlane-xyz/core'; export const interchainAccountFactories = { interchainAccountRouter: new InterchainAccountRouter__factory(), + interchainAccountIsm: new InterchainAccountIsm__factory(), proxyAdmin: new ProxyAdmin__factory(), }; diff --git a/typescript/sdk/src/router/HyperlaneRouterChecker.ts b/typescript/sdk/src/router/HyperlaneRouterChecker.ts index 3ee05a3e4..df3318bc4 100644 --- a/typescript/sdk/src/router/HyperlaneRouterChecker.ts +++ b/typescript/sdk/src/router/HyperlaneRouterChecker.ts @@ -7,7 +7,11 @@ import { HyperlaneAppChecker } from '../deploy/HyperlaneAppChecker'; import { ChainName } from '../types'; import { RouterApp } from './RouterApps'; -import { RouterConfig } from './types'; +import { + ConnectionClientViolation, + ConnectionClientViolationType, + RouterConfig, +} from './types'; export class HyperlaneRouterChecker< Factories extends HyperlaneFactories, @@ -27,24 +31,37 @@ export class HyperlaneRouterChecker< async checkHyperlaneConnectionClient(chain: ChainName): Promise { const router = this.app.router(this.app.getContracts(chain)); - const mailbox = await router.mailbox(); - const igp = await router.interchainGasPaymaster(); - const ism = await router.interchainSecurityModule(); - utils.assert( - utils.eqAddress(mailbox, this.configMap[chain].mailbox), - 'Mailbox mismatch', + + const checkConnectionClientProperty = async ( + property: keyof RouterConfig, + violationType: ConnectionClientViolationType, + ) => { + const actual = await router[property](); + const expected = + this.configMap[chain][property] ?? ethers.constants.AddressZero; + if (!utils.eqAddress(actual, expected)) { + const violation: ConnectionClientViolation = { + chain, + type: violationType, + contract: router, + actual, + expected, + }; + this.addViolation(violation); + } + }; + + await checkConnectionClientProperty( + 'mailbox', + ConnectionClientViolationType.Mailbox, ); - utils.assert( - utils.eqAddress(igp, this.configMap[chain].interchainGasPaymaster), - 'IGP mismatch', + await checkConnectionClientProperty( + 'interchainGasPaymaster', + ConnectionClientViolationType.InterchainGasPaymaster, ); - utils.assert( - utils.eqAddress( - ism, - this.configMap[chain].interchainSecurityModule ?? - ethers.constants.AddressZero, - ), - 'ISM mismatch', + await checkConnectionClientProperty( + 'interchainSecurityModule', + ConnectionClientViolationType.InterchainSecurityModule, ); } diff --git a/typescript/sdk/src/router/types.ts b/typescript/sdk/src/router/types.ts index 8b6f6f8c1..010f259d4 100644 --- a/typescript/sdk/src/router/types.ts +++ b/typescript/sdk/src/router/types.ts @@ -1,7 +1,11 @@ -import { ProxyAdmin__factory } from '@hyperlane-xyz/core'; +import { + HyperlaneConnectionClient, + ProxyAdmin__factory, +} from '@hyperlane-xyz/core'; import type { types } from '@hyperlane-xyz/utils'; import { HyperlaneFactories } from '../contracts'; +import { CheckerViolation } from '../deploy/types'; export type OwnableConfig = { owner: types.Address; @@ -24,3 +28,16 @@ export type ConnectionClientConfig = { interchainGasPaymaster: types.Address; interchainSecurityModule?: types.Address; }; + +export enum ConnectionClientViolationType { + InterchainSecurityModule = 'ConnectionClientIsm', + Mailbox = 'ConnectionClientMailbox', + InterchainGasPaymaster = 'ConnectionClientIgp', +} + +export interface ConnectionClientViolation extends CheckerViolation { + type: ConnectionClientViolationType; + contract: HyperlaneConnectionClient; + actual: string; + expected: string; +}