Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: zksync deployment logic [ZK-002] #21

Open
wants to merge 20 commits into
base: feat/zksync-sdk-provider
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8e6c6f6
feat: ZKSync functions, metadata and types for deployment
ljankovic-txfusion Jan 20, 2025
cd1eae9
docs(changeset): Added ZKSync specific deployment logic and artifact …
ljankovic-txfusion Jan 20, 2025
b83fb67
feat: ZKSync Provider types for proxy utils
ljankovic-txfusion Jan 20, 2025
ced1965
Merge remote-tracking branch 'origin/feat/zksync-sdk-provider' into f…
ljankovic-txfusion Jan 21, 2025
7ed09b8
chore: change ZKSync SDK version to minor
ljankovic-txfusion Jan 22, 2025
4befd65
refactor: rename Provider type to NetworkProvider for clarity in prox…
ljankovic-txfusion Jan 22, 2025
3e3c6f5
refactor: rename STATIC_ISM_TYPE to STATIC_ISM_TYPES for consistency …
ljankovic-txfusion Jan 22, 2025
541e650
Merge remote-tracking branch 'origin/feat/zksync-sdk-provider' into f…
ljankovic-txfusion Jan 23, 2025
4dfafc4
Merge remote-tracking branch 'origin/main' into feat/zksync-deploymen…
ljankovic-txfusion Jan 23, 2025
f363a46
Merge remote-tracking branch 'origin/feat/zksync-sdk-provider' into f…
ljankovic-txfusion Jan 23, 2025
5ffeaf6
Merge remote-tracking branch 'origin/feat/zksync-sdk-provider' into f…
ljankovic-txfusion Jan 23, 2025
42a1215
fix: await loadAllZKSyncArtifacts in getZKSyncArtifactByContractName …
ljankovic-txfusion Jan 23, 2025
8831a03
Merge remote-tracking branch 'origin/feat/zksync-sdk-provider' into f…
ljankovic-txfusion Jan 23, 2025
bbf963c
Merge remote-tracking branch 'origin/feat/zksync-sdk-provider' into f…
ljankovic-txfusion Jan 24, 2025
1e191cb
Merge remote-tracking branch 'origin/feat/zksync-sdk-provider' into f…
ljankovic-txfusion Jan 27, 2025
f9dd542
fix(zksync): remove async from loadAllZKSyncArtifacts function call
ljankovic-txfusion Jan 27, 2025
254ffb2
Merge remote-tracking branch 'origin/feat/zksync-sdk-provider' into f…
ljankovic-txfusion Jan 27, 2025
c24cfa1
Merge remote-tracking branch 'origin/feat/zksync-sdk-provider' into f…
ljankovic-txfusion Jan 27, 2025
ade32ef
Merge remote-tracking branch 'origin/feat/zksync-sdk-provider' into f…
ljankovic-txfusion Jan 29, 2025
ff8fc05
Merge remote-tracking branch 'origin/feat/zksync-sdk-provider' into f…
ljankovic-txfusion Jan 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/eleven-cows-dance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hyperlane-xyz/sdk': minor
---

Added ZKSync specific deployment logic and artifact related utils
11 changes: 7 additions & 4 deletions typescript/sdk/src/deploy/proxy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ethers } from 'ethers';
import { Provider as ZKSyncProvider } from 'zksync-ethers';

import { ProxyAdmin__factory } from '@hyperlane-xyz/core';
import { Address, ChainId, eqAddress } from '@hyperlane-xyz/utils';
Expand All @@ -7,6 +8,8 @@ import { transferOwnershipTransactions } from '../contracts/contracts.js';
import { AnnotatedEV5Transaction } from '../providers/ProviderType.js';
import { DeployedOwnableConfig } from '../types.js';

type Provider = ethers.providers.Provider | ZKSyncProvider;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ethers Provider and ZKSync Provider are not compatible with each other

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we maybe pick a more descriptive name for the Union type?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

picked NetworkProvider


