Skip to content

Commit 973aa72

Browse files
mshojaei-txfusionltyuljankovic-txfusionmortezashojaeipaulbalaji
authored
feat: zksync compatibility checks (#6329)
### Description This PR enhances ISM deployments and transaction estimation with: Technical stack compatibility verification for ISM types Static address support in ISM factory deployments Gas estimation skip for zkSync deployments txfusion#23 ### Drive-by changes Added isIsmCompatible utility function import Added technical stack validation checks Related issues https://linear.app/hyperlane-xyz/issue/ENG-1153 Previously was here: #5213 ### Backward compatibility Yes ### Testing Build passing --------- Co-authored-by: Le Yu <6251863+ltyu@users.noreply.github.com> Co-authored-by: ljankovic-txfusion <lazar@txfusion.io> Co-authored-by: ljankovic-txfusion <131957285+ljankovic-txfusion@users.noreply.github.com> Co-authored-by: Morteza Shojaei <31728528+mortezashojaei@users.noreply.github.com> Co-authored-by: Paul Balaji <10051819+paulbalaji@users.noreply.github.com> Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
1 parent 5db9491 commit 973aa72

7 files changed

Lines changed: 100 additions & 15 deletions

File tree

.changeset/honest-readers-lick.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@hyperlane-xyz/sdk': minor
3+
---
4+
5+
Check for ZKSync contracts and functionalities support

typescript/sdk/src/core/EvmCoreModule.ts

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,15 @@ import {
3535
proxyFactoryFactories,
3636
} from '../deploy/contracts.js';
3737
import { proxyAdminUpdateTxs } from '../deploy/proxy.js';
38+
import { createDefaultProxyFactoryFactories } from '../deploy/proxyFactoryUtils.js';
39+
import { ProxyFactoryFactoriesAddresses } from '../deploy/types.js';
3840
import { ContractVerifier } from '../deploy/verify/ContractVerifier.js';
3941
import { HookFactories } from '../hook/contracts.js';
4042
import { EvmIsmModule } from '../ism/EvmIsmModule.js';
4143
import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory.js';
4244
import { DerivedIsmConfig, IsmConfig } from '../ism/types.js';
45+
import { isStaticDeploymentSupported } from '../ism/utils.js';
46+
import { ChainTechnicalStack } from '../metadata/chainMetadataTypes.js';
4347
import { MultiProvider } from '../providers/MultiProvider.js';
4448
import { AnnotatedEV5Transaction } from '../providers/ProviderType.js';
4549
import { ChainName, ChainNameOrId } from '../types.js';
@@ -279,14 +283,16 @@ export class EvmCoreModule extends HyperlaneModule<
279283
contractVerifier?: ContractVerifier;
280284
}): Promise<DeployedCoreAddresses> {
281285
const { config, multiProvider, chain, contractVerifier } = params;
282-
const chainName = multiProvider.getChainName(chain);
286+
const { name: chainName, technicalStack } =
287+
multiProvider.getChainMetadata(chain);
283288

284-
const ismFactoryFactories = await EvmCoreModule.deployIsmFactories({
285-
chainName,
286-
config,
287-
multiProvider,
288-
contractVerifier,
289-
});
289+
const ismFactoryFactories: ProxyFactoryFactoriesAddresses =
290+
await this.getIsmFactoryFactories(technicalStack, {
291+
chainName,
292+
config,
293+
multiProvider,
294+
contractVerifier,
295+
});
290296

291297
const ismFactory = new HyperlaneIsmFactory(
292298
attachContractsMap(
@@ -381,7 +387,6 @@ export class EvmCoreModule extends HyperlaneModule<
381387
// Set Core & extra addresses
382388
return {
383389
...ismFactoryFactories,
384-
385390
proxyAdmin: proxyAdmin.address,
386391
mailbox: mailbox.address,
387392
interchainAccountRouter,
@@ -486,4 +491,31 @@ export class EvmCoreModule extends HyperlaneModule<
486491
);
487492
return mailbox;
488493
}
494+
495+
/**
496+
* Retrieves the ISM factory factories based on the provided technicalStack and parameters.
497+
*
498+
* @param technicalStack - The technicalStack to determine if static address set deployment should be skipped.
499+
* @param params - An object containing the parameters needed for ISM factory deployment.
500+
* @param params.chainName - The name of the chain for which the ISM factories are being deployed.
501+
* @param params.config - The core configuration to be used during deployment.
502+
* @param params.multiProvider - The multi-provider instance for interacting with the blockchain.
503+
* @param params.contractVerifier - An optional contract verifier for validating contracts during deployment.
504+
* @returns A promise that resolves to the addresses of the deployed ISM factory factories.
505+
*/
506+
private static async getIsmFactoryFactories(
507+
technicalStack: ChainTechnicalStack | undefined,
508+
params: {
509+
chainName: string;
510+
config: CoreConfig;
511+
multiProvider: MultiProvider;
512+
contractVerifier?: ContractVerifier;
513+
},
514+
): Promise<ProxyFactoryFactoriesAddresses> {
515+
// Check if we should skip static address set deployment
516+
if (!isStaticDeploymentSupported(technicalStack)) {
517+
return createDefaultProxyFactoryFactories();
518+
}
519+
return EvmCoreModule.deployIsmFactories(params);
520+
}
489521
}

typescript/sdk/src/core/HyperlaneCore.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { EvmHookReader } from '../hook/EvmHookReader.js';
3535
import { DerivedHookConfig } from '../hook/types.js';
3636
import { EvmIsmReader } from '../ism/EvmIsmReader.js';
3737
import { DerivedIsmConfig } from '../ism/types.js';
38+
import { ChainTechnicalStack } from '../metadata/chainMetadataTypes.js';
3839
import { MultiProvider } from '../providers/MultiProvider.js';
3940
import { RouterConfig } from '../router/types.js';
4041
import { ChainMap, ChainName, OwnableConfig } from '../types.js';
@@ -254,6 +255,13 @@ export class HyperlaneCore extends HyperlaneApp<CoreFactories> {
254255
}
255256

256257
async estimateHandle(message: DispatchedMessage): Promise<string> {
258+
// This estimation is not possible on zksync as it is overriding transaction.from
259+
// transaction.from must be a signer on zksync
260+
if (
261+
this.multiProvider.getChainMetadata(this.getDestination(message))
262+
.technicalStack === ChainTechnicalStack.ZkSync
263+
)
264+
return '0';
257265
return (
258266
await this.getRecipient(message).estimateGas.handle(
259267
message.parsed.origin,

typescript/sdk/src/hook/utils.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ChainTechnicalStack } from '../metadata/chainMetadataTypes.js';
2+
3+
import { HookType } from './types.js';
4+
5+
/**
6+
* Checks if the given hook type is compatible with the chain's technical stack.
7+
*
8+
* @param {HookType} params.hookType - The type of hook
9+
* @param {ChainTechnicalStack | undefined} params.chainTechnicalStack - The technical stack of the chain
10+
* @returns {boolean} True if the hook type is compatible with the chain, false otherwise
11+
*/
12+
export const isHookCompatible = ({
13+
hookType,
14+
chainTechnicalStack,
15+
}: {
16+
hookType: HookType;
17+
chainTechnicalStack?: ChainTechnicalStack;
18+
}): boolean =>
19+
!(
20+
hookType === HookType.AGGREGATION &&
21+
chainTechnicalStack === ChainTechnicalStack.ZkSync
22+
);

typescript/sdk/src/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,12 @@ export {
223223
} from './ism/types.js';
224224
export {
225225
collectValidators,
226-
moduleCanCertainlyVerify,
227-
isStaticDeploymentSupported,
228226
isIsmCompatible,
227+
isStaticDeploymentSupported,
228+
isStaticIsm,
229+
moduleCanCertainlyVerify,
229230
} from './ism/utils.js';
231+
export { isHookCompatible } from './hook/utils.js';
230232
export {
231233
AgentChainMetadata,
232234
AgentChainMetadataSchema,

typescript/sdk/src/ism/HyperlaneIsmFactory.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ import {
6868
RoutingIsmDelta,
6969
WeightedMultisigIsmConfig,
7070
} from './types.js';
71-
import { routingModuleDelta } from './utils.js';
71+
import { isIsmCompatible, routingModuleDelta } from './utils.js';
7272

7373
const ismFactories = {
7474
[IsmType.PAUSABLE]: new PausableIsm__factory(),
@@ -149,6 +149,14 @@ export class HyperlaneIsmFactory extends HyperlaneApp<ProxyFactoryFactories> {
149149
}`,
150150
);
151151

152+
const { technicalStack } = this.multiProvider.getChainMetadata(destination);
153+
154+
// For static ISM types it checks whether the technical stack supports static contract deployment
155+
assert(
156+
isIsmCompatible({ ismType, chainTechnicalStack: technicalStack }),
157+
`Technical stack ${technicalStack} is not compatible with ${ismType}`,
158+
);
159+
152160
let contract: DeployedIsmType[typeof ismType];
153161
switch (ismType) {
154162
case IsmType.MESSAGE_ID_MULTISIG:

typescript/sdk/src/ism/utils.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,16 @@ export function collectValidators(
587587
return new Set(validators);
588588
}
589589

590+
/**
591+
* Checks if the given ISM type requires static deployment
592+
*
593+
* @param {IsmType} ismType - The type of Interchain Security Module (ISM)
594+
* @returns {boolean} True if the ISM type requires static deployment, false otherwise
595+
*/
596+
export function isStaticIsm(ismType: IsmType): boolean {
597+
return STATIC_ISM_TYPES.includes(ismType);
598+
}
599+
590600
/**
591601
* Determines if static ISM deployment is supported on a given chain's technical stack
592602
* @dev Currently, only ZkSync does not support static deployments
@@ -602,9 +612,8 @@ export function isStaticDeploymentSupported(
602612
/**
603613
* Checks if the given ISM type is compatible with the chain's technical stack.
604614
*
605-
* @param {Object} params - The parameters object
606-
* @param {ChainTechnicalStack | undefined} params.chainTechnicalStack - The technical stack of the chain
607615
* @param {IsmType} params.ismType - The type of Interchain Security Module (ISM)
616+
* @param {ChainTechnicalStack | undefined} params.chainTechnicalStack - The technical stack of the chain
608617
* @returns {boolean} True if the ISM type is compatible with the chain, false otherwise
609618
*/
610619
export function isIsmCompatible({
@@ -615,7 +624,6 @@ export function isIsmCompatible({
615624
ismType: IsmType;
616625
}): boolean {
617626
// Skip compatibility check for non-static ISMs as they're always supported
618-
if (!STATIC_ISM_TYPES.includes(ismType)) return true;
619-
627+
if (!isStaticIsm(ismType)) return true;
620628
return isStaticDeploymentSupported(chainTechnicalStack);
621629
}

0 commit comments

Comments
 (0)