Compilation
Understand the key differences when compiling contracts with foundry-zksync.
zksolc
is the compiler used by Validium to convert solidity code to zkEVM-compatible bytecode. It uses the same input format as solc
but the output bytecodes and their respective hashes. Internally it uses a custom-compiled solc
.
Below are the common compilation differences development teams will need to address when making use of Foundry ZKsync.
Contract Bytecode Access
Contract bytecode cannot be accessed on the Validium architecture due to the way zkEVM handles certain instructions like EXTCODECOPY
. As a result, using address(..).code
in a Solidity contract will produce a compile-time error with zksolc
.
Issue
The EXTCODECOPY
instruction is not supported in Validium's architecture. Any attempt to access a contract's bytecode using address(..).code
will fail to compile.
Problematic Code
This code will fail during compilation because address(..).code
is unsupported in Validium:
Compilation Error
When you attempt to compile this code, you will see the following error message:
Solution
To work around this limitation, you can use Foundry's FFI (Foreign Function Interface) functionality to access contract bytecode and hash it externally, and then pass it back into the contract. This approach leverages cheatcodes to read the bytecode from a file.
Fixed Code Example
Here's how you can modify the code to avoid the use of address(..).code
:
Additional Configuration
This solution requires enabling read permissions in the foundry.toml
file for the file access during testing:
Contract Size Limit
The zksolc
compiler enforces a limit on the number of instructions a contract can have, capped at 2^16 instructions. If a contract exceeds this limit, the compilation will fail.
Issue
Contracts with a large number of instructions will not compile on ZKsync due to the 65535 addressable space limitation imposed by zksolc
.
Problematic Scenario
If you attempt to compile a large contract that exceeds this instruction limit, the compilation will fail with an error.
Example of Compilation Error
This error indicates that the contract's instruction count has exceeded the maximum allowed limit.
Solution
There are three possible solutions to address this issue:
Attempt Compilation with
--zk-force-evmla=true
: You can attempt to compile the contract using ZKsync's EVM legacy architecture by adding the--zk-force-evmla=true
flag. This can sometimes bypass the contract size limit by compiling in a different mode. Example command:Use the
--zk-fallback-oz=true
flag: If the contract size still exceeds the limit, try compiling with optimization level-Oz
by using the--zk-fallback-oz=true
flag. This tells the compiler to fall back to-Oz
optimization when the bytecode is too large, potentially reducing the contract size further. Example command:Split the Contract into Smaller Units: If neither of the above flags resolves the issue, the contract must be refactored into smaller, modular contracts. This involves separating your logic into different contracts and using contract inheritance or external contract calls to maintain functionality.
Example of Refactoring
Here’s an example of splitting a large contract into smaller units:
Before (single large contract):
After (split into smaller contracts):
Non-inlineable Libraries
Libraries that contain public or external methods cannot be inlined when compiling to ZKsync VM bytecode. Although Solidity can inline libraries during EVM compilation, this inlining is not supported in the Yul intermediate representation, which is used by zksolc
to compile for ZKsync.
Issue
On ZKsync, if your project contains non-inlineable libraries, the compilation will fail because these libraries cannot be inlined during the Yul to ZKsync bytecode compilation step.
Problematic Scenario
Consider the following library that calculates the square of a number:
Now, assume you have a smart contract that uses this library:
When you try to compile this project, the compiler will fail because the MiniMath
library is not inlined due to the public
method.
Example of Compilation Error
This error indicates that the MiniMath
library is missing because it cannot be inlined and must be deployed separately.
Solution
Libraries with public or external methods must be deployed separately, and their addresses must be passed to the compiler. The library methods will be called through their deployed address, replacing inlining.
Steps to Fix
Deploy the Missing Libraries: Run the following command to deploy the missing library:
This command will deploy the library (
MiniMath
in this case) to the specified network.Compile the Main Contract: After deploying the library, proceed with compiling the main contract by specifying the deployed library addresses during compilation:
The deployed address will be linked to the main contract, and library methods will be invoked via external calls rather than inline.
Last updated