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 support for core solidity package #5290

Open
wants to merge 50 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
dedaa34
merge with main repo latest changes
mortezashojaei Oct 16, 2024
4f541e3
Merge remote-tracking branch 'origin-root/main'
mortezashojaei Oct 22, 2024
f10e542
Merge remote-tracking branch 'origin-root/main'
mortezashojaei Oct 25, 2024
36e2b00
Merge remote-tracking branch 'origin-root/main'
mortezashojaei Oct 28, 2024
c6cc7e9
Merge remote-tracking branch 'origin-root/main'
mortezashojaei Nov 27, 2024
e13e08a
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Nov 28, 2024
0546e10
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Nov 28, 2024
2ee37d4
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Nov 28, 2024
7770bd7
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Nov 29, 2024
7d6a156
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Dec 5, 2024
b90d0f7
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Dec 5, 2024
c33d90f
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Dec 6, 2024
e3fba6a
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Dec 9, 2024
a45c50a
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Dec 10, 2024
576744b
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Dec 11, 2024
8f7d04d
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Dec 11, 2024
e16b0e3
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Dec 12, 2024
5f380e5
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Dec 13, 2024
8ac3b22
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Dec 17, 2024
074e7d4
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Dec 19, 2024
b48be06
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Jan 13, 2025
ed0f5a9
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Jan 13, 2025
8090e97
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Jan 13, 2025
af971af
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Jan 15, 2025
814bdb0
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Jan 16, 2025
827fb7c
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Jan 16, 2025
ae3acc4
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Jan 20, 2025
19a4cc2
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Jan 21, 2025
aec3579
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Jan 21, 2025
9f42411
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Jan 21, 2025
59165bb
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Jan 22, 2025
1058872
Merge branch 'hyperlane-xyz:main' into main
mshojaei-txfusion Jan 22, 2025
bf4aa1b
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Jan 22, 2025
878719b
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Jan 23, 2025
a4cd60d
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Jan 23, 2025
cad2dce
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Jan 24, 2025
3de0c45
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Jan 24, 2025
be9cc02
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Jan 24, 2025
1ebf65a
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Jan 24, 2025
08c9cf3
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Jan 27, 2025
258d535
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Jan 29, 2025
db616cc
Merge branch 'hyperlane-xyz:main' into main
ljankovic-txfusion Feb 3, 2025
0ac64e3
feat: Add ZKSync solidity support and restructure build artifacts
ljankovic-txfusion Jan 24, 2025
0c66a13
feat(zksync): introduce core ZKSync artifact management utilities
ljankovic-txfusion Jan 24, 2025
2b4dc4f
fix(zksync): update artifact comments for clarity on build output loc…
ljankovic-txfusion Jan 24, 2025
a1bf8ee
chore: remove unnecessary blank line in exportBuildArtifact.sh
ljankovic-txfusion Jan 24, 2025
119bb40
chore: update dependencies in yarn.lock and package.json
ljankovic-txfusion Jan 24, 2025
bf3ff4a
refactor(zksync): simplify artifact utility functions
ljankovic-txfusion Jan 27, 2025
d84da15
chore: update yarn.lock with ZKSync and dependency upgrades
ljankovic-txfusion Jan 27, 2025
17cf30d
feat: update ESLint configuration and add lint script in solidity/pac…
ljankovic-txfusion Feb 3, 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
11 changes: 11 additions & 0 deletions .changeset/chatty-starfishes-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@hyperlane-xyz/core': minor
---

Add ZKSync support and restructure build artifacts:

- Add ZKSync compilation support
- Restructure typechain directory location to core-utils/typechain
- Add ZKSync-specific artifact generation and exports
- Update build process to handle both standard and ZKSync artifacts
- Add new exports for ZKSync build artifacts and contract types
7 changes: 7 additions & 0 deletions solidity/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ docs
flattened/
buildArtifact.json
fixtures/
# ZKSync
artifacts-zk
cache-zk
core-utils/zksync/artifacts/output
.zksolc-libraries-cache/
typechain-types/
typechain/
2 changes: 2 additions & 0 deletions solidity/core-utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './typechain/index.js';
export * from './zksync/index.js';
5 changes: 5 additions & 0 deletions solidity/core-utils/zksync/artifacts.ts
Copy link
Collaborator Author

@ljankovic-txfusion ljankovic-txfusion Jan 24, 2025

Choose a reason for hiding this comment

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

Due to zksync conditional building. Since zksync functions are a part of core-utils and zksync classes on sdk expect a value, we need to feed them some default values not to break build process. Same applies for buildArtifact.ts

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { ZKSyncArtifact } from './types.js';

// Default empty artifact array when `yarn build:zk` hasn't been run
// This file will be populated with contract artifacts in dist after running the build:zk command
export const zkSyncContractArtifacts: ZKSyncArtifact[] = [] as const;
19 changes: 19 additions & 0 deletions solidity/core-utils/zksync/buildArtifact.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Default empty artifact array when `yarn build:zk` hasn't been run
// This file will be populated with build artifacts in dist/zksync after running the build:zk command
export const buildArtifact = {
solcLongVersion: '',
zk_version: '',
input: {
language: 'Solidity',
sources: {},
settings: {
optimizer: {
enabled: false,
runs: 200,
},
outputSelection: {},
evmVersion: 'london',
remappings: [],
},
},
};
4 changes: 4 additions & 0 deletions solidity/core-utils/zksync/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './artifacts.js';
export * from './buildArtifact.js';
export * from './utils.js';
export * from './types.js';
11 changes: 11 additions & 0 deletions solidity/core-utils/zksync/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export interface ZKSyncArtifact {
_format: string;
contractName: string;
sourceName: string;
abi: any[];
bytecode: string;
deployedBytecode: string;
linkReferences: Record<string, any>;
deployedLinkReferences: Record<string, any>;
factoryDeps: Record<string, any>;
}
23 changes: 23 additions & 0 deletions solidity/core-utils/zksync/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { zkSyncContractArtifacts } from './artifacts.js';
import { ZKSyncArtifact } from './types.js';

/**
* @dev Get a ZkSync artifact by its name.
* @param name The name of the artifact to get.
* @return The loaded ZKSyncArtifact or undefined if it cannot be found.
*/
export function getZKSyncArtifactByName(
name: string,
): ZKSyncArtifact | undefined {
return zkSyncContractArtifacts.find(
(artifact) => artifact.contractName === name,
);
}

/**
* @dev Loads all ZkSync artifacts into an array.
* @return An array of ZkSync artifacts.
*/
export function loadAllZKSyncArtifacts(): ZKSyncArtifact[] {
return zkSyncContractArtifacts;
}
6 changes: 4 additions & 2 deletions solidity/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ export default [
...MonorepoDefaults,
{
ignores: [
'./test/**/*',
'./dist/**/*',
'**/test/**/*',
'**/dist/**/*',
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

for some reason test folder was included in lint unit **/... were added

'**/typechain/**/*',
'.solcover.js',
'generate-artifact-exports.mjs',
],
},
];
39 changes: 39 additions & 0 deletions solidity/exportBuildArtifact.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,42 @@ else
echo 'Failed to process build artifact with jq'
exit 1
fi

# ZKSYNC

if [ "$ZKSYNC" = "true" ]; then
# Define the artifacts directory
artifactsDir="./artifacts-zk/build-info"
# Define the output file
outputFileJson="./dist/zksync/buildArtifact.json"
outputFileJs="./dist/zksync/buildArtifact.js"
outputFileTsd="./dist/zksync/buildArtifact.d.ts"

# log that we're in the script
echo 'Finding and processing ZKSync hardhat build artifact...'

# Find most recently modified JSON build artifact
if [ "$(uname)" = "Darwin" ]; then
# for local flow
jsonFiles=$(find "$artifactsDir" -type f -name "*.json" -exec stat -f "%m %N" {} \; | sort -rn | head -n 1 | cut -d' ' -f2-)
else
# for CI flow
jsonFiles=$(find "$artifactsDir" -type f -name "*.json" -exec stat -c "%Y %n" {} \; | sort -rn | head -n 1 | cut -d' ' -f2-)
fi

if [ ! -f "$jsonFiles" ]; then
echo 'Failed to find ZKSync build artifact'
exit 1
fi

# Extract required keys and write to outputFile
if jq -c '{input, solcLongVersion, zk_version: .output.zk_version}' "$jsonFiles" >"$outputFileJson"; then
echo "export const buildArtifact = " >"$outputFileJs"
cat "$outputFileJson" >>"$outputFileJs"
echo "export const buildArtifact: any" >"$outputFileTsd"
echo 'Finished processing ZKSync build artifact.'
else
echo 'Failed to process ZKSync build artifact with jq'
exit 1
fi
fi
174 changes: 174 additions & 0 deletions solidity/generate-artifact-exports.mjs
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This script for generating zksync artifacts only runs in nodejs environment thus 'fs' is used. Exported artifacts have .d.ts and .js extension and are generated directly to dist folder, and have a shape of js object.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I feel like scripts such as this and 'exportBuildArtifacts.sh', 'update_abis.sh', etc... belong in script folder, but its used for avs & xerc20 right now

Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import { promises as fs } from 'fs';
import { basename, dirname, join } from 'path';
import { glob } from 'typechain';
import { fileURLToPath } from 'url';

const cwd = process.cwd();
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const ROOT_OUTPUT_DIR = join(__dirname, 'dist/zksync/');
const ARTIFACTS_OUTPUT_DIR = join(ROOT_OUTPUT_DIR, 'artifacts');

/**
* @notice Templates for TypeScript artifact generation
*/
const TEMPLATES = {
JS_ARTIFACT: `\
export const {name} = {artifact};
`,

DTS_ARTIFACT: `\
import type { ZKSyncArtifact } from '../types.js';

export declare const {name}: ZKSyncArtifact;
`,

JS_INDEX: `\
{imports}

export const zkSyncContractArtifacts = [
{exports}
];
`,

DTS_INDEX: `\
import type { ZKSyncArtifact } from './types.js';

export declare const zkSyncContractArtifacts: readonly ZKSyncArtifact[];
`,
};

class ArtifactGenerator {
constructor() {
this.processedFiles = new Set();
}

/**
* @notice Retrieves paths of all relevant artifact files
* @dev Excludes debug files and build-info directory
* @return {string[]} Array of file paths matching the glob pattern
*/
getArtifactPaths() {
return glob(cwd, [
`!./artifacts-zk/!(build-info)/**/*.dbg.json`,
`./artifacts-zk/!(build-info)/**/+([a-zA-Z0-9_]).json`,
]);
}

/**
* @notice Creates the output directory if it doesn't exist
*/
async createOutputDirectory() {
await fs.mkdir(ARTIFACTS_OUTPUT_DIR, { recursive: true });
}

/**
* @notice Reads and parses a JSON artifact file
* @param filePath Path to the artifact file
* @return {Promise<Object>} Parsed JSON content
*/
async readArtifactFile(filePath) {
const content = await fs.readFile(filePath, 'utf-8');
return JSON.parse(content);
}

/**
* @notice Generates JavaScript content for a contract artifact
*/
generateJavaScriptContent(name, artifact) {
return TEMPLATES.JS_ARTIFACT.replace('{name}', name).replace(
'{artifact}',
JSON.stringify(artifact, null, 2),
);
}

/**
* @notice Generates TypeScript declaration content for a contract artifact
*/
generateDeclarationContent(name) {
return TEMPLATES.DTS_ARTIFACT.replace('{name}', name);
}

/**
* @notice Generates index file contents
*/
generateIndexContents(artifactNames) {
const imports = artifactNames
.map((name) => `import { ${name} } from './artifacts/${name}.js';`)
.join('\n');
const exports = artifactNames.map((name) => ` ${name},`).join('\n');

const jsContent = TEMPLATES.JS_INDEX.replace('{imports}', imports).replace(
'{exports}',
exports,
);

const dtsContent = TEMPLATES.DTS_INDEX.replace(
'{imports}',
imports,
).replace('{exports}', exports);

return { jsContent, dtsContent };
}

/**
* @notice Processes a single artifact file
*/
async processArtifact(filePath) {
const name = basename(filePath, '.json');

if (this.processedFiles.has(name)) {
return;
}

const artifact = await this.readArtifactFile(filePath);

// Generate and write .js file
const jsContent = this.generateJavaScriptContent(name, artifact);
await fs.writeFile(
join(ROOT_OUTPUT_DIR, 'artifacts', `${name}.js`),
jsContent,
);

// Generate and write .d.ts file
const dtsContent = this.generateDeclarationContent(name);
await fs.writeFile(
join(ROOT_OUTPUT_DIR, 'artifacts', `${name}.d.ts`),
dtsContent,
);

this.processedFiles.add(name);
}

async generate() {
try {
await this.createOutputDirectory();

const artifactPaths = this.getArtifactPaths();

for (const filePath of artifactPaths) {
await this.processArtifact(filePath);
}

const processedNames = Array.from(this.processedFiles);

// Generate and write index files
const { jsContent, dtsContent } =
this.generateIndexContents(processedNames);

await fs.writeFile(join(ROOT_OUTPUT_DIR, 'artifacts.js'), jsContent);
await fs.writeFile(join(ROOT_OUTPUT_DIR, 'artifacts.d.ts'), dtsContent);

console.log(
`Successfully processed ${processedNames.length} zksync artifacts`,
);
} catch (error) {
console.error('Error processing zksync artifacts:', error);
throw error;
}
}
}

