hardhat-zksync-solc

Guide on using the hardhat-zksync-solc plugin for compiling Solidity smart contracts on ZKsync Era.

Description

The hardhat-zksync-solc plugin extends Hardhat's compilation capabilities to support ZKsync Era smart contracts. Key features include:

  • Compilation of Solidity contracts with ZKsync Era-specific compiler
  • Support for ZKsync system contracts and libraries
  • Integration with ZKsync Era VM extensions
  • Library dependency detection and management
  • Flexible optimization modes for different contract sizes

Resources:

Installation

Prerequisites

  • Node.js version 18 or higher
  • Hardhat version 2.16.0 or higher

Setup

Add the latest version of this plugin to your project with the following command:

yarn add -D @matterlabs/hardhat-zksync-solc

Import the package in your hardhat.config.ts file:

import "@matterlabs/hardhat-zksync-solc";

Configuration

Configuration Options

NameTypeDescriptionDefaultNotes
versionstring (optional)zksolc compiler version"latest"Version from zksolc-bin repository
settings.compilerPathstring (optional)Path to zksolc binarynone
settings.librariesobject (optional)Non-inlinable library dependencies{}Key-value pairs of library addresses
settings.missingLibrariesPathstring (optional)Cache path for missing libraries"./.zksolc-libraries-cache/missingLibraryDependencies.json"Used by hardhat-zksync-deploy
settings.enableEraVMExtensionsboolean (optional)Enables Yul instructions for ZKsync system contractsfalseRequired for system contracts
settings.forceEVMLAboolean (optional)Falls back to EVM legacy assemblyfalseMay impact contract features
settings.optimizer.enabledboolean (optional)Enables compiler optimizationstrueRecommended for most cases
settings.optimizer.mode"3" | "z" (optional)Optimization mode"3""z" for large contracts
settings.optimizer.fallback_to_optimizing_for_sizeboolean (optional)Compile with mode "z" if bytecode is too largefalseRequires zksolc ≥1.3.21
settings.suppressedWarningsstring (optional)Warnings to suppressSupports "txorigin", "sendtransfer"
settings.suppressedErrorsstring (optional)Errors to suppressSupports "txorigin", "sendtransfer"
settings.contractsToCompilestring (optional)Specific contracts to compileContract names to include
settings.metadata.bytecodeHash"none" (optional)Controls metadata hash in bytecodeundefinedRemoves metadata hash if "none"

Example Configuration

import "@matterlabs/hardhat-zksync-solc";
import { HardhatUserConfig } from "hardhat/config";

const config: HardhatUserConfig = {
  solidity: {
    version: "0.8.29"
  },
  zksolc: {
    version: "1.5.13",
    settings: {
      // Compiler Settings
      compilerPath: "zksolc",
      libraries: {
        "contracts/Libraries.sol": {
          "SafeMath": "0x...",
          "StringUtils": "0x..."
        }
      },
      missingLibrariesPath: "./.zksolc-libraries-cache/missingLibraryDependencies.json",

      // Optimization Settings
      optimizer: {
        enabled: true,
        mode: "3",
        fallback_to_optimizing_for_size: true
      },

      // ERA VM Settings
      enableEraVMExtensions: false,
      forceEVMLA: false,

      // Warning & Error Management
      suppressedWarnings: ["txorigin"],
      suppressedErrors: [],

      // Compilation Control
      contractsToCompile: ["MyContract", "MyOtherContract"],

      // Metadata Settings
      metadata: {
        bytecodeHash: "none"
      }
    }
  },
  networks: {
    ZKsyncTestnet: {
      url: "https://testnet.era.zksync.dev",
      ethNetwork: "sepolia",
      zksync: true
    }
  }
};

export default config;

Network Configuration

Configure the zksync parameter in the networks to enable the zksolc compiler:

networks: {
  sepolia: {
    url: "https://sepolia.infura.io/v3/<API_KEY>",
    zksync: false, // disables zksolc compiler
  },
  ZKsyncTestnet: {
    url: "https://sepolia.era.zksync.dev",
    ethNetwork: "sepolia",
    zksync: true, // enables zksolc compiler
  }
}

Important Notes

forceEVMLA usageSetting the forceEVMLA field to true can have the following negative impacts:
  • No support for recursion
  • No support for internal function pointers
  • Possible contract size and performance impact
For Solidity versions older than 0.8, only this compilation mode is available and it is used by default.
fallback_to_optimizing_for_size option is supported for zksolc compiler version 1.3.21 or higher.

Compiler Integrations

