5/5
## Setting Up Your zkSync Development Environment with Foundry To begin testing your existing smart contract project on zkSync, the initial crucial step is to configure your development environment. This involves installing a dedicated zkSync-compatible fork of Foundry. This specialized version ensures that all tools, particularly `forge` and `cast`, are equipped to handle zkSync's unique architecture and compilation requirements. Execute the following command in your terminal to install or update to the zkSync-enabled Foundry suite: ```bash foundryup -z zksync ``` Upon running this command, `foundryup` will download and install the necessary zkSync-specific components. You should see output similar to the following, confirming a successful installation: ``` foundryup-zksync: installing foundry (version nightly, tag nightly) foundryup-zksync: downloading latest forge, and cast ... foundryup-zksync: installed - forge 0.8.2 (...) foundryup-zksync: installed - cast 0.8.2 (...) foundryup-zksync: done! ``` This output confirms that the zkSync versions of `forge` and `cast` are now installed and ready for use in your project. ## Compiling Smart Contracts for the zkSync Era With your zkSync-compatible Foundry environment established, the next step is to compile your smart contracts. This is not a standard compilation; it must be performed specifically for the zkSync environment. This process utilizes `zksolc`, the zkSync Solidity compiler, which is distinct from the Ethereum mainnet's `solc` compiler. `zksolc` is designed to handle zkSync-specific opcodes, features, and produce bytecode compatible with the zkSync Virtual Machine. To compile your project's smart contracts for zkSync, use the following `forge build` command, incorporating the `--zksync` flag: ```bash forge build --zksync ``` This command instructs Foundry to process your contracts and all their dependencies using `zksolc`. A successful compilation will typically produce output similar to this, indicating the number of files compiled and the Solc version used by `zksolc` internally: ``` [⠘] Compiling... [⠘] Compiling 53 files with 0.8.24 [⠊] Solc 0.8.24 finished in 2.09s Compiler run successful! ``` ## Understanding zkSync Compiler Warnings: A Practical Guide After a successful compilation for zkSync, you might encounter several warnings from the `zksolc` compiler. It's a critical best practice in smart contract development to thoroughly investigate and address all compiler warnings. Indiscriminately ignoring warnings can lead to vulnerabilities or unexpected behavior. However, in certain specific contexts, particularly when adapting existing projects to new environments like zkSync, some warnings can be understood and deemed acceptable after careful analysis. Let's examine common warnings you might see and how to interpret them. ### Warning: `ecrecover` Usage and Account Abstraction One common warning relates to the use of the `ecrecover` precompile: ``` Warning: It looks like you are using `ecrecover` to validate a signature of a user account. zkSync Era comes with native account abstraction support, therefore it is highly recommended NOT to rely on the fact that the account has an ECDSA private key attached to it since accounts might implement other signature schemes. Read more about Account Abstraction at https://v2-docs.zksync.io/dev/developer-guides/aa.html ``` **Interpreting the Warning:** zkSync Era natively supports Account Abstraction (AA). This powerful feature allows user accounts to be smart contracts themselves, enabling them to implement custom validation logic, including signature schemes beyond the standard Elliptic Curve Digital Signature Algorithm (ECDSA). The `ecrecover` function in Solidity is specifically designed to recover an Ethereum address from an ECDSA signature. The warning, therefore, highlights a potential incompatibility: if a signature originates from a zkSync account utilizing a non-ECDSA signature scheme (which is possible with AA), `ecrecover` might fail or produce misleading results. **Contextual Justification for this Project:** In the context of many projects, especially those involving interactions based on Layer 1 activity (like a Merkle airdrop whose proofs are generated from L1 data), this warning can often be safely acknowledged. The key consideration is the origin of the signatures being verified. If your system expects signatures to originate from Externally Owned Accounts (EOAs) on Ethereum L1, these EOAs inherently use ECDSA. Even with Account Abstraction active on zkSync, if the signature being verified was generated by an L1 EOA (e.g., for a Merkle proof claim based on L1 account activity), the `ecrecover` logic remains valid for that specific signature. The crucial assumption here is that the input data providing signatures (perhaps from an `input.json` file or similar configuration) corresponds to standard L1 EOAs. ### Warning: Native Ether Transfers with `send` or `transfer` Another frequent warning concerns the use of Solidity's native `send` or `transfer` functions for transferring Ether: ``` Warning: It looks like you are using `<address payable>.send/transfer(<0>)` without providing the gas amount. Such calls will fail depending on the pubdata costs. This might be a false positive if you are using an interface (like IERC20) instead of the native Solidity `send/transfer`. Please use `<address payable>.call{value: <0>}("")` instead, but be careful with the reentrancy attack. `send` and `transfer` send limited amount of gas that prevents reentrancy, whereas `<address>.call{value: <0>}` sends all gas to the callee. Learn more on https://docs.soliditylang.org/en/latest/security-considerations.html#reentrancy ``` **Interpreting the Warning:** This warning addresses potential issues when sending Ether using the low-level `send()` or `transfer()` functions in Solidity. These functions have a fixed, limited gas stipend (2300 gas). On zkSync, this fixed stipend may be insufficient due to variable pubdata costs associated with state changes, potentially leading to unexpected transaction failures. The compiler correctly suggests using `<address payable>.call{value: <amount>}("")` for more robust Ether transfers on zkSync, while also wisely cautioning about the reentrancy vulnerabilities associated with `call` (as it forwards all available gas). Importantly, the warning itself notes that this could be a "false positive" if your contract is interacting with token contracts via interfaces (like `IERC20`) rather than performing native Ether transfers. **Contextual Justification for this Project:** For many projects, such as a token airdrop contract, this warning is indeed a false positive. If your contract's primary function involves transferring ERC20 tokens (e.g., by calling `transfer` or `transferFrom` on an `IERC20` interface) and does *not* involve sending native Ether using Solidity's built-in `send()` or `transfer()`, then this warning is not directly applicable to your core logic. The compiler flags it because it detects the `transfer` keyword (or `send`), but it cannot always semantically distinguish between an ERC20 token transfer (e.g., `IERC20(tokenAddress).transfer(recipient, amount)`) and a native Ether transfer (`payable(recipient).transfer(amount)`). ## Executing Your Smart Contract Tests on zkSync Once your smart contracts are compiled for zkSync and you've carefully analyzed any compiler warnings, the final step in this verification process is to execute your existing test suite within the zkSync environment. This validates that your contract logic behaves as expected on the Layer 2 network, considering its specific execution model. To run your Foundry tests on zkSync, use the `forge test` command, again incorporating the `--zksync` flag. It's also often helpful to increase verbosity to see detailed output and logs from your tests using the `-vv` flag (or `-vvv` for even more detail): ```bash forge test --zksync -vv ``` Foundry will then execute your tests using its zkSync testing backend. If no contract files have changed since the last compilation, you'll see a confirmation that compilation is skipped for both standard and zkSync environments, followed by the test execution results: ``` [⠘] Compiling... No files changed, compilation skipped [⠘] Compiling (zksync)... No files changed, compilation skipped Ran 1 test for test/MerkleAirdrop.t.sol:MerkleAirdropTest [PASS] testUsersCanClaim() (gas: 33947) Logs: Ending Balance: 2500000000000000 Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 76.91ms (25.63ms CPU time) Ran 1 test suite in 87.05ms (76.91ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests) ``` **Interpreting Test Results:** The output above demonstrates a successful test run. Key indicators include: * `[PASS] testUsersCanClaim()`: This line shows that the specific test function `testUsersCanClaim()` within the `MerkleAirdropTest` contract passed successfully. The associated gas cost on zkSync is also reported (e.g., `gas: 33947`). * `Logs:`: Any `console.log` statements (or other events/logs if configured) from your Solidity tests will appear here. This is invaluable for debugging and verifying intermediate states (e.g., "Ending Balance: 2500000000000000"). * `Suite result: ok. 1 passed; 0 failed; 0 skipped`: This summary provides an overview of the entire test suite's execution, confirming that all tests passed. A successful test outcome like this provides strong evidence that your smart contract's core logic, in this instance for a Merkle airdrop, is compatible with and functions correctly within the zkSync environment. ## Verifying zkSync Compatibility: A Recap This lesson has detailed the essential steps for adapting and testing an existing Foundry-based smart contract project specifically for zkSync. By first installing the zkSync-specific Foundry tooling (`foundryup -z zksync`), then compiling your contracts with the zkSync Solidity compiler (`zksolc`) via `forge build --zksync`, and subsequently performing a careful analysis of any compiler warnings (particularly those concerning `ecrecover` in the context of Account Abstraction, and the behavior of native Ether `send`/`transfer` functions), you prepare your project for zkSync execution. The final validation comes from running your existing test suite using `forge test --zksync`. Successful execution of these steps, culminating in passing tests, indicates that your smart contract is well-prepared for deployment and operation on zkSync Era. This process leverages key zkSync infrastructure, such as its specialized compiler and runtime environment, while also necessitating an awareness of advanced features like Account Abstraction and their implications for contract design and security.
A clear-cut guide to Bringing Your Foundry Project to zkSync - Install the zkSync-enabled Foundry (with `foundryup -z zksync`), compile your contracts for the zkSync Era (`forge build --zksync`), and effectively address compiler warnings. Execute your test suite via `forge test --zksync` to confirm seamless operation on zkSync.
Previous lesson
Previous
Next lesson
Next
Give us feedback
Course Overview
About the course
Advanced smart contract development
How to develop a stablecoin
How to develop a DeFi protocol
How to develop a DAO
Advanced smart contracts testing
Fuzz testing
Manual verification
Web3 Developer Relations
$85,000 - $125,000 (avg. salary)
Web3 developer
$60,000 - $150,000 (avg. salary)
Smart Contract Engineer
$100,000 - $150,000 (avg. salary)
Smart Contract Auditor
$100,000 - $200,000 (avg. salary)
Security researcher
$49,999 - $120,000 (avg. salary)
Web3 engineer, educator, and Cyfrin co-founder. Patrick's smart contract development and security courses have helped hundreds of thousands of engineers kickstarting their careers into web3.
Guest lecturers:
Last updated on May 20, 2025
Solidity Developer
Advanced FoundryDuration: 36min
Duration: 3h 06min
Duration: 5h 02min
Duration: 6h 02min
Duration: 2h 47min
Duration: 1h 23min
Duration: 4h 28min
Duration: 1h 19min
Duration: 1h 10min
Course Overview
About the course
Advanced smart contract development
How to develop a stablecoin
How to develop a DeFi protocol
How to develop a DAO
Advanced smart contracts testing
Fuzz testing
Manual verification
Web3 Developer Relations
$85,000 - $125,000 (avg. salary)
Web3 developer
$60,000 - $150,000 (avg. salary)
Smart Contract Engineer
$100,000 - $150,000 (avg. salary)
Smart Contract Auditor
$100,000 - $200,000 (avg. salary)
Security researcher
$49,999 - $120,000 (avg. salary)
Web3 engineer, educator, and Cyfrin co-founder. Patrick's smart contract development and security courses have helped hundreds of thousands of engineers kickstarting their careers into web3.
Guest lecturers:
Last updated on May 20, 2025