Install op-deployer, prepare your environment, and deploy the L1 smart contracts for your rollup.
Welcome to the first step of creating your own L2 rollup testnet! In this section, you’ll install the op-deployer tool and deploy the necessary L1 smart contracts for your rollup.
Step 1 of 5: This tutorial is designed to be followed step-by-step. Each step builds on the previous one.
Quick Setup AvailableFor a complete automated setup that includes op-deployer deployment, check out the code/ directory. The automated setup handles all contract deployment and configuration automatically.
op-deployer simplifies the process of deploying the OP Stack. You define a declarative config file called an “intent,” then run a command to apply it. op-deployer compares your chain’s current state against the intent and makes the necessary changes to match.
There are a couple of ways to install op-deployer:
Use binary
Build from source
The recommended way to install op-deployer is to download the latest release from the monorepo’s release page.
Quick Setup AvailableFor automated installation, you can use the download script from the code directory. This script automatically downloads the latest version for your system.
Find the latest release that includes op-deployer (look for releases tagged with op-deployer/v*)
Under assets, download the binary that matches your system:
For Linux: op-deployer-linux-amd64
For macOS:
Apple Silicon (M1/M2): op-deployer-darwin-arm64
Intel processors: op-deployer-darwin-amd64
For Windows: op-deployer-windows-amd64.exe
Always download the latest version to ensure you have the most recent features and bug fixes.
Not sure which macOS version to use?
Open Terminal and run uname -m
If it shows arm64, use the arm64 version
If it shows x86_64, use the amd64 version
2
Create deployer directory and install binary
Create the rollup directory structure and enter the deployer directory:
Report incorrect code
Copy
Ask AI
# Create main rollup directorymkdir rollup && cd rollup# Create and enter the deployer directorymkdir deployer && cd deployer
Your directory structure will now look like this:
Report incorrect code
Copy
Ask AI
rollup/└── deployer/ # You are here
Move and rename the downloaded binary:
The downloaded file is likely in your Downloads folder:
macOS/Linux: /Users/YOUR_USERNAME/Downloads
Windows WSL: /mnt/c/Users/YOUR_USERNAME/Downloads
Report incorrect code
Copy
Ask AI
# Step 1: Extract the downloaded archive in the deployer directory# Replace FILENAME with the actual downloaded file name (includes version and arch)tar -xvzf /Users/USERNAME/Downloads/FILENAME.tar.gz# Step 2: Make the binary executable# Replace FILENAME with the extracted binary namechmod +x FILENAME# Step 3: Remove macOS quarantine attribute (fixes "can't be opened" warning)sudo xattr -dr com.apple.quarantine FILENAME# Step 4: Move the binary to your PATH# For Intel Macs:sudo mv FILENAME /usr/local/bin/op-deployer# For Apple Silicon Macs:sudo mv FILENAME /opt/homebrew/bin/op-deployer# Step 5: Verify installation (should print version info)op-deployer --version
Pro Tip: Use the automated download script from the code directory to avoid manual version management. It automatically detects your platform and downloads the latest version.
To install from source, you will need Go, just, and git.
After installing all of that, run following:
Report incorrect code
Copy
Ask AI
git clone https://github.com/ethereum-optimism/optimism.git # you can skip this if you already have the repocd optimism/op-deployerjust buildcp ./bin/op-deployer /usr/local/bin/op-deployer # or any other directory in your $PATH# Verify installationop-deployer --version
Before deploying your L1 contracts, you’ll need:L1 RPC URL: An Ethereum RPC endpoint for your chosen L1 network
Report incorrect code
Copy
Ask AI
# Examples:# Sepolia (recommended for testing)L1_RPC_URL=https://sepolia.infura.io/v3/YOUR-PROJECT-ID# or https://eth-sepolia.g.alchemy.com/v2/YOUR-API-KEY# Local networkL1_RPC_URL=http://localhost:8545
For testing, we recommend using Sepolia testnet. You can get free RPC access from:
The intent file defines your chain’s configuration.
1
Initialize intent file
Inside the deployer folder, run this command:
Report incorrect code
Copy
Ask AI
#You can use a 2-7 digit random number for your `<YOUR_CHAIN_ID>` op-deployer init \ --l1-chain-id 11155111 \ --l2-chain-ids <YOUR_CHAIN_ID> \ --workdir .deployer \ --intent-type standard-overrides
Show Understanding intent types
op-deployer supports three intent types:
standard: Uses default OP Stack configuration, minimal customization
standard-overrides: Recommended. Uses defaults but allows overriding specific values
custom: Full customization, requires manual configuration of all values
For most users, standard-overrides provides the best balance of simplicity and flexibility.
2
Update the intent file
Edit .deployer/intent.toml with your generated addresses. The op-deployer init command automatically populates this file with sensible defaults. Update the addresses while keeping the auto-generated contract locator values:
Report incorrect code
Copy
Ask AI
configType = "standard-overrides"l1ChainID = 11155111 # SepoliafundDevAccounts = false # Set to false for production/testnetuseInterop = falseopcmAddress = "0x3bb6437aba031afbf9cb3538fa064161e2bf2d78" # OPCM contract address on Sepolia# Contract locators - REQUIRED fields, automatically populated by op-deployer init# Keep these default values unless you need specific contract versions (advanced use case)l1ContractsLocator = "tag://op-contracts/v2.0.0"l2ContractsLocator = "tag://op-contracts/v1.7.0-beta.1+l2-contracts"# Superchain roles - only define if creating a standalone chain not part of OP Stack superchain# For standard OP Stack deployments, these are predefined and should not be set# [superchainRoles]# proxyAdminOwner = "0x..." # admin address# protocolVersionsOwner = "0x..." # admin address# guardian = "0x..." # admin address[[chains]] id = "0x000000000000000000000000000000000000000000000000000000000016de8d" baseFeeVaultRecipient = "0x..." # base_Fee_Vault_Recipient address l1FeeVaultRecipient = "0x..." # l1_Fee_Vault_Recipient address sequencerFeeVaultRecipient = "0x..." # sequencer_Fee_Vault_Recipient address eip1559DenominatorCanyon = 250 eip1559Denominator = 50 eip1559Elasticity = 6 [chains.roles] l1ProxyAdminOwner = "0x1eb2ffc903729a0f03966b917003800b145f56e2" l2ProxyAdminOwner = "0x2fc3ffc903729a0f03966b917003800b145f67f3" systemConfigOwner = "0x..." # system_config address unsafeBlockSigner = "0x..." # unsafe_block_signer address batcher = "0x..." # batcher address proposer = "0x..." # proposer address challenger = "0xfd1d2e729ae8eee2e146c033bf4400fe75284301"
Show Understanding the configuration values
Global Settings:
l1ChainID: The L1 network ID (11155111 for Sepolia)
fundDevAccounts: Creates test accounts with ETH if true (set to false for production)
useInterop: Enable interoperability features (false for standard deployments)
opcmAddress: OP Contracts Manager (OPCM) contract address on the L1 network (automatically populated for supported networks)
Contract Locators (Required):These fields are required and automatically populated by op-deployer init with default values compatible with your op-deployer version.
Removing them will cause the error: “Application failed: L1ContractsLocator undefined”.
Keep the auto-generated values unless you specifically need different contract versions.
For version compatibility details, see the op-deployer release notes.Superchain Roles (Advanced):These are commented out because for standard OP Stack deployments, superchain roles are predefined by the protocol. Only uncomment and define custom roles if you’re creating a standalone chain not part of the OP Stack superchain.Chain Configuration:
id: Unique identifier for your chain
*FeeVaultRecipient: Addresses receiving various protocol fees
eip1559*: Parameters for dynamic gas price calculation
Chain Roles:
l1ProxyAdminOwner: Can upgrade L1 contract implementations (usually same as superchain proxyAdminOwner)
l2ProxyAdminOwner: Can upgrade L2 contract implementations
systemConfigOwner: Manages system configuration parameters
unsafeBlockSigner: Signs pre-confirmation blocks (can be same as batcher)
batcher: Submits L2 transaction batches to L1
proposer: Submits L2 state roots to L1 for verification
challenger: Monitors dispute games and defends valid states
Replace all 0x... with actual addresses from your addresses.txt file.
Never use the default test mnemonic addresses in production or public testnets!
Before deploying, create a .env file in your deployer directory to store your environment variables:
Report incorrect code
Copy
Ask AI
# Create .env filecat << 'EOF' > .env# Your L1 RPC URL (e.g., from Alchemy, Infura)L1_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/YOUR_API_KEY# Private key for deployment.# Get this from your self-custody wallet, like Metamask.PRIVATE_KEY=WALLET_PRIVATE_KEYEOF
Never commit your .env file to version control. Add it to your .gitignore: