Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1041,9 +1041,10 @@ jobs:
name: Run heavy fuzz tests
command: |
mkdir -p results
just test --junit > results/results.xml
just test
environment:
FOUNDRY_PROFILE: ciheavy
JUNIT_TEST_PATH: results/results.xml
working_directory: packages/contracts-bedrock
no_output_timeout: 90m
- run:
Expand Down Expand Up @@ -1248,8 +1249,9 @@ jobs:
name: Run tests
command: |
mkdir -p results
just test-upgrade --junit > results/results.xml
just test-upgrade
environment:
JUNIT_TEST_PATH: results/results.xml
FOUNDRY_FUZZ_SEED: 42424242
FOUNDRY_FUZZ_RUNS: 1
FOUNDRY_PROFILE: ci
Expand Down Expand Up @@ -1371,7 +1373,7 @@ jobs:
command: forge --version
- run:
name: Pull cached artifacts
command: bash scripts/ops/pull-artifacts.sh --fallback-to-latest
command: bash scripts/ops/pull-artifacts.sh
working_directory: packages/contracts-bedrock
- run:
name: Run checks
Expand Down Expand Up @@ -2778,10 +2780,9 @@ workflows:
parameters:
features: &features_matrix
- main
- CUSTOM_GAS_TOKEN
- OPTIMISM_PORTAL_INTEROP
- CANNON_KONA,DEPLOY_V2_DISPUTE_GAMES
- OPCM_V2
- CUSTOM_GAS_TOKEN
- OPCM_V2,CUSTOM_GAS_TOKEN
- OPCM_V2,OPTIMISM_PORTAL_INTEROP
context:
Expand Down
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
/op-devstack @ethereum-optimism/op-stack @ethereum-optimism/go-reviewers

# Expert areas
/op-deployer @ethereum-optimism/platforms-team
/op-validator @ethereum-optimism/platforms-team

/op-node/rollup @ethereum-optimism/consensus @ethereum-optimism/go-reviewers

/op-supervisor @ethereum-optimism/interop @ethereum-optimism/go-reviewers
Expand Down
11 changes: 11 additions & 0 deletions .semgrep/rules/sol-rules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -398,3 +398,14 @@ rules:
paths:
include:
- packages/contracts-bedrock/src/L1/opcm/OPContractsManagerV2.sol

- id: sol-style-ban-forge-std-test-import
languages: [solidity]
severity: ERROR
message: Import Test from test/setup/Test.sol, not forge-std/Test.sol. Import other forge-std components (stdStorage, StdStorage, stdError, StdUtils, Vm, console2, etc.) from their specific files (forge-std/StdStorage.sol, forge-std/StdError.sol, forge-std/StdUtils.sol, forge-std/Vm.sol, forge-std/console2.sol, etc.)
pattern-regex: import\s+(\{[^}]*\}\s+from\s+)?"forge-std/Test\.sol"\s*;
paths:
include:
- packages/contracts-bedrock/test
exclude:
- packages/contracts-bedrock/test/setup/Test.sol
20 changes: 20 additions & 0 deletions .semgrep/tests/sol-rules.sol-style-ban-forge-std-test-import.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ruleid: sol-style-ban-forge-std-test-import
import { Test } from "forge-std/Test.sol";

// ruleid: sol-style-ban-forge-std-test-import
import { Test as ForgeTest } from "forge-std/Test.sol";

// ruleid: sol-style-ban-forge-std-test-import
import { Test, Vm } from "forge-std/Test.sol";

// ok: sol-style-ban-forge-std-test-import
import { Test } from "test/setup/Test.sol";

// ok: sol-style-ban-forge-std-test-import
import { Test as BaseTest } from "test/setup/Test.sol";

// ok: sol-style-ban-forge-std-test-import
import { Vm } from "forge-std/Vm.sol";

// ok: sol-style-ban-forge-std-test-import
import { StdUtils } from "forge-std/StdUtils.sol";
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ require (
lukechampine.com/blake3 v1.3.0 // indirect
)

replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101604.0-synctest.0.0.20251208094937-ba6bdcfef423
replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101603.6-rc.1