const generator = new ArtifactGenerator();
generator.generate().catch(console.error);
2 changes: 1 addition & 1 deletion solidity/hardhat.config.cts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module.exports = {
currency: 'USD',
},
typechain: {
outDir: './types',
outDir: './core-utils/typechain',
target: 'ethers-v5',
alwaysGenerateOverloads: true,
node16Modules: true,
Expand Down
14 changes: 10 additions & 4 deletions solidity/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
"devDependencies": {
"@layerzerolabs/solidity-examples": "^1.1.0",
"@matterlabs/hardhat-zksync-solc": "^1.2.4",
"@nomiclabs/hardhat-ethers": "^2.2.3",
"@nomiclabs/hardhat-waffle": "^2.0.6",
"@typechain/ethers-v5": "^11.1.2",
Expand All @@ -36,17 +37,19 @@
"ts-node": "^10.8.0",
"tsx": "^4.19.1",
"typechain": "patch:typechain@npm%3A8.3.2#~/.yarn/patches/typechain-npm-8.3.2-b02e27439e.patch",
"typescript": "5.3.3"
"typescript": "5.3.3",
"zksync-ethers": "^5.10.0"
},
"directories": {
"test": "test"
},
"type": "module",
"exports": {
".": "./dist/index.js",
"./mailbox": "./dist/contracts/Mailbox.js",
"./mailbox": "./dist/typechain/contracts/Mailbox.js",
"./buildArtifact.js": "./dist/buildArtifact.js",
"./buildArtifact.json": "./dist/buildArtifact.json",
"./buildArtifact-zksync.js": "./dist/zksync/buildArtifact.js",
"./contracts": "./contracts"
},
"types": "./dist/index.d.ts",
Expand All @@ -66,12 +69,15 @@
"license": "Apache-2.0",
"scripts": {
"build": "yarn version:update && yarn hardhat-esm compile && tsc && ./exportBuildArtifact.sh",
"lint": "solhint contracts/**/*.sol",
"clean": "yarn hardhat-esm clean && rm -rf ./dist ./cache ./types ./coverage ./out ./forge-cache ./fixtures",
"build:zk": "yarn hardhat-zk compile && tsc && ts-node generate-artifact-exports.mjs && ZKSYNC=true ./exportBuildArtifact.sh",
"prepublishOnly": "yarn build && yarn build:zk",
"lint": "solhint contracts/**/*.sol && eslint -c ./eslint.config.mjs",
"clean": "yarn hardhat-esm clean && yarn hardhat-zk clean && rm -rf ./dist ./cache ./cache-zk ./types ./coverage ./out ./forge-cache ./fixtures",
"coverage": "yarn fixtures && ./coverage.sh",
"docs": "forge doc",
"fixtures": "mkdir -p ./fixtures/aggregation ./fixtures/multisig",
"hardhat-esm": "NODE_OPTIONS='--experimental-loader ts-node/esm/transpile-only --no-warnings=ExperimentalWarning' hardhat --config hardhat.config.cts",
"hardhat-zk": "NODE_OPTIONS='--experimental-loader ts-node/esm/transpile-only --no-warnings=ExperimentalWarning' hardhat --config zk-hardhat.config.cts",
"prettier": "prettier --write ./contracts ./test",
"test": "yarn version:exhaustive && yarn hardhat-esm test && yarn test:forge",
"test:hardhat": "yarn hardhat-esm test",
Expand Down
4 changes: 2 additions & 2 deletions solidity/test/lib/mailboxes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import {
LegacyMultisigIsm,
TestMailbox,
TestMerkleTreeHook,
} from '../../types';
import { DispatchEvent } from '../../types/contracts/Mailbox';
} from '../../core-utils/typechain';
import { DispatchEvent } from '../../core-utils/typechain/contracts/Mailbox';

export type MessageAndProof = {
proof: MerkleProof;
Expand Down
Loading
Loading