diff --git a/typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts b/typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts index be82786cfb..0d31f31b54 100644 --- a/typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts +++ b/typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts @@ -1,5 +1,6 @@ import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers.js'; import { expect } from 'chai'; +import { ethers } from 'ethers'; import hre from 'hardhat'; import { objMap } from '@hyperlane-xyz/utils'; @@ -26,28 +27,58 @@ describe.only('EvmCoreModule', async () => { }); }); describe('Create', async () => { - it('should create deploy an ICA', async () => { + it('should create deploy an ICA', () => { const { interchainAccountRouter, interchainAccountIsm } = evmCoreModule.serialize(); - expect(interchainAccountIsm).to.not.be.undefined; - expect(interchainAccountRouter).to.not.be.undefined; + expect(interchainAccountIsm).to.exist; + expect(interchainAccountRouter).to.exist; }); - it('should return the correct addresses', async () => { + it('should deploy ISM factories', () => { // Each ISM factory - objMap(evmCoreModule.serialize().ismFactories, (_, contract) => { - expect(contract.address).to.be.not.undefined; - }); + objMap( + evmCoreModule.serialize().ismFactoryFactories, + (_: any, contract: any) => { + expect(contract.address).to.exist; + }, + ); + }); + + it('should deploy proxyAdmin', () => { + expect(evmCoreModule.serialize().proxyAdmin.address).to.exist; + }); - // proxyAdmin - expect(evmCoreModule.serialize().proxyAdmin.address).to.be.not.undefined; + it('should deploy mailbox', () => { + expect(evmCoreModule.serialize().mailbox.address).to.exist; + }); + + it('should deploy mailbox default Ism', async () => { + const mailbox = evmCoreModule.serialize().mailbox; + expect(await mailbox.defaultIsm()).to.not.equal( + ethers.constants.AddressZero, + ); + }); - // mailbox - expect(evmCoreModule.serialize().mailbox.address).to.be.not.undefined; + it('should deploy mailbox default hook', async () => { + const mailbox = evmCoreModule.serialize().mailbox; + expect(await mailbox.defaultHook()).to.not.equal( + ethers.constants.AddressZero, + ); + }); + + it('should deploy mailbox required hook', async () => { + const mailbox = evmCoreModule.serialize().mailbox; + expect(await mailbox.requiredHook()).to.not.equal( + ethers.constants.AddressZero, + ); + }); + + it('should deploy validatorAnnounce', () => { + expect(evmCoreModule.serialize().validatorAnnounce.address).to.exist; + }); - // validatorAnnounce - expect(evmCoreModule.serialize().validatorAnnounce.address).to.be.not - .undefined; + it('should deploy testRecipient', () => { + expect(evmCoreModule.serialize().testRecipient.address).to.exist; }); }); }); diff --git a/typescript/sdk/src/core/EvmCoreModule.ts b/typescript/sdk/src/core/EvmCoreModule.ts index 03c759aa07..dfba98755c 100644 --- a/typescript/sdk/src/core/EvmCoreModule.ts +++ b/typescript/sdk/src/core/EvmCoreModule.ts @@ -1,10 +1,12 @@ -import { ProtocolType, rootLogger } from '@hyperlane-xyz/utils'; +import { Mailbox, TestRecipient } from '@hyperlane-xyz/core'; +import { Address, ProtocolType, rootLogger } from '@hyperlane-xyz/utils'; import { HyperlaneContracts } from '../contracts/types.js'; import { CoreFactories } from '../core/contracts.js'; import { CoreConfig } from '../core/types.js'; import { HyperlaneProxyFactoryDeployer } from '../deploy/HyperlaneProxyFactoryDeployer.js'; import { ProxyFactoryFactories } from '../deploy/contracts.js'; +import { EvmIsmModule } from '../ism/EvmIsmModule.js'; import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory.js'; import { InterchainAccountFactories } from '../middleware/account/contracts.js'; import { MultiProvider } from '../providers/MultiProvider.js'; @@ -23,7 +25,8 @@ type DerivedInterchainAccountFactories = HyperlaneContracts< >; type ExtraArgs = { - ismFactories: HyperlaneContracts; + testRecipient: TestRecipient; + ismFactoryFactories: HyperlaneContracts; } & DerivedInterchainAccountFactories; export class EvmCoreModule extends HyperlaneModule< @@ -63,11 +66,8 @@ export class EvmCoreModule extends HyperlaneModule< const chainName = multiProvider.getChainName(chain); // Deploy Ism Factories - const { ismFactories, ismFactory } = await EvmCoreModule.deployIsmFactories( - chainName, - config, - multiProvider, - ); + const { ismFactory, ismFactoriesFactory } = + await EvmCoreModule.deployIsmFactories(chainName, config, multiProvider); // Initalize Deployer const hyperlaneCoreDeployer = new HyperlaneCoreDeployer( @@ -76,27 +76,29 @@ export class EvmCoreModule extends HyperlaneModule< ); // Deploy proxyAdmin - const proxyAdmin = await hyperlaneCoreDeployer.deployContract( + const proxyAdmin = await EvmCoreModule.deployProxyAdmin( chainName, - 'proxyAdmin', - [], + hyperlaneCoreDeployer, ); // Deploy Mailbox - const mailbox = await hyperlaneCoreDeployer.deployMailbox( + const mailbox = await EvmCoreModule.deployMailbox( chainName, config, proxyAdmin.address, + hyperlaneCoreDeployer, + ismFactoriesFactory[chain], + multiProvider, ); - // Deploy Ica Router - const evmIcaModule = await EvmIcaModule.create({ - chain: chainName, - multiProvider, - config: { mailbox: mailbox.address, owner: config.owner }, - }); - const { interchainAccountRouter, interchainAccountIsm } = - evmIcaModule.serialize(); + // Deploy ICA ISM and Router + const { interchainAccountRouter, interchainAccountIsm } = ( + await EvmIcaModule.create({ + chain: chainName, + multiProvider, + config: { mailbox: mailbox.address, owner: config.owner }, + }) + ).serialize(); // Deploy Validator announce const validatorAnnounce = @@ -106,10 +108,10 @@ export class EvmCoreModule extends HyperlaneModule< ); // Deploy Test Receipient - // const testRecipient = await hyperlaneCoreDeployer.deployTestRecipient( - // chainName, - // evmIcaModule.args.config, - // ); + const testRecipient = await hyperlaneCoreDeployer.deployTestRecipient( + chainName, + await mailbox.defaultIsm(), + ); return new EvmCoreModule(multiProvider, { addresses: { @@ -118,31 +120,106 @@ export class EvmCoreModule extends HyperlaneModule< validatorAnnounce, interchainAccountIsm, interchainAccountRouter, - ismFactories: ismFactories[chainName], + testRecipient, + ismFactoryFactories: ismFactoriesFactory[chainName], }, chain, config, }); } + static async deployProxyAdmin( + chainName: string, + hyperlaneCoreDeployer: HyperlaneCoreDeployer, + ) { + return hyperlaneCoreDeployer.deployContract(chainName, 'proxyAdmin', []); + } + static async deployIsmFactories( chainName: string, config: CoreConfig, multiProvider: MultiProvider, - // @NTS FIGURE THIS OUT - // @NTS FIGURE OUT THE NAMING OF ISMFACTORY VS ISMFACTORIES. IS CONFUSING! ): Promise<{ - ismFactories: ChainMap>; ismFactory: HyperlaneIsmFactory; + ismFactoriesFactory: ChainMap>; }> { const proxyFactoryDeployer = new HyperlaneProxyFactoryDeployer( multiProvider, ); - const ismFactories = await proxyFactoryDeployer.deploy({ + const ismFactoriesFactory = await proxyFactoryDeployer.deploy({ [chainName]: config, }); - const ismFactory = new HyperlaneIsmFactory(ismFactories, multiProvider); + const ismFactory = new HyperlaneIsmFactory( + ismFactoriesFactory, + multiProvider, + ); + + return { ismFactory, ismFactoriesFactory }; + } + + static async deployMailbox( + chain: ChainNameOrId, + config: CoreConfig, + proxyAdmin: Address, + deployer: HyperlaneCoreDeployer, + factories: HyperlaneContracts, + multiProvider: MultiProvider, + ): Promise { + const chainName = multiProvider.getChainName(chain); + const domain = deployer.multiProvider.getDomainId(chainName); + const mailbox = await deployer.deployProxiedContract( + chainName, + 'mailbox', + 'mailbox', + proxyAdmin, + [domain], + ); + + if (typeof config.defaultIsm !== 'string') { + const evmIsmModule = await EvmIsmModule.create({ + chain, + config: config.defaultIsm, + deployer, + factories, + multiProvider, + }); + + config.defaultIsm = evmIsmModule.serialize().deployedIsm; + } + + // @todo refactor when 1) HookModule is ready, and 2) Hooks Config can handle strings + // The pattern should be the same as the above defaultIsm + const deployedDefaultHook = await deployer.deployHook( + chainName, + config.defaultHook, + { + mailbox: mailbox.address, + proxyAdmin, + }, + ); - return { ismFactories, ismFactory }; + // @todo refactor when 1) HookModule is ready, and 2) Hooks Config can handle strings + // The pattern should be the same as the above defaultIsm + const deployedRequiredHook = await deployer.deployHook( + chainName, + config.requiredHook, + { + mailbox: mailbox.address, + proxyAdmin, + }, + ); + + // Initialize Mailbox + await multiProvider.handleTx( + chain, + mailbox.initialize( + proxyAdmin, + config.defaultIsm, + deployedDefaultHook.address, + deployedRequiredHook.address, + multiProvider.getTransactionOverrides(chain), + ), + ); + return mailbox; } } diff --git a/typescript/sdk/src/core/HyperlaneCoreDeployer.ts b/typescript/sdk/src/core/HyperlaneCoreDeployer.ts index dc36a05b9b..6a3d09ed54 100644 --- a/typescript/sdk/src/core/HyperlaneCoreDeployer.ts +++ b/typescript/sdk/src/core/HyperlaneCoreDeployer.ts @@ -29,7 +29,7 @@ export class HyperlaneCoreDeployer extends HyperlaneDeployer< testRecipient: TestRecipientDeployer; constructor( - multiProvider: MultiProvider, + public multiProvider: MultiProvider, readonly ismFactory: HyperlaneIsmFactory, contractVerifier?: ContractVerifier, ) { diff --git a/typescript/sdk/src/core/types.ts b/typescript/sdk/src/core/types.ts index fa86a50a68..672afe1795 100644 --- a/typescript/sdk/src/core/types.ts +++ b/typescript/sdk/src/core/types.ts @@ -13,8 +13,8 @@ export type CoreConfig = OwnableConfig & { defaultIsm: IsmConfig; defaultHook: HookConfig; requiredHook: HookConfig; - remove?: boolean; - upgrade?: UpgradeConfig; + remove?: boolean; // Unused + upgrade?: UpgradeConfig; // Unused when deployer is removed }; export enum CoreViolationType {