Skip to content

Commit

Permalink
Add mailbox deploy logic, and rest of Core deploy
Browse files Browse the repository at this point in the history
  • Loading branch information
ltyu committed May 9, 2024
1 parent 7f9d4af commit 22015e9
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 47 deletions.
59 changes: 45 additions & 14 deletions typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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;
});
});
});
137 changes: 107 additions & 30 deletions typescript/sdk/src/core/EvmCoreModule.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -23,7 +25,8 @@ type DerivedInterchainAccountFactories = HyperlaneContracts<
>;

type ExtraArgs = {
ismFactories: HyperlaneContracts<ProxyFactoryFactories>;
testRecipient: TestRecipient;
ismFactoryFactories: HyperlaneContracts<ProxyFactoryFactories>;
} & DerivedInterchainAccountFactories;

export class EvmCoreModule extends HyperlaneModule<
Expand Down Expand Up @@ -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(
Expand All @@ -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 =
Expand All @@ -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: {
Expand All @@ -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<HyperlaneContracts<ProxyFactoryFactories>>;
ismFactory: HyperlaneIsmFactory;
ismFactoriesFactory: ChainMap<HyperlaneContracts<ProxyFactoryFactories>>;
}> {
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<ProxyFactoryFactories>,
multiProvider: MultiProvider,
): Promise<Mailbox> {
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;
}
}
2 changes: 1 addition & 1 deletion typescript/sdk/src/core/HyperlaneCoreDeployer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class HyperlaneCoreDeployer extends HyperlaneDeployer<
testRecipient: TestRecipientDeployer;

constructor(
multiProvider: MultiProvider,
public multiProvider: MultiProvider,
readonly ismFactory: HyperlaneIsmFactory,
contractVerifier?: ContractVerifier,
) {
Expand Down
4 changes: 2 additions & 2 deletions typescript/sdk/src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export type CoreConfig = OwnableConfig<keyof CoreFactories> & {
defaultIsm: IsmConfig;
defaultHook: HookConfig;
requiredHook: HookConfig;
remove?: boolean;
upgrade?: UpgradeConfig;
remove?: boolean; // Unused
upgrade?: UpgradeConfig; // Unused when deployer is removed
};

export enum CoreViolationType {
Expand Down

0 comments on commit 22015e9

Please sign in to comment.