Hello! Welcome to the first lesson in our module on the multi-chain ecosystem. Given your extensive background in development, you're likely familiar with the concept of deploying applications to different environments. In the world of blockchain, this often means deploying to different networks.
Today, we'll focus on a critical part of the modern Ethereum landscape: Layer 2 (L2) networks. Our goal is to learn how to deploy and verify a smart contract on an L2, specifically using Arbitrum and Optimism as our examples.
We'll cover:
- The role of L2s in scaling Ethereum.
- The importance of contract verification for transparency and trust.
- The practical steps to configure your development environment (Hardhat and Foundry) for L2 deployment.
- The process of deploying a contract and verifying it on an L2 block explorer like Arbiscan.
This lesson will build a practical foundation for the rest of the module, where we'll explore how these different chains can communicate with one another.
Why Deploy to Layer 2?
Before we jump into the "how," let's briefly touch on the "why." As Ethereum has grown in popularity, the demand for block space has led to higher transaction fees (gas costs) and slower confirmation times. Layer 2 solutions are designed to address this by processing transactions "off-chain" (on their own separate, faster chain) and then periodically submitting a summary of those transactions back to the main Ethereum blockchain (Layer 1).
For a quick and clear overview of how Arbitrum fits into the Ethereum ecosystem, please read the short section below from the official Arbitrum documentation.
Build a decentralized app with Solidity (Quickstart)
This brief reading from the Arbitrum documentation provides a high-level comparison between Ethereum and Arbitrum, clarifying Arbitrum's role as a scaling solution.
Please read the section titled 'Ethereum and Arbitrum in a nutshell'. It clearly defines the purpose of each network and why a developer might choose to build on an L2 like Arbitrum.
In essence, by deploying on an L2, you offer your users significantly lower fees and faster interactions while still benefiting from the security of the underlying Ethereum network.
The Importance of Contract Verification
Once a contract is deployed, its bytecode is publicly visible on the blockchain, but it's not human-readable. Verification is the process of linking that bytecode back to the original Solidity source code.
Why is this essential?
- Trust and Transparency: It proves that the deployed code does exactly what the source code claims. Users and other developers can inspect the code to check for vulnerabilities or malicious logic.
- Interoperability: A verified contract provides a clean Application Binary Interface (ABI) on the block explorer, allowing anyone to easily read its state and call its functions directly from the explorer's UI.
To see the difference firsthand, watch the first minute of the following video. It clearly demonstrates the user experience of an unverified contract versus a verified one.
How to Verify Ethereum Smart Contracts
This video, from Moralis for Developers, provides a great visual explanation of why contract verification is a critical step after deployment.
Watch the segment from the beginning until 01:01. Pay close attention to the difference in the block explorer UI between the unverified and verified contracts. This will make the value of verification immediately apparent.
Now that we understand the what and why, let's get hands-on.
Deploying to Arbitrum with Hardhat
We'll start by deploying a contract to the Arbitrum Sepolia testnet using Hardhat. The overall process is very similar to deploying to an L1 testnet, with the main differences being in the configuration.
The following video provides a complete walkthrough. While it uses a slightly outdated testnet (Rinkeby), the core steps—configuration, funding, deployment, and verification—remain the same. We will adapt this process for the modern Arbitrum Sepolia testnet.
Deploy Smart Contract to Arbitrum | Layer 2
This video from 'Smart Contract Programmer' demonstrates the end-to-end process of deploying a contract to an L2 using Hardhat.
Watch the video from 00:00 to 06:02. Focus on the general workflow: Configuring hardhat.config.js for the L2 network. Getting testnet funds and bridging them. Running the deployment script. Manually verifying the contract on the block explorer. We will update the specific values for the current testnet in the steps below.
Now, let's apply those concepts to the Arbitrum Sepolia testnet.
1. Project Setup and Configuration
Assuming you have a standard Hardhat TypeScript project, your first step is to update hardhat.config.ts. You need to add a network configuration for Arbitrum Sepolia and an API key for Arbiscan to enable automated verification.
Here is a sample configuration. Notice the arbitrumSepolia network object and the etherscan object with a custom chain definition.
// hardhat.config.ts
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import "dotenv/config";
const SEPOLIA_RPC_URL = process.env.SEPOLIA_RPC_URL || "https://sepolia.infura.io/v3/your-key";
const ARBITRUM_SEPOLIA_RPC_URL = process.env.ARBITRUM_SEPOLIA_RPC_URL || "https://sepolia-rollup.arbitrum.io/rpc";
const PRIVATE_KEY = process.env.PRIVATE_KEY || "your-private-key";
const ARBISCAN_API_KEY = process.env.ARBISCAN_API_KEY || "your-arbiscan-key";
const config: HardhatUserConfig = {
solidity: "0.8.20",
networks: {
sepolia: {
url: SEPOLIA_RPC_URL,
accounts: [PRIVATE_KEY],
},
arbitrumSepolia: {
url: ARBITRUM_SEPOLIA_RPC_URL,
accounts: [PRIVATE_KEY],
},
},
etherscan: {
apiKey: {
// No API key required for Sepolia, but good to have for other networks
sepolia: '',
// Arbiscan API key
arbitrumSepolia: ARBISCAN_API_KEY,
},
},
};
export default config;
What you need to do:
- Install dependencies: Make sure you have
dotenvinstalled (npm install dotenv). - Create
.envfile: Create a.envfile in your project root. - Get an RPC URL: You can get a free one from services like Alchemy or Infura for
ARBITRUM_SEPOLIA_RPC_URL. - Get an Arbiscan API Key: Create an account on Arbiscan (the block explorer for Arbitrum) and get a free API key. Add it to your
.envasARBISCAN_API_KEY. - Add your Private Key: Export the private key of your development wallet and add it to
.envasPRIVATE_KEY. Remember to prefix it with0x.
2. Fund Your Account on Arbitrum Sepolia
Transactions on L2 still cost gas, albeit much less than on L1. You'll need Arbitrum Sepolia ETH to pay for the deployment. The process is a two-step "bridge":
- Get Sepolia ETH (L1): Use a public faucet like sepoliafaucet.com to get test ETH on the base Sepolia network.
- Bridge to Arbitrum Sepolia (L2): Go to the Official Arbitrum Bridge and connect your wallet. Make sure you are on the Sepolia network, and then deposit your Sepolia ETH to Arbitrum Sepolia. The funds should arrive on the L2 within a few minutes.
You can add the Arbitrum Sepolia network to MetaMask using the details from the Arbitrum documentation (LINK) or by using a site like Chainlist.
3. Deploy and Verify
With your configuration set and your account funded, deployment is straightforward.
-
Run the deployment script:
npx hardhat run scripts/deploy.ts --network arbitrumSepoliaAfter a successful run, Hardhat will print the deployed contract address. Copy it.
-
Verify the contract:
Instead of the manual copy-paste method, we can use Hardhat's built-in plugin. This is far more reliable, especially for contracts with imports.npx hardhat verify --network arbitrumSepolia <YOUR_CONTRACT_ADDRESS> "Constructor argument 1" "Argument 2"Replace
<YOUR_CONTRACT_ADDRESS>with the address from the previous step and provide any constructor arguments your contract requires. If successful, you'll get a link to the verified contract on Arbiscan.
Test your understanding!
You've successfully deployed your contract to Arbitrum Sepolia, but the automated verification with npx hardhat verify... fails with an error: 'Contract source code not found'. What are two common reasons for this failure, and how would you troubleshoot them?
Show answer
- Propagation Delay: The block explorer's backend might not have indexed your new contract yet. This is the most common issue. The solution is simply to wait 30-60 seconds and run the
verifycommand again. - Configuration Mismatch: The
etherscanconfiguration inhardhat.config.tsmight be incorrect. You should check that theapiKeyforarbitrumSepoliais correct and that the network name matches exactly. A typo in the network name can cause Hardhat to look for the contract on the wrong chain.
Deploying to Optimism with Foundry
To show the versatility of the process, let's briefly look at deploying to another major L2, Optimism, using a different toolchain, Foundry. The principles are identical: configure the network, fund the account, and run a command.
The GitHub repository below contains helpful snippets for deploying to Optimism with various frameworks. We'll focus on the Foundry approach.
This GitHub Gist by 'thegeorgenikhil' serves as a concise cheat sheet for deploying to Optimism using different toolchains. We'll use it as a reference for the Foundry configuration.
Review Section 2, 'Deploying (along with verification) to Optimism using Foundry'. Note how environment variables are used for the private key, API key, and RPC URL. We will adapt this for the modern Foundry CLI commands.
Foundry's CLI, forge, is powerful and can handle deployment and verification in a single command.
-
Setup Environment Variables:
Foundry typically reads environment variables directly from your shell.export OP_SEPOLIA_RPC_URL="https://sepolia.optimism.io" export PRIVATE_KEY="0x..." export ETHERSCAN_API_KEY="your-etherscan-key"Note: Optimism's block explorer, Optimistic Etherscan, uses the same API key as Ethereum's Etherscan.
-
Fund Your Account:
The process is identical to Arbitrum's:- Get L1 Sepolia ETH from a faucet.
- Use the Official Optimism Superchain Bridge to transfer it to the Optimism Sepolia testnet.
-
Deploy and Verify with Forge:
Theforge createcommand deploys your contract. By adding the--verifyflag, Foundry will automatically attempt to verify it on the block explorer after deployment.forge create --rpc-url $OP_SEPOLIA_RPC_URL \ --private-key $PRIVATE_KEY \ --etherscan-api-key $ETHERSCAN_API_KEY \ --verify \ src/YourContract.sol:YourContractName \ --constructor-args "Argument 1"This single command handles everything. It compiles, deploys, and verifies, making for a very efficient workflow, which is one of Foundry's main strengths.
Conclusion
Congratulations on making it through this lesson! You are now equipped to deploy smart contracts to the leading Ethereum Layer 2 networks.
Key Takeaways:
- Deploying to an L2 is very similar to deploying to Ethereum L1, primarily requiring configuration changes for the specific network's RPC URL and Chain ID.
- Each L2 ecosystem has its own testnet (e.g., Arbitrum Sepolia, Optimism Sepolia), block explorer (e.g., Arbiscan, Optimistic Etherscan), and a bridge to move assets from L1.
- Contract verification is a crucial step for establishing trust and enabling interaction. Modern toolchains like Hardhat and Foundry provide plugins and flags to automate this process.
- Using automated verification is the professional standard, as it's faster and less error-prone than manually pasting code, especially for complex contracts with dependencies.
Preview of the Next Lesson:
Now that we've deployed a contract to a single L2, a natural next question arises: how can an application on Arbitrum interact with a contract on Optimism, or back on Ethereum? In our next lesson, we will describe the architectures and security trade-offs of different cross-chain communication patterns, setting the stage for building true multi-chain applications.
Can't find a good explanation? Sign up and we'll make it for you
Sign up