@ -1,9 +1,16 @@
import { confirm } from '@inquirer/prompts' ;
import { stringify as yamlStringify } from 'yaml' ;
import { IRegistry } from '@hyperlane-xyz/registry' ;
import {
EvmIsmModule ,
HypERC20Deployer ,
HypERC721Deployer ,
HyperlaneAddresses ,
HyperlaneContractsMap ,
HyperlaneDeployer ,
HyperlaneProxyFactoryDeployer ,
MultiProvider ,
TOKEN_TYPE_TO_STANDARD ,
TokenFactories ,
TokenType ,
@ -11,14 +18,19 @@ import {
WarpRouteDeployConfig ,
getTokenConnectionId ,
isTokenMetadata ,
serializeContracts ,
} from '@hyperlane-xyz/sdk' ;
import { ProtocolType } from '@hyperlane-xyz/utils' ;
import { ProtocolType , objMap , promiseObjAll } from '@hyperlane-xyz/utils' ;
import { readWarpRouteDeployConfig } from '../config/warp.js' ;
import { MINIMUM_WARP_DEPLOY_GAS } from '../consts.js' ;
import { WriteCommandContext } from '../context/types.js' ;
import { log , logBlue , logGray , logGreen , logTable } from '../logger.js' ;
import { isFile , runFileSelectionStep } from '../utils/files.js' ;
import {
indentYamlOrJson ,
isFile ,
runFileSelectionStep ,
} from '../utils/files.js' ;
import {
completeDeploy ,
@ -119,7 +131,18 @@ async function executeDeploy(params: DeployParams) {
? { [ dryRunChain ] : configMap [ dryRunChain ] }
: configMap ;
const deployedContracts = await deployer . deploy ( config ) ;
const ismFactoryDeployer = new HyperlaneProxyFactoryDeployer ( multiProvider ) ;
// For each chain in WarpRouteConfig, deploy each Ism Factory, if it's not in the registry
// Then return a modified config with the ism address as a string
const modifiedConfig = await deployAndResolveWarpIsm (
config ,
multiProvider ,
registry ,
ismFactoryDeployer ,
) ;
const deployedContracts = await deployer . deploy ( modifiedConfig ) ;
logGreen ( '✅ Hyp token deployments complete' ) ;
@ -128,10 +151,110 @@ async function executeDeploy(params: DeployParams) {
log ( 'Writing deployment artifacts' ) ;
await registry . addWarpRoute ( warpCoreConfig ) ;
}
log ( JSON . s tringify( warpCoreConfig , null , 2 ) ) ;
log ( indentYamlOrJson ( yamlS tringify( warpCoreConfig , null , 2 ) , 4 ) ) ;
logBlue ( 'Deployment is complete!' ) ;
}
async function deployAndResolveWarpIsm (
warpConfig : WarpRouteDeployConfig ,
multiProvider : MultiProvider ,
registry : IRegistry ,
ismFactoryDeployer : HyperlaneProxyFactoryDeployer ,
) : Promise < WarpRouteDeployConfig > {
return promiseObjAll (
objMap ( warpConfig , async ( chain , config ) = > {
// Skip deployment if Ism is empty, or a string
if (
! config . interchainSecurityModule ||
typeof config . interchainSecurityModule === 'string'
) {
logGray (
` Config Ism is ${
! config . interchainSecurityModule
? 'empty'
: config . interchainSecurityModule
} , skipping deployment ` ,
) ;
return config ;
}
logBlue ( 'Loading Registry factory addresses' ) ;
let chainAddresses = await registry . getChainAddresses ( chain ) ; // Can includes other addresses
if ( ! chainAddresses ) {
logGray ( 'Registry factory addresses not found, deploying' ) ;
chainAddresses = serializeContracts (
await ismFactoryDeployer . deployContracts ( chain ) ,
) as Record < string , string > ;
}
logGray (
` Creating ${ config . interchainSecurityModule . type } Ism for ${ config . type } token on ${ chain } chain ` ,
) ;
const deployedIsm = await createWarpIsm (
chain ,
warpConfig ,
multiProvider ,
ismFactoryDeployer ,
{
domainRoutingIsmFactory : chainAddresses.domainRoutingIsmFactory ,
staticAggregationHookFactory :
chainAddresses . staticAggregationHookFactory ,
staticAggregationIsmFactory :
chainAddresses . staticAggregationIsmFactory ,
staticMerkleRootMultisigIsmFactory :
chainAddresses . staticMerkleRootMultisigIsmFactory ,
staticMessageIdMultisigIsmFactory :
chainAddresses . staticMessageIdMultisigIsmFactory ,
} ,
) ;
logGreen (
` Finished creating ${ config . interchainSecurityModule . type } Ism for ${ config . type } token on ${ chain } chain ` ,
) ;
return { . . . warpConfig [ chain ] , interchainSecurityModule : deployedIsm } ;
} ) ,
) ;
}
/ * *
* Deploys the Warp ISM for a given config
*
* @returns The deployed ism address
* /
async function createWarpIsm (
chain : string ,
warpConfig : WarpRouteDeployConfig ,
multiProvider : MultiProvider ,
ismFactoryDeployer : HyperlaneDeployer < any , any > ,
factoryAddresses : HyperlaneAddresses < any > ,
) : Promise < string > {
const {
domainRoutingIsmFactory ,
staticAggregationHookFactory ,
staticAggregationIsmFactory ,
staticMerkleRootMultisigIsmFactory ,
staticMessageIdMultisigIsmFactory ,
} = factoryAddresses ;
const evmIsmModule = await EvmIsmModule . create ( {
chain ,
multiProvider ,
deployer : ismFactoryDeployer ,
mailbox : warpConfig [ chain ] . mailbox ,
factories : {
domainRoutingIsmFactory ,
staticAggregationHookFactory ,
staticAggregationIsmFactory ,
staticMerkleRootMultisigIsmFactory ,
staticMessageIdMultisigIsmFactory ,
} ,
config : warpConfig [ chain ] . interchainSecurityModule ! ,
} ) ;
const { deployedIsm } = evmIsmModule . serialize ( ) ;
return deployedIsm ;
}
async function getWarpCoreConfig (
{ configMap , context } : DeployParams ,
contracts : HyperlaneContractsMap < TokenFactories > ,