The zksolc compilers are stored in the cache folder with the path {cache}/hardhat-nodejs/compilers-v2/zksolc. In this location, you can inspect the locally stored compiler versions.

{cache} is a placeholder for a path that is resolved by Hardhat.

The compilerVersion.json file is used by the plugin to get the latest available version and the minimum required compiler version. This file undergoes invalidation every 24 hours (currently), subsequently being updated with fresh information. This approach is implemented to provide a caching mechanism, avoiding the risk of encountering GitHub throttling issues during fetching new releases.

ZKsync Era Solidity Compiler

Due to several codegen limitations of the upstream Solidity compiler, our team had to fork it in order to effectively address and resolve these constraints.

For usage of EraVM compiler, eraVersion should be added inside solidity property in the hardhat.config.ts file:

solidity: {
    version: "0.8.29",

}
FieldTypeDescriptionDefaultNotes
eraVersionstringVersion of the Era Solidity compiler1.0.1Must be a specific version (e.g. "1.0.0"). Using "latest" is not supported. Required for using EraVM compiler.
warning EraVM compiler usageTo use the EraVM compiler, the zksolc compiler version must be equal to or greater than 1.3.22.

Additions

Extended Tasks

The plugin modifies the following Hardhat tasks:

Task NameDescriptionParameters
compileCompiles Solidity contracts for ZKsync EraNone
cleanClears the ZKsync compilation artifactsNone

Commands

yarn hardhat compile

Compiles all the smart contracts in the contracts directory and creates the artifacts-zk folder with all the compilation artifacts, including factory dependencies for the contracts, which could be used for contract deployment.

To understand what the factory dependencies are, read more about them here documentation.

Usage

Basic Compilation

  1. Create your Solidity contracts in the contracts directory
  2. Configure hardhat.config.ts with ZKsync settings
  3. Run compilation:
    npx hardhat compile
    
  4. Find compilation artifacts in artifacts-zk/contracts

Working with Libraries

  1. Define library dependencies in configuration:
    zksolc: {
      settings: {
        libraries: {
          "contracts/MyContract.sol": {
            "MyLibrary": "0x..."
          }
        }
      }
    }
    
  2. For missing non-inline libraries:
    • The plugin will detect them during compilation
    • Use hardhat-zksync-deploy plugin's deploy-zksync:libraries task
    • Libraries will be deployed in correct dependency order

Optimization Strategies

  1. For standard contracts:
    optimizer: {
      enabled: true,
      mode: "3"
    }
    
  2. For large contracts:
    optimizer: {
      enabled: true,
      mode: "z",
      fallback_to_optimizing_for_size: true
    }
    

System Contracts Development

When developing system contracts:

  1. Enable EraVM extensions:
    settings: {
      enableEraVMExtensions: true
    }
    

Troubleshooting

Invalid zksolc compiler version

Problem: Error message "Invalid zksolc compiler version"

Solutions:

  1. Update version in config:
    zksolc: {
      version: "1.5.13" // Use latest compatible version
    }
    
  2. Check minimum required version in compiler documentation

Unexpected end of JSON input

Problem: Compilation fails with "unexpected end of JSON input"

Solutions:

  1. Update plugin:
    npm install @matterlabs/hardhat-zksync-solc@latest
    
  2. If "Library not found" error occurs:

Large Contract Size

Problem: Contract bytecode exceeds size limits

Solutions:

  1. Enable size optimization:
    optimizer: {
      mode: "z",
      fallback_to_optimizing_for_size: true
    }
    
  2. Split contract into smaller components
  3. Remove unused functions and variables

Compilation Fails with Legacy Assembly

Problem: Yul compilation pipeline errors

Solutions:

  1. Enable legacy assembly:
    settings: {
      forceEVMLA: true
    }
    
  2. Be aware of limitations:
    • No recursion support
    • No internal function pointers
    • Possible performance impact

Missing Library Dependencies

Problem: Compilation fails due to missing libraries

Solutions:

  1. Check library configuration:
    settings: {
      libraries: {
        "contracts/MyContract.sol": {
          "MyLibrary": "0x..."
        }
      }
    }
    
  2. Use the library deployment task:
    npx hardhat deploy-zksync:libraries
    
  3. Verify library addresses are correct for the target network

Cache Issues

Problem: Unexpected compilation results or errors

Solutions:

  1. Clear cache:
    npx hardhat clean
    
  2. Remove cache directories manually:
    rm -rf artifacts-zk cache-zk
    
  3. Recompile from scratch

For more help, please refer to the GitHub issues.


Made with ❤️ by the ZKsync Community