המהנדסים שלנו נתקלים לא פעם במפתחים שמעבירים חוזי EVM ל-zkSync ללא שינויים — ומקבלים הפתעות: CREATE2 לא עובד, הגז עולה פי 3 מהצפוי, והאימות נכשל עקב אי-תאימות bytecode. במאמר זה, נפרק כיצד לפרוס נכון חוזים חכמים של zkSync על zkSync Era: עם zksolc, EraVM, Native Account Abstraction, ומודל הגז הדו-ממדי. פריסת חוזים חכמים zkSync דורשת הבנה של ההבדלים הללו.
בעיות שאנחנו פותרים
אי-תאימות bytecode. zksolc מייצר bytecode של EraVM, לא של EVM. אם לא מציינים תלות במפעל (factory dependencies), CREATE (ו-CREATE2) פשוט לא יעבדו — צריך להצהיר מראש על כל החוזים שנוצרים מהקוד. מודל גז. zkSync משתמש בגז דו-ממדי: גז רגיל לביצוע ו-gasPerPubdata לפרסום נתונים ל-L1. כשפורסים חוזה כבד (למשל עם קונסטרוקטורים גדולים), העלות הסופית יכולה להיות גבוהה פי 2–3 מאשר ב-Ethereum Mainnet אם לא מייעלים את ה-payload. חוסר תיעוד. רבים לא יודעים על Native Account Abstraction zkSync ומפספסים את ההזדמנות ליישם חשבונות חכמים עם אימות מותאם אישית ישירות ברמת הפרוטוקול, ללא entrypoint נפרד.
אם נתקלתם בבעיות אלה, צרו קשר — נעזור.
איך אנחנו עושים את זה
אנחנו משתמשים בסט טכנולוגיות מוכח: תוסף Hardhat zkSync (לפרויקטים מורכבים) או Foundry zkSync (לאב-טיפוסים מהירים). אנו מגדירים את הגדרות האופטימיזציה (size/speed/balanced) לפי מאפייני הפרויקט — הן משפיעות על גודל החוזה בעד 40% ועל צריכת הגז בעד 50%. להלן השוואת כלים:
| כלי | קומפילציה | אימות | גמישות | אידיאלי עבור |
|---|---|---|---|---|
| Hardhat | zksolc, תמיכה מלאה | מובנה דרך התוסף | גבוהה, מודולים רבים | חוזי production עם תלויות רבות |
| Foundry zkSync | forge עם --zksync | דרך API | בינונית, פחות תוספים | אב-טיפוסים ובדיקות מהירים |
Foundry zkSync, לפי המדידות שלנו, פורס חוזים פי 2–3 מהר יותר בזכות שליחה ישירה של עסקאות, אבל Hardhat נותן שליטה מפורטת יותר על תלויות מפעל ואימות.
| מצב אופטימיזציה של zksolc | גודל חוזה | גז ביצוע | היכן ליישם |
|---|---|---|---|
| size | -40% | +20% | חוזים קלים עם מעט קריאות |
| speed | +10% | -30% | חוזים הנקראים לעתים קרובות (טוקנים, DEX) |
| balanced | קו בסיס | קו בסיס | אפשרות אוניברסלית |
מצב size מקטין את גודל החוזה ב-40% בהשוואה למצב balanced, אבל מגדיל את גז הביצוע ב-20%, מה שהופך אותו לאידיאלי עבור חוזים שנקראים לעתים רחוקות.
zksolc וחשיבותו
המהדר // hardhat.config.ts import { HardhatUserConfig } from 'hardhat/config' import '@matterlabs/hardhat-zksync' const config: HardhatUserConfig = { zksolc: { version: 'latest', settings: { optimizer: { enabled: true, mode: '3', }, }, }, networks: { zkSyncMainnet: { url: 'https://mainnet.era.zksync.io', ethNetwork: 'mainnet', zksync: true, verifyURL: 'https://zksync2-mainnet-explorer.zksync.io/contract_verification', }, zkSyncTestnet: { url: 'https://sepolia.era.zksync.dev', ethNetwork: 'sepolia', zksync: true, verifyURL: 'https://explorer.sepolia.era.zksync.dev/contract_verification', }, }, solidity: '0.8.24', } export default config ממיר Solidity ל-bytecode עבור EraVM המותאם אישית. זה אומר:
- תבניות סטנדרטיות (CREATE2 לפריסה דטרמיניסטית) דורשות תלויות מפעל מפורשות. בלעדיהן, הפריסה נכשלת עם
import { Wallet, Provider } from 'zksync-ethers' import { Deployer } from '@matterlabs/hardhat-zksync' import { HardhatRuntimeEnvironment } from 'hardhat/types' export default async function (hre: HardhatRuntimeEnvironment) { const provider = new Provider(hre.network.config.url) const wallet = new Wallet(process.env.DEPLOYER_PRIVATE_KEY!, provider) const deployer = new Deployer(hre, wallet) const artifact = await deployer.loadArtifact('MyContract') const deploymentFee = await deployer.estimateDeployFee(artifact, []) console.log(`Estimated deploy fee: ${ethers.formatEther(deploymentFee)} ETH`) const contract = await deployer.deploy(artifact, []) await contract.waitForDeployment() console.log(`Deployed to: ${await contract.getAddress()}`) }. - ה-opcode
curl -L https://raw.githubusercontent.com/matter-labs/foundry-zksync/main/install-foundry-zksync | bash forge create src/MyContract.sol:MyContract \ --rpc-url https://mainnet.era.zksync.io \ --private-key $PRIVATE_KEY \ --zksync \ --constructor-args "arg1" 123לא משמיד את החוזה — zkSync עוקב אחרי EIP-6049 ומחזיר שגיאה. -
import "@matterlabs/zksync-contracts/l2/system-contracts/interfaces/IAccount.sol"; contract MyAccount is IAccount { function validateTransaction( bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction ) external payable override returns (bytes4 magic) { // кастомная валидация } function executeTransaction( bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction ) external payable override { // исполнение } }עשוי שלא להיות נתמך בגרסאות zksolc ישנות יותר, מה ששובר חוזים עםpragma ^0.8.19. במקרים כאלה, השתמשו ב-pragma ^0.8.13או הוסיפו fallback.
מדריך המפתחים של ZkSync קובע: 'יש להצהיר על תלויות מפעל עבור כל החוזים שנוצרו דרך CREATE.'
פריסה דרך Hardhat
התקינו את התוסף והגדירו את הקונפיג:
// hardhat.config.ts
import { HardhatUserConfig } from 'hardhat/config'
import '@matterlabs/hardhat-zksync'
const config: HardhatUserConfig = {
zksolc: {
version: 'latest',
settings: {
optimizer: {
enabled: true,
mode: '3',
},
},
},
networks: {
zkSyncMainnet: {
url: 'https://mainnet.era.zksync.io',
ethNetwork: 'mainnet',
zksync: true,
verifyURL: 'https://zksync2-mainnet-explorer.zksync.io/contract_verification',
},
zkSyncTestnet: {
url: 'https://sepolia.era.zksync.dev',
ethNetwork: 'sepolia',
zksync: true,
verifyURL: 'https://explorer.sepolia.era.zksync.dev/contract_verification',
},
},
solidity: '0.8.24',
}
export default config
סקריפט פריסה באמצעות Deployer:
import { Wallet, Provider } from 'zksync-ethers'
import { Deployer } from '@matterlabs/hardhat-zksync'
import { HardhatRuntimeEnvironment } from 'hardhat/types'
export default async function (hre: HardhatRuntimeEnvironment) {
const provider = new Provider(hre.network.config.url)
const wallet = new Wallet(process.env.DEPLOYER_PRIVATE_KEY!, provider)
const deployer = new Deployer(hre, wallet)
const artifact = await deployer.loadArtifact('MyContract')
const deploymentFee = await deployer.estimateDeployFee(artifact, [])
console.log(`Estimated deploy fee: ${ethers.formatEther(deploymentFee)} ETH`)
const contract = await deployer.deploy(artifact, [])
await contract.waitForDeployment()
console.log(`Deployed to: ${await contract.getAddress()}`)
}הריצו: npx hardhat deploy-zksync --script deploy.ts --network zkSyncMainnet
פריסה דרך Foundry
התקינו את Foundry zkSync והריצו:
curl -L https://raw.githubusercontent.com/matter-labs/foundry-zksync/main/install-foundry-zksync | bash
forge create src/MyContract.sol:MyContract \
--rpc-url https://mainnet.era.zksync.io \
--private-key $PRIVATE_KEY \
--zksync \
--constructor-args "arg1" 123אימות דרך API נעשה על ידי שליחת בקשת POST אל https://zksync2-mainnet-explorer.zksync.io/contract_verification עם גוף JSON.
Native Account Abstraction ב-zkSync
Native AA עובד ברמת הפרוטוקול — כל חשבון יכול להיות חוזה חכם. כדי ליישם אותו, צריך לממש את הממשק IAccount:
import "@matterlabs/zksync-contracts/l2/system-contracts/interfaces/IAccount.sol";
contract MyAccount is IAccount {
function validateTransaction(
bytes32 _txHash,
bytes32 _suggestedSignedHash,
Transaction calldata _transaction
) external payable override returns (bytes4 magic) {
// кастомная валидация
}
function executeTransaction(
bytes32 _txHash,
bytes32 _suggestedSignedHash,
Transaction calldata _transaction
) external payable override {
// исполнение
}
}זה חוסך עד 30% גז בהשוואה ל-ERC-4337 בזכות היעדר חוזה entrypoint נפרד.
למה zkSync דורש אופטימיזציית גז מיוחדת
גז דו-ממדי הוא תכונה מרכזית. gasPerPubdata יכול להוות עד 40% מעלות העסקה. ייעלו את ה-calldata: הימנעו מארגומנטים ארוכים של מחרוזות וממערכים בקונסטרוקטורים. השתמשו במצב האופטימיזציה 'size' כדי לחסוך במקום אם החוזה נפרס פעם אחת ונקרא לעתים רחוקות. הבנת מודל הגז zkSync היא קריטית לייעול עלויות.
טעויות אופייניות בפריסה על zkSync
- תלויות מפעל חסרות — הגורם השכיח ביותר לכישלון פריסה. עבור כל חוזה שנוצר דרך CREATE/CREATE2, יש להוסיף את כתובתו למערך התלויות במהלך הפריסה.
- התעלמות מגז דו-ממדי — גז לפרסום נתונים (gasPerPubdata) יכול להוות עד 40% מעלות העסקה.
- שימוש ב-opcodes לא נתמכים — SELFDESTRUCT, PUSH0, חלק מהגרסאות של DELEGATECALL עשויות לא לעבוד או לעבוד אחרת. תמיד בדקו על testnet.
רשימת בדיקה לתאימות zkSync
- בדקו תלויות מפעל עבור כל החוזים הדינמיים
- ודאו ש-opcodes לא נתמכים (SELFDESTRUCT, PUSH0) אינם בשימוש
- הגדירו את האופטימייזר של zksolc (מצב size/speed/balanced)
- בדקו על zkSync Sepolia testnet
- אמתו את החוזה לאחר הפריסה
מה כלול בעבודת הפריסה?
שלב 1. ניתוח וביקורת של חוזים קיימים לתאימות zkSync. אנו בודקים אבטחה on-chain ו-off-chain, ומזהים opcodes בעייתיים. שלב 2. הגדרת מהדר zksolc ואופטימיזציה של מודל הגז. אנו בוחרים את מצב האופטימיזציה ומגדירים תלויות מפעל. שלב 3. הכנת סקריפטים לפריסה (Hardhat/Foundry). כולל הערכת גז, תלויות מפעל, הגדרות רשת. שלב 4. אימות חוזה zkSync בסייר הבלוקים. אנו משתמשים בתוסף hardhat-zksync-verify או בקריאות API ישירות. שלב 5. כתיבת תיעוד פריסה והמלצות תפעוליות. אנו מתעדים את כל הפרמטרים והתלויות. שלב 6. תמיכה טכנית במהלך ההשקה (שבועיים). אנו עוזרים לשלב את החוזה בממשקים.
עם ניסיון של 7+ שנים בבלוקצ'יין ויותר מ-200 חוזים חכמים שנפרסו, הצוות שלנו מבטיח אחוזי הצלחה של 100% ביותר מ-50 פריסות L2. לפרויקטים מורכבים, אנו מוסיפים אימות פורמלי באמצעות solc-verify או Certora.
עלות פריסה עבור חוזה ERC-20 טיפוסי מתחילה ב-$199. האופטימיזציה שלנו יכולה לחסוך לכם עד $300 בחודש בעמלות גז.
לוח זמנים: 1 עד 5 ימים תלוי במורכבות.
קבלו ייעוץ — צרו קשר לביקורת תאימות החוזה שלכם ל-zkSync. פריסת חוזה turnkey עם אחריות לתאימות.







