OPStack是Optimism开发的模块化区块链技术栈,允许开发者轻松创建自己的Layer2网络。本指南提供了在Ubuntu环境下从零开始搭建一个完整的Layer2网络,包括环境配置、合约部署、节点启动和基本操作验证。
OP Stack 是 Optimism 开发的模块化区块链技术栈,允许开发者轻松创建自己的 Layer2 网络。本指南提供了在 Ubuntu 环境下从零开始搭建一个完整的 Layer2 网络,包括环境配置、合约部署、节点启动和基本操作验证。
打开 Windows PowerShell 终端
# 查看可用的 Ubuntu 发行版
wsl --list --online
# 安装指定版本的 Ubuntu
wsl --install -d Ubuntu-24.04
打开 Ubuntu-24.04 子系统(在安装 pnpm 和 mise 时,需修改自己环境变量加载的路径)
# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装基础依赖
sudo apt install -y curl wget git build-essential
# 安装 go
wget https://go.dev/dl/go1.25.0.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.25.0.linux-amd64.tar.gz
rm go1.25.0.linux-amd64.tar.gz
echo -e '\n# Go Language\nexport PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
source ~/.bashrc
# 安装 node.js
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
# 安装 pnpm
curl -fsSL https://get.pnpm.io/install.sh | sh
source /home/eth/.bashrc
# 安装 foundry
curl -L https://foundry.paradigm.xyz | bash
source ~/.bashrc
~/.foundry/bin/foundryup
# 安装 make
sudo apt install -y make
# 安装 jq
sudo apt install -y jq
# 安装 direnv
sudo apt install -y direnv
echo -e '\n# Direnv hook\neval "$(direnv hook bash)"' >> ~/.bashrc
source ~/.bashrc
# 安装 just
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
. "$HOME/.cargo/env"
cargo install just
# 安装 mise
curl https://mise.run | sh
echo "eval \"\$(/home/eth/.local/bin/mise activate bash)\"" >> ~/.bashrc
source ~/.bashrc
# 检查所需软件依赖是否正确安装
git --version # git version 2.43.0
go version # go version go1.25.0 linux/amd64
node --version # v22.19.0
pnpm --version # 10.16.1
forge --version # forge Version: 1.3.5-stable
make --version # GNU Make 4.3
jq --version # jq-1.7
direnv --version # 2.32.1
rustc --version # rustc 1.89.0 (29483883e 2025-08-04)
just --version # just 1.42.4
mise --version # 2025.9.10 linux-x64 (2025-09-13)
从以下服务之一获取 Sepolia RPC URL:
在以下链接中获取测试币 SepoliaETH。
# 克隆 optimism 并切换到最新 release 分支
cd ~
git clone https://github.com/ethereum-optimism/optimism.git
cd optimism
git checkout v1.13.6 -b v1.13.6
# 克隆 op-geth 到 optimism 目录下并切换到最新 release 分支
git clone https://github.com/ethereum-optimism/op-geth.git
cd op-geth
git checkout v1.101602.0 -b v1.101602.0
cd ~/optimism/op-geth
make geth
cd ..
make op-node op-batcher op-proposer
# 检查组件是否构建成功
./op-geth/build/bin/geth --version
./op-node/bin/op-node --version
./op-batcher/bin/op-batcher --version
./op-proposer/bin/op-proposer --version
cd ~/optimism
./packages/contracts-bedrock/scripts/getting-started/wallets.sh
此命令会生成五个地址及其私钥:
Admin
(管理员)Batcher
(批处理者)Proposer
(提议者)Sequencer
(排序者)Challenger
(挑战者)创建.envrc
文件
nano .envrc
填写以下变量:
# Admin account
export GS_ADMIN_ADDRESS=
export GS_ADMIN_PRIVATE_KEY=
# Batcher account
export GS_BATCHER_ADDRESS=
export GS_BATCHER_PRIVATE_KEY=
# Proposer account
export GS_PROPOSER_ADDRESS=
export GS_PROPOSER_PRIVATE_KEY=
# Sequencer account
export GS_SEQUENCER_ADDRESS=
export GS_SEQUENCER_PRIVATE_KEY=
# Challenger account
export GS_CHALLENGER_ADDRESS=
export GS_CHALLENGER_PRIVATE_KEY=
##################################################
# Layer1 RPC Configuration #
##################################################
# RPC URL for the L1 network to interact with
export L1_RPC_URL=
export L1_BEACON_URL="https://ethereum-sepolia-beacon-api.publicnode.com"
# The kind of RPC provider, used to inform optimal transactions receipts
# fetching. Valid options: alchemy, quicknode, infura, parity, nethermind,
# debug_geth, erigon, basic, any.
export L1_RPC_KIND=
##################################################
# Chain Configuration #
##################################################
# The unique chain ID of the Layer 1 network(e.g., Sepolia = 11155111)
export L1_CHAIN_ID=11155111
# The unique chain ID you assign to your Layer 2 network (custom value)
export L2_CHAIN_ID=
# The average block time of the Layer 1 network (in seconds)
export L1_BLOCK_TIME=12
# The block time you configure for your Layer 2 network (in seconds)
export L2_BLOCK_TIME=2
保存文件(Ctrl+O, Enter, Ctrl+X)
direnv allow
验证环境变量是否加载
echo "=== 环境变量检查 ==="
echo "GS_ADMIN_ADDRESS: $GS_ADMIN_ADDRESS"
echo "GS_BATCHER_ADDRESS: $GS_BATCHER_ADDRESS"
echo "GS_PROPOSER_ADDRESS: $GS_PROPOSER_ADDRESS"
echo "GS_SEQUENCER_ADDRESS: $GS_SEQUENCER_ADDRESS"
echo "GS_CHALLENGER_ADDRESS: $GS_CHALLENGER_ADDRESS"
echo "L1_RPC_KIND: $L1_RPC_KIND"
echo "L1_RPC_URL: $L1_RPC_URL"
echo "L1_BEACON_URL: $L1_BEACON_URL"
echo "L1_CHAIN_ID: $L1_CHAIN_ID"
echo "L2_CHAIN_ID: $L2_CHAIN_ID"
echo "L1_BLOCK_TIME: $L1_BLOCK_TIME"
echo "L2_BLOCK_TIME: $L2_BLOCK_TIME"
为以下地址充值 SepoliaETH:
Admin
— 0.5 SepoliaETHBatcher
— 0.1 SepoliaETHProposer
— 0.2 SepoliaETH# 查看账户余额
cast balance $GS_ADMIN_ADDRESS --rpc-url $L1_RPC_URL
cast balance $GS_BATCHER_ADDRESS --rpc-url $L1_RPC_URL
cast balance $GS_PROPOSER_ADDRESS --rpc-url $L1_RPC_URL
cd ~/optimism
mkdir -p bin
wget https://github.com/ethereum-optimism/optimism/releases/download/op-deployer%2Fv0.2.6/op-deployer-0.2.6-linux-amd64.tar.gz
sudo tar -C ./bin -xzf op-deployer-0.2.6-linux-amd64.tar.gz --strip-components=1
rm op-deployer-0.2.6-linux-amd64.tar.gz
# 验证是否下载解压成功
./bin/op-deployer --version
mkdir -p ~/.deployer
./bin/op-deployer init --l1-chain-id $L1_CHAIN_ID --l2-chain-ids $L2_CHAIN_ID --workdir .deployer
此命令会生成 intend.json
和 state.json
nano .deployer/intent.toml
确保配置中包含以下内容并替换相应的地址:
configType = "standard"
l1ChainID = 11155111
opcmAddress = "0x6b6f9129efb1b7a48f84e3b787333d1dca02ee34" # L1 上的 OP Chain Manager 合约地址
fundDevAccounts = false
useInterop = false
l1ContractsLocator = "tag://op-contracts/v2.2.0"
l2ContractsLocator = "tag://op-contracts/v1.7.0-beta.1+l2-contracts"
[[chains]]
id = "0x00000000000000000000000000000000000000000000000000000000004f5da2" # L2_CHAIN_ID 的十六进制
baseFeeVaultRecipient = "YOUR_ADMIN_ADDRESS"
l1FeeVaultRecipient = "YOUR_ADMIN_ADDRESS"
sequencerFeeVaultRecipient = "YOUR_ADMIN_ADDRESS"
eip1559DenominatorCanyon = 250
eip1559Denominator = 50
eip1559Elasticity = 6
[chains.roles]
l1ProxyAdminOwner = "0x1eb2ffc903729a0f03966b917003800b145f56e2"
l2ProxyAdminOwner = "0x2fc3ffc903729a0f03966b917003800b145f67f3"
systemConfigOwner = "YOUR_ADMIN_ADDRESS"
unsafeBlockSigner = "YOUR_SEQUENCER_ADDRESS"
batcher = "YOUR_BATCHER_ADDRESS"
proposer = "YOUR_PROPOSER_ADDRESS"
challenger = "0xfd1d2e729ae8eee2e146c033bf4400fe75284301"
# 查询 L1 gas fee,判断 L1 RPC 是否连接成功
cast gas-price --rpc-url $L1_RPC_URL
# 部署合约
./bin/op-deployer apply --workdir .deployer --l1-rpc-url $L1_RPC_URL --private-key $GS_ADMIN_PRIVATE_KEY
# 生成 genesis.json(用于 op-geth)
./bin/op-deployer inspect genesis --workdir .deployer $L2_CHAIN_ID > .deployer/genesis.json
# 生成 rollup.json(用于 op-node)
./bin/op-deployer inspect rollup --workdir .deployer $L2_CHAIN_ID > .deployer/rollup.json
# 生成 jwt 密钥用于 op-geth 与 op-node 通信
cd ~/optimism/op-geth
openssl rand -hex 32 > jwt.txt
cp jwt.txt ../op-node/
# 初始化 op-geth
mkdir -p datadir
build/bin/geth init --state.scheme=hash --datadir=datadir ../.deployer/genesis.json
#启动 op-geth
./build/bin/geth \
--datadir ./datadir \
--http \
--http.corsdomain="*" \
--http.vhosts="*" \
--http.addr=0.0.0.0 \
--http.api=web3,debug,eth,txpool,net,engine,miner \
--ws \
--ws.addr=0.0.0.0 \
--ws.port=8546 \
--ws.origins="*" \
--ws.api=debug,eth,txpool,net,engine,miner \
--syncmode=full \
--gcmode=archive \
--nodiscover \
--maxpeers=0 \
--networkid=$L2_CHAIN_ID \
--authrpc.vhosts="*" \
--authrpc.addr=0.0.0.0 \
--authrpc.port=8551 \
--authrpc.jwtsecret=./jwt.txt \
--rollup.disabletxpoolgossip=true
cd ~/optimism/op-node
./bin/op-node \
--l2=http://localhost:8551 \
--l2.jwt-secret=./jwt.txt \
--sequencer.enabled \
--sequencer.l1-confs=5 \
--verifier.l1-confs=4 \
--rollup.config=../.deployer/rollup.json \
--rpc.addr=0.0.0.0 \
--rpc.port=9545 \
--p2p.disable \
--rpc.enable-admin \
--p2p.sequencer.key=$GS_SEQUENCER_PRIVATE_KEY \
--l1=$L1_RPC_URL \
--l1.rpckind=$L1_RPC_KIND \
--l1.beacon=$L1_BEACON_URL
cd ~/optimism/op-batcher
./bin/op-batcher \
--l2-eth-rpc=http://localhost:8545 \
--rollup-rpc=http://localhost:9545 \
--poll-interval=1s \
--sub-safety-margin=6 \
--num-confirmations=1 \
--safe-abort-nonce-too-low-count=3 \
--resubmission-timeout=30s \
--rpc.addr=0.0.0.0 \
--rpc.port=8548 \
--rpc.enable-admin \
--max-channel-duration=25 \
--l1-eth-rpc=$L1_RPC_URL \
--private-key=$GS_BATCHER_PRIVATE_KEY
# 加载 op-proposer 配置变量(也可加到 .envrc 里面)
export OP_PROPOSER_WAIT_NODE_SYNC=true
export OP_PROPOSER_PROPOSAL_INTERVAL=15m
export OP_PROPOSER_GAME_FACTORY_ADDRESS=$(cat ~/.deployer/state.json | jq -r '.opChainDeployments[0].disputeGameFactoryProxyAddress')
export OP_PROPOSER_GAME_TYPE=1
cd ~/optimism/op-proposer
./bin/op-proposer \
--poll-interval=12s \
--rpc.port=8560 \
--rollup-rpc=http://localhost:9545 \
--private-key=$GS_PROPOSER_PRIVATE_KEY \
--l1-eth-rpc=$L1_RPC_URL
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
$L2_RPC_URL
在 MetaMask 中添加自定义网络:
# 获取 L1StandardBridge 地址
L1StandardBridge=$(cat ~/optimism/.deployer/state.json | jq -r '.opChainDeployments[0].l1StandardBridgeProxyAddress')
echo "L1StandardBridge 地址: $L1StandardBridge"
通过 Metamask 向你的 桥接地址 发送(0.0001 SepoliaETH),发送成功后大约需要 5 分钟才能在 Layer2 上看到 ETH.
Hooray!Op Stack 部署成功!!!
cast send $L1StandardBridge \
--rpc-url $L1_RPC_URL \
--private-key $GS_ADMIN_PRIVATE_KEY \
--value 0.0001ether \
"depositETH(uint32,bytes)" \
200000 \
"0x"
# 查看 Admin L1 和 L2 的余额
cast balance $GS_ADMIN_ADDRESS --rpc-url $L1_RPC_URL
cast balance $GS_ADMIN_ADDRESS --rpc-url $L2_RPC_URL
cast send $L1StandardBridge \
--rpc-url $L1_RPC_URL \
--private-key $GS_ADMIN_PRIVATE_KEY \
--value 0.0001ether \
"depositETHTo(address,uint32,bytes)" \
$GS_BATCHER_ADDRESS \
200000 \
"0x"
# 查看 Admin L1 和 Batcher L2 的余额
cast balance $GS_ADMIN_ADDRESS --rpc-url $L1_RPC_URL
cast balance $GS_BATCHER_ADDRESS --rpc-url $L2_RPC_URL
# L2 从 Batcher 转账到 Admin
cast send $GS_ADMIN_ADDRESS \
--rpc-url $L2_RPC_URL \
--private-key $GS_BATCHER_PRIVATE_KEY \
--value 0.00001ether
# 查看 Admin L2 和 Batcher L2 的余额
cast balance $GS_ADMIN_ADDRESS --rpc-url $L2_RPC_URL
cast balance $GS_BATCHER_ADDRESS --rpc-url $L2_RPC_URL
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!