// replace github.com/ethereum/go-ethereum => ../op-geth

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A=
github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.4-0.20251001155152-4eb15ccedf7e h1:iy1vBIzACYUyOVyoADUwvAiq2eOPC0yVsDUdolPwQjk=
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.4-0.20251001155152-4eb15ccedf7e/go.mod h1:DYj7+vYJ4cIB7zera9mv4LcAynCL5u4YVfoeUu6Wa+w=
github.com/ethereum-optimism/op-geth v1.101604.0-synctest.0.0.20251208094937-ba6bdcfef423 h1:5xVkCCBRWkOt+bzVWL1p3mOwrpZLjxi/+yWUsja0E48=
github.com/ethereum-optimism/op-geth v1.101604.0-synctest.0.0.20251208094937-ba6bdcfef423/go.mod h1:fCNAwDynfAP6EKsmLqwSDUDgi+GtJIir74Ui3fXXMps=
github.com/ethereum-optimism/op-geth v1.101603.6-rc.1 h1:C4MAM29WbeXeNELMLpX1xU6c6OIwBRNposAcl1NHvVk=
github.com/ethereum-optimism/op-geth v1.101603.6-rc.1/go.mod h1:fCNAwDynfAP6EKsmLqwSDUDgi+GtJIir74Ui3fXXMps=
github.com/ethereum-optimism/superchain-registry/validation v0.0.0-20251121143344-5ac16e0fbb00 h1:TR5Y7B+5m63V0Dno7MHcFqv/XZByQzx/4THV1T1A7+U=
github.com/ethereum-optimism/superchain-registry/validation v0.0.0-20251121143344-5ac16e0fbb00/go.mod h1:NZ816PzLU1TLv1RdAvYAb6KWOj4Zm5aInT0YpDVml2Y=
github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s=
Expand Down
1 change: 0 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,3 @@ update-op-geth ref:
go mod edit -replace=github.com/ethereum/go-ethereum=github.com/ethereum-optimism/op-geth@"$ver"; \
go mod tidy; \
echo "Updated op-geth to $ver"

