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
51 changes: 7 additions & 44 deletions op-deployer/pkg/deployer/integration_test/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"log/slog"
"math/big"
"strings"
"testing"
"time"

"github.com/Masterminds/semver/v3"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/bootstrap"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/inspect"
Expand All @@ -36,7 +34,6 @@ import (
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/testutil"
opbindings "github.com/ethereum-optimism/optimism/op-e2e/bindings"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rpc"
Expand All @@ -51,7 +48,6 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-core/predeploys"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
Expand Down Expand Up @@ -818,7 +814,7 @@ func runEndToEndBootstrapAndApplyUpgradeTest(t *testing.T, afactsFS foundry.Stat
require.NoError(t, err)
defer versionClient.Close()

shouldUpgradeSuperchainConfig, err := needsSuperchainConfigUpgrade(
shouldUpgradeSuperchainConfig, err := testutil.NeedsSuperchainConfigUpgrade(
ctx,
versionClient,
implementationsConfig.SuperchainConfigProxy,
Expand All @@ -842,13 +838,18 @@ func runEndToEndBootstrapAndApplyUpgradeTest(t *testing.T, afactsFS foundry.Stat
)
require.NoError(t, err)

opcmAddress := impls.Opcm
if deployer.IsDevFeatureEnabled(implementationsConfig.DevFeatureBitmap, deployer.OPCMV2DevFlag) {
opcmAddress = impls.OpcmV2
}

// Only run the superchain config upgrade if the live superchain config is behind the freshly deployed
// implementation. Running the script when versions match will revert and panic the test harness.
if shouldUpgradeSuperchainConfig {
t.Run("upgrade superchain config", func(t *testing.T) {
upgradeConfig := embedded.UpgradeSuperchainConfigInput{
Prank: superchainProxyAdminOwner,
Opcm: impls.Opcm,
Opcm: opcmAddress,
SuperchainConfig: implementationsConfig.SuperchainConfigProxy,
}

Expand Down Expand Up @@ -1051,44 +1052,6 @@ func runEndToEndBootstrapAndApplyUpgradeTest(t *testing.T, afactsFS foundry.Stat
})
}

func needsSuperchainConfigUpgrade(
ctx context.Context,
client *ethclient.Client,
currentProxy, targetImpl common.Address,
) (bool, error) {
currentVersion, err := superchainConfigVersion(ctx, client, currentProxy)
if err != nil {
return false, fmt.Errorf("failed to fetch proxy superchain config version: %w", err)
}

targetVersion, err := superchainConfigVersion(ctx, client, targetImpl)
if err != nil {
return false, fmt.Errorf("failed to fetch implementation superchain config version: %w", err)
}

return currentVersion.LessThan(targetVersion), nil
}

func superchainConfigVersion(
ctx context.Context,
client *ethclient.Client,
addr common.Address,
) (*semver.Version, error) {
contract, err := opbindings.NewSuperchainConfig(addr, client)
if err != nil {
return nil, fmt.Errorf("failed to bind superchain config at %s: %w", addr.Hex(), err)
}
versionStr, err := contract.Version(&bind.CallOpts{Context: ctx})
if err != nil {
return nil, fmt.Errorf("failed to read version from %s: %w", addr.Hex(), err)
}
version, err := semver.NewVersion(versionStr)
if err != nil {
return nil, fmt.Errorf("failed to parse version %q from %s: %w", versionStr, addr.Hex(), err)
}
return version, nil
}

func setupGenesisChain(t *testing.T, l1ChainID uint64) (deployer.ApplyPipelineOpts, *state.Intent, *state.State) {
lgr := testlog.Logger(t, slog.LevelDebug)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@ import (
"time"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/bootstrap"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/integration_test/shared"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/pipeline"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/testutil"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/upgrade/embedded"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum-optimism/optimism/op-service/testutils"
"github.com/ethereum-optimism/optimism/op-service/testutils/devnet"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/crypto"
"github.com/holiman/uint256"
"github.com/stretchr/testify/require"

"github.com/ethereum-optimism/optimism/op-chain-ops/devkeys"
)

func TestManageAddGameTypeV2_CLI(t *testing.T) {
Expand Down Expand Up @@ -109,8 +110,6 @@ func TestManageAddGameTypeV2_CLI(t *testing.T) {

// Tests the manage add-game-type-v2 command, from the CLI to the actual contract execution through the Solidity scripts.
func TestManageAddGameTypeV2_Integration(t *testing.T) {
// TODO(#18718): Update this to use an actual deployed OPCM V2 contract once we have one.
// For now, we manually deploy the OPCM V2 contract using bootstrap.Implementations.
lgr := testlog.Logger(t, slog.LevelDebug)

l1Rpc, stopL1, err := devnet.NewForkedSepolia(lgr)
Expand All @@ -121,17 +120,12 @@ func TestManageAddGameTypeV2_Integration(t *testing.T) {
runner := NewCLITestRunnerWithNetwork(t, WithL1RPC(l1Rpc.RPCUrl()))
workDir := runner.GetWorkDir()

// Test values - using arbitrary addresses for testing
l1ProxyAdminOwner := deployer.DefaultL1ProxyAdminOwnerSepolia
systemConfigProxy := deployer.DefaultSystemConfigProxySepolia

// Deploy the OPCM V2 contract.
opcmV2 := deployDependencies(t, runner)
// We deploy superchain, OPCM V2, and a fresh OP chain.
deployed := deployDependencies(t, runner)

// Run past upgrades before testing the V2 command.
// This is necessary when forking a network at a block before certain upgrades were executed.
_, afactsFS := testutil.LocalArtifacts(t)
shared.RunPastUpgradesWithRPC(t, runner.l1RPC, afactsFS, lgr, 11155111, l1ProxyAdminOwner, systemConfigProxy)
l1ProxyAdminOwner := deployed.proxyAdminOwner
systemConfigProxy := deployed.systemConfigProxy
opcmV2 := deployed.opcmV2

// FaultDisputeGameConfig just needs absolutePrestate (bytes32)
testPrestate := common.Hash{'P', 'R', 'E', 'S', 'T', 'A', 'T', 'E'}
Expand Down Expand Up @@ -247,64 +241,68 @@ func TestManageAddGameTypeV2_Integration(t *testing.T) {
require.Equal(t, l1ProxyAdminOwner.Hex(), dump[0].To.Hex(), "calldata should be sent to prank address")
}

// TODO(#18718): Remove this once we have a deployed OPCM V2 contract.
// deployDependencies deploys the superchain contracts and OPCM V2 implementation
// using the DeployImplementations script, and returns the OPCM V2 address
func deployDependencies(t *testing.T, runner *CLITestRunner) common.Address {
// deployedChain holds the addresses returned from deploying a fresh OP chain
type deployedChain struct {
opcmV2 common.Address
systemConfigProxy common.Address
proxyAdminOwner common.Address
}

// deployDependencies deploys superchain, OPCM V2, and a fresh OP chain using ApplyPipeline.
// Returns addresses needed for testing the add-game-type-v2 command.
func deployDependencies(t *testing.T, runner *CLITestRunner) deployedChain {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()

testCacheDir := testutils.IsolatedTestDirWithAutoCleanup(t)

// First, deploy superchain contracts (required for OPCM deployment)
superchainProxyAdminOwner := common.Address{'S'}
superchainOut, err := bootstrap.Superchain(ctx, bootstrap.SuperchainConfig{
L1RPCUrl: runner.l1RPC,
PrivateKey: runner.privateKeyHex,
ArtifactsLocator: artifacts.EmbeddedLocator,
Logger: runner.lgr,
SuperchainProxyAdminOwner: superchainProxyAdminOwner,
ProtocolVersionsOwner: common.Address{'P'},
Guardian: common.Address{'G'},
Paused: false,
RequiredProtocolVersion: params.ProtocolVersionV0{Major: 1}.Encode(),
RecommendedProtocolVersion: params.ProtocolVersionV0{Major: 2}.Encode(),
CacheDir: testCacheDir,
})
require.NoError(t, err, "Failed to deploy superchain contracts")

// Deploy implementations with OPCM V2 enabled
implOut, err := bootstrap.Implementations(ctx, bootstrap.ImplementationsConfig{
L1RPCUrl: runner.l1RPC,
PrivateKey: runner.privateKeyHex,
ArtifactsLocator: artifacts.EmbeddedLocator,
Logger: runner.lgr,
WithdrawalDelaySeconds: standard.WithdrawalDelaySeconds,
MinProposalSizeBytes: standard.MinProposalSizeBytes,
ChallengePeriodSeconds: standard.ChallengePeriodSeconds,
ProofMaturityDelaySeconds: standard.ProofMaturityDelaySeconds,
DisputeGameFinalityDelaySeconds: standard.DisputeGameFinalityDelaySeconds,
MIPSVersion: int(standard.MIPSVersion),
DevFeatureBitmap: deployer.OPCMV2DevFlag, // Enable OPCM V2
SuperchainConfigProxy: superchainOut.SuperchainConfigProxy,
ProtocolVersionsProxy: superchainOut.ProtocolVersionsProxy,
SuperchainProxyAdmin: superchainOut.SuperchainProxyAdmin,
L1ProxyAdminOwner: superchainProxyAdminOwner,
Challenger: common.Address{'C'},
CacheDir: testCacheDir,
FaultGameMaxGameDepth: standard.DisputeMaxGameDepth,
FaultGameSplitDepth: standard.DisputeSplitDepth,
FaultGameClockExtension: standard.DisputeClockExtension,
FaultGameMaxClockDuration: standard.DisputeMaxClockDuration,
// Get the private key and devkeys
pk, err := crypto.HexToECDSA(runner.privateKeyHex)
require.NoError(t, err)

dk, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic)
require.NoError(t, err)

l1ChainID := big.NewInt(11155111)

// We use the shared helper to create an intent and state
loc, _ := testutil.LocalArtifacts(t)
l2ChainID := uint256.NewInt(12345) // Test L2 chain ID

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

// Ensure we are using OPCM V2
intent.GlobalDeployOverrides = map[string]any{
"devFeatureBitmap": deployer.OPCMV2DevFlag,
}

// Deploy using ApplyPipeline with live target
err = deployer.ApplyPipeline(ctx, deployer.ApplyPipelineOpts{
DeploymentTarget: deployer.DeploymentTargetLive,
L1RPCUrl: runner.l1RPC,
DeployerPrivateKey: pk,
Intent: intent,
State: st,
Logger: runner.lgr,
StateWriter: pipeline.NoopStateWriter(),
CacheDir: testCacheDir,
})
require.NoError(t, err, "Failed to deploy implementations")
require.NoError(t, err, "Failed to deploy OP chain")

// Verify OPCM V2 was deployed
require.NotEqual(t, common.Address{}, implOut.OpcmV2, "OPCM V2 address should be set")
require.Equal(t, common.Address{}, implOut.Opcm, "OPCM V1 address should be zero when V2 is deployed")
require.NotEqual(t, common.Address{}, st.ImplementationsDeployment.OpcmV2Impl, "OPCM V2 address should be set")

t.Logf("Deployed OPCM V2 at address: %s", implOut.OpcmV2.Hex())
t.Logf("SuperchainConfigProxy: %s", superchainOut.SuperchainConfigProxy.Hex())
// Get the chain state
require.Len(t, st.Chains, 1, "Expected one chain to be deployed")
chainState := st.Chains[0]

return implOut.OpcmV2
t.Logf("Deployed OPCM V2 at address: %s", st.ImplementationsDeployment.OpcmV2Impl.Hex())
t.Logf("Deployed SystemConfigProxy at address: %s", chainState.SystemConfigProxy.Hex())
t.Logf("ProxyAdminOwner: %s", intent.Chains[0].Roles.L1ProxyAdminOwner.Hex())

return deployedChain{
opcmV2: st.ImplementationsDeployment.OpcmV2Impl,
systemConfigProxy: chainState.SystemConfigProxy,
proxyAdminOwner: intent.Chains[0].Roles.L1ProxyAdminOwner,
}
}
6 changes: 3 additions & 3 deletions op-deployer/pkg/deployer/integration_test/shared/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,8 @@ func buildV2OPCMUpgradeConfig(t *testing.T, prank, opcmAddr, systemConfigProxy c
}
}

// deployDummyCaller deploys DummyCaller at the prank address with the given OPCM address.
func deployDummyCaller(t *testing.T, rpcClient *rpc.Client, afactsFS foundry.StatDirFs, prank, opcmAddr common.Address) {
// DeployDummyCaller deploys DummyCaller at the prank address with the given OPCM address.
func DeployDummyCaller(t *testing.T, rpcClient *rpc.Client, afactsFS foundry.StatDirFs, prank, opcmAddr common.Address) {
t.Helper()

artifacts := &foundry.ArtifactsFS{FS: afactsFS}
Expand Down Expand Up @@ -429,7 +429,7 @@ func RunPastUpgradesWithRPC(t *testing.T, l1RPCUrl string, afactsFS foundry.Stat
// Process each OPCM upgrade: deploy DummyCaller with correct OPCM, run upgrade, broadcast
for _, opcm := range toApply {
// Deploy DummyCaller with this OPCM's address
deployDummyCaller(t, rpcClient, afactsFS, prank, opcm.Address)
DeployDummyCaller(t, rpcClient, afactsFS, prank, opcm.Address)

// Create fresh broadcaster and host for this upgrade
bcaster := NewImpersonationBroadcaster(lgr, ethClient, rpcClient, prank, networkChainID)
Expand Down
Loading