improve formatting + support checking legacy Icas

trevor/dao-ism
pbio 20 hours ago
parent 110de0525a
commit 0410b4e4b1
  1. 96
      typescript/infra/scripts/ica/check-owner-ica.ts
  2. 52
      typescript/infra/scripts/ica/get-owner-ica.ts
  3. 184
      typescript/infra/src/config/icas.ts

@ -1,7 +1,19 @@
import chalk from 'chalk';
import { ethers } from 'ethers';
import { AccountConfig, InterchainAccount } from '@hyperlane-xyz/sdk'; import { AccountConfig, InterchainAccount } from '@hyperlane-xyz/sdk';
import { eqAddress, isZeroishAddress } from '@hyperlane-xyz/utils'; import {
LogFormat,
LogLevel,
assert,
configureRootLogger,
eqAddress,
isZeroishAddress,
rootLogger,
} from '@hyperlane-xyz/utils';
import awIcas from '../../config/environments/mainnet3/aw-icas.json'; import awIcas from '../../config/environments/mainnet3/aw-icas.json';
import { oldIcas } from '../../config/environments/mainnet3/owners.js';
import { chainsToSkip } from '../../src/config/chain.js'; import { chainsToSkip } from '../../src/config/chain.js';
import { IcaArtifact } from '../../src/config/icas.js'; import { IcaArtifact } from '../../src/config/icas.js';
import { isEthereumProtocolChain } from '../../src/utils/utils.js'; import { isEthereumProtocolChain } from '../../src/utils/utils.js';
@ -9,61 +21,82 @@ import { getArgs as getEnvArgs, withChains } from '../agent-utils.js';
import { getEnvironmentConfig, getHyperlaneCore } from '../core-utils.js'; import { getEnvironmentConfig, getHyperlaneCore } from '../core-utils.js';
function getArgs() { function getArgs() {
return withChains(getEnvArgs()).option('ownerChain', { return withChains(getEnvArgs())
type: 'string', .option('ownerChain', {
description: 'Origin chain where the Safe owner lives', type: 'string',
default: 'ethereum', description: 'Origin chain where the Safe owner lives',
}).argv; default: 'ethereum',
})
.describe('legacy', 'If enabled, checks legacy ICAs')
.boolean('legacy')
.default('legacy', false).argv;
} }
async function main() { async function main() {
const { environment, ownerChain, chains } = await getArgs(); const { environment, ownerChain, chains, legacy } = await getArgs();
configureRootLogger(LogFormat.Pretty, LogLevel.Info);
assert(environment === 'mainnet3', 'Only mainnet3 is supported');
const config = getEnvironmentConfig(environment); const config = getEnvironmentConfig(environment);
const multiProvider = await config.getMultiProvider(); const multiProvider = await config.getMultiProvider();
const owner = config.owners[ownerChain].ownerOverrides?._safeAddress; const ownerAddress = config.owners[ownerChain].ownerOverrides?._safeAddress;
if (!owner) { if (!ownerAddress) {
console.error(`No Safe owner found for ${ownerChain}`); rootLogger.error(chalk.bold.red(`No Safe owner found for ${ownerChain}`));
process.exit(1); process.exit(1);
} }
console.log(`Safe owner on ${ownerChain}: ${owner}`); rootLogger.info(`Safe owner on ${ownerChain}: ${ownerAddress}`);
const { chainAddresses } = await getHyperlaneCore(environment, multiProvider); const { chainAddresses } = await getHyperlaneCore(environment, multiProvider);
const ica = InterchainAccount.fromAddressesMap(chainAddresses, multiProvider); const ica = InterchainAccount.fromAddressesMap(chainAddresses, multiProvider);
const checkOwnerIcaChains = ( const checkOwnerIcaChains = (
chains?.length ? chains : Object.keys(awIcas) chains?.length ? chains : Object.keys(legacy ? oldIcas : awIcas)
).filter( ).filter(
(chain) => isEthereumProtocolChain(chain) && !chainsToSkip.includes(chain), (chain) => isEthereumProtocolChain(chain) && !chainsToSkip.includes(chain),
); );
const ownerConfig: AccountConfig = { // Check that the interchain account router address is not zero
origin: ownerChain,
owner: owner,
};
const ownerChainInterchainAccountRouter = const ownerChainInterchainAccountRouter =
ica.contractsMap[ownerChain].interchainAccountRouter.address; ica.contractsMap[ownerChain].interchainAccountRouter.address;
if (isZeroishAddress(ownerChainInterchainAccountRouter)) { if (isZeroishAddress(ownerChainInterchainAccountRouter)) {
console.error(`Interchain account router address is zero`); rootLogger.error(
chalk.bold.red(`Interchain account router address is zero`),
);
process.exit(1); process.exit(1);
} }
// Create the owner config
const ownerConfig: AccountConfig = {
origin: ownerChain,
owner: ownerAddress,
routerOverride: ownerChainInterchainAccountRouter,
};
const expectedIcas: Record<string, IcaArtifact> = {};
const mismatchedResults: Record< const mismatchedResults: Record<
string, string,
{ Expected: IcaArtifact; Actual: IcaArtifact } { Expected: IcaArtifact; Actual: IcaArtifact }
> = {}; > = {};
for (const chain of checkOwnerIcaChains) { for (const chain of checkOwnerIcaChains) {
const expected = awIcas[chain as keyof typeof awIcas]; const expected = getExpectedIca(chain, legacy);
expectedIcas[chain] = expected;
if (!expected) { if (!expected) {
console.error(`No expected address found for ${chain}`); rootLogger.warn(chalk.yellow(`No expected address found for ${chain}`));
continue; continue;
} }
if (isZeroishAddress(expected.ica)) {
rootLogger.warn(chalk.yellow(`ICA address is zero for ${chain}`));
continue;
}
const actualAccount = await ica.getAccount(chain, { const actualAccount = await ica.getAccount(chain, {
...ownerConfig, ...ownerConfig,
ismOverride: expected.ism, ismOverride: expected.ism,
routerOverride: ownerChainInterchainAccountRouter,
}); });
if (!eqAddress(expected.ica, actualAccount)) { if (!eqAddress(expected.ica, actualAccount)) {
mismatchedResults[chain] = { mismatchedResults[chain] = {
@ -77,16 +110,31 @@ async function main() {
} }
if (Object.keys(mismatchedResults).length > 0) { if (Object.keys(mismatchedResults).length > 0) {
console.error('\nMismatched ICAs found:'); rootLogger.error(chalk.bold.red('\nMismatched ICAs found:'));
console.table(mismatchedResults); console.table(mismatchedResults);
process.exit(1); process.exit(1);
} else { } else {
console.log('✅ All ICAs match the expected addresses.'); rootLogger.info(
chalk.bold.green('✅ All ICAs match the expected addresses.'),
);
console.table(expectedIcas);
} }
process.exit(0); process.exit(0);
} }
// Enables support for checking legacy ICAs
function getExpectedIca(chain: string, legacy: boolean): IcaArtifact {
return legacy
? {
ica:
oldIcas[chain as keyof typeof oldIcas] ||
ethers.constants.AddressZero,
ism: ethers.constants.AddressZero,
}
: awIcas[chain as keyof typeof awIcas];
}
main().catch((err) => { main().catch((err) => {
console.error('Error:', err); rootLogger.error('Error:', err);
process.exit(1); process.exit(1);
}); });

@ -1,9 +1,15 @@
import chalk from 'chalk';
import { AccountConfig, ChainMap, InterchainAccount } from '@hyperlane-xyz/sdk'; import { AccountConfig, ChainMap, InterchainAccount } from '@hyperlane-xyz/sdk';
import { import {
LogFormat,
LogLevel,
assert, assert,
configureRootLogger,
eqAddress, eqAddress,
isZeroishAddress, isZeroishAddress,
objFilter, objFilter,
rootLogger,
} from '@hyperlane-xyz/utils'; } from '@hyperlane-xyz/utils';
import { getIcaIsm } from '../../config/environments/mainnet3/ica.js'; import { getIcaIsm } from '../../config/environments/mainnet3/ica.js';
@ -52,6 +58,7 @@ async function main() {
deploy, deploy,
owner: ownerOverride, owner: ownerOverride,
} = await getArgs(); } = await getArgs();
configureRootLogger(LogFormat.Pretty, LogLevel.Info);
assert(environment === 'mainnet3', 'Only mainnet3 is supported'); assert(environment === 'mainnet3', 'Only mainnet3 is supported');
@ -63,7 +70,10 @@ async function main() {
try { try {
artifacts = await readAbacusWorksIcas(environment); artifacts = await readAbacusWorksIcas(environment);
} catch (err) { } catch (err) {
console.error('Error reading artifacts, defaulting to no artifacts:', err); rootLogger.error(
chalk.bold.red('Error reading artifacts, defaulting to no artifacts:'),
err,
);
artifacts = {}; artifacts = {};
} }
@ -82,7 +92,7 @@ async function main() {
} }
// Log the owner address // Log the owner address
console.log(`Governance owner on ${ownerChain}: ${originOwner}`); rootLogger.info(`Governance owner on ${ownerChain}: ${originOwner}`);
// Get the chain addresses // Get the chain addresses
const { chainAddresses } = await getHyperlaneCore(environment, multiProvider); const { chainAddresses } = await getHyperlaneCore(environment, multiProvider);
@ -102,7 +112,9 @@ async function main() {
const ownerChainInterchainAccountRouter = const ownerChainInterchainAccountRouter =
ica.contractsMap[ownerChain].interchainAccountRouter.address; ica.contractsMap[ownerChain].interchainAccountRouter.address;
if (isZeroishAddress(ownerChainInterchainAccountRouter)) { if (isZeroishAddress(ownerChainInterchainAccountRouter)) {
console.error(`Interchain account router address is zero`); rootLogger.error(
chalk.bold.red(`Interchain account router address is zero`),
);
process.exit(1); process.exit(1);
} }
@ -119,8 +131,10 @@ async function main() {
chains = chainsArg; chains = chainsArg;
} else { } else {
chains = ica.chains().filter((chain) => chain !== ownerChain); chains = ica.chains().filter((chain) => chain !== ownerChain);
console.log( rootLogger.debug(
'Chains not supplied, using all ICA supported chains other than the owner chain:', chalk.italic.gray(
'Chains not supplied, using all ICA supported chains other than the owner chain:',
),
chains, chains,
); );
} }
@ -137,15 +151,16 @@ async function main() {
// Verify or deploy each chain's ICA // Verify or deploy each chain's ICA
const settledResults = await Promise.allSettled( const settledResults = await Promise.allSettled(
chains.map(async (chain) => { chains.map(async (chain) => {
return abacusWorksIca.verifyOrDeployChainIca(chain, { return abacusWorksIca.recoverOrDeployChainIca(
chainArtifact: artifacts[chain], chain,
deploy,
ownerConfig, ownerConfig,
}); artifacts[chain],
deploy,
);
}), }),
); );
// User-friendly output for the console.table // User-friendly output for the rootLogger.table
const results: Record<string, Omit<IcaDeployResult, 'chain'>> = {}; const results: Record<string, Omit<IcaDeployResult, 'chain'>> = {};
// Map of chain to ICA artifact // Map of chain to ICA artifact
const icaArtifacts: ChainMap<IcaArtifact> = {}; const icaArtifacts: ChainMap<IcaArtifact> = {};
@ -153,7 +168,7 @@ async function main() {
if (settledResult.status === 'fulfilled') { if (settledResult.status === 'fulfilled') {
const { chain, result, error, deployed, recovered } = settledResult.value; const { chain, result, error, deployed, recovered } = settledResult.value;
if (error || !result) { if (error || !result) {
console.error(`Failed to process ${chain}:`, error); rootLogger.error(chalk.red(`Failed to process ${chain}:`), error);
} else { } else {
results[chain] = { results[chain] = {
deployed, deployed,
@ -163,23 +178,26 @@ async function main() {
icaArtifacts[chain] = result; icaArtifacts[chain] = result;
} }
} else { } else {
console.error(`Promise rejected:`, settledResult.reason); rootLogger.error(chalk.red(`Promise rejected:`), settledResult.reason);
} }
}); });
console.table(results); console.table(results);
console.log( rootLogger.info(
`Writing results to local artifacts: ${getAbacusWorksIcasPath( chalk.italic.gray(
environment, `Writing results to local artifacts: ${getAbacusWorksIcasPath(
)}`, environment,
)}`,
),
); );
persistAbacusWorksIcas(environment, icaArtifacts); persistAbacusWorksIcas(environment, icaArtifacts);
process.exit(0);
} }
main() main()
.then() .then()
.catch((err) => { .catch((err) => {
console.error('Error:', err); rootLogger.error(chalk.bold.red('Error:'), err);
process.exit(1); process.exit(1);
}); });

@ -1,3 +1,4 @@
import chalk from 'chalk';
import { ethers } from 'ethers'; import { ethers } from 'ethers';
import { import {
@ -11,7 +12,13 @@ import {
MultiProvider, MultiProvider,
normalizeConfig, normalizeConfig,
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
import { Address, deepEquals, eqAddress } from '@hyperlane-xyz/utils'; import {
Address,
deepEquals,
eqAddress,
rootLogger,
stringifyObject,
} from '@hyperlane-xyz/utils';
import { getAbacusWorksIcasPath } from '../../scripts/agent-utils.js'; import { getAbacusWorksIcasPath } from '../../scripts/agent-utils.js';
import { readJSONAtPath, writeMergedJSONAtPath } from '../utils/utils.js'; import { readJSONAtPath, writeMergedJSONAtPath } from '../utils/utils.js';
@ -24,7 +31,7 @@ export interface IcaArtifact {
} }
export interface IcaDeployResult { export interface IcaDeployResult {
chain: string; chain: ChainName;
result?: IcaArtifact; result?: IcaArtifact;
error?: string; error?: string;
deployed?: string; deployed?: string;
@ -45,7 +52,35 @@ export function readAbacusWorksIcas(
return readJSONAtPath(getAbacusWorksIcasPath(environment)); return readJSONAtPath(getAbacusWorksIcasPath(environment));
} }
/**
* Manages the Interchain Accounts (ICAs) for Abacus Works
*
* Public methods:
* - getIcaAccount(ownerConfig: AccountConfig, icaChain: ChainName, ismAddress: Address): Promise<string>
* Gets the ICA address using the owner config and ISM address.
*
* - recoverOrDeployChainIca(chain: ChainName, ownerConfig: AccountConfig, chainArtifact?: IcaArtifact, deploy: boolean): Promise<IcaDeployResult>
* Recovers or deploys the ICA for a given chain. If deploy is true and the existing ICA does not match expected config, deploys a new one.
* Returns result containing ICA address, ISM address, and deployment status.
*
* - artifactMatchesExpectedConfig(ownerConfig: AccountConfig, icaChain: ChainName, icaArtifact: IcaArtifact): Promise<boolean>
* Verifies that an ICA artifact matches the expected configuration by checking ISM config and ICA address recovery
*
* - deployNewIca(chain: ChainName, ownerConfig: AccountConfig): Promise<IcaDeployResult>
* Deploys a new ICA with proper ownership setup:
* 1. Deploys ISM with deployer as initial owner.
* 2. Deploys ICA using the ISM.
* 3. Transfers ISM ownership to the ICA.
* 4. Verifies deployment matches expected config.
*
* - getExpectedIsmConfig(chain: ChainName, ownerConfig: AccountConfig, icaAddress: Address): Promise<IsmConfig>
* Gets the expected ISM configuration for a chain and owner.
*/
export class AbacusWorksIcaManager { export class AbacusWorksIcaManager {
private readonly logger = rootLogger.child({
module: 'AbacusWorksIcaManager',
});
constructor( constructor(
private readonly multiProvider: MultiProvider, private readonly multiProvider: MultiProvider,
private readonly ica: InterchainAccount, private readonly ica: InterchainAccount,
@ -60,6 +95,11 @@ export class AbacusWorksIcaManager {
/** /**
* Gets the ICA address using the owner config and ISM address * Gets the ICA address using the owner config and ISM address
*
* @param ownerConfig - The owner config for the ICA
* @param icaChain - The chain where the ICA exists
* @param ismAddress - The address of the ISM
* @returns The ICA address
*/ */
public async getIcaAccount( public async getIcaAccount(
ownerConfig: AccountConfig, ownerConfig: AccountConfig,
@ -77,33 +117,33 @@ export class AbacusWorksIcaManager {
} }
/** /**
* Verifies or deploys the ICA for a given chain. * Recovers or deploys the ICA for a given chain.
* @param chain - The chain to process. * @param chain - The chain to process.
* @param options - The options for verifying or deploying the ICA. * @param ownerConfig - The owner config for the ICA.
* @returns The result of verifying or deploying the ICA. * @param chainArtifact - The existing ICA artifact for the chain, if it exists.
* @param deploy - Whether to deploy a new ICA if the existing one does not match the expected config.
* @returns The result of recovering or deploying the ICA.
*/ */
public async verifyOrDeployChainIca( public async recoverOrDeployChainIca(
chain: string, chain: ChainName,
{ ownerConfig: AccountConfig,
ownerConfig, chainArtifact: IcaArtifact | undefined,
chainArtifact, deploy: boolean,
deploy,
}: {
ownerConfig: AccountConfig;
chainArtifact?: IcaArtifact;
deploy: boolean;
},
): Promise<IcaDeployResult> { ): Promise<IcaDeployResult> {
// Try to recover existing ICA // Try to recover existing ICA
// If the chain artifact is undefined, we assume the ICA is not deployed
// If the ISM address is zero, we assume the ICA is not deployed
if ( if (
chainArtifact && chainArtifact &&
!eqAddress(chainArtifact.ism, ethers.constants.AddressZero) !eqAddress(chainArtifact.ism, ethers.constants.AddressZero)
) { ) {
console.log( this.logger.debug(
'Attempting ICA recovery on chain', chalk.italic.gray(
chain, 'Attempting ICA recovery on chain',
'with existing artifact', chain,
chainArtifact, 'with existing artifact',
chainArtifact,
),
); );
const matches = await this.artifactMatchesExpectedConfig( const matches = await this.artifactMatchesExpectedConfig(
@ -113,7 +153,7 @@ export class AbacusWorksIcaManager {
); );
if (matches) { if (matches) {
console.log('Recovered ICA on chain', chain); this.logger.info(chalk.bold.green(`Recovered ICA on chain ${chain}`));
return { return {
chain, chain,
result: chainArtifact, result: chainArtifact,
@ -122,17 +162,17 @@ export class AbacusWorksIcaManager {
}; };
} }
console.warn( this.logger.warn(
`Chain ${chain} ICA artifact does not match expected config, will redeploy`, `Chain ${chain} ICA artifact does not match expected config, will redeploy`,
); );
} }
// Handle case where deployment is not allowed // If we're not deploying, we can't have an ICA
if (!deploy) { if (!deploy) {
console.log( this.logger.debug(
'Skipping required ISM deployment for chain', chalk.italic.gray(
chain, `Skipping required ISM deployment for chain ${chain}, will not have an ICA`,
', will not have an ICA', ),
); );
return { return {
chain, chain,
@ -154,8 +194,7 @@ export class AbacusWorksIcaManager {
* 1. Checking that the ISM configuration matches what we expect * 1. Checking that the ISM configuration matches what we expect
* 2. Verifying we can recover the correct ICA address * 2. Verifying we can recover the correct ICA address
* *
* @param originChain - The chain where the owner account exists * @param ownerConfig - The owner config for the ICA
* @param originOwner - The address of the owner account
* @param icaChain - The chain where the ICA exists * @param icaChain - The chain where the ICA exists
* @param icaArtifact - The artifact containing ICA and ISM addresses * @param icaArtifact - The artifact containing ICA and ISM addresses
* @returns True if the artifact matches expected config, false otherwise * @returns True if the artifact matches expected config, false otherwise
@ -215,13 +254,15 @@ export class AbacusWorksIcaManager {
); );
if (!matches) { if (!matches) {
console.log( this.logger.error(
`Somehow after everything, the ICA artifact on chain ${chain} still does not match the expected config! There's probably a bug.`, chalk.bold.red(
`Somehow after everything, the ICA artifact on chain ${chain} still does not match the expected config! There's probably a bug.`,
),
); );
return { chain, result: undefined, deployed: '❌', recovered: '❌' }; return { chain, result: undefined, deployed: '❌', recovered: '❌' };
} }
return { chain, result: newChainArtifact, deployed: '✅', recovered: '' }; return { chain, result: newChainArtifact, deployed: '✅', recovered: '-' };
} }
/** /**
@ -255,16 +296,25 @@ export class AbacusWorksIcaManager {
// Read the actual config from the deployed ISM // Read the actual config from the deployed ISM
const actualIsmConfig = await ismModule.read(); const actualIsmConfig = await ismModule.read();
const normalizedActualIsmConfig = normalizeConfig(actualIsmConfig);
const normalizedDesiredIsmConfig = normalizeConfig(desiredIsmConfig);
// Compare normalized configs to handle any formatting differences // Compare normalized configs to handle any formatting differences
const configsMatch = deepEquals( const configsMatch = deepEquals(
normalizeConfig(actualIsmConfig), normalizedActualIsmConfig,
normalizeConfig(desiredIsmConfig), normalizedDesiredIsmConfig,
); );
if (!configsMatch) { if (!configsMatch) {
console.log('ISM mismatch for', icaChain); this.logger.error(chalk.bold.red(`ISM mismatch for ${icaChain}`));
console.log('actualIsmConfig:', JSON.stringify(actualIsmConfig)); this.logger.error(
console.log('desiredIsmConfig:', JSON.stringify(desiredIsmConfig)); chalk.red('Actual ISM config:\n'),
stringifyObject(normalizedActualIsmConfig),
);
this.logger.error(
chalk.red('Desired ISM config:\n'),
stringifyObject(normalizedDesiredIsmConfig),
);
} }
return configsMatch; return configsMatch;
@ -273,8 +323,7 @@ export class AbacusWorksIcaManager {
/** /**
* Verifies that we can recover the correct ICA address using the owner config * Verifies that we can recover the correct ICA address using the owner config
* *
* @param originChain - The chain where the owner account exists * @param ownerConfig - The owner config for the ICA
* @param originOwner - The address of the owner account
* @param icaChain - The chain where the ICA exists * @param icaChain - The chain where the ICA exists
* @param icaArtifact - The artifact containing the ICA address * @param icaArtifact - The artifact containing the ICA address
* @returns True if recovered address matches artifact, false otherwise * @returns True if recovered address matches artifact, false otherwise
@ -294,14 +343,16 @@ export class AbacusWorksIcaManager {
// Check if recovered address matches the artifact // Check if recovered address matches the artifact
const accountMatches = eqAddress(account, icaArtifact.ica); const accountMatches = eqAddress(account, icaArtifact.ica);
if (!accountMatches) { if (!accountMatches) {
console.error( this.logger.error(
` Failed to recover ICA for ${icaChain}. Expected: ${ chalk.bold.red(
icaArtifact.ica ` Failed to recover ICA for ${icaChain}. Expected: ${
}, got: ${account}. Chain owner config: ${JSON.stringify({ icaArtifact.ica
origin: ownerConfig.origin, }, got: ${account}. Chain owner config: ${JSON.stringify({
owner: ownerConfig.owner, origin: ownerConfig.origin,
ismOverride: icaArtifact.ism, owner: ownerConfig.owner,
})} `, ismOverride: icaArtifact.ism,
})} `,
),
); );
} }
@ -314,7 +365,10 @@ export class AbacusWorksIcaManager {
* @param chain - The destination chain for the ICA deployment * @param chain - The destination chain for the ICA deployment
* @returns ISM module and address * @returns ISM module and address
*/ */
private async deployInitialIsm(chain: ChainName) { private async deployInitialIsm(chain: ChainName): Promise<{
ismModule: EvmIsmModule;
ismAddress: Address;
}> {
// Initially configure ISM with deployer as owner since ICA address is unknown // Initially configure ISM with deployer as owner since ICA address is unknown
const deployerOwnedIsm = this.getIcaIsm( const deployerOwnedIsm = this.getIcaIsm(
chain, chain,
@ -322,7 +376,9 @@ export class AbacusWorksIcaManager {
this.deployer, this.deployer,
); );
console.log('Deploying ISM for ICA on chain', chain); this.logger.info(
chalk.italic.blue(`Deploying ISM for ICA on chain ${chain}`),
);
// Create and deploy the ISM module // Create and deploy the ISM module
const ismModule = await EvmIsmModule.create({ const ismModule = await EvmIsmModule.create({
chain, chain,
@ -350,23 +406,25 @@ export class AbacusWorksIcaManager {
chain: ChainName, chain: ChainName,
ownerConfig: AccountConfig, ownerConfig: AccountConfig,
ismAddress: Address, ismAddress: Address,
) { ): Promise<Address> {
// Configure ICA with deployed ISM address // Configure ICA with deployed ISM address
const chainOwnerConfig = { const icaOwnerConfig = {
...ownerConfig, ...ownerConfig,
ismOverride: ismAddress, ismOverride: ismAddress,
}; };
console.log( this.logger.info(
'Deploying ICA on chain', chalk.italic.blue(
chain, `Deploying ICA on chain ${chain} with owner config`,
'with owner config', stringifyObject(icaOwnerConfig),
chainOwnerConfig, ),
); );
// Deploy the ICA // Deploy the ICA
const deployedIca = await this.ica.deployAccount(chain, chainOwnerConfig); const deployedIca = await this.ica.deployAccount(chain, icaOwnerConfig);
console.log(`Deployed ICA on chain: ${chain}: ${deployedIca}`); this.logger.info(
chalk.bold.green(`Deployed ICA on chain ${chain}: ${deployedIca}`),
);
return deployedIca; return deployedIca;
} }
@ -391,9 +449,11 @@ export class AbacusWorksIcaManager {
chain, chain,
}); });
const updateTxs = await ismModule.update(icaOwnedIsmConfig); const updateTxs = await ismModule.update(icaOwnedIsmConfig);
console.log( this.logger.info(
`Updating routing ISM owner on ${chain} with transactions:`, chalk.italic.blue(`Updating routing ISM owner on ${chain}`),
updateTxs, );
this.logger.debug(
chalk.italic.gray(`Update transactions:`, stringifyObject(updateTxs)),
); );
await submitter.submit(...updateTxs); await submitter.submit(...updateTxs);
} }

Loading…
Cancel
Save