3 changes: 1 addition & 2 deletions op-acceptance-tests/tests/interop/proofs/challenger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ func TestChallengerPlaysGame(gt *testing.T) {
badClaim := common.HexToHash("0xdeadbeef00000000000000000000000000000000000000000000000000000000")
attacker := sys.FunderL1.NewFundedEOA(eth.Ether(15))
dgf := sys.DisputeGameFactory()

game := dgf.StartSuperCannonGame(attacker, proofs.WithRootClaim(badClaim))
game := dgf.StartSuperCannonGame(attacker, proofs.WithSuperRootFrom(eth.Bytes32(badClaim), eth.Bytes32(badClaim)))

claim := game.RootClaim() // This is the bad claim from attacker
counterClaim := claim.WaitForCounterClaim() // This is the counter-claim from the challenger
Expand Down
17 changes: 17 additions & 0 deletions op-acceptance-tests/tests/sequencer/init_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package sequencer

import (
"log/slog"
"testing"

"github.com/ethereum-optimism/optimism/op-devstack/compat"
"github.com/ethereum-optimism/optimism/op-devstack/presets"
)

// TestMain creates the test-setups against the shared backend
func TestMain(m *testing.M) {
presets.DoMain(m, presets.WithMinimal(),
presets.WithCompatibleTypes(compat.SysGo),
presets.WithLogLevel(slog.LevelDebug),
)
}
45 changes: 45 additions & 0 deletions op-acceptance-tests/tests/sequencer/recover_mode_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package sequencer

import (
"testing"
"time"

"github.com/ethereum-optimism/optimism/op-devstack/devtest"
"github.com/ethereum-optimism/optimism/op-devstack/presets"
"github.com/stretchr/testify/require"
)

// TestRecoverModeWhenChainHealthy checks that the chain
// can progress as normal when recover mode is activated.
// Recover mode is designed to recover from a sequencing
// window expiry when there are ample L1 blocks to eagerly
// progress the l1 origin to. But when the l1 origin is
// close to the tip of the l1 chain, the eagerness would cause
// a delay in unsafe block production while the sequencer waits
// for the next l1 origin to become available. Recover mode
// has since been patched, and the sequencer will not demand the
// next l1 origin until it is actually available. This tests
// protects against a regeression in that behavior.
func TestRecoverModeWhenChainHealthy(gt *testing.T) {
t := devtest.ParallelT(gt)
sys := presets.NewMinimal(t)
tracer := t.Tracer()
ctx := t.Ctx()

err := sys.L2CL.SetSequencerRecoverMode(true)
require.NoError(t, err)
blockTime := sys.L2Chain.Escape().RollupConfig().BlockTime
numL2Blocks := uint64(20)
waitTime := time.Duration(blockTime*numL2Blocks+5) * time.Second

num := sys.L2CL.SyncStatus().UnsafeL2.Number
new_num := num
require.Eventually(t, func() bool {
ctx, span := tracer.Start(ctx, "check head")
defer span.End()

new_num, num = sys.L2CL.SyncStatus().UnsafeL2.Number, new_num
t.Logger().InfoContext(ctx, "unsafe head", "number", new_num, "safe head", sys.L2CL.SyncStatus().SafeL2.Number)
return new_num >= numL2Blocks
}, waitTime, time.Duration(blockTime)*time.Second)
}
30 changes: 30 additions & 0 deletions op-chain-ops/cmd/check-output-root/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Overview

Generates an output root for a given block using only the execution client RPC endpoint.

## Prerequisites:

1. git clone or pull the latest develop branch of the optimism repo
2. Go Installed
- You can follow the instructions in the [CONTRIBUTING.md](http://CONTRIBUTING.md) to install all software dependencies of the repo
3. RPC URL for the **L2** chain execution client you want to generate a output root for.
- **Important**: The RPC endpoint must be trusted as it provide the chain state used to compute the output root.

## Usage:

```bash
go run op-chain-ops/cmd/check-output-root/ --l2-eth-rpc $RPC_URL --block-num $BLOCK_NUM
```

Output:

```text
0xfefc68b1c0aa7f6e744a8c74084142cf3daa8692179fd5b9ff46c6eacdffe9aa
```

## Environment Variables

Alternatively, you can use environment variables to configure the script:

- `CHECK_OUTPUT_ROOT_L2_ETH_RPC`: L2 execution client RPC endpoint.
- `CHECK_OUTPUT_ROOT_BLOCK_NUM`: Block number to calculate the output root for.
91 changes: 91 additions & 0 deletions op-chain-ops/cmd/check-output-root/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package main

import (
"context"
"fmt"
"math/big"
"os"

"github.com/ethereum-optimism/optimism/op-service/ctxinterrupt"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/urfave/cli/v2"

oplog "github.com/ethereum-optimism/optimism/op-service/log"
)

const (
// L2EthRpcFlagname defines the flag name for the l2 eth RPC endpoint.
L2EthRpcFlagName = "l2-eth-rpc"
// BlockNumberFlagName defines the flag name for the L2 block number.
BlockNumberFlagName = "block-num"
)

// Flags contains the list of configuration options available to the binary.
var Flags = []cli.Flag{
&cli.StringFlag{
Name: L2EthRpcFlagName,
Usage: "Required: L2 execution client RPC endpoint (e.g., http://host:port).",
Required: true,
EnvVars: []string{"CHECK_OUTPUT_ROOT_L2_ETH_RPC"},
},
&cli.Uint64Flag{
Name: BlockNumberFlagName,
Usage: "Required: L2 block number to calculate the output root for.",
EnvVars: []string{"CHECK_OUTPUT_ROOT_BLOCK_NUM"},
},
}

func main() {
oplog.SetupDefaults()

app := cli.NewApp()
app.Name = "check-output-root"
app.Usage = "Calculates a output root from an L2 EL endpoint."
// Combine specific flags with log flags
app.Flags = append(Flags, oplog.CLIFlags("CHECK_OUTPUT_ROOT")...)

app.Action = func(c *cli.Context) error {
ctx := ctxinterrupt.WithCancelOnInterrupt(c.Context)
rpcUrl := c.String(L2EthRpcFlagName)
blockNum := c.Uint64(BlockNumberFlagName)
root, err := CalculateOutputRoot(ctx, rpcUrl, blockNum)
if err != nil {
return err
}
fmt.Println(root.Hex())
return nil
}

if err := app.Run(os.Args); err != nil {
log.Crit("Application failed", "err", err)
}
}

func CalculateOutputRoot(ctx context.Context, rpcUrl string, blockNum uint64) (common.Hash, error) {
client, err := ethclient.DialContext(ctx, rpcUrl)
if err != nil {
return common.Hash{}, fmt.Errorf("failed to connect to L2 RPC endpoint: %w", err)
}
header, err := client.HeaderByNumber(ctx, new(big.Int).SetUint64(blockNum))
if err != nil {
return common.Hash{}, fmt.Errorf("failed to get L2 block header: %w", err)
}
// Isthmus assumes WithdrawalsHash is present in the header.
if header.WithdrawalsHash == nil {
return common.Hash{}, fmt.Errorf("target block %d (%s) is missing withdrawals hash, required for Isthmus output root calculation",
header.Number.Uint64(), header.Hash())
}

// Construct OutputV0 using StateRoot, WithdrawalsHash (as MessagePasserStorageRoot), and BlockHash
output := &eth.OutputV0{
StateRoot: eth.Bytes32(header.Root),
MessagePasserStorageRoot: eth.Bytes32(*header.WithdrawalsHash),
BlockHash: header.Hash(),
}

// Calculate the output root hash
return common.Hash(eth.OutputRoot(output)), nil
}
1 change: 1 addition & 0 deletions op-chain-ops/interopgen/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ func DeployL2ToL1(l1Host *script.Host, superCfg *SuperchainConfig, superDeployme
AllowCustomDisputeParameters: true,
OperatorFeeScalar: cfg.GasPriceOracleOperatorFeeScalar,
OperatorFeeConstant: cfg.GasPriceOracleOperatorFeeConstant,
SuperchainConfig: superDeployment.SuperchainConfigProxy,
UseCustomGasToken: cfg.UseCustomGasToken,
})
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions op-deployer/pkg/deployer/devfeatures.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ var (
// DeployV2DisputeGamesDevFlag enables deployment of V2 dispute game contracts.
DeployV2DisputeGamesDevFlag = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000100")

// OpcmV2DevFlag enables deployment of OPCM V2.
OpcmV2DevFlag = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000010000")
// OPCMV2DevFlag enables the OPContractsManagerV2 contract.
OPCMV2DevFlag = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000010000")
)

// IsDevFeatureEnabled checks if a specific development feature is enabled in a feature bitmap.
Expand Down
56 changes: 56 additions & 0 deletions op-deployer/pkg/deployer/integration_test/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,62 @@ func TestEndToEndApply(t *testing.T) {
require.True(t, exists, "Native asset liquidity predeploy should exist in L2 genesis")
require.Equal(t, amount, account.Balance, "Native asset liquidity predeploy should have the configured balance")
})

