Merkle Tree Hook Deployer changes (#2747)

### Description

- Interceptor is the pair <hook, ism>
- `MerkleTreeInterceptorDeployer` for deploying merkle root hook and the
`StaticMerkleRootMultisigIsm` on chain

### Drive-by changes

- None

### Related issues

- addresses https://github.com/hyperlane-xyz/issues/issues/621

### Backward compatibility

Yes

### Testing

Manual
pull/2774/head
Kunal Arora 1 year ago committed by GitHub
parent 8e4f2bbe18
commit f0a45bd6b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      rust/utils/run-locally/src/ethereum.rs
  2. 35
      typescript/infra/config/aggregationIsm.ts
  3. 35
      typescript/infra/config/environments/mainnet2/hooks.ts
  4. 2
      typescript/infra/config/environments/mainnet2/index.ts
  5. 39
      typescript/infra/config/environments/test/hooks.ts
  6. 6
      typescript/infra/config/environments/test/index.ts
  7. 6
      typescript/infra/config/environments/test/multisigIsm.ts
  8. 34
      typescript/infra/config/environments/testnet3/hooks.ts
  9. 2
      typescript/infra/config/environments/testnet3/index.ts
  10. 133
      typescript/infra/config/multisigIsm.ts
  11. 96
      typescript/infra/config/rcMultisigIsmConfigs.ts
  12. 2
      typescript/infra/package.json
  13. 20
      typescript/infra/scripts/deploy.ts
  14. 22
      typescript/infra/scripts/utils.ts
  15. 4
      typescript/infra/src/config/environment.ts
  16. 111
      typescript/sdk/src/hook/HyperlaneHookDeployer.ts
  17. 14
      typescript/sdk/src/hook/config.ts
  18. 21
      typescript/sdk/src/hook/contracts.ts
  19. 23
      typescript/sdk/src/hook/types.ts
  20. 7
      typescript/sdk/src/index.ts
  21. 2
      typescript/sdk/src/ism/HyperlaneIsmFactory.ts
  22. 9
      typescript/sdk/src/ism/types.ts

@ -48,6 +48,9 @@ pub fn start_anvil(config: Arc<Config>) -> AgentHandles {
log!("Deploying hyperlane core contracts...");
yarn_infra.clone().cmd("deploy-core").run().join();
log!("Deploying hyperlane hook contracts...");
yarn_infra.clone().cmd("deploy-hook").run().join();
log!("Deploying hyperlane igp contracts...");
yarn_infra.cmd("deploy-igp").run().join();

@ -1,32 +1,21 @@
import {
AggregationIsmConfig,
ChainMap,
ChainName,
Chains,
IsmConfig,
ModuleType,
MultisigIsmConfig,
RoutingIsmConfig,
defaultMultisigIsmConfigs,
} from '@hyperlane-xyz/sdk';
import { Address, objFilter, objMap } from '@hyperlane-xyz/utils';
import { Address } from '@hyperlane-xyz/utils';
import { DeployEnvironment } from '../src/config';
import { Contexts } from './contexts';
import { supportedChainNames as mainnet2Chains } from './environments/mainnet2/chains';
import { owners as mainnet2Owners } from './environments/mainnet2/owners';
import { chainNames as testChains } from './environments/test/chains';
import { owners as testOwners } from './environments/test/owners';
import { supportedChainNames as testnet3Chains } from './environments/testnet3/chains';
import { owners as testnet3Owners } from './environments/testnet3/owners';
import { rcMultisigIsmConfigs } from './multisigIsm';
const chains = {
mainnet2: mainnet2Chains,
testnet3: testnet3Chains,
test: testChains,
};
import { multisigIsms } from './multisigIsm';
const owners = {
testnet3: testnet3Owners,
@ -34,26 +23,6 @@ const owners = {
test: testOwners,
};
export const multisigIsms = (
env: DeployEnvironment,
local: ChainName,
type: MultisigIsmConfig['type'],
context: Contexts,
): ChainMap<MultisigIsmConfig> =>
objMap(
objFilter(
context === Contexts.ReleaseCandidate
? rcMultisigIsmConfigs
: defaultMultisigIsmConfigs,
(chain, config): config is MultisigIsmConfig =>
chain !== local && chains[env].includes(chain),
),
(_, config) => ({
...config,
type,
}),
);
/// Routing => Multisig ISM type
export const routingIsm = (
environment: DeployEnvironment,

@ -1,35 +0,0 @@
import {
ChainMap,
HookConfig,
HookContractType,
MessageHookConfig,
NoMetadataIsmConfig,
filterByChains,
} from '@hyperlane-xyz/sdk';
import { objMap } from '@hyperlane-xyz/utils';
import { owners } from './owners';
const chainNameFilter = new Set(['ethereum', 'optimism']);
const filteredOwnersResult = filterByChains<string>(owners, chainNameFilter);
export const hooks: ChainMap<HookConfig> = objMap(
filteredOwnersResult,
(chain) => {
if (chain === 'ethereum') {
const hookConfig: MessageHookConfig = {
hookContractType: HookContractType.HOOK,
nativeBridge: '0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1',
remoteIsm: '0x4c5859f0f772848b2d91f1d83e2fe57935348029', // dummy, remoteISM should be deployed first
destination: 'optimism',
};
return hookConfig;
} else {
const ismConfig: NoMetadataIsmConfig = {
hookContractType: HookContractType.ISM,
nativeBridge: '0x4200000000000000000000000000000000000007',
};
return ismConfig;
}
},
);

@ -14,7 +14,6 @@ import { core } from './core';
import { keyFunderConfig } from './funding';
import { storageGasOracleConfig } from './gas-oracle';
import { helloWorld } from './helloworld';
import { hooks } from './hooks';
import { igp } from './igp';
import { infrastructure } from './infrastructure';
import { bridgeAdapterConfigs, relayerConfig } from './liquidityLayer';
@ -45,7 +44,6 @@ export const environment: EnvironmentConfig = {
igp,
owners,
infra: infrastructure,
hooks,
helloWorld,
keyFunderConfig,
storageGasOracleConfig,

@ -1,35 +1,16 @@
import {
ChainMap,
HookConfig,
HookContractType,
MessageHookConfig,
NoMetadataIsmConfig,
filterByChains,
} from '@hyperlane-xyz/sdk';
import { ChainMap } from '@hyperlane-xyz/sdk';
import { MerkleTreeHookConfig } from '@hyperlane-xyz/sdk/dist/hook/types';
import { HookType } from '@hyperlane-xyz/sdk/src/hook/types';
import { objMap } from '@hyperlane-xyz/utils';
import { owners } from './owners';
const chainNameFilter = new Set(['test1', 'test2']);
const filteredOwnersResult = filterByChains<string>(owners, chainNameFilter);
export const hooks: ChainMap<HookConfig> = objMap(
filteredOwnersResult,
(chain) => {
if (chain === 'test1') {
const hookConfig: MessageHookConfig = {
hookContractType: HookContractType.HOOK,
nativeBridge: '0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1',
remoteIsm: '0x4c5859f0f772848b2d91f1d83e2fe57935348029', // dummy, remoteISM should be deployed first
destination: 'test2',
};
return hookConfig;
} else {
const ismConfig: NoMetadataIsmConfig = {
hookContractType: HookContractType.ISM,
nativeBridge: '0x4200000000000000000000000000000000000007',
};
return ismConfig;
}
export const merkleTree: ChainMap<MerkleTreeHookConfig> = objMap(
owners,
(_, __) => {
const config: MerkleTreeHookConfig = {
type: HookType.MERKLE_TREE_HOOK,
};
return config;
},
);

@ -1,6 +1,6 @@
import { JsonRpcProvider } from '@ethersproject/providers';
import { MultiProvider, TestChains } from '@hyperlane-xyz/sdk';
import { MultiProvider } from '@hyperlane-xyz/sdk';
import { EnvironmentConfig } from '../../../src/config';
@ -8,7 +8,7 @@ import { agents } from './agent';
import { testConfigs } from './chains';
import { core } from './core';
import { storageGasOracleConfig } from './gas-oracle';
import { hooks } from './hooks';
import { merkleTree } from './hooks';
import { igp } from './igp';
import { infra } from './infra';
import { owners } from './owners';
@ -18,7 +18,7 @@ export const environment: EnvironmentConfig = {
chainMetadataConfigs: testConfigs,
agents,
core,
hooks,
hook: merkleTree,
igp,
owners,
infra,

@ -27,7 +27,7 @@ export const messageIdMultisig = (validatorKey: string): MultisigIsmConfig => {
// the addresses here must line up with the e2e test's validator addresses
export const multisigIsm: ChainMap<MultisigIsmConfig> = {
// Validators are anvil accounts 4-6
test1: messageIdMultisig('test1'),
test2: merkleRootMultisig('test2'),
test3: messageIdMultisig('test3'),
test1: messageIdMultisig(chainToValidator['test1']),
test2: merkleRootMultisig(chainToValidator['test2']),
test3: messageIdMultisig(chainToValidator['test3']),
};

@ -1,34 +0,0 @@
import {
ChainMap,
HookConfig,
HookContractType,
MessageHookConfig,
NoMetadataIsmConfig,
filterByChains,
} from '@hyperlane-xyz/sdk';
import { objMap } from '@hyperlane-xyz/utils';
import { owners } from './owners';
const chainNameFilter = new Set(['goerli', 'optimismgoerli']);
const filteredOwnersResult = filterByChains<string>(owners, chainNameFilter);
export const hooks: ChainMap<HookConfig> = objMap(
filteredOwnersResult,
(chain) => {
if (chain === 'goerli') {
const hookConfig: MessageHookConfig = {
hookContractType: HookContractType.HOOK,
nativeBridge: '0x5086d1eEF304eb5284A0f6720f79403b4e9bE294',
destination: 'optimismgoerli',
};
return hookConfig;
} else {
const ismConfig: NoMetadataIsmConfig = {
hookContractType: HookContractType.ISM,
nativeBridge: '0x4200000000000000000000000000000000000007',
};
return ismConfig;
}
},
);

@ -14,7 +14,6 @@ import { core } from './core';
import { keyFunderConfig } from './funding';
import { storageGasOracleConfig } from './gas-oracle';
import { helloWorld } from './helloworld';
import { hooks } from './hooks';
import { igp } from './igp';
import { infrastructure } from './infrastructure';
import { bridgeAdapterConfigs } from './liquidityLayer';
@ -46,7 +45,6 @@ export const environment: EnvironmentConfig = {
igp,
infra: infrastructure,
helloWorld,
hooks,
owners,
keyFunderConfig,
liquidityLayerConfig: {

@ -1,96 +1,41 @@
import { ChainMap, MultisigConfig } from '@hyperlane-xyz/sdk';
import {
ChainMap,
ChainName,
MultisigIsmConfig,
defaultMultisigIsmConfigs,
} from '@hyperlane-xyz/sdk';
import { objFilter, objMap } from '@hyperlane-xyz/utils';
export const rcMultisigIsmConfigs: ChainMap<MultisigConfig> = {
// ----------------- Mainnets -----------------
celo: {
threshold: 1,
validators: [
'0xe7a82e210f512f8e9900d6bc2acbf7981c63e66e', // abacus
],
},
ethereum: {
threshold: 1,
validators: [
'0xaea1adb1c687b061e5b60b9da84cb69e7b5fab44', // abacus
],
},
avalanche: {
threshold: 1,
validators: [
'0x706976391e23dea28152e0207936bd942aba01ce', // abacus
],
},
polygon: {
threshold: 1,
validators: [
'0xef372f6ff7775989b3ac884506ee31c79638c989', // abacus
],
},
bsc: {
threshold: 1,
validators: [
'0x0823081031a4a6f97c6083775c191d17ca96d0ab', // abacus
],
},
arbitrum: {
threshold: 1,
validators: [
'0x1a95b35fb809d57faf1117c1cc29a6c5df289df1', // abacus
],
},
optimism: {
threshold: 1,
validators: [
'0x60e938bf280bbc21bacfd8bf435459d9003a8f98', // abacus
],
},
moonbeam: {
threshold: 1,
validators: [
'0x0df7140811e309dc69638352545151ebb9d5e0fd', // abacus
],
},
gnosis: {
threshold: 1,
validators: [
'0x15f48e78092a4f79febface509cfd76467c6cdbb', // abacus
],
},
// ----------------- Testnets -----------------
alfajores: {
threshold: 1,
validators: ['0x45e5c228b38e1cf09e9a3423ed0cf4862c4bf3de'],
},
fuji: {
threshold: 1,
validators: ['0xd81ba169170a9b582812cf0e152d2c168572e21f'],
},
mumbai: {
threshold: 1,
validators: ['0xb537c4ce34e1cad718be52aa30b095e416eae46a'],
},
bsctestnet: {
threshold: 1,
validators: ['0x77f80ef5b18977e15d81aea8dd3a88e7df4bc0eb'],
},
goerli: {
threshold: 1,
validators: ['0x9597ddb4ad2af237665559574b820596bb77ae7a'],
},
sepolia: {
threshold: 1,
validators: ['0x183f15924f3a464c54c9393e8d268eb44d2b208c'],
},
moonbasealpha: {
threshold: 1,
validators: ['0xbeaf158f85d7b64ced36b8aea0bbc4cd0f2d1a5d'],
},
optimismgoerli: {
threshold: 1,
validators: ['0x1d6798671ac532f2bf30c3a5230697a4695705e4'],
},
arbitrumgoerli: {
threshold: 1,
validators: ['0x6d13367c7cd713a4ea79a2552adf824bf1ecdd5e'],
},
import { DeployEnvironment } from '../src/config';
import { Contexts } from './contexts';
import { supportedChainNames as mainnet2Chains } from './environments/mainnet2/chains';
import { chainNames as testChains } from './environments/test/chains';
import { supportedChainNames as testnet3Chains } from './environments/testnet3/chains';
import { rcMultisigIsmConfigs } from './rcMultisigIsmConfigs';
const chains = {
mainnet2: mainnet2Chains,
testnet3: testnet3Chains,
test: testChains,
};
export const multisigIsms = (
env: DeployEnvironment,
local: ChainName,
type: MultisigIsmConfig['type'],
context: Contexts,
): ChainMap<MultisigIsmConfig> =>
objMap(
objFilter(
context === Contexts.ReleaseCandidate
? rcMultisigIsmConfigs
: defaultMultisigIsmConfigs,
(chain, config): config is MultisigIsmConfig =>
chain !== local && chains[env].includes(chain),
),
(_, config) => ({
...config,
type,
}),
);

@ -0,0 +1,96 @@
import { ChainMap, MultisigConfig } from '@hyperlane-xyz/sdk';
export const rcMultisigIsmConfigs: ChainMap<MultisigConfig> = {
// ----------------- Mainnets -----------------
celo: {
threshold: 1,
validators: [
'0xe7a82e210f512f8e9900d6bc2acbf7981c63e66e', // abacus
],
},
ethereum: {
threshold: 1,
validators: [
'0xaea1adb1c687b061e5b60b9da84cb69e7b5fab44', // abacus
],
},
avalanche: {
threshold: 1,
validators: [
'0x706976391e23dea28152e0207936bd942aba01ce', // abacus
],
},
polygon: {
threshold: 1,
validators: [
'0xef372f6ff7775989b3ac884506ee31c79638c989', // abacus
],
},
bsc: {
threshold: 1,
validators: [
'0x0823081031a4a6f97c6083775c191d17ca96d0ab', // abacus
],
},
arbitrum: {
threshold: 1,
validators: [
'0x1a95b35fb809d57faf1117c1cc29a6c5df289df1', // abacus
],
},
optimism: {
threshold: 1,
validators: [
'0x60e938bf280bbc21bacfd8bf435459d9003a8f98', // abacus
],
},
moonbeam: {
threshold: 1,
validators: [
'0x0df7140811e309dc69638352545151ebb9d5e0fd', // abacus
],
},
gnosis: {
threshold: 1,
validators: [
'0x15f48e78092a4f79febface509cfd76467c6cdbb', // abacus
],
},
// ----------------- Testnets -----------------
alfajores: {
threshold: 1,
validators: ['0x45e5c228b38e1cf09e9a3423ed0cf4862c4bf3de'],
},
fuji: {
threshold: 1,
validators: ['0xd81ba169170a9b582812cf0e152d2c168572e21f'],
},
mumbai: {
threshold: 1,
validators: ['0xb537c4ce34e1cad718be52aa30b095e416eae46a'],
},
bsctestnet: {
threshold: 1,
validators: ['0x77f80ef5b18977e15d81aea8dd3a88e7df4bc0eb'],
},
goerli: {
threshold: 1,
validators: ['0x9597ddb4ad2af237665559574b820596bb77ae7a'],
},
sepolia: {
threshold: 1,
validators: ['0x183f15924f3a464c54c9393e8d268eb44d2b208c'],
},
moonbasealpha: {
threshold: 1,
validators: ['0xbeaf158f85d7b64ced36b8aea0bbc4cd0f2d1a5d'],
},
optimismgoerli: {
threshold: 1,
validators: ['0x1d6798671ac532f2bf30c3a5230697a4695705e4'],
},
arbitrumgoerli: {
threshold: 1,
validators: ['0x6d13367c7cd713a4ea79a2552adf824bf1ecdd5e'],
},
};

@ -58,7 +58,7 @@
"deploy-igp": "ts-node scripts/deploy.ts -e test -m igp",
"deploy-ism": "ts-node scripts/deploy.ts -e test -m ism",
"deploy-helloworld": "ts-node scripts/deploy.ts -e test -m helloworld",
"deploy-hook": "ts-node scripts/deploy.ts -e testnet3 -m hook",
"deploy-hook": "ts-node scripts/deploy.ts -e test -m hook",
"build": "tsc",
"clean": "rm -rf ./dist ./cache",
"check": "tsc --noEmit",

@ -5,6 +5,7 @@ import {
ChainMap,
HyperlaneCoreDeployer,
HyperlaneDeployer,
HyperlaneHookDeployer,
HyperlaneIgpDeployer,
HyperlaneIsmFactory,
HyperlaneIsmFactoryDeployer,
@ -12,7 +13,7 @@ import {
InterchainQueryDeployer,
LiquidityLayerDeployer,
} from '@hyperlane-xyz/sdk';
import { objMap } from '@hyperlane-xyz/utils';
import { Address, objMap } from '@hyperlane-xyz/utils';
import { Contexts } from '../config/contexts';
import { deployEnvToSdkEnv } from '../src/config/environment';
@ -71,9 +72,20 @@ async function main() {
);
deployer = new HyperlaneCoreDeployer(multiProvider, ismFactory);
} else if (module === Modules.HOOK) {
throw new Error('Hook deployment unimplemented');
// config = envConfig.hooks;
// deployer = new HyperlaneHookDeployer(multiProvider);
if (!envConfig.hook) {
throw new Error(`No hook config for ${environment}`);
}
config = envConfig.hook;
const ismFactory = HyperlaneIsmFactory.fromAddressesMap(
getAddresses(environment, Modules.ISM_FACTORY),
multiProvider,
);
const mailboxes: ChainMap<Address> = {};
for (const chain in getAddresses(environment, Modules.CORE)) {
mailboxes[chain] = getAddresses(environment, Modules.CORE)[chain].mailbox;
}
deployer = new HyperlaneHookDeployer(multiProvider, ismFactory, mailboxes);
} else if (module === Modules.INTERCHAIN_GAS_PAYMASTER) {
config = envConfig.igp;
deployer = new HyperlaneIgpDeployer(multiProvider);

@ -39,7 +39,6 @@ import {
import { fetchProvider } from '../src/config/chain';
import { EnvironmentNames, deployEnvToSdkEnv } from '../src/config/environment';
import { Role } from '../src/roles';
import { impersonateAccount, useLocalProvider } from '../src/utils/fork';
import { assertContext, assertRole, readJSON } from '../src/utils/utils';
export enum Modules {
@ -380,24 +379,3 @@ export function getValidatorsByChain(
}
return validators;
}
export async function getHooksProvider(
multiProvider: MultiProvider,
environment: DeployEnvironment,
): Promise<MultiProvider> {
const hooksProvider = new MultiProvider();
const hooksConfig = getEnvironmentConfig(environment).hooks;
if (!hooksConfig) {
return hooksProvider;
}
for (const chain of Object.keys(hooksConfig)) {
// need to use different url for two forks simultaneously
// need another rpc param
await useLocalProvider(multiProvider, chain);
}
const signer = await impersonateAccount(
'0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
);
hooksProvider.setSharedSigner(signer);
return hooksProvider;
}

@ -5,8 +5,8 @@ import {
ChainMetadata,
ChainName,
CoreConfig,
HookConfig,
HyperlaneEnvironment,
MerkleTreeHookConfig,
MultiProvider,
OverheadIgpConfig,
} from '@hyperlane-xyz/sdk';
@ -37,7 +37,7 @@ export type EnvironmentConfig = {
// Each AgentConfig, keyed by the context
agents: Partial<Record<Contexts, RootAgentConfig>>;
core: ChainMap<CoreConfig>;
hooks: ChainMap<HookConfig>;
hook?: ChainMap<MerkleTreeHookConfig>;
igp: ChainMap<OverheadIgpConfig>;
owners: ChainMap<Address>;
infra: InfrastructureConfig;

@ -1,104 +1,55 @@
import debug from 'debug';
import { objFilter, objMap, promiseObjAll } from '@hyperlane-xyz/utils';
import { Address } from '@hyperlane-xyz/utils';
import {
HyperlaneAddressesMap,
HyperlaneContracts,
HyperlaneContractsMap,
} from '../contracts/types';
import { CoreFactories } from '../core/contracts';
import { HyperlaneContracts } from '../contracts/types';
import { HyperlaneDeployer } from '../deploy/HyperlaneDeployer';
import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory';
import { MultiProvider } from '../providers/MultiProvider';
import { ChainMap, ChainName } from '../types';
import { isHookConfig, isISMConfig } from './config';
import { OptimismHookFactories, optimismHookFactories } from './contracts';
import { HookConfig, MessageHookConfig, NoMetadataIsmConfig } from './types';
import {
HookFactories,
MerkleTreeHookFactory,
hookFactories,
} from './contracts';
import { HookConfig, HookType } from './types';
// TODO: make generic from optimism hooks
export class HyperlaneHookDeployer extends HyperlaneDeployer<
HookConfig,
OptimismHookFactories
HookFactories
> {
constructor(
multiProvider: MultiProvider,
public core: HyperlaneAddressesMap<CoreFactories>,
readonly ismFactory: HyperlaneIsmFactory,
readonly mailboxes: ChainMap<Address>,
) {
super(multiProvider, optimismHookFactories, {
logger: debug('hyperlane:HookDeployer'),
super(multiProvider, hookFactories, {
logger: debug('hyperlane:HyperlaneHookDeployer'),
});
}
async deploy(
configMap: ChainMap<HookConfig>,
): Promise<HyperlaneContractsMap<OptimismHookFactories>> {
// deploy ISMs first
const ismConfigMap = objFilter(
configMap,
(_, config): config is NoMetadataIsmConfig => isISMConfig(config),
);
await super.deploy(ismConfigMap);
// deploy Hooks next
const hookConfigMap = objFilter(
configMap,
(_, config): config is MessageHookConfig => isHookConfig(config),
);
await super.deploy(hookConfigMap);
// configure ISMs with authorized hooks
await promiseObjAll(
objMap(hookConfigMap, (hookChain, hookConfig) => {
const hookAddress = this.deployedContracts[hookChain].hook.address;
const ism = this.deployedContracts[hookConfig.destination].ism;
return this.multiProvider.handleTx(
hookConfig.destination,
ism.setAuthorizedHook(hookAddress),
);
}),
);
return this.deployedContracts;
}
async deployContracts(
chain: ChainName,
config: HookConfig,
): Promise<HyperlaneContracts<OptimismHookFactories>> {
this.logger(`Deploying ${config.hookContractType} on ${chain}`);
if (isISMConfig(config)) {
const ism = await this.multiProvider.handleDeploy(
chain,
this.factories.ism,
[config.nativeBridge],
);
// @ts-ignore
return { ism, hook: undefined };
} else if (isHookConfig(config)) {
const remoteIsm = this.deployedContracts[config.destination].ism;
if (!remoteIsm) {
throw new Error(`Remote ISM not found for ${config.destination}`);
}
const mailbox = this.core[chain].mailbox;
if (!mailbox) {
throw new Error(`Mailbox not found for ${chain}`);
}
const destinationDomain = this.multiProvider.getDomainId(
config.destination,
);
const hook = await this.multiProvider.handleDeploy(
chain,
this.factories.hook,
[mailbox, destinationDomain, remoteIsm.address, config.nativeBridge],
);
// @ts-ignore
return { hook, ism: undefined };
): Promise<HyperlaneContracts<HookFactories>> {
if (config.type === HookType.MERKLE_TREE_HOOK) {
return this.deployMerkleTreeHook(chain, config);
} else {
throw new Error(`Invalid config type: ${config}`);
throw new Error(`Unsupported hook type: ${config.type}`);
}
}
async deployMerkleTreeHook(
chain: ChainName,
_: HookConfig,
): Promise<HyperlaneContracts<MerkleTreeHookFactory>> {
this.logger(`Deploying MerkleTreeHook to ${chain}`);
const merkleTreeHook = await this.deployContract(chain, 'merkleTreeHook', [
this.mailboxes[chain],
]);
return {
merkleTreeHook: merkleTreeHook,
};
}
}

@ -1,14 +0,0 @@
import {
HookConfig,
HookContractType,
MessageHookConfig,
NoMetadataIsmConfig,
} from './types';
export const isISMConfig = (
config: HookConfig,
): config is NoMetadataIsmConfig =>
config.hookContractType === HookContractType.ISM;
export const isHookConfig = (config: HookConfig): config is MessageHookConfig =>
config.hookContractType === HookContractType.HOOK;

@ -1,18 +1,9 @@
import {
AbstractMessageIdAuthHook__factory,
AbstractMessageIdAuthorizedIsm__factory,
OPStackHook__factory,
OPStackIsm__factory,
} from '@hyperlane-xyz/core';
import { MerkleTreeHook__factory } from '@hyperlane-xyz/core';
export type HookFactories = {
hook: AbstractMessageIdAuthHook__factory;
ism: AbstractMessageIdAuthorizedIsm__factory;
export const merkleTreeHookFactory = {
merkleTreeHook: new MerkleTreeHook__factory(),
};
export const hookFactories = merkleTreeHookFactory;
export type MerkleTreeHookFactory = typeof merkleTreeHookFactory;
export const optimismHookFactories = {
hook: new OPStackHook__factory(),
ism: new OPStackIsm__factory(),
};
export type OptimismHookFactories = typeof optimismHookFactories;
export type HookFactories = MerkleTreeHookFactory;

@ -1,22 +1,9 @@
import type { Address } from '@hyperlane-xyz/utils';
import { ChainName } from '../types';
export enum HookContractType {
HOOK = 'hook',
ISM = 'ism',
export enum HookType {
MERKLE_TREE_HOOK = 'merkleTreeHook',
}
export type MessageHookConfig = {
hookContractType: HookContractType.HOOK;
nativeBridge: Address;
remoteIsm?: Address;
destination: ChainName;
};
export type NoMetadataIsmConfig = {
hookContractType: HookContractType.ISM;
nativeBridge: Address;
export type MerkleTreeHookConfig = {
type: HookType.MERKLE_TREE_HOOK;
};
export type HookConfig = MessageHookConfig | NoMetadataIsmConfig;
export type HookConfig = MerkleTreeHookConfig;

@ -109,12 +109,7 @@ export {
OverheadIgpConfig,
} from './gas/types';
export { HyperlaneHookDeployer } from './hook/HyperlaneHookDeployer';
export {
HookConfig,
HookContractType,
MessageHookConfig,
NoMetadataIsmConfig,
} from './hook/types';
export { HookConfig, HookType, MerkleTreeHookConfig } from './hook/types';
export {
HyperlaneIsmFactory,
collectValidators,

@ -195,10 +195,10 @@ export class HyperlaneIsmFactory extends HyperlaneApp<IsmFactoryFactories> {
threshold: number,
): Promise<Address> {
const sorted = [...values].sort();
const address = await factory.getAddress(sorted, threshold);
const provider = this.multiProvider.getProvider(chain);
const code = await provider.getCode(address);
if (code === '0x') {
this.logger(
`Deploying new ${threshold} of ${values.length} address set to ${chain}`,

@ -3,6 +3,8 @@ import {
IInterchainSecurityModule,
IMultisigIsm,
IRoutingIsm,
StaticMerkleRootMultisigIsm,
StaticMessageIdMultisigIsm,
} from '@hyperlane-xyz/core';
import type { Address } from '@hyperlane-xyz/utils';
@ -12,14 +14,15 @@ export type DeployedIsm =
| IInterchainSecurityModule
| IMultisigIsm
| IAggregationIsm
| IRoutingIsm;
| IRoutingIsm
| StaticMessageIdMultisigIsm
| StaticMerkleRootMultisigIsm;
export enum ModuleType {
UNUSED,
ROUTING,
AGGREGATION,
// DEPRECATED
LEGACY_MULTISIG,
LEGACY_MULTISIG, // DEPRECATED
MERKLE_ROOT_MULTISIG,
MESSAGE_ID_MULTISIG,
}

Loading…
Cancel
Save