5/5
# Deploying Smart Contracts: Ethereum vs. zkSync and the Hidden Transaction Difference When developers move from Ethereum Mainnet to Layer 2 solutions like zkSync, the Solidity code often remains identical. However, the mechanism that transports that code to the network—the transaction itself—undergoes a fundamental change. In this lesson, we will set up a Foundry project, deploy a standard `Counter.sol` contract to both Ethereum Sepolia and zkSync Sepolia, and uncover a "sneaky" architectural difference by analyzing the resulting transaction types. ## Setting Up the Development Environment Before writing code, we must ensure our tooling allows us to interact with the zkSync Virtual Machine (zkEVM). Standard Foundry does not support zkSync out of the box; it requires a specific fork of the framework to handle the `zksolc` compiler and VM-specific adaptations. ### Project Initialization and Tooling First, initialize a standard project structure: ```bash mkdir eth-vs-zksync cd eth-vs-zksync code . forge init ``` To enable zkSync deployment, install the specific Foundry fork. This grants access to the `foundry-zksync` extension: ```bash foundryup-zksync ``` ### Configuring RPC Providers To interact with the testnets, we require Remote Procedure Call (RPC) URLs. Using a provider like **Alchemy**, generate endpoints for both **Sepolia** (Ethereum) and **zkSync Sepolia**. Create a `.env` file in your root directory to store these endpoints securely: ```env ZKSYNC_SEPOLIA=https://zksync-sepolia.g.alchemy.com/v2/YOUR_API_KEY SEPOLIA=https://eth-sepolia.g.alchemy.com/v2/YOUR_API_KEY ``` Load these variables into your current terminal session: ```bash source .env ``` ## Deploying the Contract to zkSync Sepolia We will use the default `Counter.sol` template generated by `forge init`. While the Solidity code is standard, the deployment command for zkSync requires specific flags to ensure the bytecode is compiled and formatted correctly for the zkEVM. Run the following command: ```bash forge create --zksync --legacy \ --rpc-url $ZKSYNC_SEPOLIA \ --broadcast \ --account dev-wallet \ src/Counter.sol:Counter ``` ### Understanding the Flags * **`--zksync`**: This is the critical switch. It instructs Foundry to use the `zksolc` compiler rather than the standard `solc`, ensuring compatibility with the zkSync VM. * **`--legacy`**: This flag ensures the transaction formatting is compatible with the current network expectations for this deployment. * **`--rpc-url`**: Directs the deployment to the zkSync testnet. Upon success, the terminal will return a **Transaction Hash**. Keep this hash accessible for analysis. ## Deploying the Contract to Ethereum Sepolia Now, we deploy the exact same contract to the standard Ethereum Sepolia testnet. Note that the command changes significantly because we are reverting to the standard Ethereum Virtual Machine (EVM) environment. Run the following command: ```bash forge create \ --rpc-url $SEPOLIA \ --broadcast \ --account dev-wallet \ src/Counter.sol:Counter ``` ### Key Differences Notice the omission of the `--zksync` and `--legacy` flags. By removing these, Foundry reverts to standard Solidity compilation and standard Ethereum transaction formatting. Once deployed, copy the resulting **Transaction Hash**. We now have two successful deployments of the same code on two different chains. ## The "Sneaky Difference": Analyzing Transaction Types The core lesson lies in inspecting what happened "under the hood." By using block explorers, we can view the raw data of the transactions we just generated. ### 1. The Ethereum Transaction Open Etherscan (or Blockscout) for Sepolia and paste your Ethereum deployment hash. Navigate to the detailed view of the transaction. Look for the **Transaction Type**. * **Observation:** You will see **Type 2 (EIP-1559)**. * **Context:** This is the industry standard for Ethereum transactions following the London Hard Fork. It utilizes a base fee and a priority fee (tip) structure. ### 2. The zkSync Transaction Open the zkSync Sepolia Explorer and paste your zkSync deployment hash. Look for the **Transaction Type**. * **Observation:** You will see **Type 113**. * **Context:** This is a custom transaction type specific to zkSync. ## Conclusion This exercise demonstrates a critical concept in Web3 development: **Same Code, Different Transport.** While your smart contract logic (`Counter.sol`) did not change, the "envelope" used to deliver that code to the chain differed radically. * **Ethereum** used the standard **EIP-1559 (Type 2)** envelope. * **zkSync** used a specialized **Type 113** envelope. This distinction is not merely cosmetic. Transaction Type 113 allows zkSync to support native features such as Account Abstraction and paymasters directly at the protocol level. As you deepen your knowledge of Layer 2 scaling solutions, understanding these unique transaction types explains why certain capabilities exist on L2s that are not yet possible on Ethereum L1.
When developers move from Ethereum Mainnet to Layer 2 solutions like zkSync, the Solidity code often remains identical. However, the mechanism that transports that code to the network—the transaction itself—undergoes a fundamental change.
In this lesson, we will set up a Foundry project, deploy a standard Counter.sol contract to both Ethereum Sepolia and zkSync Sepolia, and uncover a "sneaky" architectural difference by analyzing the resulting transaction types.
Before writing code, we must ensure our tooling allows us to interact with the zkSync Virtual Machine (zkEVM). Standard Foundry does not support zkSync out of the box; it requires a specific fork of the framework to handle the zksolc compiler and VM-specific adaptations.
First, initialize a standard project structure:
To enable zkSync deployment, install the specific Foundry fork. This grants access to the foundry-zksync extension:
To interact with the testnets, we require Remote Procedure Call (RPC) URLs. Using a provider like Alchemy, generate endpoints for both Sepolia (Ethereum) and zkSync Sepolia.
Create a .env file in your root directory to store these endpoints securely:
Load these variables into your current terminal session:
We will use the default Counter.sol template generated by forge init. While the Solidity code is standard, the deployment command for zkSync requires specific flags to ensure the bytecode is compiled and formatted correctly for the zkEVM.
Run the following command:
--zksync: This is the critical switch. It instructs Foundry to use the zksolc compiler rather than the standard solc, ensuring compatibility with the zkSync VM.
--legacy: This flag ensures the transaction formatting is compatible with the current network expectations for this deployment.
--rpc-url: Directs the deployment to the zkSync testnet.
Upon success, the terminal will return a Transaction Hash. Keep this hash accessible for analysis.
Now, we deploy the exact same contract to the standard Ethereum Sepolia testnet. Note that the command changes significantly because we are reverting to the standard Ethereum Virtual Machine (EVM) environment.
Run the following command:
Notice the omission of the --zksync and --legacy flags. By removing these, Foundry reverts to standard Solidity compilation and standard Ethereum transaction formatting.
Once deployed, copy the resulting Transaction Hash. We now have two successful deployments of the same code on two different chains.
The core lesson lies in inspecting what happened "under the hood." By using block explorers, we can view the raw data of the transactions we just generated.
Open Etherscan (or Blockscout) for Sepolia and paste your Ethereum deployment hash. Navigate to the detailed view of the transaction.
Look for the Transaction Type.
Observation: You will see Type 2 (EIP-1559).
Context: This is the industry standard for Ethereum transactions following the London Hard Fork. It utilizes a base fee and a priority fee (tip) structure.
Open the zkSync Sepolia Explorer and paste your zkSync deployment hash.
Look for the Transaction Type.
Observation: You will see Type 113.
Context: This is a custom transaction type specific to zkSync.
This exercise demonstrates a critical concept in Web3 development: Same Code, Different Transport.
While your smart contract logic (Counter.sol) did not change, the "envelope" used to deliver that code to the chain differed radically.
Ethereum used the standard EIP-1559 (Type 2) envelope.
zkSync used a specialized Type 113 envelope.
This distinction is not merely cosmetic. Transaction Type 113 allows zkSync to support native features such as Account Abstraction and paymasters directly at the protocol level. As you deepen your knowledge of Layer 2 scaling solutions, understanding these unique transaction types explains why certain capabilities exist on L2s that are not yet possible on Ethereum L1.
A practical deep-dive to Deploying Smart Contracts: Ethereum vs. zkSync and the Hidden Transaction Difference - Configure a specific Foundry environment to deploy identical smart contracts to both Ethereum and zkSync Sepolia. Compare the resulting transaction hashes to understand the architectural shift from EIP-1559 to zkSync's native Type 113.
Previous lesson
Previous
Next lesson
Next
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 February 17, 2026
Duration: 37min
Duration: 3h 06min
Duration: 5h 03min
Duration: 6h 22min
Duration: 2h 48min
Duration: 1h 24min
Duration: 4h 28min
Duration: 1h 20min
Duration: 1h 11min
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 February 17, 2026