t.Run("OPCMV2 deployment", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

lgr := testlog.Logger(t, slog.LevelDebug)
l1RPC, l1Client := devnet.DefaultAnvilRPC(t, lgr)
_, pk, dk := shared.DefaultPrivkey(t)
l1ChainID := new(big.Int).SetUint64(devnet.DefaultChainID)
l2ChainID := uint256.NewInt(1)
loc, _ := testutil.LocalArtifacts(t)
testCacheDir := testutils.IsolatedTestDirWithAutoCleanup(t)

intent, st := shared.NewIntent(t, l1ChainID, dk, l2ChainID, loc, loc, testCustomGasLimit)

// Enable OPCMV2 dev flag
intent.GlobalDeployOverrides = map[string]any{
"devFeatureBitmap": deployer.OPCMV2DevFlag,
}

require.NoError(t, deployer.ApplyPipeline(
ctx,
deployer.ApplyPipelineOpts{
DeploymentTarget: deployer.DeploymentTargetLive,
L1RPCUrl: l1RPC,
DeployerPrivateKey: pk,
Intent: intent,
State: st,
Logger: lgr,
StateWriter: pipeline.NoopStateWriter(),
CacheDir: testCacheDir,
},
))

// Verify that OPCMV2 was deployed in implementations
require.NotEmpty(t, st.ImplementationsDeployment.OpcmV2Impl, "OPCMV2 implementation should be deployed")
require.NotEmpty(t, st.ImplementationsDeployment.OpcmContainerImpl, "OPCM container implementation should be deployed")
require.NotEmpty(t, st.ImplementationsDeployment.OpcmStandardValidatorImpl, "OPCM standard validator implementation should be deployed")

// Verify that implementations are deployed on L1
cg := ethClientCodeGetter(ctx, l1Client)

opcmV2Code := cg(t, st.ImplementationsDeployment.OpcmV2Impl)
require.NotEmpty(t, opcmV2Code, "OPCMV2 should have code deployed")

// Verify that the dev feature bitmap is set to OPCMV2
require.Equal(t, deployer.OPCMV2DevFlag, intent.GlobalDeployOverrides["devFeatureBitmap"])

// Assert that the OPCM V1 addresses are zero
require.Equal(t, common.Address{}, st.ImplementationsDeployment.OpcmImpl, "OPCM V1 implementation should be zero")
require.Equal(t, common.Address{}, st.ImplementationsDeployment.OpcmContractsContainerImpl, "OPCM container implementation should be zero")
require.Equal(t, common.Address{}, st.ImplementationsDeployment.OpcmGameTypeAdderImpl, "OPCM game type adder implementation should be zero")
require.Equal(t, common.Address{}, st.ImplementationsDeployment.OpcmDeployerImpl, "OPCM deployer implementation should be zero")
require.Equal(t, common.Address{}, st.ImplementationsDeployment.OpcmUpgraderImpl, "OPCM upgrader implementation should be zero")
require.Equal(t, common.Address{}, st.ImplementationsDeployment.OpcmInteropMigratorImpl, "OPCM interop migrator implementation should be zero")
})
}

func TestGlobalOverrides(t *testing.T) {
Expand Down
Loading