export type UpgradeConfig = {
timelock: {
delay: number;
Expand All @@ -19,7 +22,7 @@ export type UpgradeConfig = {
};

export async function proxyImplementation(
provider: ethers.providers.Provider,
provider: Provider,
proxy: Address,
): Promise<Address> {
// Hardcoded storage slot for implementation per EIP-1967
Expand All @@ -31,7 +34,7 @@ export async function proxyImplementation(
}

export async function isInitialized(
provider: ethers.providers.Provider,
provider: Provider,
contract: Address,
): Promise<boolean> {
// Using OZ's Initializable 4.9 which keeps it at the 0x0 slot
Expand All @@ -43,7 +46,7 @@ export async function isInitialized(
}

export async function proxyAdmin(
provider: ethers.providers.Provider,
provider: Provider,
proxy: Address,
): Promise<Address> {
// Hardcoded storage slot for admin per EIP-1967
Expand All @@ -66,7 +69,7 @@ export function proxyConstructorArgs<C extends ethers.Contract>(
}

export async function isProxy(
provider: ethers.providers.Provider,
provider: Provider,
proxy: Address,
): Promise<boolean> {
const admin = await proxyAdmin(provider, proxy);
Expand Down
16 changes: 16 additions & 0 deletions typescript/sdk/src/deploy/proxyFactoryUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ethers } from 'ethers';

import { proxyFactoryFactories } from './contracts.js';
import { ProxyFactoryFactoriesAddresses } from './types.js';

/**
* Creates a default ProxyFactoryFactoriesAddresses object with all values set to ethers.constants.AddressZero.
* @returns {ProxyFactoryFactoriesAddresses} An object with all factory addresses set to AddressZero.
*/
export function createDefaultProxyFactoryFactories(): ProxyFactoryFactoriesAddresses {
const defaultAddress = ethers.constants.AddressZero;
return Object.keys(proxyFactoryFactories).reduce((acc, key) => {
acc[key as keyof ProxyFactoryFactoriesAddresses] = defaultAddress; // Type assertion added here
return acc;
}, {} as ProxyFactoryFactoriesAddresses);
}
15 changes: 15 additions & 0 deletions typescript/sdk/src/hook/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@ export enum HookType {
ARB_L2_TO_L1 = 'arbL2ToL1Hook',
}

export const HookTypeToContractNameMap: Record<
Exclude<HookType, HookType.CUSTOM>,
string
> = {
[HookType.MERKLE_TREE]: 'merkleTreeHook',
[HookType.INTERCHAIN_GAS_PAYMASTER]: 'interchainGasPaymaster',
[HookType.AGGREGATION]: 'staticAggregationHook',
[HookType.PROTOCOL_FEE]: 'protocolFee',
[HookType.OP_STACK]: 'opStackHook',
[HookType.ROUTING]: 'domainRoutingHook',
[HookType.FALLBACK_ROUTING]: 'fallbackDomainRoutingHook',
[HookType.PAUSABLE]: 'pausableHook',
[HookType.ARB_L2_TO_L1]: 'arbL2ToL1Hook',
};

export type MerkleTreeHookConfig = z.infer<typeof MerkleTreeSchema>;
export type IgpHookConfig = z.infer<typeof IgpSchema>;
export type ProtocolFeeHookConfig = z.infer<typeof ProtocolFeeSchema>;
Expand Down
7 changes: 6 additions & 1 deletion typescript/sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,12 @@ export {
WeightedMultisigIsmConfig,
WeightedMultisigIsmConfigSchema,
} from './ism/types.js';
export { collectValidators, moduleCanCertainlyVerify } from './ism/utils.js';
export {
collectValidators,
moduleCanCertainlyVerify,
isStaticDeploymentSupported,
isIsmCompatible,
} from './ism/utils.js';
export {
AgentChainMetadata,
AgentChainMetadataSchema,
Expand Down
10 changes: 10 additions & 0 deletions typescript/sdk/src/ism/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ export const MUTABLE_ISM_TYPE = [
IsmType.PAUSABLE,
];

// ISM types that require static deployment
export const STATIC_ISM_TYPE = [
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

Suggested change
export const STATIC_ISM_TYPE = [
export const STATIC_ISM_TYPES = [

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved. Made a separate commit, since its used in multiple places

IsmType.AGGREGATION,
IsmType.MERKLE_ROOT_MULTISIG,
IsmType.MESSAGE_ID_MULTISIG,
IsmType.WEIGHTED_MERKLE_ROOT_MULTISIG,
IsmType.WEIGHTED_MESSAGE_ID_MULTISIG,
IsmType.ICA_ROUTING,
];

// mapping between the two enums
export function ismTypeToModuleType(ismType: IsmType): ModuleType {
switch (ismType) {
Expand Down
36 changes: 36 additions & 0 deletions typescript/sdk/src/ism/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {

import { HyperlaneContracts } from '../contracts/types.js';
import { ProxyFactoryFactories } from '../deploy/contracts.js';
import { ChainTechnicalStack } from '../metadata/chainMetadataTypes.js';
import { MultiProvider } from '../providers/MultiProvider.js';
import { ChainName } from '../types.js';

Expand All @@ -34,6 +35,7 @@ import {
ModuleType,
RoutingIsmConfig,
RoutingIsmDelta,
STATIC_ISM_TYPE,
ismTypeToModuleType,
} from './types.js';

Expand Down Expand Up @@ -534,3 +536,37 @@ export function collectValidators(

return new Set(validators);
}

/**
* Determines if static ISM deployment is supported on a given chain's technical stack
* @dev Currently, only ZkSync does not support static deployments
* @param chainTechnicalStack - The technical stack of the target chain
* @returns boolean - true if static deployment is supported, false for ZkSync
*/
export function isStaticDeploymentSupported(
chainTechnicalStack: ChainTechnicalStack | undefined,
): boolean {
if (chainTechnicalStack === undefined) return true;
return chainTechnicalStack !== ChainTechnicalStack.ZkSync;
}

/**
* Checks if the given ISM type is compatible with the chain's technical stack.
*
* @param {Object} params - The parameters object
* @param {ChainTechnicalStack | undefined} params.chainTechnicalStack - The technical stack of the chain
* @param {IsmType} params.ismType - The type of Interchain Security Module (ISM)
* @returns {boolean} True if the ISM type is compatible with the chain, false otherwise
*/
export function isIsmCompatible({
chainTechnicalStack,
ismType,
}: {
chainTechnicalStack: ChainTechnicalStack | undefined;
ismType: IsmType;
}): boolean {
// Skip compatibility check for non-static ISMs as they're always supported
if (!STATIC_ISM_TYPE.includes(ismType)) return true;

return isStaticDeploymentSupported(chainTechnicalStack);
}
1 change: 1 addition & 0 deletions typescript/sdk/src/metadata/chainMetadataTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export enum ExplorerFamily {
Etherscan = 'etherscan',
Blockscout = 'blockscout',
Routescan = 'routescan',
ZkSync = 'zksync',
Other = 'other',
}

Expand Down
32 changes: 32 additions & 0 deletions typescript/sdk/src/utils/zksync.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ZKSyncArtifact, loadAllZKSyncArtifacts } from '@hyperlane-xyz/core';

/**
* @dev Retrieves a ZkSync artifact by its contract name or qualified name.
* @param name The name of the contract or qualified name in the format "sourceName:contractName".
* @return The corresponding ZKSyncArtifact if found, or undefined if not found.
*/
export const getZKSyncArtifactByContractName = async (
name: string,
): Promise<ZKSyncArtifact | undefined> => {
// Load all ZkSync artifacts
const allArtifacts = loadAllZKSyncArtifacts();

// Find the artifact that matches the contract name or qualified name
const artifact = Object.values(allArtifacts).find(
({ contractName, sourceName }: ZKSyncArtifact) => {
const lowerCaseContractName = contractName.toLowerCase();
const lowerCaseName = name.toLowerCase();

// Check if the contract name matches
if (lowerCaseContractName === lowerCaseName) {
return true;
}

// Check if the qualified name matches
const qualifiedName = `${sourceName}:${contractName}`;
return qualifiedName === name; // Return true if qualified name matches
},
);

return artifact;
};
Loading
Loading